Compare commits

...

5 Commits

Author SHA1 Message Date
LFE 91168f6431 lfe
10 months ago
LFE 7743b2f150 lfe
10 months ago
LFE 33b73603ff lfe
10 months ago
LFE df7b5a641e lfe
10 months ago
LFE 2e4f4cd1e4 lfe
10 months ago

@ -13,93 +13,128 @@ import java.util.Map;
*
*/
public class Cart {
// 注释掉的代码表示之前可能考虑过直接存储总数和总价,但在此实现中,选择动态计算这些值
//private Integer totalCount;
//private BigDecimal totalPrice;
/**
*
*/
public Integer getTotalCount() {
Integer totalCount = 0;
// 初始化总数量为0
for (Map.Entry<Integer,CartItem>entry : items.entrySet()) {
// 遍历购物车中的每一项
totalCount += entry.getValue().getCount();
// 累加每一项的数量
}
return totalCount;
// 返回总数量
}
/**
*
*/
public BigDecimal getTotalPrice() {
BigDecimal totalPrice = new BigDecimal(0);
// 初始化总价格为0
for (Map.Entry<Integer,CartItem>entry : items.entrySet()) {
// 遍历购物车中的每一项
totalPrice = totalPrice.add(entry.getValue().getTotalPrice());
// 累加每一项的总价格
}
return totalPrice;
// 返回总价格
}
/**
*
*/
public Map<Integer, CartItem> getItems() {
return items;
// 返回购物车中的商品项
}
/**
*
*/
public void setItems(Map<Integer, CartItem> items) {
this.items = items;
// 设置购物车中的商品项
}
/**
* keyvalue
* Mapkeyvalue使LinkedHashMap
*/
private Map<Integer,CartItem> items = new LinkedHashMap<Integer, CartItem>();
/**
* toString
*/
@Override
public String toString() {
return "Cart{" +
"totalCount=" + getTotalCount() +
// 总数量
", totalPrice=" + getTotalPrice() +
// 总价格
", items=" + items +
// 商品项
'}';
}
/**
*
* @param cartItem
*
* @param cartItem
*/
public void addItem(CartItem cartItem) {
//先查看购物车中是否包含次商品,如果有的话,数量更新,总金额更新;如果没有,直接放到集合中即可
// 先查看购物车中是否包含此商品
CartItem item = items.get(cartItem.getId());
if(item == null) {
//之前没有添加过此商品
// 之前没有添加过此商品,直接添加到购物车中
items.put(cartItem.getId(),cartItem);
} else {
item.setCount(item.getCount() + 1);//数量累计
item.setTotalPrice(item.getPrice().multiply(new BigDecimal(item.getCount())));//更新总金额
// 购物车中已有此商品数量加1并更新总金额
item.setCount(item.getCount() + 1);
// 数量累计
item.setTotalPrice(item.getPrice().multiply(new BigDecimal(item.getCount())));
// 更新总金额
}
}
/**
*
* @param id
*
* @param id
*/
public void deleteItem(Integer id) {
items.remove(id);
// 从购物车中删除指定编号的商品项
}
/**
*
*
*/
public void clear() {
items.clear();
// 清空购物车
}
/**
*
* @param id
* @param count
*
* @param id
* @param count
*/
public void updateCount(Integer id,Integer count) {
//先查看购物车中是否包含次商品,如果有的话,数量更新,总金额更新;
// 先查看购物车中是否包含此商品项
CartItem cartItem = items.get(id);
if(cartItem != null) {
cartItem.setCount(count);
cartItem.setTotalPrice(cartItem.getPrice().multiply(new BigDecimal(cartItem.getCount())));
if(cartItem != null) {
// 购物车中已有此商品项,修改数量并更新总金额
cartItem.setCount(count);
// 修改数量
cartItem.setTotalPrice(cartItem.getPrice().multiply(new BigDecimal(cartItem.getCount())));
// 更新总金额
}
}
}
}

@ -10,72 +10,101 @@ import java.math.BigDecimal;
/**
*
*/
// 定义一个名为CartItem的类代表购物车中的一个商品项
public class CartItem {
// 定义一个私有变量id用于存储商品的唯一标识符
private Integer id;
// 定义一个私有变量name用于存储商品的名称
private String name;
// 定义一个私有变量count用于存储商品的数量
private Integer count;
// 定义一个私有变量price用于存储商品的单价使用BigDecimal类型以支持精确的小数计算
private BigDecimal price;
// 定义一个私有变量totalPrice用于存储商品的总价单价乘以数量同样使用BigDecimal类型
private BigDecimal totalPrice;
// 定义一个公开的getter方法用于获取商品的id
public Integer getId() {
return id;
}
// 定义一个公开的setter方法用于设置商品的id
public void setId(Integer id) {
this.id = id;
}
// 定义一个公开的getter方法用于获取商品的名称
public String getName() {
return name;
}
// 定义一个公开的setter方法用于设置商品的名称
public void setName(String name) {
this.name = name;
}
// 定义一个公开的getter方法用于获取商品的数量
public Integer getCount() {
return count;
}
// 定义一个公开的setter方法用于设置商品的数量
public void setCount(Integer count) {
this.count = count;
}
// 定义一个公开的getter方法用于获取商品的单价
public BigDecimal getPrice() {
return price;
}
// 定义一个公开的setter方法用于设置商品的单价
public void setPrice(BigDecimal price) {
this.price = price;
}
// 定义一个公开的getter方法用于获取商品的总价
public BigDecimal getTotalPrice() {
return totalPrice;
}
// 定义一个公开的setter方法用于设置商品的总价
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
// 定义一个公开的构造方法用于创建CartItem对象并初始化其所有属性
public CartItem(Integer id, String name, Integer count, BigDecimal price, BigDecimal totalPrice) {
// 使用this关键字将传入的id参数赋值给当前对象的id属性
this.id = id;
// 设置商品的唯一标识符
// 使用this关键字将传入的name参数赋值给当前对象的name属性
this.name = name;
// 设置商品的名称
// 使用this关键字将传入的count参数赋值给当前对象的count属性
this.count = count;
// 设置商品的数量
// 使用this关键字将传入的price参数赋值给当前对象的price属性
this.price = price;
// 设置商品的单价使用BigDecimal类型以支持精确的小数计算
// 使用this关键字将传入的totalPrice参数赋值给当前对象的totalPrice属性
this.totalPrice = totalPrice;
// 设置商品的总价单价乘以数量同样使用BigDecimal类型
}
// 定义一个无参构造方法用于创建CartItem对象时不初始化任何属性
public CartItem() {
}
// 重写toString方法用于返回CartItem对象的字符串表示形式
@Override
public String toString() {
// 返回的字符串包含CartItem对象的所有属性信息
return "Cart{" +
"id=" + id +
// 显示商品的id
", name='" + name + '\'' +
// 显示商品的名称
", count=" + count +
// 显示商品的数量
", price=" + price +
// 显示商品的单价
", totalPrice=" + totalPrice +
// 显示商品的总价
'}';
}
}

@ -1,90 +1,118 @@
package com.yj.bean;
// 定义包名,用于组织相关的类和接口
import java.util.List;
// 导入List接口用于存储数据集合
/**
* @author yj
* @create 2020-08-25 9:27
* @author yj // 类的作者
* @create 2020-08-25 9:27 // 类的创建时间
*/
public class Page <T>{
// 定义一个泛型类PageT表示该Page类可以持有任何类型的对象
public static final Integer PAGE_SIZE = 4;
// 定义一个常量,表示每页显示的数据条数
//当前页
private Integer pageNo;
// 当前页码
//总页码
private Integer pageTotal;
// 总页数
//当前页显示数量
private Integer pageSize = PAGE_SIZE;
// 每页显示的数据条数默认为常量PAGE_SIZE的值
//总的记录数
private Integer pageTotalCount;
// 数据总条数
//当前页数据
private List<T> items;
// 存储当前页的数据
//分页条的请求地址
private String url;
// 分页条请求的URL地址
// 获取分页条请求的URL地址
public String getUrl() {
return url;
}
// 设置分页条请求的URL地址
public void setUrl(String url) {
this.url = url;
}
// 获取当前页码
public Integer getPageNo() {
return pageNo;
}
// 获取总页数
public Integer getPageTotal() {
return pageTotal;
}
// 设置总页数
public void setPageTotal(Integer pageTotal) {
this.pageTotal = pageTotal;
}
// 获取每页显示的数据条数
public Integer getPageSize() {
return pageSize;
}
// 设置每页显示的数据条数
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
// 获取数据总条数
public Integer getPageTotalCount() {
return pageTotalCount;
}
// 设置数据总条数
public void setPageTotalCount(Integer pageTotalCount) {
this.pageTotalCount = pageTotalCount;
}
// 获取当前页的数据
public List<T> getItems() {
return items;
}
// 设置当前页的数据
public void setItems(List<T> items) {
this.items = items;
}
// 设置当前页码
public void setPageNo(Integer pageNo) {
this.pageNo = pageNo;
}
// 重写toString方法用于打印Page对象的详细信息
@Override
public String toString() {
return "Page{" +
"pageNo=" + pageNo +
// 当前页码
", pageTotal=" + pageTotal +
// 总页数
", pageSize=" + pageSize +
// 每页显示的数据条数
", pageTotalCount=" + pageTotalCount +
// 数据总条数
", items=" + items +
// 当前页的数据
", url='" + url + '\'' +
// 分页条请求的URL地址
'}';
}
}
}

@ -1,85 +1,124 @@
package com.yj.dao.impl;
// 定义包名,组织相关的类
import com.yj.utils.JDBCUtils;
// 导入JDBC工具类用于获取数据库连接
import org.apache.commons.dbutils.QueryRunner;
// 导入DbUtils的QueryRunner类用于简化JDBC操作
import org.apache.commons.dbutils.handlers.BeanHandler;
// 导入BeanHandler用于将结果集的第一行数据封装为JavaBean对象
import org.apache.commons.dbutils.handlers.BeanListHandler;
// 导入BeanListHandler用于将结果集的每一行数据封装为JavaBean对象并存储在List集合中
import org.apache.commons.dbutils.handlers.ScalarHandler;
// 导入ScalarHandler用于返回结果集的一行一列数据
import java.sql.Connection;
// 导入Connection接口用于数据库连接
import java.sql.SQLException;
// 导入SQLException类处理SQL异常
import java.util.List;
// 导入List接口用于存储数据集合
/**
* @author yj
* @create 2020-08-21 11:32
* @author yj // 类的作者
* @create 2020-08-21 11:32 // 类的创建时间
*/
public abstract class BaseDao {
//使用DbUtils操作数据库
// 定义一个抽象类BaseDao作为数据访问层的基类
// 使用DbUtils操作数据库
private QueryRunner queryRunner = new QueryRunner();
/*
*update()Insert\Update\Delete
// 初始化QueryRunner对象用于执行SQL语句
/**
* update()Insert\Update\Delete
* @param sql SQL
* @param args SQL
* @return -1
*/
public int update(String sql,Object ... args) {
public int update(String sql, Object ... args) {
Connection connection = JDBCUtils.getConnection();
// 调用JDBCUtils工具类获取数据库连接
try {
return queryRunner.update(connection,sql,args);
// 使用QueryRunner的update方法执行更新操作并返回影响的行数
return queryRunner.update(connection, sql, args);
} catch (SQLException e) {
e.printStackTrace();
// 打印SQL异常堆栈信息
throw new RuntimeException(e);
// 将SQL异常转换为运行时异常抛出
} finally {
// 注意原代码中缺少了关闭连接的逻辑应在此处添加但在实际使用中JDBCUtils的getConnection可能已负责关闭
// JDBCUtils.close(connection); // 关闭数据库连接
}
}
/**
*JavabeanSQL
* JavabeanSQL
* @param type
* @param sql sql
* @param args sql
* @param sql SQL
* @param args SQL
* @param <T>
* @return
* @return JavaBean
*/
public <T> T queryForOne(Class<T> type,String sql,Object ... args) {
public <T> T queryForOne(Class<T> type, String sql, Object ... args) {
Connection connection = JDBCUtils.getConnection();
// 获取数据库连接
try {
return queryRunner.query(connection,sql,new BeanHandler<T>(type),args);
// 使用QueryRunner的query方法执行查询操作并将结果集的第一行数据封装为指定的JavaBean对象
return queryRunner.query(connection, sql, new BeanHandler<T>(type), args);
} catch (SQLException e) {
e.printStackTrace();
// 打印SQL异常堆栈信息
throw new RuntimeException(e);
// 将SQL异常转换为运行时异常抛出
} finally {
// 注意:同样缺少了关闭连接的逻辑,应在实际使用中添加
}
}
/**
*JavabeanSQL
* JavabeanSQL
* @param type
* @param sql sql
* @param args sql
* @param sql SQL
* @param args SQL
* @param <T>
* @return
* @return JavaBean
*/
public <T> List<T> queryForList(Class<T> type, String sql, Object ... args) {
Connection connection = JDBCUtils.getConnection();
// 获取数据库连接
try {
return queryRunner.query(connection,sql,new BeanListHandler<T>(type),args);
// 使用QueryRunner的query方法执行查询操作并将结果集的每一行数据封装为指定的JavaBean对象存储在List集合中返回
return queryRunner.query(connection, sql, new BeanListHandler<T>(type), args);
} catch (SQLException e) {
e.printStackTrace();
// 打印SQL异常堆栈信息
throw new RuntimeException(e);
// 将SQL异常转换为运行时异常抛出
} finally {
// 注意:同样缺少了关闭连接的逻辑,应在实际使用中添加
}
}
/**
* sql
* @param sql sql
* @param args sql
* @return
* SQL
* @param sql SQL
* @param args SQL
* @return
*/
public Object queryForSingleValue(String sql,Object ... args) {
public Object queryForSingleValue(String sql, Object ... args) {
Connection connection = JDBCUtils.getConnection();
// 获取数据库连接
try {
return queryRunner.query(connection,sql,new ScalarHandler(),args);
}catch (SQLException e) {
// 使用QueryRunner的query方法执行查询操作并返回结果集的一行一列数据
return queryRunner.query(connection, sql, new ScalarHandler(), args);
} catch (SQLException e) {
e.printStackTrace();
// 打印SQL异常堆栈信息
throw new RuntimeException(e);
// 将SQL异常转换为运行时异常抛出
} finally {
// 注意同样缺少了关闭连接的逻辑但在实际中JDBCUtils的getConnection可能已负责关闭连接
}
}
}
}

@ -10,44 +10,64 @@ import java.math.BigDecimal;
* @author yj
* @create 2020-08-26 20:30
*/
// 定义一个测试类CartTest用于测试Cart类的功能
public class CartTest {
// 使用@Test注解标记的方法表示这是一个测试方法通常与测试框架如JUnit一起使用
@Test
public void addItem() {
// 创建一个新的Cart对象
Cart cart = new Cart();
// 向购物车中添加一个商品项注意这里totalPrice应该是根据price和count计算得出的但此处直接给出
cart.addItem(new CartItem(1,"lkjs",1,new BigDecimal(5),new BigDecimal(66)));
// 再次添加相同的商品项,理论上应该更新数量而不是添加新项(但根据代码,它会添加新项)
cart.addItem(new CartItem(1,"lkjs",1,new BigDecimal(5),new BigDecimal(66)));
// 添加一个不同的商品项
cart.addItem(new CartItem(2,"你妹的",1,new BigDecimal(5),new BigDecimal(66)));
// 打印购物车的内容输出将取决于Cart类的toString方法实现
System.out.println(cart);
}
// 另一个测试方法,用于测试删除商品项的功能
@Test
public void deleteItem() {
// 创建一个新的Cart对象并添加一些商品项
Cart cart = new Cart();
cart.addItem(new CartItem(1,"lkjs",1,new BigDecimal(5),new BigDecimal(66)));
cart.addItem(new CartItem(1,"lkjs",1,new BigDecimal(5),new BigDecimal(66)));
cart.addItem(new CartItem(2,"你妹的",1,new BigDecimal(5),new BigDecimal(66)));
// 根据商品ID删除商品项理论上应该删除所有ID匹配的项
cart.deleteItem(1);
// 打印购物车的内容,查看删除操作的结果
System.out.println(cart);
}
// 测试清空购物车的方法
@Test
public void clear() {
// 创建一个新的Cart对象并添加一些商品项
Cart cart = new Cart();
cart.addItem(new CartItem(1,"lkjs",1,new BigDecimal(5),new BigDecimal(66)));
cart.addItem(new CartItem(1,"lkjs",1,new BigDecimal(5),new BigDecimal(66)));
cart.addItem(new CartItem(2,"你妹的",1,new BigDecimal(5),new BigDecimal(66)));
// 清空购物车中的所有商品项
cart.clear();
// 打印购物车的内容,应该为空
System.out.println(cart);
}
// 测试更新商品数量的方法
@Test
public void updateCount() {
// 创建一个新的Cart对象并添加一些商品项
Cart cart = new Cart();
cart.addItem(new CartItem(1,"lkjs",1,new BigDecimal(5),new BigDecimal(66)));
cart.addItem(new CartItem(1,"lkjs",1,new BigDecimal(5),new BigDecimal(66)));
cart.addItem(new CartItem(2,"你妹的",1,new BigDecimal(5),new BigDecimal(66)));
// 根据商品ID更新商品数量注意这里可能需要根据业务逻辑决定是更新现有项还是添加新项
cart.updateCount(1,5);
// 假设意图是将ID为1的商品数量更新为5
// 打印购物车的内容,查看更新操作的结果
System.out.println(cart);
}
}

@ -1,29 +1,44 @@
package com.yj.test;
// 声明包名,用于组织类
import com.yj.utils.JDBCUtils;
// 导入JDBCUtils工具类用于数据库连接
import org.junit.Test;
// 导入JUnit测试注解
import java.sql.Connection;
// 导入Connection接口用于数据库连接
import java.sql.ResultSet;
// 导入ResultSet接口用于处理查询结果集
import java.sql.Statement;
// 导入Statement接口用于执行SQL语句
/**
* @author yj
* @create 2020-08-21 11:25
*/
public class JDBCUtilsTest {
@Test
public class JDBCUtilsTest { // 定义一个测试类
@Test // 标记此方法为一个测试方法
public void testJdbcUtils() {
// 定义一个测试方法
Connection connection = JDBCUtils.getConnection();
// 通过JDBCUtils工具类获取数据库连接
String sql = "select * from t_book";
// 定义SQL查询语句查询t_book表中的所有记录
try (Statement st = connection.createStatement()) {
// 创建Statement对象用于执行SQL语句使用try-with-resources语法自动关闭资源
ResultSet rs = st.executeQuery(sql);
while(rs.next()){
// 执行查询语句并将结果存储在ResultSet对象中
while(rs.next()){ // 遍历ResultSet对象中的每一条记录
System.out.println(rs.getString("author")+" "
// 从当前记录中获取"author"字段的值,并输出
+rs.getString("name"));
// 从当前记录中获取"name"字段的值,并输出,与"author"字段的值用空格分隔
}
}catch (Exception e) {
// 捕获并处理异常
e.printStackTrace();
// 打印异常堆栈信息
}
}
}
}

@ -1,79 +1,107 @@
package com.yj.utils;
// 声明包名
import com.alibaba.druid.pool.DruidDataSource;
// 导入Druid连接池的数据源类
import com.alibaba.druid.pool.DruidDataSourceFactory;
// 导入Druid连接池的工厂类
import com.alibaba.druid.util.JdbcUtils;
// 导入Druid的工具类注意此处的JdbcUtils并非JDK自带的而是Druid框架提供的但在此代码中未直接使用
import java.io.InputStream;
// 导入输入流接口
import java.sql.Connection;
// 导入数据库连接接口
import java.sql.SQLException;
// 导入SQL异常类
import java.util.Properties;
// 导入属性类
/**
* @author yj
* @create 2020-08-21 10:48
*/
public class JDBCUtils {
// 定义一个工具类
private static DruidDataSource dataSource;
// 定义一个静态的Druid数据源对象
private static ThreadLocal<Connection> conns = new ThreadLocal<Connection>();
// 定义一个ThreadLocal对象用于存储每个线程的数据库连接
static {
// 静态代码块,用于初始化静态变量
try {
Properties properties = new Properties();
//读取jdbc.properties属性配置文件
InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties" );
//从流中加载数据
// 创建一个属性对象
// 读取jdbc.properties属性配置文件
InputStream inputStream = JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
// 从流中加载数据到属性对象中
properties.load(inputStream);
//创建数据库连接池
// 创建数据库连接池
dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
// 使用Druid工厂类创建数据源对象
} catch (Exception e) {
// 捕获异常
e.printStackTrace();
// 打印异常堆栈信息
}
}
/*
@retrun null
/**
*
* @return null
*/
public static Connection getConnection() {
Connection conn = conns.get();
if(conn == null) {
try {
conn = dataSource.getConnection();//从数据库池中获取连接
conns.set(conn);//保存到ThreadLocal对象中供后面的JDBC操作使用
conn.setAutoCommit(false);//设置为手动管理事务
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
return conn;
// 定义一个静态方法,用于获取数据库连接
Connection conn = conns.get();
// 从ThreadLocal对象中获取当前线程的连接
if(conn == null) {
// 如果当前线程没有连接
try {
conn = dataSource.getConnection();
// 从数据库池中获取连接
conns.set(conn);
// 将连接保存到ThreadLocal对象中供后面的JDBC操作使用
conn.setAutoCommit(false);
// 设置为手动管理事务
} catch (SQLException throwables) {
// 捕获SQL异常
throwables.printStackTrace();
// 打印异常堆栈信息
}
}
return conn;
// 返回连接
}
/**
*
*/
public static void commitAndClose() {
// 定义一个静态方法,用于提交事务并关闭连接
Connection connection = conns.get();
// 从ThreadLocal对象中获取连接
if(connection!=null) {
// 如果连接不为空
try {
connection.commit();//提交事务
connection.commit();// 提交事务
} catch (SQLException throwables) {
// 捕获SQL异常
throwables.printStackTrace();
// 打印异常堆栈信息
}finally {
try {
connection.close();//关闭连接释放资源
connection.close();
// 关闭连接释放资源
} catch (SQLException throwables) {
// 捕获SQL异常
throwables.printStackTrace();
// 打印异常堆栈信息
}
}
}
//一定要执行remove操作否则就会出错因为tomcat底层使用了线程池技术
// 移除ThreadLocal对象中的连接防止内存泄漏特别是在使用线程池时
conns.remove();
}
@ -81,35 +109,45 @@ public class JDBCUtils {
*
*/
public static void rollbackAndClose() {
// 定义一个静态方法,用于回滚事务并关闭连接
Connection connection = conns.get();
// 从ThreadLocal对象中获取连接
if(connection!=null) {
// 如果连接不为空
try {
connection.rollback();//回滚事务
connection.rollback();
// 回滚事务
} catch (SQLException throwables) {
// 捕获SQL异常
throwables.printStackTrace();
// 打印异常堆栈信息
}finally {
try {
connection.close();//关闭连接释放资源
connection.close();
// 关闭连接释放资源
} catch (SQLException throwables) {
// 捕获SQL异常
throwables.printStackTrace();
// 打印异常堆栈信息
}
}
}
//一定要执行remove操作否则就会出错因为tomcat底层使用了线程池技术
// 移除ThreadLocal对象中的连接防止内存泄漏特别是在使用线程池时
conns.remove();
}
/*
使
public static void close(Connection conn) {
if(conn != null) {
try {
conn.close();
// 这里实际上并不是将连接关闭,而是将连接归还给连接池(对于连接池而言)
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}*/
}
}

@ -12,10 +12,11 @@ import java.util.Arrays;
public class PaymentUtil {
// 定义字符编码
private static String encodingCharset = "UTF-8";
/**
* hmac
* hmac
*
* @param p0_Cmd
* @param p1_MerId
@ -31,45 +32,34 @@ public class PaymentUtil {
* @param pd_FrpId
* @param pr_NeedResponse
* @param keyValue
* @return
* @return hmac
*/
public static String buildHmac(String p0_Cmd,String p1_MerId,
String p2_Order, String p3_Amt, String p4_Cur,String p5_Pid, String p6_Pcat,
String p7_Pdesc,String p8_Url, String p9_SAF,String pa_MP,String pd_FrpId,
String pr_NeedResponse,String keyValue) {
public static String buildHmac(String p0_Cmd, String p1_MerId,
String p2_Order, String p3_Amt, String p4_Cur, String p5_Pid, String p6_Pcat,
String p7_Pdesc, String p8_Url, String p9_SAF, String pa_MP, String pd_FrpId,
String pr_NeedResponse, String keyValue) {
StringBuilder sValue = new StringBuilder();
// 业务类型
// 依次追加所有参数到StringBuilder
sValue.append(p0_Cmd);
// 商户编号
sValue.append(p1_MerId);
// 商户订单号
sValue.append(p2_Order);
// 支付金额
sValue.append(p3_Amt);
// 交易币种
sValue.append(p4_Cur);
// 商品名称
sValue.append(p5_Pid);
// 商品种类
sValue.append(p6_Pcat);
// 商品描述
sValue.append(p7_Pdesc);
// 商户接收支付成功数据的地址
sValue.append(p8_Url);
// 送货地址
sValue.append(p9_SAF);
// 商户扩展信息
sValue.append(pa_MP);
// 银行编码
sValue.append(pd_FrpId);
// 应答机制
sValue.append(pr_NeedResponse);
// 调用hmacSign方法生成签名
return PaymentUtil.hmacSign(sValue.toString(), keyValue);
}
/**
* hmac
* hmac
*
* @param hmac
* @param p1_MerId
@ -84,57 +74,54 @@ public class PaymentUtil {
* @param r8_MP
* @param r9_BType
* @param keyValue
* @return
* @return true
*/
public static boolean verifyCallback(String hmac, String p1_MerId,
String r0_Cmd, String r1_Code, String r2_TrxId, String r3_Amt,
String r4_Cur, String r5_Pid, String r6_Order, String r7_Uid,
String r8_MP, String r9_BType, String keyValue) {
StringBuilder sValue = new StringBuilder();
// 商户编号
// 依次追加所有回调参数到StringBuilder
sValue.append(p1_MerId);
// 业务类型
sValue.append(r0_Cmd);
// 支付结果
sValue.append(r1_Code);
// 易宝支付交易流水号
sValue.append(r2_TrxId);
// 支付金额
sValue.append(r3_Amt);
// 交易币种
sValue.append(r4_Cur);
// 商品名称
sValue.append(r5_Pid);
// 商户订单号
sValue.append(r6_Order);
// 易宝支付会员ID
sValue.append(r7_Uid);
// 商户扩展信息
sValue.append(r8_MP);
// 交易结果返回类型
sValue.append(r9_BType);
// 调用hmacSign方法生成签名并与支付网关的签名比较
String sNewString = PaymentUtil.hmacSign(sValue.toString(), keyValue);
return sNewString.equals(hmac);
}
/**
* @param aValue
* @param aKey
* @return
* 使HMAC-MD5
*
* @param aValue
* @param aKey
* @return
*/
public static String hmacSign(String aValue, String aKey) {
// 初始化内部填充字节数组
byte k_ipad[] = new byte[64];
byte k_opad[] = new byte[64];
byte keyb[];
byte value[];
try {
// 使用指定的字符编码获取字节数组
keyb = aKey.getBytes(encodingCharset);
value = aValue.getBytes(encodingCharset);
} catch (UnsupportedEncodingException e) {
// 如果不支持指定的字符编码,则使用默认字符编码
keyb = aKey.getBytes();
value = aValue.getBytes();
}
// 填充k_ipad和k_opad数组
Arrays.fill(k_ipad, keyb.length, 64, (byte) 54);
Arrays.fill(k_opad, keyb.length, 64, (byte) 92);
for (int i = 0; i < keyb.length; i++) {
@ -142,23 +129,32 @@ public class PaymentUtil {
k_opad[i] = (byte) (keyb[i] ^ 0x5c);
}
// 获取MD5算法的MessageDigest实例
MessageDigest md = null;
try {
md = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
// 如果MD5算法不可用则返回null
return null;
}
// 对k_ipad和待签名数据进行更新
md.update(k_ipad);
md.update(value);
byte dg[] = md.digest();
md.reset();
byte dg[] = md.digest(); // 进行第一次摘要
md.reset(); // 重置MessageDigest实例
// 对k_opad和第一次摘要结果进行更新
md.update(k_opad);
md.update(dg, 0, 16);
dg = md.digest();
return toHex(dg);
dg = md.digest(); // 进行第二次摘要,得到最终的签名
return toHex(dg); // 将字节数组转换为十六进制字符串
}
/**
*
*
* @param input
* @return
*/
public static String toHex(byte input[]) {
if (input == null)
return null;
@ -169,15 +165,15 @@ public class PaymentUtil {
output.append("0");
output.append(Integer.toString(current, 16));
}
return output.toString();
}
/**
* HMAC
*
* @param args
* @param key
* @return
* @param args
* @param key
* @return HMAC
*/
public static String getHmac(String[] args, String key) {
if (args == null || args.length == 0) {
@ -191,8 +187,10 @@ public class PaymentUtil {
}
/**
* @param aValue
* @return
* 使SHA
*
* @param aValue
* @return
*/
public static String digest(String aValue) {
aValue = aValue.trim();

@ -1,12 +1,20 @@
// 导入所需的包和类
package com.yj.web;
import com.google.gson.Gson;
// 用于将Java对象转换为JSON字符串
import com.yj.bean.Book;
// 书籍实体类
import com.yj.bean.Cart;
// 购物车实体类
import com.yj.bean.CartItem;
// 购物车商品项实体类
import com.yj.service.BookService;
// 书籍服务接口
import com.yj.service.impl.BookServiceImpl;
// 书籍服务接口的实现类
import com.yj.utils.WebUtils;
// 工具类用于处理Web请求中的常见操作
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ -15,100 +23,93 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @author yj
* @create 2020-08-27 9:47
*/
// 定义一个Servlet类用于处理与购物车相关的请求
public class CartServlet extends BaseServlet {
// 创建一个书籍服务实例,用于访问书籍数据
private BookService bookService = new BookServiceImpl();
// 处理通过AJAX方式添加商品到购物车的请求
protected void ajaxAddItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int id = WebUtils.parseInt(req.getParameter("id"),0);
// 从请求中获取书籍ID并转换为整数类型默认为0
int id = WebUtils.parseInt(req.getParameter("id"), 0);
// 根据书籍ID查询书籍信息
Book book = bookService.queryBookById(id);
CartItem cartItem = new CartItem(book.getId(),book.getName(),1,book.getPrice(),book.getPrice());
// 创建一个购物车商品项实例数量为1单价和总价均为书籍价格
CartItem cartItem = new CartItem(book.getId(), book.getName(), 1, book.getPrice(), book.getPrice());
// 从会话中获取购物车对象,如果不存在则创建一个新的购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if(cart==null) {
if (cart == null) {
cart = new Cart();
req.getSession().setAttribute("cart",cart);
req.getSession().setAttribute("cart", cart);
}
// 将商品项添加到购物车中
cart.addItem(cartItem);
req.getSession().setAttribute("lastName",cartItem.getName());
// 在会话中保存最后添加的商品名称(可能用于显示或提示)
req.getSession().setAttribute("lastName", cartItem.getName());
//返回购物车总数量和最后一个商品的名称
Map<String,Object> resultMap = new HashMap<String,Object>();
resultMap.put("totalCount",cart.getTotalCount());
resultMap.put("lastName",cartItem.getName());
// 准备返回给客户端的数据,包括购物车总数量和最后一个商品的名称
Map<String, Object> resultMap = new HashMap<String, Object>();
resultMap.put("totalCount", cart.getTotalCount());
resultMap.put("lastName", cartItem.getName());
// 使用Gson将Map对象转换为JSON字符串
Gson gson = new Gson();
String resultMapJsonString = gson.toJson(resultMap);
// 将JSON字符串写入响应中
resp.getWriter().write(resultMapJsonString);
}
/**
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
// 处理添加商品到购物车的请求非AJAX方式
protected void addItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int id = WebUtils.parseInt(req.getParameter("id"),0);
Book book = bookService.queryBookById(id);
CartItem cartItem = new CartItem(book.getId(),book.getName(),1,book.getPrice(),book.getPrice());
// 以下代码与ajaxAddItem方法中的代码大致相同只是最后返回的是页面重定向
int id = WebUtils.parseInt(req.getParameter("id"), 0);
Book book = bookService.queryBookById(id);
CartItem cartItem = new CartItem(book.getId(), book.getName(), 1, book.getPrice(), book.getPrice());
Cart cart = (Cart) req.getSession().getAttribute("cart");
if(cart==null) {
if (cart == null) {
cart = new Cart();
req.getSession().setAttribute("cart",cart);
req.getSession().setAttribute("cart", cart);
}
cart.addItem(cartItem);
req.getSession().setAttribute("lastName",cartItem.getName());
req.getSession().setAttribute("lastName", cartItem.getName());
// 重定向到请求来源页面通常是通过Referer头部获取的
resp.sendRedirect(req.getHeader("Referer"));
}
/**
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
// 处理删除购物车中商品项的请求
protected void deleteItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int id = WebUtils.parseInt(req.getParameter("id"),0);
// 从请求中获取要删除的商品项ID
int id = WebUtils.parseInt(req.getParameter("id"), 0);
// 从会话中获取购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if(cart!=null) {
// 如果购物车对象存在则删除指定ID的商品项
if (cart != null) {
cart.deleteItem(id);
resp.sendRedirect(req.getHeader("Referer"));
}
// 重定向到请求来源页面
resp.sendRedirect(req.getHeader("Referer"));
}
/**
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
// 处理清空购物车中所有商品项的请求
protected void clearItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getSession().removeAttribute("cart");
// 从会话中移除购物车对象,从而清空购物车
req.getSession().removeAttribute("cart");
// 重定向到请求来源页面
resp.sendRedirect(req.getHeader("Referer"));
}
/**
*
* @param req
* @param resp
* @throws ServletException
* @throws IOException
*/
// 处理修改购物车中商品项数量的请求
protected void updateCount(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int id = WebUtils.parseInt(req.getParameter("id"),0);
int count = WebUtils.parseInt(req.getParameter("count"),1);
// 从请求中获取要修改的商品项ID和新的数量
int id = WebUtils.parseInt(req.getParameter("id"), 0);
int count = WebUtils.parseInt(req.getParameter("count"), 1);
// 从会话中获取购物车对象
Cart cart = (Cart) req.getSession().getAttribute("cart");
if(cart!=null) {
cart.updateCount(id,count);
resp.sendRedirect(req.getHeader("Referer"));
// 如果购物车对象存在则修改指定ID的商品项数量
if (cart != null) {
cart.updateCount(id, count);
}
// 重定向到请求来源页面
resp.sendRedirect(req.getHeader("Referer"));
}
}
}

@ -1,28 +1,45 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- 引入JSTL核心标签库用于简化JSP页面的内容 -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- 设置页面内容类型和字符编码 -->
<!DOCTYPE html>
<!-- 声明文档类型为HTML5 -->
<html>
<head>
<meta charset="UTF-8">
<title>购物车</title>
<meta charset="UTF-8">
<!-- 设置页面的字符编码 -->
<title>购物车</title>
<!-- 设置页面标题 -->
<%@include file="/pages/common/header.jsp"%>
<!-- 引入头部文件通常包含CSS和JavaScript的引用 -->
<script type="text/javascript">
$(function () {
// 当文档加载完成后执行的函数
$("a.deleteItem").click(function () {
// 为删除按钮绑定点击事件
return confirm("你确定要删除【"+$(this).parent().parent().find("td:first").text() +"】么?");
// 弹出确认框询问是否删除
});
$("#clearCart").click(function () {
// 为清空购物车按钮绑定点击事件
return confirm("你确定要清空购物车么?");
// 弹出确认框询问是否清空购物车
});
$(".updateCount").change(function () {
// 为数量输入框绑定值改变事件
var name = $(this).parent().parent().find("td:first").text();
// 获取商品名称
var count = this.value;
// 获取输入的新数量
var id = $(this).attr("bookId");
// 获取商品的ID
if(confirm("你确定要修改【"+name+"】数量为"+count+"么?")) {
location.href="http://localhost:8080/Book/cartServlet?action=updateCount&count="+count+"&id="+id;
// 弹出确认框询问是否修改数量
location.href="http://localhost:8080/Book/cartServlet?action=updateCount&count="+count+"&id="+id; // 跳转到更新数量的Servlet
} else {
this.value = this.defaultValue;
// 如果取消,则恢复默认数量
}
})
});
@ -30,58 +47,80 @@
</script>
</head>
<body>
<div id="header">
<img class="logo_img" alt="" src="static/img/logo.jpg" >
<span class="wel_word">购物车</span>
<%@include file="/pages/common/login_success_menu.jsp"%>
</div>
<div id="main">
<table>
<div id="header">
<!-- 头部区域 -->
<img class="logo_img" alt="" src="static/img/logo.jpg" >
<!-- 引入logo图片 -->
<span class="wel_word">购物车</span>
<!-- 显示欢迎文字 -->
<%@include file="/pages/common/login_success_menu.jsp"%>
<!-- 引入登录成功后的菜单 -->
</div>
<div id="main">
<!-- 主内容区域 -->
<table>
<!-- 商品列表表格 -->
<tr>
<td>商品名称</td>
<td>数量</td>
<td>单价</td>
<td>金额</td>
<td>操作</td>
</tr>
<c:if test="${empty sessionScope.cart.items}">
<!-- 判断购物车是否为空 -->
<tr>
<td>商品名称</td>
<td>数量</td>
<td>单价</td>
<td>金额</td>
<td>操作</td>
<td colspan="5"><a href="index.jsp">亲,当前购物车为空,快去和小伙伴浏览书籍吧! </a> </td>
<!-- 显示购物车为空的信息 -->
</tr>
</c:if>
<c:if test="${empty sessionScope.cart.items}">
<c:if test="${not empty sessionScope.cart.items}">
<!-- 判断购物车是否不为空 -->
<c:forEach items="${sessionScope.cart.items}" var="entry">
<!-- 遍历购物车中的商品 -->
<tr>
<td colspan="5"><a href="index.jsp">亲,当前购物车为空,快去和小伙伴浏览书籍吧! </a> </td>
<td>${entry.value.name}</td>
<!-- 显示商品名称 -->
<td>
<input class="updateCount" style="width: 70px;" bookId="${entry.value.id}" type="text" value="${entry.value.count}">
<!-- 数量输入框 -->
</td>
<td>${entry.value.price}</td>
<!-- 显示商品单价 -->
<td>${entry.value.totalPrice}</td>
<!-- 显示商品总价 -->
<td><a class="deleteItem" href="cartServlet?action=deleteItem&id=${entry.value.id}">删除</a></td>
<!-- 删除按钮 -->
</tr>
</c:if>
</c:forEach>
</c:if>
<c:if test="${not empty sessionScope.cart.items}">
<c:forEach items="${sessionScope.cart.items}" var="entry">
<tr>
<td>${entry.value.name}</td>
<td>
<input class="updateCount" style="width: 70px;" bookId="${entry.value.id}" type="text" value="${entry.value.count}">
</td>
<td>${entry.value.price}</td>
<td>${entry.value.totalPrice}</td>
<td><a class="deleteItem" href="cartServlet?action=deleteItem&id=${entry.value.id}">删除</a></td>
</tr>
</c:forEach>
</c:if>
</table>
<c:if test="${not empty sessionScope.cart.items}">
</table>
<c:if test="${not empty sessionScope.cart.items}">
<!-- 判断购物车是否不为空 -->
<div class="cart_info">
<!-- 购物车信息区域 -->
<span class="cart_span">购物车中共有<span class="b_count">${sessionScope.cart.totalCount}</span>本书籍</span>
<!-- 显示购物车中商品的总数 -->
<span class="cart_span">总金额<span class="b_price">${sessionScope.cart.totalPrice}</span>元</span>
<!-- 显示购物车中商品的总金额 -->
<span class="cart_span"><a id="clearCart" href="cartServlet?action=clearItem">清空购物车</a></span>
<!-- 清空购物车按钮 -->
<span class="cart_span"><a href="client/orderServlet?action=isLogin">去结账</a></span>
<!-- 去结账按钮 -->
</div>
</c:if>
</c:if>
</div>
</div>
<%@include file="/pages/common/footer.jsp"%>
<%@include file="/pages/common/footer.jsp"%>
<!-- 引入页脚文件 -->
</body>
</html>
</html>

@ -1,32 +1,52 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- 指定页面使用的内容类型为HTML字符集为UTF-8并声明使用Java作为脚本语言 -->
<!DOCTYPE html>
<!-- 声明文档类型为HTML5 -->
<html>
<!-- HTML文档的根元素 -->
<head>
<meta charset="UTF-8">
<title>结算页面</title>
<!-- 头部元素,包含文档的元数据 -->
<meta charset="UTF-8">
<!-- 设置文档的字符编码为UTF-8 -->
<title>结算页面</title>
<!-- 设置网页的标题 -->
<%@include file="/pages/common/header.jsp"%>
<style type="text/css">
<!-- 包含插入一个公共的头部JSP文件通常包含CSS和JavaScript链接 -->
<style type="text/css">
<!-- 定义内嵌的CSS样式 -->
h1 {
<!-- 设置h1标签的样式 -->
text-align: center;
<!-- 文本居中对齐 -->
margin-top: 200px;
<!-- 上边距为200像素 -->
}
</style>
</style>
</head>
<body>
<div id="header">
<img class="logo_img" alt="" src="static/img/logo.jpg" >
<span class="wel_word">结算</span>
<%@include file="/pages/common/login_success_menu.jsp"%>
</div>
<div id="main">
<h1>你的订单已结算,订单号为${sessionScope.orderId},店主很快就会发货啦!</h1>
</div>
<!-- 网页的主体部分 -->
<%@include file="/pages/common/footer.jsp"%>
<div id="header">
<!-- 头部区域的容器 -->
<img class="logo_img" alt="" src="static/img/logo.jpg" >
<!-- 显示网站的logo图片 -->
<span class="wel_word">结算</span>
<!-- 显示欢迎词或当前页面标识 -->
<%@include file="/pages/common/login_success_menu.jsp"%>
<!-- 包含登录成功后的菜单JSP文件 -->
</div>
<div id="main">
<!-- 主要内容的容器 -->
<h1>你的订单已结算,订单号为${sessionScope.orderId},店主很快就会发货啦!</h1>
<!-- 显示订单结算成功的消息,${sessionScope.orderId}用于从会话范围获取订单号 -->
</div>
<%@include file="/pages/common/footer.jsp"%>
<!-- 包含页脚的JSP文件通常包含版权信息和链接 -->
</body>
</html>
</html>
<!-- HTML文档的结束 -->

@ -1,78 +1,98 @@
<%--
这是一个JSP注释不会被发送到客户端。它包含了文件的创建信息。
Created by IntelliJ IDEA.
User: jhu
Date: 2020/10/5
Time: 14:50
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!-- 指定页面内容类型、字符集和脚本语言 -->
<html>
<!-- HTML文档的根元素 -->
<head>
<!-- 文档的头部 -->
<title>结算页面</title>
<!-- 设置页面标题 -->
<%@include file="/pages/common/header.jsp"%>
<!-- 包含公共头部文件通常包含CSS、JavaScript链接等 -->
<!-- 下面的div元素应该放在body内而不是head内但这里可能是个错误或复制粘贴时的疏忽 -->
<div id="header">
<!-- 头部容器 -->
<img class="logo_img" alt="" src="static/img/logo.jpg" >
<!-- 网站logo图片 -->
<span class="wel_word">结算</span>
<!-- 欢迎词或当前页面标识 -->
<%@include file="/pages/common/login_success_menu.jsp"%>
<!-- 包含登录成功后的菜单 -->
</div>
<!-- 注意上面的div元素应该被移除到body标签内 -->
</head>
<body>
<!-- 文档的主体 -->
<div id="main">
<!-- 主要内容容器 -->
<form action="client/orderServlet?action=createOrder" method="post">
<!-- 提交表单到orderServlet的createOrder动作 -->
<input type="hidden">
<!-- 隐藏输入字段此处未指定name属性可能是个占位符 -->
<table width="80%">
<!-- 表格宽度为页面宽度的80% -->
<tr>
<td bgcolor="#F7FEFF" colspan="4">
支付金额:<INPUT id="money" TYPE="text" NAME="money" size="6" value="${sessionScope.cart.totalPrice}">元</td>
<!-- 表格单元格,背景色为#F7FEFF横跨4列 -->
支付金额:<INPUT id="money" TYPE="text" NAME="money" size="6" value="${sessionScope.cart.totalPrice}">元</td> <!-- 显示支付金额,从会话中获取购物车总价 -->
</tr>
<tr>
<td><br />
</td>
<td><br /></td>
<!-- 空行 -->
</tr>
<tr>
<td colspan="4">请您选择在线支付银行</td>
<!-- 提示用户选择支付银行 -->
</tr>
<!-- 下面的几行是银行选择项,每个单选按钮代表一个银行 -->
<tr>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="CMBCHINA-NET">招商银行
</td>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="CMBCHINA-NET">招商银行</td>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="ICBC-NET">工商银行</td>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="ABC-NET">农业银行</td>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="CCB-NET">建设银行
</td>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="CCB-NET">建设银行</td>
</tr>
<tr>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="CMBC-NET">中国民生银行总行</td>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="CEB-NET">光大银行
</td>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="CEB-NET">光大银行</td>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="BOCO-NET">交通银行</td>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="SDB-NET">深圳发展银行</td>
</tr>
<tr>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="BCCB-NET">北京银行</td>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="CIB-NET">兴业银行
</td>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="SPDB-NET">上海浦东发展银行
</td>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="CIB-NET">兴业银行</td>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="SPDB-NET">上海浦东发展银行</td>
<td><INPUT TYPE="radio" NAME="pd_FrpId" value="ECITIC-NET">中信银行</td>
</tr>
<tr>
<td><br />
</td>
<td><br /></td>
<!-- 空行 -->
</tr>
<tr>
<td colspan="4"><INPUT TYPE="submit" value="确定支付">
</td>
<td colspan="4"><INPUT TYPE="submit" value="确定支付"></td>
<!-- 提交按钮 -->
</tr>
</table>
</form>
</div>
<%@include file="/pages/common/footer.jsp"%>
<!-- 包含公共页脚文件 -->
</body>
</body>
</html>
<!-- 注意:这里有一个多余的</body>标签,应该被移除 -->
</html>

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save