【JavaWeb】书城项目(270-292)
创始人
2025-06-01 18:48:53
0

270.书城项目-显示登录的用户信息

UserServlet 程序中保存用户登录的信息
在这里插入图片描述
修改 login_succuess_menu.jsp
在这里插入图片描述
还要修改首页 index.jsp 页面的菜单
在这里插入图片描述

271.书城项目-注销登录

1、销毁 Session 中用户登录的信息(或者销毁 Session)
2、重定向到首页(或登录页面)。

UserServlet 程序中添加 logout 方法

	/*** 注销* @param req* @param resp* @throws ServletException* @throws IOException*/protected void logout(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        1、销毁Session中用户登录的信息(或者销毁Session)req.getSession().invalidate();
//        2、重定向到首页(或登录页面)。resp.sendRedirect(req.getContextPath());}

修改【注销】的菜单地址

注销

272.书城项目-表单重复提交的三种常见情况

一、按下功能键 F5:提交完表单。服务器使用请求转来进行页面跳转。这个时候,用户按下功能键 F5,就会发起最后一次的请求。造成表单重复提交问题。解决方法:使用重定向来进行跳转

二、网络延迟多点了几次提交操作:用户正常提交服务器,但是由于网络延迟等原因,迟迟未收到服务器的响应,这个时候,用户以为提交失败,就会着急,然后多点了几次提交操作,也会造成表单重复提交。

三、用户回退浏览器:用户正常提交服务器。服务器也没有延迟,但是提交完成后,用户回退浏览器。重新提交。也会造成表单重复提交。

在这里插入图片描述

273.书城项目-验证码底层原理

在这里插入图片描述

274.书城项目-谷歌验证码的使用

1、导入谷歌验证码的 jar 包:kaptcha-2.3.2.jar
2、在 web.xml 中去配置用于生成验证码的 Servlet 程序
3、在表单中使用 img 标签去显示验证码图片并使用它
4、在服务器获取谷歌生成的验证码和客户端发送过来的验证码比较使用。

275.书城项目-把谷歌验证码加入到书城中使用

1、导入谷歌验证码的 jar 包:kaptcha-2.3.2.jar
2、在 web.xml 中去配置用于生成验证码的 Servlet 程序

KaptchaServletcom.google.code.kaptcha.servlet.KaptchaServlet

KaptchaServlet/kaptcha.jpg

3、在表单中使用 img 标签去显示验证码图片并使用它

用户名:
验证码:

4、在服务器获取谷歌生成的验证码和客户端发送过来的验证码比较使用。

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取Session 中的验证码String token = (String)req.getSession().getAttribute(KAPTCHA_SESSION_KEY);// 删除 Session 中的验证码req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);String code = req.getParameter("code");// 获取用户名String username = req.getParameter("username");if (token != null && token.equalsIgnoreCase(code)) { 		System.out.println("保存到数据库:" + username);//用户注册成功	resp.sendRedirect(req.getContextPath() + "/ok.jsp");} else {System.out.println("请不要重复提交表单");}
}

276.书城项目-验证码的切换

切换验证码:

// 给验证码的图片,绑定单击事件
$("#code_img").click(function () {// 在事件响应的function 函数中有一个this 对象。这个this 对象,是当前正在响应事件的dom 对象// src 属性表示验证码img 标签的图片路径。它可读,可写// alert(this.src);this.src = "${basePath}kaptcha.jpg?d=" + new Date();
});

277.书城项目-购物车模块的分析

在这里插入图片描述

278.书城项目-购物车模型的创建

购物车的商品项

package com.atguigu.pojo;import java.math.BigDecimal;//购物车的商品项
public class CartItem {private Integer id;private String name;private Integer count;private BigDecimal price;private BigDecimal totalPrice;public CartItem() {}
}

购物车对象

package com.atguigu.pojo;import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.Map;/*** 购物车对象*/
public class Cart {
//    private Integer totalCount;
//    private BigDecimal totalPrice;/*** key是商品编号,* value,是商品信息*/private Map items = new LinkedHashMap();/*** 添加商品项** @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() )) ); // 更新总金额}}/*** 删除商品项*/public void deleteItem(Integer id) {items.remove(id);}/*** 清空购物车*/public void clear() {items.clear();}/*** 修改商品数量*/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() )) ); // 更新总金额}}public Integer getTotalCount() {Integer totalCount = 0;for (Map.Entryentry : items.entrySet()) {totalCount += entry.getValue().getCount();}return totalCount;}public BigDecimal getTotalPrice() {BigDecimal totalPrice = new BigDecimal(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;}@Overridepublic String toString() {return "Cart{" +"totalCount=" + getTotalCount() +", totalPrice=" + getTotalPrice() +", items=" + items +'}';}
}

279.书城项目-购物车功能方法的实现和测试

购物车的测试:

package com.atguigu.test;import com.atguigu.pojo.Cart;
import com.atguigu.pojo.CartItem;
import org.junit.Test;import java.math.BigDecimal;import static org.junit.Assert.*;public class CartTest {@Testpublic void addItem() {Cart cart = new Cart();cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));cart.addItem(new CartItem(2, "数据结构与算法", 1, new BigDecimal(100),new BigDecimal(100)));System.out.println(cart);}@Testpublic void deleteItem() {Cart cart = new Cart();cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));cart.addItem(new CartItem(2, "数据结构与算法", 1, new BigDecimal(100),new BigDecimal(100)));cart.deleteItem(1);System.out.println(cart);}@Testpublic void clear() {Cart cart = new Cart();cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));cart.addItem(new CartItem(2, "数据结构与算法", 1, new BigDecimal(100),new BigDecimal(100)));cart.deleteItem(1);cart.clear();System.out.println(cart);}@Testpublic void updateCount() {Cart cart = new Cart();cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));cart.addItem(new CartItem(2, "数据结构与算法", 1, new BigDecimal(100),new BigDecimal(100)));cart.deleteItem(1);cart.clear();cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));cart.updateCount(1, 10);System.out.println(cart);}
}

280.书城项目-添加商品到购物车功能的实现

CartServlet 程序中的代码:

	/*** 加入购物车* @param req* @param resp* @throws ServletException* @throws IOException*/protected void addItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取请求的参数 商品编号int id = WebUtils.parseInt(req.getParameter("id"), 0);// 调用bookService.queryBookById(id):Book得到图书的信息Book book = bookService.queryBookById(id);// 把图书信息,转换成为CartItem商品项CartItem cartItem = new CartItem(book.getId(),book.getName(),1,book.getPrice(),book.getPrice());// 调用Cart.addItem(CartItem);添加商品项Cart cart = (Cart) req.getSession().getAttribute("cart");if (cart == null) {cart = new Cart();req.getSession().setAttribute("cart",cart);}cart.addItem(cartItem);System.out.println(cart);System.out.println("请求头Referer的值:" + req.getHeader("Referer"));// 最后一个添加的商品名称req.getSession().setAttribute("lastName", cartItem.getName());// 重定向回原来商品所在的地址页面resp.sendRedirect(req.getHeader("Referer"));}

index.jsp 页面 js 的代码
在这里插入图片描述


图解说明,如何跳回添加商品的页面:
在这里插入图片描述

281.书城项目-购物车的演示

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>




购物车<%-- 静态包含 base标签、css样式、jQuery文件 --%><%@ include file="/pages/common/head.jsp"%>
购物车<%--静态包含,登录 成功之后的菜单 --%><%@ include file="/pages/common/login_success_menu.jsp"%>
<%--如果购物车空的情况--%><%--如果购物车非空的情况--%>
商品名称数量单价金额操作
亲,当前购物车为空!快跟小伙伴们去浏览商品吧!!!
${entry.value.name}${entry.value.price}${entry.value.totalPrice}删除
<%--如果购物车非空才输出页面的内容--%>
购物车中共有${sessionScope.cart.totalCount}件商品总金额${sessionScope.cart.totalPrice}清空购物车去结账
<%--静态包含页脚内容--%><%@include file="/pages/common/footer.jsp"%>

282.书城项目-删除购物车中的商品项

CartServlet 程序:

  	/*** 删除商品项* @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);// 获取购物车对象Cart cart = (Cart) req.getSession().getAttribute("cart");if (cart != null) {// 删除 了购物车商品项cart.deleteItem(id);// 重定向回原来购物车展示页面resp.sendRedirect(req.getHeader("Referer"));}}

购物车/pages/cart/cart.jsp 页面的代码:
删除的请求地址:
在这里插入图片描述
删除的确认提示操作:


283.书城项目-清空购物车的实现

CartServlet 程序

	 /*** 清空购物车* @param req* @param resp* @throws ServletException* @throws IOException*/protected void clear(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{// 1 获取购物车对象Cart cart = (Cart) req.getSession().getAttribute("cart");if (cart != null) {// 清空购物车cart.clear();// 重定向回原来购物车展示页面resp.sendRedirect(req.getHeader("Referer"));}}

cart.jsp 页面的内容
给清空购物车添加请求地址,和添加 id 属性:
在这里插入图片描述
清空的确认提示操作:

// 给清空购物车绑定单击事件
$("#clearCart").click(function () {return confirm("你确定要清空购物车吗?");
})

284.书城项目-修改购物车商品数量

CartServlet 程序

	/*** 修改商品数量* @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);// 获取Cart购物车对象Cart cart = (Cart) req.getSession().getAttribute("cart");if (cart != null) {// 修改商品数量cart.updateCount(id,count);// 重定向回原来购物车展示页面resp.sendRedirect(req.getHeader("Referer"));}}

修改 pages/cart/cart.jsp 购物车页面:
在这里插入图片描述
修改商品数量 js 代码

// 给输入框绑定 onchange 内容发生改变事件
$(".updateCount").change(function () {// 获取商品名称var name = $(this).parent().parent().find("td:first").text();var id = $(this).attr('bookId');// 获取商品数量var count = this.value;if ( confirm("你确定要将【" + name + "】商品修改数量为:" + count + " 吗?") ) {//发起请求。给服务器保存修改location.href =
"http://localhost:8080/book/cartServlet?action=updateCount&count="+count+"&id="+id;} else {// defaultValue 属性是表单项Dom 对象的属性。它表示默认的value 属性值。this.value = this.defaultValue;}
});

285.书城项目-首页购物车数据展示

在添加商品到购物车的时候,保存最后一个添加的商品名称:
在这里插入图片描述
在 pages/client/index.jsp 页面中输出购物车信息:

<%--购物车为空的输出--%>
当前购物车为空
<%--购物车非空的输出--%>您的购物车中有 ${sessionScope.cart.totalCount} 件商品
您刚刚将${sessionScope.lastName}加入到了购物车中

286.书城项目-订单模块的分析

在这里插入图片描述
请添加图片描述

287.书城项目-创建订单模型的数据库表

use book;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`)
);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`)
);

288.书城项目-编写订单模块的两个数据模型Order和OrderItem

/**
* 订 单
*/
public class Order { private String orderId; private Date createTime;private BigDecimal price;// 0 未发货,1 已发货,2 表示已签收private Integer status = 0; private Integer userId;/**
* 订单项
*/
public class OrderItem { private Integer id; private String name; private Integer count; private BigDecimal price;private BigDecimal totalPrice;private String orderId;

289.书城项目-编写订单模块的Dao和测试

OrderDao 接口

public interface OrderDao {public int saveOrder(Order order);
}

OrderDao 实现

package com.atguigu.dao.impl;import com.atguigu.dao.OrderDao;
import com.atguigu.pojo.Order;public class OrderDaoImpl extends BaseDao implements OrderDao {@Overridepublic int saveOrder(Order order) {String sql = "insert into t_order(`order_id`,`create_time`,`price`,`status`,`user_id`) values(?,?,?,?,?)";return update(sql,order.getOrderId(),order.getCreateTime(),order.getPrice(),order.getStatus(),order.getUserId());}
}

OrderItemDao 接口

public interface OrderItemDao {public int saveOrderItem(OrderItem orderItem);
}

OrderItemDao 实现

package com.atguigu.dao.impl;import com.atguigu.dao.OrderItemDao;
import com.atguigu.pojo.OrderItem;public class OrderItemDaoImpl extends BaseDao implements OrderItemDao {@Overridepublic int saveOrderItem(OrderItem orderItem) {String sql = "insert into t_order_item(`name`,`count`,`price`,`total_price`,`order_id`) values(?,?,?,?,?)";return update(sql,orderItem.getName(),orderItem.getCount(),orderItem.getPrice(),orderItem.getTotalPrice(),orderItem.getOrderId());}
}

测试

public class OrderDaoTest {@Testpublic void saveOrder() {OrderDao orderDao = new OrderDaoImpl();orderDao.saveOrder(new Order("1234567891",new Date(),new BigDecimal(100),0, 1));}
}public class OrderItemDaoTest {@Testpublic void saveOrderItem() {OrderItemDao orderItemDao = new OrderItemDaoImpl();orderItemDao.saveOrderItem(new OrderItem(null,"java从入门到精通", 1,new BigDecimal(100),new BigDecimal(100),"1234567890"));orderItemDao.saveOrderItem(new OrderItem(null,"javaScript从入门到精通", 2,new BigDecimal(100),new BigDecimal(200),"1234567890"));orderItemDao.saveOrderItem(new OrderItem(null,"Netty入门", 1,new BigDecimal(100),new BigDecimal(100),"1234567890"));}
}

290.书城项目-编写订单模块的Service和测试

OrderService 接口

public interface OrderService {public String createOrder(Cart cart,Integer userId);
}

OrderService 实现类

package com.atguigu.service.impl;import com.atguigu.dao.BookDao;
import com.atguigu.dao.OrderDao;
import com.atguigu.dao.OrderItemDao;
import com.atguigu.dao.impl.BookDaoImpl;
import com.atguigu.dao.impl.OrderDaoImpl;
import com.atguigu.dao.impl.OrderItemDaoImpl;
import com.atguigu.pojo.*;
import com.atguigu.service.OrderService;import java.util.Date;
import java.util.Map;public class OrderServiceImpl implements OrderService {private OrderDao orderDao = new OrderDaoImpl();private OrderItemDao orderItemDao = new OrderItemDaoImpl();private BookDao bookDao = new BookDaoImpl();@Overridepublic String createOrder(Cart cart, Integer userId) {// 订单号===唯一性String orderId = System.currentTimeMillis()+""+userId;// 创建一个订单对象Order order = new Order(orderId,new Date(),cart.getTotalPrice(), 0,userId);// 保存订单orderDao.saveOrder(order);// 遍历购物车中每一个商品项转换成为订单项保存到数据库for (Map.Entryentry : cart.getItems().entrySet()){// 获取每一个购物车中的商品项CartItem cartItem = entry.getValue();// 转换为每一个订单项OrderItem orderItem = new OrderItem(null,cartItem.getName(),cartItem.getCount(),cartItem.getPrice(),cartItem.getTotalPrice(), orderId);// 保存订单项到数据库orderItemDao.saveOrderItem(orderItem);// 更新库存和销量Book book = bookDao.queryBookById(cartItem.getId());book.setSales( book.getSales() + cartItem.getCount() );book.setStock( book.getStock() - cartItem.getCount() );bookDao.updateBook(book);}// 清空购物车cart.clear();return orderId;}
}

测试

package com.atguigu.test;import com.atguigu.pojo.Cart;
import com.atguigu.pojo.CartItem;
import com.atguigu.service.OrderService;
import com.atguigu.service.impl.OrderServiceImpl;
import org.junit.Test;import java.math.BigDecimal;public class OrderServiceTest {@Testpublic void createOrder() {Cart cart = new Cart();cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));cart.addItem(new CartItem(2, "数据结构与算法", 1, new BigDecimal(100),new BigDecimal(100)));OrderService orderService = new OrderServiceImpl();System.out.println( "订单号是:" + orderService.createOrder(cart, 1) );}
}

291.书城项目-结账功能实现,生成订单

OrderServlet

package com.atguigu.web;import com.atguigu.pojo.Cart;
import com.atguigu.pojo.User;
import com.atguigu.service.OrderService;
import com.atguigu.service.impl.OrderServiceImpl;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;public class OrderServlet extends BaseServlet {private OrderService orderService = new OrderServiceImpl();/*** 生成订单** @param req* @param resp* @throws ServletException* @throws IOException*/protected void createOrder(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 先获取Cart购物车对象Cart cart = (Cart) req.getSession().getAttribute("cart");// 获取UseridUser loginUser = (User) req.getSession().getAttribute("user");if (loginUser == null) {req.getRequestDispatcher("/pages/user/login.jsp").forward(req,resp);return;}Integer userId = loginUser.getId();
//        调用orderService.createOrder(Cart,Userid);生成订单String orderId = orderService.createOrder(cart, userId);//        req.setAttribute("orderId", orderId);// 请求转发到/pages/cart/checkout.jsp
//        req.getRequestDispatcher("/pages/cart/checkout.jsp").forward(req, resp);req.getSession().setAttribute("orderId",orderId);resp.sendRedirect(req.getContextPath()+"/pages/cart/checkout.jsp");}}

292.书城项目-解决生成订单的bug

修改 pages/cart/cart.jsp 页面,结账的请求地址:在这里插入图片描述
修改 pages/cart/checkout.jsp 页面,输出订单号:
在这里插入图片描述
在这里插入图片描述

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...