Web项目延伸与完善


1、登陆—-显示用户名

UserServlet 程序中保存用户登录的信息:
image.png
修改 login_succuess_menu.jsp
image.png

还要修改首页 index.jsp 页面的菜单 :
image.png

2、登出—-注销用户

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

UserServlet 程序中添加 logout 方法

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

修改“注销”的菜单地址:

  1. <a href="userServlet?action=logout">注销</a>

3、表单重复提交之——-验证码

表单重复提交有三种常见的情况:

  1. 提交完表单。服务器使用请求转来进行页面跳转。这个时候,用户按下功能键 F5,就会发起最后一次的请求。 造成表单重复提交问题。
    解决方法:使用重定向来进行跳转
  2. 用户正常提交服务器,但是由于网络延迟等原因,迟迟未收到服务器的响应,这个时候,用户以为提交失败, 就会着急,然后多点了几次提交操作,也会造成表单重复提交。
  3. 用户正常提交服务器。服务器也没有延迟,但是提交完成后,用户回退浏览器。重新提交。也会造成表单重复提交

image.png

4、谷歌 kaptcha 图片验证码的使用

谷歌验证码 kaptcha 使用步骤如下:

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

    1. <servlet>
    2. <servlet-name>KaptchaServlet</servlet-name>
    3. <servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
    4. </servlet>
    5. <servlet-mapping>
    6. <servlet-name>KaptchaServlet</servlet-name>
    7. <url-pattern>/kaptcha.jpg</url-pattern>
    8. </servlet-mapping>
  3. 在表单中使用 img 标签去显示验证码图片并使用它

    1. <form action="http://localhost:8080/tmp/registServlet" method="get">
    2. 用户名:<input type="text" name="username" > <br>
    3. 验证码:<input type="text" style="width: 80px;" name="code">
    4. <img src="http://localhost:8080/tmp/kaptcha.jpg" alt="" style="width: 100px; height: 28px;"> <br>
    5. <input type="submit" value="登录">
    6. </form>
  4. 在服务器获取谷歌生成的验证码和客户端发送过来的验证码比较使用

    1. @Override
    2. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
    3. // 获取 Session 中的验证码
    4. String token = (String) req.getSession().getAttribute(KAPTCHA_SESSION_KEY);
    5. // 删除 Session 中的验证码
    6. req.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
    7. String code = req.getParameter("code");
    8. // 获取用户名
    9. String username = req.getParameter("username");
    10. if (token != null && token.equalsIgnoreCase(code)) {
    11. System.out.println("保存到数据库:" + username);
    12. resp.sendRedirect(req.getContextPath() + "/ok.jsp");
    13. } else {
    14. System.out.println("请不要重复提交表单");
    15. }
    16. }
  5. 切换验证码

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

5、购物车模块

5.1、模块分析

image.png

5.2、购物车模型编写

5.2.1、购物车模型

  1. /**
  2. * 购物车的商品项
  3. */
  4. public class CartItem {
  5. private Integer id;
  6. private String name;
  7. private Integer count;
  8. private BigDecimal price;
  9. private BigDecimal totalPrice;
  10. /**
  11. * 购物车对象
  12. */
  13. public class Cart {
  14. // private Integer totalCount;
  15. // private BigDecimal totalPrice;
  16. /**
  17. * key 是商品编号,
  18. * value,是商品信息
  19. */
  20. private Map<Integer,CartItem> items = new LinkedHashMap<Integer,CartItem>();
  21. /**
  22. * 添加商品项
  23. *
  24. * @param cartItem
  25. */
  26. public void addItem(CartItem cartItem) {
  27. // 先查看购物车中是否已经添加过此商品,如果已添加,则数量累加,总金额更新,如果没有添加过,直接放到 集合中即可
  28. CartItem item = items.get(cartItem.getId());
  29. if (item == null) {
  30. // 之前没添加过此商品
  31. items.put(cartItem.getId(), cartItem);
  32. } else {
  33. // 已经 添加过的情况
  34. item.setCount( item.getCount() + 1 ); // 数量 累加
  35. item.setTotalPrice( item.getPrice().multiply(new BigDecimal( item.getCount() )) ); // 更新总金额
  36. }
  37. }
  38. /**
  39. * 删除商品项
  40. */
  41. public void deleteItem(Integer id) {
  42. items.remove(id);
  43. }
  44. /**
  45. * 清空购物车
  46. */
  47. public void clear() {
  48. items.clear();
  49. }
  50. /**
  51. * 修改商品数量
  52. */
  53. public void updateCount(Integer id,Integer count) {
  54. // 先查看购物车中是否有此商品。如果有,修改商品数量,更新总金额
  55. CartItem cartItem = items.get(id);
  56. if (cartItem != null) {
  57. cartItem.setCount(count);// 修改商品数量
  58. cartItem.setTotalPrice( cartItem.getPrice().multiply(new BigDecimal(cartItem.getCount() )) ); // 更新总金额
  59. }
  60. }
  61. public Integer getTotalCount() {
  62. Integer totalCount = 0;
  63. for (Map.Entry<Integer,CartItem>entry : items.entrySet()) {
  64. totalCount += entry.getValue().getCount();
  65. }
  66. return totalCount;
  67. }
  68. public BigDecimal getTotalPrice() {
  69. BigDecimal totalPrice = new BigDecimal(0);
  70. for (Map.Entry<Integer,CartItem>entry : items.entrySet()) {
  71. totalPrice = totalPrice.add(entry.getValue().getTotalPrice());
  72. }
  73. return totalPrice;
  74. }
  75. public Map<Integer, CartItem> getItems() {
  76. return items;
  77. }
  78. public void setItems(Map<Integer, CartItem> items) {
  79. this.items = items;
  80. }
  81. @Override
  82. public String toString() {
  83. return "Cart{" +
  84. "totalCount=" + getTotalCount() +
  85. ", totalPrice=" + getTotalPrice() +
  86. ", items=" + items +
  87. '}';
  88. }
  89. }

5.2.3、购物车的测试

  1. public class CartTest {
  2. @Test
  3. public void addItem() {
  4. Cart cart = new Cart();
  5. cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));
  6. cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));
  7. cart.addItem(new CartItem(2, "数据结构与算法", 1, new BigDecimal(100),new BigDecimal(100)));
  8. System.out.println(cart);
  9. }
  10. @Test
  11. public void deleteItem() {
  12. Cart cart = new Cart();
  13. cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));
  14. cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));
  15. cart.addItem(new CartItem(2, "数据结构与算法", 1, new BigDecimal(100),new BigDecimal(100)));
  16. cart.deleteItem(1);
  17. System.out.println(cart);
  18. }
  19. @Test
  20. public void clear() {
  21. Cart cart = new Cart();
  22. cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));
  23. cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));
  24. cart.addItem(new CartItem(2, "数据结构与算法", 1, new BigDecimal(100),new BigDecimal(100)));
  25. cart.deleteItem(1);
  26. cart.clear();
  27. System.out.println(cart);
  28. }
  29. @Test
  30. public void updateCount() {
  31. Cart cart = new Cart();
  32. cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));
  33. cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));
  34. cart.addItem(new CartItem(2, "数据结构与算法", 1, new BigDecimal(100),new BigDecimal(100)));
  35. cart.deleteItem(1);
  36. cart.clear();
  37. cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));
  38. cart.updateCount(1, 10);
  39. System.out.println(cart);
  40. }
  41. }

5.3、加入购物车功能的实现

CartServlet 程序中的代码

  1. /**
  2. * 加入购物车
  3. * @param req
  4. * @param resp
  5. * @throws ServletException
  6. * @throws IOException
  7. */
  8. protected void addItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
  9. // 获取请求的参数 商品编号
  10. int id = WebUtils.parseInt(req.getParameter("id"), 0);
  11. // 调用 bookService.queryBookById(id):Book 得到图书的信息
  12. Book book = bookService.queryBookById(id);
  13. // 把图书信息,转换成为 CartItem 商品项
  14. CartItem cartItem = new CartItem(book.getId(),book.getName(),1,book.getPrice(),book.getPrice());
  15. // 调用 Cart.addItem(CartItem);添加商品项
  16. Cart cart = (Cart) req.getSession().getAttribute("cart");
  17. if (cart == null) {
  18. cart = new Cart();
  19. req.getSession().setAttribute("cart",cart);
  20. }
  21. cart.addItem(cartItem);
  22. System.out.println(cart);
  23. System.out.println("请求头 Referer 的值:" + req.getHeader("Referer"));
  24. // 重定向回原来商品所在的地址页面
  25. resp.sendRedirect(req.getHeader("Referer"));
  26. }

index.jsp 页面 js 的代码
image.png

  1. <Script type="text/javascript">
  2. $(function () {
  3. // 给加入购物车按钮绑定单击事件
  4. $("button.addToCart").click(function () {
  5. /**
  6. * 在事件响应的function函数中,有一个 this 对象,这个 this 对象,是当前正在响应事件的 dom 对象
  7. * @type {jQuery}
  8. */
  9. var bookId = $(this).attr("bookId");
  10. location.href = "http://localhost:8080/book/cartServlet?action=addItem&id=" + bookId;
  11. });
  12. });
  13. </Script>

如何跳回添加商品的页面:
image.png

5.4、购物车的展示

  1. <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
  2. <%@ page contentType="text/html;charset=UTF-8" language="java" %>
  3. <!DOCTYPE html>
  4. <html>
  5. <head>
  6. <meta charset="UTF-8">
  7. <title>购物车</title>
  8. <%-- 静态包含 base 标签、css 样式、jQuery 文件 --%>
  9. <%@ include file="/pages/common/head.jsp"%>
  10. </head>
  11. <body>
  12. <div id="header">
  13. <img class="logo_img" alt="" src="static/img/logo.gif" >
  14. <span class="wel_word">购物车</span>
  15. <%--静态包含,登录 成功之后的菜单 --%>
  16. <%@ include file="/pages/common/login_success_menu.jsp"%>
  17. </div>
  18. <div id="main">
  19. <table>
  20. <tr>
  21. <td>商品名称</td>
  22. <td>数量</td>
  23. <td>单价</td>
  24. <td>金额</td>
  25. <td>操作</td>
  26. </tr>
  27. <c:if test="${empty sessionScope.cart.items}">
  28. <%--如果购物车空的情况--%>
  29. <tr>
  30. <td colspan="5"><a href="index.jsp">亲,当前购物车为空!快跟小伙伴们去浏览商品吧!!!</a></td>
  31. </tr>
  32. </c:if>
  33. <c:if test="${not empty sessionScope.cart.items}">
  34. <%--如果购物车非空的情况--%>
  35. <c:forEach items="${sessionScope.cart.items}" var="entry">
  36. <tr>
  37. <td>${entry.value.name}</td>
  38. <td>${entry.value.count}</td>
  39. <td>${entry.value.price}</td>
  40. <td>${entry.value.totalPrice}</td>
  41. <td><a href="#">删除</a></td>
  42. </tr>
  43. </c:forEach>
  44. </c:if>
  45. </table>
  46. <%--如果购物车非空才输出页面的内容--%>
  47. <c:if test="${not empty sessionScope.cart.items}">
  48. <div class="cart_info">
  49. <span class="cart_span">购物车中共有<span class="b_count">${sessionScope.cart.totalCount}</span>件商品</span>
  50. <span class="cart_span">总金额<span class="b_price">${sessionScope.cart.totalPrice}</span></span>
  51. <span class="cart_span"><a href="#">清空购物车</a></span>
  52. <span class="cart_span"><a href="pages/cart/checkout.jsp">去结账</a></span>
  53. </div>
  54. </c:if>
  55. </div>
  56. <%--静态包含页脚内容--%>
  57. <%@include file="/pages/common/footer.jsp"%>
  58. </body>
  59. </html

5.5、删除购物车商品项

CartServlet 程序

  1. /**
  2. * 删除商品项
  3. * @param req
  4. * @param resp
  5. * @throws ServletException
  6. * @throws IOException
  7. */
  8. protected void deleteItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException{
  9. // 获取商品编号
  10. int id = WebUtils.parseInt(req.getParameter("id"), 0);
  11. // 获取购物车对象
  12. Cart cart = (Cart) req.getSession().getAttribute("cart");
  13. if (cart != null) {
  14. // 删除 了购物车商品项
  15. cart.deleteItem(id);
  16. // 重定向回原来购物车展示页面
  17. resp.sendRedirect(req.getHeader("Referer"));
  18. }
  19. }

购物车/pages/cart/cart.jsp 页面的代码:

删除的请求地址:
image.png

删除的确认提示操作:

  1. <script type="text/javascript">
  2. $(function () {
  3. // 给 【删除】绑定单击事件
  4. $("a.deleteItem").click(function () {
  5. return confirm("你确定要删除【" + $(this).parent().parent().find("td:first").text() +"】吗?")
  6. });
  7. });
  8. </script>

5.6、清空购物车

CartServlet 程序

  1. /**
  2. * 清空购物车
  3. * @param req
  4. * @param resp
  5. * @throws ServletException
  6. * @throws IOException
  7. */
  8. protected void clear(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
  9. IOException{
  10. // 1 获取购物车对象
  11. Cart cart = (Cart) req.getSession().getAttribute("cart");
  12. if (cart != null) {
  13. // 清空购物车
  14. cart.clear();
  15. // 重定向回原来购物车展示页面
  16. resp.sendRedirect(req.getHeader("Referer"));
  17. }
  18. }

cart.jsp 页面的内容

给清空购物车添加请求地址,和添加 id 属性:
image.png

清空的确认提示操作:

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

5.7、修改购物车商品数量

CartServlet 程序

  1. /**
  2. * 修改商品数量
  3. * @param req
  4. * @param resp
  5. * @throws ServletException
  6. * @throws IOException
  7. */
  8. protected void updateCount(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException{
  9. // 获取请求的参数 商品编号 、商品数量
  10. int id = WebUtils.parseInt(req.getParameter("id"),0);
  11. int count = WebUtils.parseInt(req.getParameter("count"), 1);
  12. // 获取 Cart 购物车对象
  13. Cart cart = (Cart) req.getSession().getAttribute("cart");
  14. if (cart != null) {
  15. // 修改商品数量
  16. cart.updateCount(id,count);
  17. // 重定向回原来购物车展示页面
  18. resp.sendRedirect(req.getHeader("Referer"));
  19. }
  20. }

修改 pages/cart/cart.jsp 购物车页面:
image.png

修改商品数量 js 代码:

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

5.8、首页、购物车数据回显

在添加商品到购物车的时候,保存最后一个添加的商品名称

image.png
在 pages/client/index.jsp 页面中输出购物车信息:

  1. <div style="text-align: center">
  2. <c:if test="${empty sessionScope.cart.items}">
  3. <%--购物车为空的输出--%>
  4. <span> </span>
  5. <div>
  6. <span style="color: red">当前购物车为空</span>
  7. </div>
  8. </c:if>
  9. <c:if test="${not empty sessionScope.cart.items}">
  10. <%--购物车非空的输出--%>
  11. <span>您的购物车中有 ${sessionScope.cart.totalCount} 件商品</span>
  12. <div>
  13. 您刚刚将<span style="color: red">${sessionScope.lastName}</span>加入到了购物车中
  14. </div>
  15. </c:if>
  16. </div>

6、订单模块

6.1、订单模块分析

image.png

6.2、订单模块的实现

6.2.1、创建订单模块的数据库表

  1. use book;
  2. create table t_order(
  3. `order_id` varchar(50) primary key,
  4. `create_time` datetime,
  5. `price` decimal(11,2),
  6. `status` int,
  7. `user_id` int,
  8. foreign key(`user_id`) references t_user(`id`)
  9. );
  10. create table t_order_item(
  11. `id` int primary key auto_increment,
  12. `name` varchar(100),
  13. `count` int,
  14. `price` decimal(11,2),
  15. `total_price` decimal(11,2),
  16. `order_id` varchar(50),
  17. foreign key(`order_id`) references t_order(`order_id`)
  18. );

6.2.2、创建订单模块的数据模型

  1. /**
  2. * 订单
  3. */
  4. public class Order {
  5. private String orderId;
  6. private Date createTime;
  7. private BigDecimal price;
  8. // 0 未发货,1 已发货,2 表示已签收
  9. private Integer status = 0;
  10. private Integer userId;
  11. /**
  12. * 订单项
  13. */
  14. public class OrderItem {
  15. private Integer id;
  16. private String name;
  17. private Integer count;
  18. private BigDecimal price;
  19. private BigDecimal totalPrice;
  20. private String orderId;

6.2.3、编写订单模块的 Dao 程序和测试

OrderDao 接口:

  1. public interface OrderDao {
  2. public int saveOrder(Order order);
  3. }

OrderDao 实现:

  1. public class OrderDaoImpl extends BaseDao implements OrderDao {
  2. @Override
  3. public int saveOrder(Order order) {
  4. String sql = "insert into t_order(`order_id`,`create_time`,`price`,`status`,`user_id`) values(?,?,?,?,?)";
  5. return update(sql,order.getOrderId(),order.getCreateTime(),order.getPrice(),order.getStatus(),order.getUserId());
  6. }
  7. }

OrderItemDao 接口:

  1. public interface OrderItemDao {
  2. public int saveOrderItem(OrderItem orderItem);
  3. }

OrderItemDao 实现:

  1. public class OrderItemDaoImpl extends BaseDao implements OrderItemDao {
  2. @Override
  3. public int saveOrderItem(OrderItem orderItem) {
  4. String sql = "insert into t_order_item(`name`,`count`,`price`,`total_price`,`order_id`) values(?,?,?,?,?)";
  5. return update(sql,orderItem.getName(),orderItem.getCount(),orderItem.getPrice(),orderItem.getTotalPrice(),orderItem.getOrderId());
  6. }
  7. }

测试

  1. public class OrderDaoTest {
  2. @Test
  3. public void saveOrder() {
  4. OrderDao orderDao = new OrderDaoImpl();
  5. orderDao.saveOrder(new Order("1234567891",new Date(),new BigDecimal(100),0, 1));
  6. }
  7. }
  8. public class OrderItemDaoTest {
  9. @Test
  10. public void saveOrderItem() {
  11. OrderItemDao orderItemDao = new OrderItemDaoImpl();
  12. orderItemDao.saveOrderItem(new OrderItem(null,"java 从入门到精通", 1,new BigDecimal(100),new BigDecimal(100),"1234567890"));
  13. orderItemDao.saveOrderItem(new OrderItem(null,"javaScript 从入门到精通", 2,new BigDecimal(100),new BigDecimal(200),"1234567890"));
  14. orderItemDao.saveOrderItem(new OrderItem(null,"Netty 入门", 1,new BigDecimal(100),new BigDecimal(100),"1234567890"));
  15. }
  16. }

6.2.4、编写订单模块的 Service 和测试

OrderService 接口

  1. public interface OrderService {
  2. public String createOrder(Cart cart,Integer userId);
  3. }

OrderService 实现类

  1. public class OrderServiceImpl implements OrderService {
  2. private OrderDao orderDao = new OrderDaoImpl();
  3. private OrderItemDao orderItemDao = new OrderItemDaoImpl();
  4. @Override
  5. public String createOrder(Cart cart, Integer userId) {
  6. // 订单号===唯一性
  7. String orderId = System.currentTimeMillis()+""+userId;
  8. // 创建一个订单对象
  9. Order order = new Order(orderId,new Date(),cart.getTotalPrice(), 0,userId);
  10. // 保存订单
  11. orderDao.saveOrder(order);
  12. // 遍历购物车中每一个商品项转换成为订单项保存到数据库
  13. for (Map.Entry<Integer, CartItem>entry : cart.getItems().entrySet()){
  14. // 获取每一个购物车中的商品项
  15. CartItem cartItem = entry.getValue();
  16. // 转换为每一个订单项
  17. OrderItem orderItem = new OrderItem(null,cartItem.getName(),cartItem.getCount(),cartItem.getPrice(),cartItem.getTotalPrice(),orderId);
  18. // 保存订单项到数据库
  19. orderItemDao.saveOrderItem(orderItem);
  20. }
  21. // 清空购物车
  22. cart.clear();
  23. return orderId;
  24. }
  25. }

测试

  1. public class OrderServiceTest {
  2. @Test
  3. public void createOrder() {
  4. Cart cart = new Cart();
  5. cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));
  6. cart.addItem(new CartItem(1, "java从入门到精通", 1, new BigDecimal(1000),new BigDecimal(1000)));
  7. cart.addItem(new CartItem(2, "数据结构与算法", 1, new BigDecimal(100),new BigDecimal(100)));
  8. OrderService orderService = new OrderServiceImpl();
  9. System.out.println( "订单号是:" + orderService.createOrder(cart, 1) );
  10. }
  11. }

6.2.5、编写订单模块的 web 层和页面联调

修改 OrderService 程序:

  1. public class OrderServiceImpl implements OrderService {
  2. private OrderDao orderDao = new OrderDaoImpl();
  3. private OrderItemDao orderItemDao = new OrderItemDaoImpl();
  4. private BookDao bookDao = new BookDaoImpl();
  5. @Override
  6. public String createOrder(Cart cart, Integer userId) {
  7. // 订单号===唯一性
  8. String orderId = System.currentTimeMillis()+""+userId;
  9. // 创建一个订单对象
  10. Order order = new Order(orderId,new Date(),cart.getTotalPrice(), 0,userId);
  11. // 保存订单
  12. orderDao.saveOrder(order);
  13. // 遍历购物车中每一个商品项转换成为订单项保存到数据库
  14. for (Map.Entry<Integer, CartItem>entry : cart.getItems().entrySet()){
  15. // 获取每一个购物车中的商品项
  16. CartItem cartItem = entry.getValue();
  17. // 转换为每一个订单项
  18. OrderItem orderItem = new OrderItem(null,cartItem.getName(),cartItem.getCount(),cartItem.getPrice(),cartItem.getTotalPrice(),orderId);
  19. // 保存订单项到数据库
  20. orderItemDao.saveOrderItem(orderItem);
  21. // 更新库存和销量
  22. Book book = bookDao.queryBookById(cartItem.getId());
  23. book.setSales( book.getSales() + cartItem.getCount() );
  24. book.setStock( book.getStock() - cartItem.getCount() );
  25. bookDao.updateBook(book);
  26. }
  27. // 清空购物车
  28. cart.clear();
  29. return orderId;
  30. }
  31. }

OrderServlet 程序:

  1. public class OrderServlet extends BaseServlet {
  2. private OrderService orderService = new OrderServiceImpl();
  3. /**
  4. * 生成订单
  5. *
  6. * @param req
  7. * @param resp
  8. * @throws ServletException
  9. * @throws IOException
  10. */
  11. protected void createOrder(HttpServletRequest req, HttpServletResponse resp) throws
  12. ServletException, IOException {
  13. // 先获取 Cart 购物车对象
  14. Cart cart = (Cart) req.getSession().getAttribute("cart");
  15. // 获取 Userid
  16. User loginUser = (User) req.getSession().getAttribute("user");
  17. if (loginUser == null) {
  18. req.getRequestDispatcher("/pages/user/login.jsp").forward(req,resp);
  19. return;
  20. }
  21. Integer userId = loginUser.getId();
  22. // 调用 orderService.createOrder(Cart,Userid);生成订单
  23. String orderId = orderService.createOrder(cart, userId);
  24. // req.setAttribute("orderId", orderId);
  25. // 请求转发到/pages/cart/checkout.jsp
  26. // req.getRequestDispatcher("/pages/cart/checkout.jsp").forward(req, resp);
  27. req.getSession().setAttribute("orderId",orderId);
  28. resp.sendRedirect(req.getContextPath()+"/pages/cart/checkout.jsp");
  29. }
  30. }

修改 pages/cart/cart.jsp 页面,结账的请求地址:
image.png

修改 pages/cart/checkout.jsp 页面,输出订单号:
image.png

7、使用 Filter 过滤器实现权限检查

使用 Filter 过滤器拦截/pages/manager/所有内容,实现权限检查

Filter 代码

  1. public class ManagerFilter implements Filter {
  2. @Override
  3. public void init(FilterConfig filterConfig) throws ServletException {
  4. }
  5. @Override
  6. public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  7. HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
  8. Object user = httpServletRequest.getSession().getAttribute("user");
  9. if (user == null) {
  10. httpServletRequest.getRequestDispatcher("/pages/user/login.jsp").forward(servletRequest,servletResponse);
  11. } else {
  12. filterChain.doFilter(servletRequest,servletResponse);
  13. }
  14. }
  15. @Override
  16. public void destroy() {
  17. }
  18. }

web.xml 中的配置

  1. <filter>
  2. <filter-name>ManagerFilter</filter-name>
  3. <filter-class>com.atguigu.filter.ManagerFilter</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>ManagerFilter</filter-name>
  7. <url-pattern>/pages/manager/*</url-pattern>
  8. <url-pattern>/manager/bookServlet</url-pattern>
  9. </filter-mapping>

8、JSON与AJAX操作

使用 AJAX 验证用户名是否可用

image.png

UserServlet 程序中 ajaxExistsUsername 方法:

  1. protected void ajaxExistsUsername(HttpServletRequest req, HttpServletResponse resp) throws
  2. ServletException, IOException {
  3. // 获取请求的参数 username
  4. String username = req.getParameter("username");
  5. // 调用 userService.existsUsername();
  6. boolean existsUsername = userService.existsUsername(username);
  7. // 把返回的结果封装成为 map 对象
  8. Map<String,Object> resultMap = new HashMap<>();
  9. resultMap.put("existsUsername",existsUsername);
  10. Gson gson = new Gson();
  11. String json = gson.toJson(resultMap);
  12. resp.getWriter().write(json);
  13. }

regist.jsp 页面中的代码:

  1. $("#username").blur(function () {
  2. //1 获取用户名
  3. var username = this.value;
  4. $.getJSON("http://localhost:8080/book/userServlet","action=ajaxExistsUsername&username=" + username,function (data) {
  5. if (data.existsUsername) {
  6. $("span.errorMsg").text("用户名已存在!");
  7. } else {
  8. $("span.errorMsg").text("用户名可用!");
  9. }
  10. });
  11. });

使用 AJAX修改把商品添加到购物车

image.png

CartServlet 程序:

  1. protected void ajaxAddItem(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
  2. // 获取请求的参数 商品编号
  3. int id = WebUtils.parseInt(req.getParameter("id"), 0);
  4. // 调用 bookService.queryBookById(id):Book 得到图书的信息
  5. Book book = bookService.queryBookById(id);
  6. // 把图书信息,转换成为 CartItem 商品项
  7. CartItem cartItem = new CartItem(book.getId(),book.getName(),1,book.getPrice(),book.getPrice());
  8. // 调用 Cart.addItem(CartItem);添加商品项
  9. Cart cart = (Cart) req.getSession().getAttribute("cart");
  10. if (cart == null) {
  11. cart = new Cart();
  12. req.getSession().setAttribute("cart",cart);
  13. }
  14. cart.addItem(cartItem);
  15. System.out.println(cart);
  16. // 最后一个添加的商品名称
  17. req.getSession().setAttribute("lastName", cartItem.getName());
  18. //6、返回购物车总的商品数量和最后一个添加的商品名称
  19. Map<String,Object> resultMap = new HashMap<String,Object>();
  20. resultMap.put("totalCount", cart.getTotalCount());
  21. resultMap.put("lastName",cartItem.getName());
  22. Gson gson = new Gson();
  23. String resultMapJsonString = gson.toJson(resultMap);
  24. resp.getWriter().write(resultMapJsonString);
  25. }

pages/client/index.jsp 页面

html 代码:

  1. <div style="text-align: center">
  2. <c:if test="${empty sessionScope.cart.items}">
  3. <%--购物车为空的输出--%>
  4. <span id="cartTotalCount"> </span>
  5. <div>
  6. <span style="color: red" id="cartLastName">当前购物车为空</span>
  7. </div>
  8. </c:if>
  9. <c:if test="${not empty sessionScope.cart.items}">
  10. <%--购物车非空的输出--%>
  11. <span id="cartTotalCount">您的购物车中有 ${sessionScope.cart.totalCount} 件商品</span>
  12. <div>
  13. 您刚刚将<span style="color: red" id="cartLastName">${sessionScope.lastName}</span>加入到了购物车中
  14. </div>
  15. </c:if>
  16. </div>

javaScript 代码:

  1. <Script type="text/javascript">
  2. $(function () {
  3. // 给加入购物车按钮绑定单击事件
  4. $("button.addToCart").click(function () {
  5. /**
  6. * 在事件响应的 function 函数 中,有一个 this 对象,这个 this 对象,是当前正在响应事件的 dom 对象
  7. * @type {jQuery}
  8. */
  9. var bookId = $(this).attr("bookId");
  10. // location.href = "http://localhost:8080/book/cartServlet?action=addItem&id=" + bookId;
  11. // 发 ajax 请求,添加商品到购物车
  12. $.getJSON("http://localhost:8080/book/cartServlet","action=ajaxAddItem&id=" + bookId,function (data) {
  13. $("#cartTotalCount").text("您的购物车中有 " + data.totalCount + " 件商品");
  14. $("#cartLastName").text(data.lastName);
  15. })
  16. });
  17. });
  18. </Script>