diff --git a/sql/bookstore.sql b/sql/bookstore.sql index 4baa7bf..62c6171 100644 --- a/sql/bookstore.sql +++ b/sql/bookstore.sql @@ -20,62 +20,87 @@ INSERT INTO t_user(username,`password`,email,address) VALUES('admin','admin','ad ## 查询表 SELECT * FROM t_user; +-- 创建名为t_book的表 CREATE TABLE t_book( - `id` INT PRIMARY KEY AUTO_INCREMENT, - `name` VARCHAR(100), - `price` DECIMAL(11,2), - `author` VARCHAR(100), - `classification` VARCHAR(20), - `sales` INT, - `stock` INT, - `imgpath` VARCHAR(200) + -- 定义名为id的字段,数据类型为INT(整数类型),将其设置为主键,并且设置为自增(AUTO_INCREMENT),这样每插入一条新记录时,该字段的值会自动按顺序递增,用于为每本图书生成唯一的标识符 + `id` INT PRIMARY KEY AUTO_INCREMENT, + -- 定义名为name的字段,数据类型为VARCHAR(可变长度字符串),长度为100,用于存储图书的书名信息 + `name` VARCHAR(100), + -- 定义名为price的字段,数据类型为DECIMAL(精确数值类型),总长度为11位,其中小数部分占2位,用于存储图书的价格信息 + `price` DECIMAL(11,2), + -- 定义名为author的字段,数据类型为VARCHAR,长度为100,用来记录图书的作者姓名 + `author` VARCHAR(100), + -- 定义名为classification的字段,数据类型为VARCHAR,长度为20,可用于存储图书的分类信息,例如文学、科技等类别 + `classification` VARCHAR(20), + -- 定义名为sales的字段,数据类型为INT,用于记录图书的销量情况 + `sales` INT, + -- 定义名为stock的字段,数据类型为INT,用于表示图书的库存数量 + `stock` INT, + -- 定义名为imgpath的字段,数据类型为VARCHAR,长度为200,可用于存储图书封面图片的路径信息,方便在应用中展示图书封面图片 + `imgpath` VARCHAR(200) ); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('解忧杂货店','东野圭吾','文学',27.20,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('边城','沈从文','文学',23.00,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('中国哲学史','冯友兰','文学',44.5,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('苏东坡传','林语堂','文学',19.30,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('百年孤独','马尔克斯','文学',29.50,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('扶桑','严歌苓','文学',19.8,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('给孩子的诗','北岛','文学',22.20,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('为奴十二年','所罗门','文学',16.5,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('平凡的世界','路遥','文学',55.00,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('悟空传','今何在','文学',14.00,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('硬派健身','斌卡','文学',31.20,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('从晚清到民国','唐德刚','文学',39.90,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('三体','刘慈欣','文学',56.5,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('看见','柴静','文学',19.50,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('活着','余华','文学',11.00,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('小王子','安托万','文学',19.20,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('我们仨','杨绛','文学',11.30,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification,price, sales , stock , imgpath) VALUES('生命不息,折腾不止','罗永浩','文学',25.20,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification,price, sales , stock , imgpath) VALUES('皮囊','蔡崇达','文学',23.90,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('恰到好处的幸福','毕淑敏','文学',16.40,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('大数据预测','埃里克','文学',37.20,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('人月神话','布鲁克斯','文学',55.90,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('C语言入门经典','霍尔顿','文学',45.00,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('数学之美','吴军','文学',29.90,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('Java编程思想','埃史尔','文学',70.50,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('设计模式之禅','秦小波','文学',20.20,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('图解机器学习','杉山将','文学',33.80,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('艾伦图灵传','安德鲁','文学',47.20,100,100,'static/img/default.jpg'); -INSERT INTO t_book (name, author, classification, price, sales , stock , imgpath) VALUES('教父','马里奥普佐','文学',29.00,100,100,'static/img/default.jpg'); - +-- 向t_book表中插入一条图书数据记录,指定要插入值的字段为(name, author, classification, price, sales, stock, imgpath),并对应给出具体的值,分别为图书的书名、作者、分类、价格、销量、库存以及封面图片路径 +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('解忧杂货店','东野圭吾','文学',27.20,100,100,'static/img/default.jpg'); +-- 同样是向t_book表中插入图书数据记录,以下每条INSERT语句的结构和作用与上面类似,只是对应不同的图书信息 +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('边城','沈从文','文学',23.00,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('中国哲学史','冯友兰','文学',44.5,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('苏东坡传','林语堂','文学',19.30,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('百年孤独','马尔克斯','文学',29.50,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('扶桑','严歌苓','文学',19.8,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('给孩子的诗','北岛','文学',22.20,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('为奴十二年','所罗门','文学',16.5,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('平凡的世界','路遥','文学',55.00,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('悟空传','今何在','文学',14.00,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('硬派健身','斌卡','文学',31.20,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('从晚清到民国','唐德刚','文学',39.90,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('三体','刘慈欣','文学',56.5,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('看见','柴静','文学',19.50,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('活着','余华','文学',11.00,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('小王子','安托万','文学',19.20,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('我们仨','杨绛','文学',11.30,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification,price, sales, stock, imgpath) VALUES('生命不息,折腾不止','罗永浩','文学',25.20,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification,price, sales, stock, imgpath) VALUES('皮囊','蔡崇达','文学',23.90,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('恰到好处的幸福','毕淑敏','文学',16.40,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('大数据预测','埃里克','文学',37.20,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('人月神话','布鲁克斯','文学',55.90,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('C语言入门经典','霍尔顿','文学',45.00,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('数学之美','吴军','文学',29.90,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('Java编程思想','埃史尔','文学',70.50,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('设计模式之禅','秦小波','文学',20.20,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('图解机器学习','杉山将','文学',33.80,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('艾伦图灵传','安德鲁','文学',47.20,100,100,'static/img/default.jpg'); +INSERT INTO t_book (name, author, classification, price, sales, stock, imgpath) VALUES('教父','马里奥普佐','文学',29.00,100,100,'static/img/default.jpg'); +-- 创建名为t_order的表 CREATE TABLE t_order( - `order_id` VARCHAR(50) PRIMARY KEY, - `create_time` DATETIME, - `price` DECIMAL(11,2), - `status` INT, - `user_id` INT, - FOREIGN KEY(`user_id`) REFERENCES t_user(`id`) + -- 定义名为order_id的字段,数据类型为VARCHAR(可变长度字符串),长度为50,并且将该字段设置为主键,用于唯一标识每条订单记录 + `order_id` VARCHAR(50) PRIMARY KEY, + -- 定义名为create_time的字段,数据类型为DATETIME(用于存储日期和时间信息),用来记录订单创建的时间 + `create_time` DATETIME, + -- 定义名为price的字段,数据类型为DECIMAL(精确数值类型),总长度为11位,其中小数部分占2位,用于存储订单的价格信息 + `price` DECIMAL(11,2), + -- 定义名为status的字段,数据类型为INT(整数类型),可能用于表示订单的状态,比如不同的数值对应不同的订单处理阶段等情况 + `status` INT, + -- 定义名为user_id的字段,数据类型为INT,该字段将作为外键,与另一个表(t_user)中的id字段建立关联关系 + `user_id` INT, + -- 使用FOREIGN KEY关键字为user_id字段添加外键约束,指定它参照t_user表中的id字段,意味着t_order表中的user_id值必须在t_user表的id字段值中存在,以此建立起两张表之间的关联,通常表示订单所属的用户 + FOREIGN KEY(`user_id`) REFERENCES t_user(`id`) ); +-- 创建名为t_order_item的表 CREATE TABLE t_order_item( - `id` INT PRIMARY KEY AUTO_INCREMENT, - `name` VARCHAR(100), - `count` INT, - `price` DECIMAL(11,2), - `total_price` DECIMAL(11,2), - `order_id` VARCHAR(50), - FOREIGN KEY(`order_id`) REFERENCES t_order(`order_id`) + -- 定义名为id的字段,数据类型为INT(整数类型),并将该字段设置为主键,同时设置为自增(AUTO_INCREMENT),这样每当插入一条新记录时,该字段的值会自动按顺序递增,常用于为每条记录生成唯一的标识符 + `id` INT PRIMARY KEY AUTO_INCREMENT, + -- 定义名为name的字段,数据类型为VARCHAR,长度为100,可用于存储商品名称等相关信息,比如订单中具体商品的名字 + `name` VARCHAR(100), + -- 定义名为count的字段,数据类型为INT,用于记录商品的数量,比如某个商品在该订单中的购买数量 + `count` INT, + -- 定义名为price的字段,数据类型为DECIMAL,总长度11位,小数部分占2位,可能用于存储单个商品的价格信息 + `price` DECIMAL(11,2), + -- 定义名为total_price的字段,数据类型为DECIMAL,总长度11位,小数部分占2位,用于存储该商品的总价(可能是通过商品单价乘以数量计算得出) + `total_price` DECIMAL(11,2), + -- 定义名为order_id的字段,数据类型为VARCHAR,长度为50,该字段将作为外键,与t_order表中的order_id字段建立关联关系 + `order_id` VARCHAR(50), + -- 使用FOREIGN KEY关键字为order_id字段添加外键约束,指定它参照t_order表中的order_id字段,意味着t_order_item表中的order_id值必须在t_order表的order_id字段值中存在,以此建立起两张表之间的关联,表明该订单项所属的订单 + FOREIGN KEY(`order_id`) REFERENCES t_order(`order_id`) ); diff --git a/src/com/yj/bean/Book.java b/src/com/yj/bean/Book.java index 30432c7..3f6e5c6 100644 --- a/src/com/yj/bean/Book.java +++ b/src/com/yj/bean/Book.java @@ -5,88 +5,176 @@ import java.math.BigDecimal; /** * @author yj * @create 2020-10-02 19:51 + * + * Book类表示一本书的信息,包含了书籍的基本属性,如ID、书名、作者、价格、销量、库存、分类和图片路径等。 */ public class Book { - private Integer id;//id - private String name;//姓名 - private String author;//作者 + + // 书籍的唯一标识符 + private Integer id; + + // 书籍的名称 + private String name; + + // 书籍的作者 + private String author; + + // 书籍的价格,使用BigDecimal类型以确保精度 private BigDecimal price; + + // 书籍的销量 private Integer sales; + + // 书籍的库存数量 private Integer stock; + + // 书籍的分类 private String classification; - private String imgPath="static/img/default.jpg"; + // 书籍的图片路径,默认值为"static/img/default.jpg" + private String imgPath = "static/img/default.jpg"; + + /** + * 获取书籍的分类 + * @return 书籍的分类 + */ public String getClassification() { return classification; } + /** + * 设置书籍的分类 + * @param classification 书籍的分类 + */ public void setClassification(String classification) { this.classification = classification; } - - + /** + * 获取书籍的ID + * @return 书籍的ID + */ public Integer getId() { return id; } + /** + * 设置书籍的ID + * @param id 书籍的ID + */ public void setId(Integer id) { this.id = id; } + /** + * 获取书籍的名称 + * @return 书籍的名称 + */ public String getName() { return name; } + /** + * 设置书籍的名称 + * @param name 书籍的名称 + */ public void setName(String name) { this.name = name; } + /** + * 获取书籍的作者 + * @return 书籍的作者 + */ public String getAuthor() { return author; } + /** + * 设置书籍的作者 + * @param author 书籍的作者 + */ public void setAuthor(String author) { this.author = author; } + /** + * 获取书籍的价格 + * @return 书籍的价格 + */ public BigDecimal getPrice() { return price; } + /** + * 设置书籍的价格 + * @param price 书籍的价格 + */ public void setPrice(BigDecimal price) { this.price = price; } + /** + * 获取书籍的销量 + * @return 书籍的销量 + */ public Integer getSales() { return sales; } + /** + * 设置书籍的销量 + * @param sales 书籍的销量 + */ public void setSales(Integer sales) { this.sales = sales; } + /** + * 获取书籍的库存数量 + * 如果库存数量小于0,则返回0 + * @return 书籍的库存数量 + */ public Integer getStock() { - if(stock<0) stock=0;return stock; + if (stock < 0) stock = 0; + return stock; } + /** + * 设置书籍的库存数量 + * 如果库存数量小于0,则将其设置为0 + * @param stock 书籍的库存数量 + */ public void setStock(Integer stock) { - if(stock<0) stock=0; + if (stock < 0) stock = 0; this.stock = stock; } + /** + * 获取书籍的图片路径 + * @return 书籍的图片路径 + */ public String getImgPath() { return imgPath; } + /** + * 设置书籍的图片路径 + * 如果传入的图片路径为null或空字符串,则使用默认图片路径"static/img/default.jpg" + * @param imgPath 书籍的图片路径 + */ public void setImgPath(String imgPath) { - if(imgPath==null||"".equals(imgPath)) { + if (imgPath == null || "".equals(imgPath)) { this.imgPath = "static/img/default.jpg"; } else { this.imgPath = imgPath; } } + /** + * 重写toString方法,返回书籍的详细信息 + * @return 书籍的详细信息字符串 + */ @Override public String toString() { return "Book{" + @@ -101,9 +189,23 @@ public class Book { '}'; } + /** + * 无参构造方法 + */ public Book() { } + /** + * 全参构造方法 + * @param id 书籍的ID + * @param name 书籍的名称 + * @param author 书籍的作者 + * @param price 书籍的价格 + * @param sales 书籍的销量 + * @param stock 书籍的库存数量 + * @param classification 书籍的分类 + * @param imgPath 书籍的图片路径 + */ public Book(Integer id, String name, String author, BigDecimal price, Integer sales, Integer stock, String classification, String imgPath) { this.id = id; this.name = name; @@ -114,4 +216,4 @@ public class Book { this.classification = classification; this.imgPath = imgPath; } -} +} \ No newline at end of file diff --git a/src/com/yj/bean/Cart.java b/src/com/yj/bean/Cart.java index 3ba99bf..782eac6 100644 --- a/src/com/yj/bean/Cart.java +++ b/src/com/yj/bean/Cart.java @@ -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.Entryentry : items.entrySet()) { + // 遍历购物车中的每一项 totalCount += entry.getValue().getCount(); + // 累加每一项的数量 } return totalCount; + // 返回总数量 } - + /** + * 获取购物车中所有商品的总价格 + */ public BigDecimal getTotalPrice() { BigDecimal totalPrice = new BigDecimal(0); + // 初始化总价格为0 for (Map.Entryentry : items.entrySet()) { + // 遍历购物车中的每一项 totalPrice = totalPrice.add(entry.getValue().getTotalPrice()); + // 累加每一项的总价格 } return totalPrice; + // 返回总价格 } - + /** + * 获取购物车中的所有商品项 + */ public Map getItems() { return items; + // 返回购物车中的商品项 } + /** + * 设置购物车中的所有商品项 + */ public void setItems(Map items) { this.items = items; + // 设置购物车中的商品项 } /** - * key是商品编号,value是商品信息 + * 商品项存储的Map,key是商品编号,value是商品信息,使用LinkedHashMap保持插入顺序 */ private Map items = new LinkedHashMap(); + /** + * 重写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()))); + // 更新总金额 } } -} +} \ No newline at end of file diff --git a/src/com/yj/bean/CartItem.java b/src/com/yj/bean/CartItem.java index c9feca1..bcc656f 100644 --- a/src/com/yj/bean/CartItem.java +++ b/src/com/yj/bean/CartItem.java @@ -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 + + // 显示商品的总价 '}'; } } diff --git a/src/com/yj/bean/Page.java b/src/com/yj/bean/Page.java index 5869cab..ed5f155 100644 --- a/src/com/yj/bean/Page.java +++ b/src/com/yj/bean/Page.java @@ -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 { + // 定义一个泛型类Page,T表示该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 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 getItems() { return items; } + // 设置当前页的数据 public void setItems(List 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地址 '}'; } -} +} \ No newline at end of file diff --git a/src/com/yj/dao/BookDao.java b/src/com/yj/dao/BookDao.java index 48740be..65ba631 100644 --- a/src/com/yj/dao/BookDao.java +++ b/src/com/yj/dao/BookDao.java @@ -8,34 +8,108 @@ import java.util.List; /** * @author yj * @create 2020-08-23 21:08 + * + * BookDao接口定义了对书籍数据的操作方法,包括增删改查、分页查询、按价格范围查询、按名称或作者查询等功能。 */ public interface BookDao { + /** + * 添加一本书籍到数据库 + * @param book 要添加的书籍对象 + * @return 受影响的行数,成功返回1,失败返回0 + */ public int addBook(Book book); + /** + * 根据书籍ID删除书籍 + * @param id 要删除的书籍ID + * @return 受影响的行数,成功返回1,失败返回0 + */ public int deleteBookById(Integer id); + /** + * 更新书籍信息 + * @param book 包含更新信息的书籍对象 + * @return 受影响的行数,成功返回1,失败返回0 + */ public int updateBook(Book book); + /** + * 根据书籍ID查询书籍信息 + * @param id 要查询的书籍ID + * @return 查询到的书籍对象,如果未找到返回null + */ public Book queryBookById(Integer id); + /** + * 查询所有书籍信息 + * @return 包含所有书籍的列表 + */ public List queryBooks(); + /** + * 查询所有书籍的总记录数 + * @return 所有书籍的总记录数 + */ Integer queryForPageTotalCount(); + /** + * 分页查询书籍信息 + * @param begin 分页的起始索引 + * @param pageSize 每页显示的记录数 + * @return 当前页的书籍列表 + */ List queryForPageItems(int begin, int pageSize); + /** + * 根据价格范围查询书籍的总记录数 + * @param min 价格范围的最小值 + * @param max 价格范围的最大值 + * @return 符合价格范围的书籍总记录数 + */ Integer queryForPageTotalCountByPrice(int min, int max); + /** + * 根据价格范围分页查询书籍信息 + * @param begin 分页的起始索引 + * @param pageSize 每页显示的记录数 + * @param min 价格范围的最小值 + * @param max 价格范围的最大值 + * @return 当前页的书籍列表 + */ List queryForPageItemsByPrice(int begin, int pageSize, int min, int max); + /** + * 根据书籍名称或作者查询书籍的总记录数 + * @param nameorauthor 书籍名称或作者的关键字 + * @return 符合条件的书籍总记录数 + */ Integer queryForPageTotalCountByNameOrAuthor(String nameorauthor); + /** + * 根据书籍名称或作者分页查询书籍信息 + * @param begin 分页的起始索引 + * @param pageSize 每页显示的记录数 + * @param nameorauthor 书籍名称或作者的关键字 + * @return 当前页的书籍列表 + */ List queryForPageItemsByNameOrAuthor(int begin, int pageSize, String nameorauthor); + /** + * 查询所有书籍并按某种顺序排序(如销量、价格等) + * @return 按顺序排序的书籍列表 + */ List queryForPageItemsOrder(); + /** + * 查询所有书籍的总金额(价格总和) + * @return 所有书籍的总金额 + */ BigDecimal queryTotalMoney(); + /** + * 查询书籍的总数量 + * @return 书籍的总数量 + */ public Integer queryBooknums(); -} +} \ No newline at end of file diff --git a/src/com/yj/dao/impl/BaseDao.java b/src/com/yj/dao/impl/BaseDao.java index 60a0e28..4a215d7 100644 --- a/src/com/yj/dao/impl/BaseDao.java +++ b/src/com/yj/dao/impl/BaseDao.java @@ -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); // 关闭数据库连接 } } /** - *查询返回一个Javabean的SQL语句 + * 查询返回一个Javabean的SQL语句 * @param type 返回的对象类型 - * @param sql 执行的sql语句 - * @param args sql对应的参数值 + * @param sql 执行的SQL语句 + * @param args SQL语句对应的参数值,可变参数 * @param 返回的类型的泛型 - * @return + * @return 返回查询结果的第一行数据封装成的JavaBean对象 */ - public T queryForOne(Class type,String sql,Object ... args) { + public T queryForOne(Class type, String sql, Object ... args) { Connection connection = JDBCUtils.getConnection(); + // 获取数据库连接 try { - return queryRunner.query(connection,sql,new BeanHandler(type),args); + // 使用QueryRunner的query方法执行查询操作,并将结果集的第一行数据封装为指定的JavaBean对象 + return queryRunner.query(connection, sql, new BeanHandler(type), args); } catch (SQLException e) { e.printStackTrace(); + // 打印SQL异常堆栈信息 throw new RuntimeException(e); + // 将SQL异常转换为运行时异常抛出 + } finally { + // 注意:同样缺少了关闭连接的逻辑,应在实际使用中添加 } } /** - *查询返回多个Javabean的SQL语句 + * 查询返回多个Javabean的SQL语句 * @param type 返回的对象类型 - * @param sql 执行的sql语句 - * @param args sql对应的参数值 + * @param sql 执行的SQL语句 + * @param args SQL语句对应的参数值,可变参数 * @param 返回的类型的泛型 - * @return + * @return 返回查询结果的每一行数据封装成的JavaBean对象列表 */ public List queryForList(Class type, String sql, Object ... args) { Connection connection = JDBCUtils.getConnection(); + // 获取数据库连接 try { - return queryRunner.query(connection,sql,new BeanListHandler(type),args); + // 使用QueryRunner的query方法执行查询操作,并将结果集的每一行数据封装为指定的JavaBean对象,存储在List集合中返回 + return queryRunner.query(connection, sql, new BeanListHandler(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可能已负责关闭连接 } } -} +} \ No newline at end of file diff --git a/src/com/yj/service/BookService.java b/src/com/yj/service/BookService.java index 94a4b80..3916727 100644 --- a/src/com/yj/service/BookService.java +++ b/src/com/yj/service/BookService.java @@ -9,28 +9,84 @@ import java.util.List; /** * @author yj * @create 2020-08-24 14:40 + * + * BookService接口定义了与书籍相关的业务逻辑操作,包括书籍的增删改查、分页查询、按价格范围查询、按名称或作者查询等功能。 */ public interface BookService { + /** + * 添加一本书籍 + * @param book 要添加的书籍对象 + */ public void addBook(Book book); + /** + * 更新书籍信息 + * @param book 包含更新信息的书籍对象 + */ public void updateBook(Book book); + /** + * 根据书籍ID删除书籍 + * @param id 要删除的书籍ID + */ public void deleteBookById(Integer id); + /** + * 根据书籍ID查询书籍信息 + * @param id 要查询的书籍ID + * @return 查询到的书籍对象,如果未找到返回null + */ public Book queryBookById(Integer id); + /** + * 查询所有书籍信息 + * @return 包含所有书籍的列表 + */ public List queryBooks(); + /** + * 分页查询书籍信息 + * @param pageNo 当前页码 + * @param pageSize 每页显示的记录数 + * @return 分页对象,包含当前页的书籍列表和分页信息 + */ Page page(int pageNo, int pageSize); + /** + * 根据价格范围分页查询书籍信息 + * @param pageNo 当前页码 + * @param pageSize 每页显示的记录数 + * @param min 价格范围的最小值 + * @param max 价格范围的最大值 + * @return 分页对象,包含当前页的书籍列表和分页信息 + */ Page pageByPrice(int pageNo, int pageSize, int min, int max); + /** + * 根据书籍名称或作者分页查询书籍信息 + * @param pageNo 当前页码 + * @param pageSize 每页显示的记录数 + * @param nameOrAuthor 书籍名称或作者的关键字 + * @return 分页对象,包含当前页的书籍列表和分页信息 + */ Page pageByNameOrAuthor(int pageNo, int pageSize, String nameOrAuthor); + /** + * 查询所有书籍并按某种顺序排序(如销量、价格等) + * @return 分页对象,包含按顺序排序的书籍列表和分页信息 + */ Page pageOrder(); + /** + * 查询书籍的总数量 + * @return 书籍的总数量 + */ public Integer queryTotalBooks(); + /** + * 查询所有书籍的总金额(价格总和) + * @return 所有书籍的总金额 + */ BigDecimal queryTotalMoney(); -} +} \ No newline at end of file diff --git a/src/com/yj/test/BookDaoTest.java b/src/com/yj/test/BookDaoTest.java index 19ca13d..dd64eda 100644 --- a/src/com/yj/test/BookDaoTest.java +++ b/src/com/yj/test/BookDaoTest.java @@ -10,59 +10,102 @@ import java.math.BigDecimal; /** * @author yj * @create 2020-08-24 11:01 + * + * BookDaoTest类用于测试BookDao接口的实现类BookDaoImpl中的各个方法。 + * 通过JUnit测试框架,验证数据库操作的正确性。 */ public class BookDaoTest { + + // 创建BookDao接口的实现类BookDaoImpl对象 BookDao bookDao = new BookDaoImpl(); + /** + * 测试添加书籍的方法 + */ @Test public void addBook() { - //`name`,`author`,`classification`,`price`,`sales`,`stock`,`img_path` - //Integer id, String name, String author, BigDecimal price, Integer sales, Integer stock, String classification, String imgPath) - bookDao.addBook(new Book(null,"舌的中国","yjjj",new BigDecimal("5"),100,23,"","")); + // 创建一个新的Book对象,并调用addBook方法将其添加到数据库中 + bookDao.addBook(new Book(null, "舌的中国", "yjjj", new BigDecimal("5"), 100, 23, "", "")); } + /** + * 测试删除书籍的方法 + */ @Test public void deleteBook() { + // 调用deleteBookById方法,删除ID为3的书籍 bookDao.deleteBookById(3); } + /** + * 测试根据ID查询书籍的方法 + */ @Test public void queryById() { + // 调用queryBookById方法,查询ID为64的书籍,并打印结果 System.out.println(bookDao.queryBookById(64)); } + /** + * 测试更新书籍信息的方法 + */ @Test public void update() { - bookDao.updateBook(new Book(35,"舌尖的中国","yj",new BigDecimal("5"),100,23,"文学","")); + // 创建一个新的Book对象,并调用updateBook方法更新ID为35的书籍信息 + bookDao.updateBook(new Book(35, "舌尖的中国", "yj", new BigDecimal("5"), 100, 23, "文学", "")); } + /** + * 测试查询所有书籍的方法 + */ @Test public void queryList() { + // 调用queryBooks方法,查询所有书籍,并打印结果 System.out.println(bookDao.queryBooks()); } + /** + * 测试查询书籍总记录数的方法 + */ @Test public void queryForPageTotalCount() { + // 调用queryForPageTotalCount方法,查询所有书籍的总记录数,并打印结果 System.out.println(bookDao.queryForPageTotalCount()); } + /** + * 测试分页查询书籍的方法 + */ @Test public void queryForPageItems() { - System.out.println(bookDao.queryForPageItems(1,4)); + // 调用queryForPageItems方法,分页查询书籍,并打印结果 + System.out.println(bookDao.queryForPageItems(1, 4)); } + /** + * 测试根据价格范围查询书籍总记录数的方法 + */ @Test public void queryForPageTotalCountByPrice() { - System.out.println(bookDao.queryForPageTotalCountByPrice(10,50)); + // 调用queryForPageTotalCountByPrice方法,查询价格在10到50之间的书籍总记录数,并打印结果 + System.out.println(bookDao.queryForPageTotalCountByPrice(10, 50)); } + /** + * 测试根据价格范围分页查询书籍的方法 + */ @Test public void queryForPageItemsByPrice() { - System.out.println(bookDao.queryForPageItemsByPrice(1,4,10,50)); + // 调用queryForPageItemsByPrice方法,根据价格范围分页查询书籍,并打印结果 + System.out.println(bookDao.queryForPageItemsByPrice(1, 4, 10, 50)); } + /** + * 测试查询书籍总数量的方法 + */ @Test public void queryBooknums() { + // 调用queryBooknums方法,查询书籍的总数量,并打印结果 System.out.println(bookDao.queryBooknums()); } -} +} \ No newline at end of file diff --git a/src/com/yj/test/BookServiceTest.java b/src/com/yj/test/BookServiceTest.java index f2358b1..8ffc3ee 100644 --- a/src/com/yj/test/BookServiceTest.java +++ b/src/com/yj/test/BookServiceTest.java @@ -12,43 +12,78 @@ import java.math.BigDecimal; /** * @author yj * @create 2020-08-24 14:57 + * + * BookServiceTest类用于测试BookService接口的实现类BookServiceImpl中的各个方法。 + * 通过JUnit测试框架,验证业务逻辑的正确性。 */ public class BookServiceTest { + // 创建BookDao接口的实现类BookDaoImpl对象 private BookDao bookDao = new BookDaoImpl(); + + // 创建BookService接口的实现类BookServiceImpl对象 private BookService bookService = new BookServiceImpl(); + + /** + * 测试添加书籍的方法 + */ @Test public void addBook() { - bookDao.addBook(new Book(null,"舌尖上的中国","yj",new BigDecimal("5"),100,23,"文学","")); + // 创建一个新的Book对象,并调用addBook方法将其添加到数据库中 + bookDao.addBook(new Book(null, "舌尖上的中国", "yj", new BigDecimal("5"), 100, 23, "文学", "")); } + /** + * 测试更新书籍信息的方法 + */ @Test public void updateBook() { - bookDao.updateBook(new Book(null,"舌尖上的中国","yj",new BigDecimal("5"),100,23,"文学","")); + // 创建一个新的Book对象,并调用updateBook方法更新书籍信息 + bookDao.updateBook(new Book(null, "舌尖上的中国", "yj", new BigDecimal("5"), 100, 23, "文学", "")); } + /** + * 测试根据ID删除书籍的方法 + */ @Test public void deleteBookById() { + // 调用deleteBookById方法,删除ID为25的书籍,并打印受影响的行数 System.out.println(bookDao.deleteBookById(25)); } + /** + * 测试根据ID查询书籍的方法 + */ @Test public void queryBookById() { + // 调用queryBookById方法,查询ID为23的书籍,并打印结果 System.out.println(bookDao.queryBookById(23)); } + /** + * 测试查询所有书籍的方法 + */ @Test public void queryBooks() { + // 调用queryBooks方法,查询所有书籍,并打印结果 System.out.println(bookDao.queryBooks()); } + /** + * 测试分页查询书籍总记录数的方法 + */ @Test public void page() { + // 调用queryForPageTotalCount方法,查询所有书籍的总记录数,并打印结果 System.out.println(bookDao.queryForPageTotalCount()); } + /** + * 测试查询所有书籍的总金额的方法 + */ @Test public void queryTotalMoney() { + // 调用queryTotalMoney方法,查询所有书籍的总金额,并打印结果 System.out.println(bookDao.queryTotalMoney()); } } \ No newline at end of file diff --git a/src/com/yj/test/CartTest.java b/src/com/yj/test/CartTest.java index f4b6506..7562506 100644 --- a/src/com/yj/test/CartTest.java +++ b/src/com/yj/test/CartTest.java @@ -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); } } \ No newline at end of file diff --git a/src/com/yj/test/JDBCUtilsTest.java b/src/com/yj/test/JDBCUtilsTest.java index 3c762af..546fbd6 100644 --- a/src/com/yj/test/JDBCUtilsTest.java +++ b/src/com/yj/test/JDBCUtilsTest.java @@ -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(); + // 打印异常堆栈信息 } } -} +} \ No newline at end of file diff --git a/src/com/yj/utils/JDBCUtils.java b/src/com/yj/utils/JDBCUtils.java index e189e44..f991314 100644 --- a/src/com/yj/utils/JDBCUtils.java +++ b/src/com/yj/utils/JDBCUtils.java @@ -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 conns = new ThreadLocal(); + // 定义一个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(); } } }*/ -} +} \ No newline at end of file diff --git a/src/com/yj/utils/PaymentUtil.java b/src/com/yj/utils/PaymentUtil.java index fbdb457..a3ba130 100644 --- a/src/com/yj/utils/PaymentUtil.java +++ b/src/com/yj/utils/PaymentUtil.java @@ -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(); diff --git a/src/com/yj/web/BaseServlet.java b/src/com/yj/web/BaseServlet.java index 39a2021..1c5e289 100644 --- a/src/com/yj/web/BaseServlet.java +++ b/src/com/yj/web/BaseServlet.java @@ -10,26 +10,54 @@ import java.lang.reflect.Method; /** * @author yj * @create 2020-08-23 16:51 + * + * BaseServlet类是一个抽象的Servlet基类,用于简化Servlet的开发。 + * 它通过反射机制动态调用子类中的方法,避免了在每个Servlet中重复编写doGet和doPost方法。 */ public abstract class BaseServlet extends HttpServlet { + /** + * 处理GET请求,直接调用doPost方法 + * @param req HttpServletRequest对象 + * @param resp HttpServletResponse对象 + * @throws ServletException + * @throws IOException + */ @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - doPost(req,resp); + doPost(req, resp); } + /** + * 处理POST请求,通过反射机制动态调用子类中的方法 + * @param req HttpServletRequest对象 + * @param resp HttpServletResponse对象 + * @throws ServletException + * @throws IOException + */ + @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - //解决post请求中文乱码 + // 解决POST请求中文乱码问题 req.setCharacterEncoding("utf-8"); - //解决相应的中文乱码 + + // 解决响应的中文乱码问题 resp.setContentType("text/html;charset=UTF-8"); + + // 获取请求参数action,该参数用于指定要调用的方法名 String action = req.getParameter("action"); + try { - Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class,HttpServletResponse.class); - method.invoke(this,req,resp); + // 通过反射获取当前类中指定名称的方法 + Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class, HttpServletResponse.class); + + // 调用方法,传入请求和响应对象 + method.invoke(this, req, resp); } catch (Exception e) { + // 捕获异常并打印堆栈信息 e.printStackTrace(); + + // 将异常包装为运行时异常抛出,便于上层处理 throw new RuntimeException(e); } } -} +} \ No newline at end of file diff --git a/src/com/yj/web/BookServlet.java b/src/com/yj/web/BookServlet.java index 0688f86..b498d62 100644 --- a/src/com/yj/web/BookServlet.java +++ b/src/com/yj/web/BookServlet.java @@ -15,72 +15,137 @@ import java.util.List; /** * @author yj * @create 2020-08-24 15:25 + * + * BookServlet类继承自BaseServlet,用于处理与书籍相关的请求。 + * 通过调用BookService接口的实现类BookServiceImpl,完成书籍的增删改查、分页查询等操作。 */ public class BookServlet extends BaseServlet { + // 创建BookService接口的实现类BookServiceImpl对象 private BookService bookService = new BookServiceImpl(); + /** + * 处理添加书籍的请求 + * @param req HttpServletRequest对象 + * @param resp HttpServletResponse对象 + * @throws ServletException + * @throws IOException + */ protected void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - int pageNo = WebUtils.parseInt(req.getParameter("pageNo"),0); - pageNo+=1; - Book book = (Book) WebUtils.copyParamToBean(req.getParameterMap(),new Book()); + // 获取当前页码,默认从0开始 + int pageNo = WebUtils.parseInt(req.getParameter("pageNo"), 0); + // 页码加1,表示添加书籍后跳转到下一页 + pageNo += 1; + + // 将请求参数封装到Book对象中 + Book book = (Book) WebUtils.copyParamToBean(req.getParameterMap(), new Book()); + + // 调用BookService的addBook方法添加书籍 bookService.addBook(book); - //req.getRequestDispatcher("/manager/bookServlet?action=list").forward(req,resp); - resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=page&pageNo="+pageNo); - } + // 重定向到书籍管理页面,并跳转到添加书籍后的页码 + resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=page&pageNo=" + pageNo); + } + /** + * 处理删除书籍的请求 + * @param req HttpServletRequest对象 + * @param resp HttpServletResponse对象 + * @throws ServletException + * @throws IOException + */ protected void delete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - String id = req.getParameter("id"); - int i = Integer.parseInt(id); - bookService.deleteBookById(i); - resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=page&pageNo="+req.getParameter("pageNo")); - } + // 获取要删除的书籍ID + String id = req.getParameter("id"); + int i = Integer.parseInt(id); + // 调用BookService的deleteBookById方法删除书籍 + bookService.deleteBookById(i); + // 重定向到书籍管理页面,并保持当前页码 + resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=page&pageNo=" + req.getParameter("pageNo")); + } + + /** + * 处理更新书籍的请求 + * @param req HttpServletRequest对象 + * @param resp HttpServletResponse对象 + * @throws ServletException + * @throws IOException + */ protected void update(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - Book book = (Book) WebUtils.copyParamToBean(req.getParameterMap(),new Book()); + // 将请求参数封装到Book对象中 + Book book = (Book) WebUtils.copyParamToBean(req.getParameterMap(), new Book()); + + // 调用BookService的updateBook方法更新书籍 bookService.updateBook(book); - resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=page&pageNo="+req.getParameter("pageNo")); + + // 重定向到书籍管理页面,并保持当前页码 + resp.sendRedirect(req.getContextPath() + "/manager/bookServlet?action=page&pageNo=" + req.getParameter("pageNo")); } /** - * - * @param req - * @param resp + * 处理获取单个书籍信息的请求 + * @param req HttpServletRequest对象 + * @param resp HttpServletResponse对象 * @throws ServletException * @throws IOException */ protected void getBook(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + // 获取要查询的书籍ID String id = req.getParameter("id"); int i = Integer.parseInt(id); + + // 调用BookService的queryBookById方法查询书籍 Book book = bookService.queryBookById(i); - req.setAttribute("book",book); - req.getRequestDispatcher("/pages/manager/book_edit.jsp").forward(req,resp); - } + // 将查询到的书籍信息保存到request域中 + req.setAttribute("book", book); + // 请求转发到书籍编辑页面 + req.getRequestDispatcher("/pages/manager/book_edit.jsp").forward(req, resp); + } + + /** + * 处理查询所有书籍的请求 + * @param req HttpServletRequest对象 + * @param resp HttpServletResponse对象 + * @throws ServletException + * @throws IOException + */ protected void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - //1、通过BookService查询数据 - Listbooks = bookService.queryBooks(); - //2、将数据保存在request域中 - req.setAttribute("books",books); - //3、请求转发到pages/manager/book_manager.jsp - req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req,resp); + // 调用BookService的queryBooks方法查询所有书籍 + List books = bookService.queryBooks(); + + // 将查询到的书籍列表保存到request域中 + req.setAttribute("books", books); + + // 请求转发到书籍管理页面 + req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req, resp); } + /** + * 处理分页查询书籍的请求 + * @param req HttpServletRequest对象 + * @param resp HttpServletResponse对象 + * @throws ServletException + * @throws IOException + */ protected void page(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - //1、获取请求的参数pageNo和pageSize - int pageNo = WebUtils.parseInt(req.getParameter("pageNo"),1); + // 获取请求参数pageNo和pageSize + int pageNo = WebUtils.parseInt(req.getParameter("pageNo"), 1); int pageSize = WebUtils.parseInt(req.getParameter("pageSize"), Page.PAGE_SIZE); - //2、调用BookService.page(pageNo,pageSize)方法:返回page对象 - Page page = bookService.page(pageNo,pageSize); + // 调用BookService的page方法进行分页查询 + Page page = bookService.page(pageNo, pageSize); + + // 设置分页请求的URL page.setUrl("manager/bookServlet?action=page"); - //3、保存Page对象到request域中 - req.setAttribute("page",page); - //4、请求转发到page/manager/book_manager.jsp页面 - req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req,resp); + // 将分页对象保存到request域中 + req.setAttribute("page", page); + + // 请求转发到书籍管理页面 + req.getRequestDispatcher("/pages/manager/book_manager.jsp").forward(req, resp); } -} +} \ No newline at end of file diff --git a/src/com/yj/web/CartServlet.java b/src/com/yj/web/CartServlet.java index cfa53cd..b6beb41 100644 --- a/src/com/yj/web/CartServlet.java +++ b/src/com/yj/web/CartServlet.java @@ -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 resultMap = new HashMap(); - resultMap.put("totalCount",cart.getTotalCount()); - resultMap.put("lastName",cartItem.getName()); + // 准备返回给客户端的数据,包括购物车总数量和最后一个商品的名称 + Map resultMap = new HashMap(); + 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")); } - -} +} \ No newline at end of file diff --git a/web/pages/cart/cart.jsp b/web/pages/cart/cart.jsp index 84c5289..60c7d91 100644 --- a/web/pages/cart/cart.jsp +++ b/web/pages/cart/cart.jsp @@ -1,28 +1,45 @@ <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + <%@ page contentType="text/html;charset=UTF-8" language="java" %> + + - -购物车 + + + 购物车 + <%@include file="/pages/common/header.jsp"%> + - - - -
- - + + + +
+ + +
+ + + + + + + + + + + - - - - - + + + - + + + + - + + + + + + + + + - + + - - - - - - - - - - - - -
商品名称数量单价金额操作
商品名称数量单价金额操作亲,当前购物车为空,快去和小伙伴浏览书籍吧!
亲,当前购物车为空,快去和小伙伴浏览书籍吧! ${entry.value.name} + + + ${entry.value.price}${entry.value.totalPrice}删除
${entry.value.name} - - ${entry.value.price}${entry.value.totalPrice}删除
- + + +
+ 购物车中共有${sessionScope.cart.totalCount}本书籍 + 总金额${sessionScope.cart.totalPrice} + 清空购物车 + 去结账 +
-
+
-
+ - <%@include file="/pages/common/footer.jsp"%> +<%@include file="/pages/common/footer.jsp"%> + - + \ No newline at end of file diff --git a/web/pages/cart/checkout.jsp b/web/pages/cart/checkout.jsp index 8d4efd6..313620c 100644 --- a/web/pages/cart/checkout.jsp +++ b/web/pages/cart/checkout.jsp @@ -1,32 +1,52 @@ <%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + - -结算页面 + + + + 结算页面 + <%@include file="/pages/common/header.jsp"%> - + - - - -
- -

你的订单已结算,订单号为${sessionScope.orderId},店主很快就会发货啦!

- - -
+ - <%@include file="/pages/common/footer.jsp"%> + + +
+ + +

你的订单已结算,订单号为${sessionScope.orderId},店主很快就会发货啦!

+ + + +
+ +<%@include file="/pages/common/footer.jsp"%> + - \ No newline at end of file + + \ No newline at end of file diff --git a/web/pages/cart/pay.jsp b/web/pages/cart/pay.jsp index 6db9fe5..bc4b993 100644 --- a/web/pages/cart/pay.jsp +++ b/web/pages/cart/pay.jsp @@ -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" %> + + + + 结算页面 + + <%@include file="/pages/common/header.jsp"%> + + + + + +
+
+ + + + + 支付金额:元 - + + + + - + - + - + - - + + - + + - + +
- 支付金额:

-

请您选择在线支付银行
招商银行 - 招商银行 工商银行 农业银行建设银行 - 建设银行
中国民生银行总行光大银行 - 光大银行 交通银行 深圳发展银行
北京银行兴业银行 - 上海浦东发展银行 - 兴业银行上海浦东发展银行 中信银行

-

-
-
<%@include file="/pages/common/footer.jsp"%> + - - + + \ No newline at end of file diff --git a/web/pages/client/index.jsp b/web/pages/client/index.jsp index 7ecae77..077ce4e 100644 --- a/web/pages/client/index.jsp +++ b/web/pages/client/index.jsp @@ -1,11 +1,6 @@ <%-- - Created by IntelliJ IDEA. - User: jhu - Date: 2020/10/5 - Time: 15:44 - To change this template use File | Settings | File Templates. + 此文件的创建信息注释,表明是由 IntelliJ IDEA 创建,作者是 jhu,创建日期是 2020 年 10 月 5 日,时间是 15 时 44 分,并且提示修改此模板的相关设置路径。 --%> - <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> @@ -13,21 +8,25 @@ 书城首页 + <%-- 包含公共的头部页面(header.jsp),可能包含一些通用的样式、脚本或者页面头部结构相关的内容,方便复用。 --%> <%@include file="/pages/common/header.jsp"%> @@ -35,35 +34,40 @@ Bookstore
+ - + 登录 | 注册    热榜 - + 欢迎${sessionScope.user.username}光临书城 我的订单 个人信息 注销   - + 购物车 后台管理
+
+ 图书搜索
+
+ 价格: 元 - 元 @@ -71,6 +75,7 @@
+
@@ -78,13 +83,16 @@
+ 您的购物车中有${sessionScope.cart.totalCount}件商品
+ 您刚刚将${sessionScope.lastName}加入到了购物车中
+
@@ -112,6 +120,7 @@ ${book.stock}
+
@@ -120,10 +129,12 @@
+ <%@include file="/pages/common/page_nav.jsp"%>
+ <%@include file="/pages/common/footer.jsp"%> - + \ No newline at end of file diff --git a/web/pages/client/top.jsp b/web/pages/client/top.jsp index 1c7b058..f4c1017 100644 --- a/web/pages/client/top.jsp +++ b/web/pages/client/top.jsp @@ -1,9 +1,5 @@ <%-- - Created by IntelliJ IDEA. - User: jhu - Date: 2020/10/19 - Time: 22:56 - To change this template use File | Settings | File Templates. + 此部分为文件的创建相关注释,表明该文件是通过 IntelliJ IDEA 创建的,创建者是 jhu,创建时间为 2020 年 10 月 19 日 22 时 56 分,同时说明了修改该模板的相关设置操作的路径信息。 --%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> @@ -12,11 +8,10 @@ 图书热销榜单 + <%-- 包含公共的头部页面(header.jsp),这里面通常会放置页面通用的样式表引入、脚本引入或者一些页面头部布局相关的内容,以实现代码复用。 --%> <%@include file="/pages/common/header.jsp"%> - -