第14章 项目实战——尚硅谷书城¶
第 14 章¶
项目实战 —— 尚硅谷书城¶
前面介绍了 JavaWeb 学习阶段所涉及的技术知识,从前端页面开发,到后端接口实现,以及借助框架优化开发,实现前后端分离。至此,大家可以独自完成 JavaWeb 项目了。本章将带领大家共同完成一个项目 “尚硅谷书城”,综合运用本书所学知识,巩固和检验所学成果。
14.1 项目概述¶
尚硅谷书城项目主要是搭建一个图书的销售平台,后台进行图书的数据维护、添加图书、修改图书、删除图书等功能。前台进行图书的展示、加入购物车、购物车图书商品的操作,以及结账等功能。
14.1.1 功能介绍¶
尚硅谷书城项目包括的功能有登录注册、图书的增删改查操作、加入购物车、清空购物车、购物车商品数量的修改,以及结账等功能。该项目基本上能够涵盖本书所有的知识点,希望大家认真练习,做到知其然并知其所以然,在今后的开发中灵活运用所学知识,能够举一反三,融会贯通。
下面给大家展示一些项目截图,如图 14-1、图 14-2、图 14-3 所示。

这几张图片就是我们项目中要实现的部分功能,接下来我们从零开始,逐步完成一个成品项目。创建该项目的关键在于应用前面所学的知识点,基于此有一些功能暂时无法实现,例如,后台管理的权限控制、结账中支付接口的对接等,但并不影响项目的整体效果。尚硅谷书城项目采用 MVC 架构进行开发,涉及的技术有 Servlet、Thymeleaf、Filter、Session 等,数据库使用的是 MySQL。


14.1.2 数据库设计¶
尚硅谷书城项目的数据库共涉及 4 张表,分别为用户表 t_users、图书表 t_books、订单表 t_order、订单详情表 t_order_item,表结构分别如表 14-1 至表 14-4 所示。
表 14-1 t_users 表结构
| 字段 | 类型 | 说明 |
| id | int、自增主键 | 用户 ID |
| username | varchar(20) | 用户名 |
| password | varchar(50) | 密码 |
| varchar(50) | 邮箱 |
表 14-2 t_books 表结构
| 字段 | 类型 | 说明 |
| id | int、自增主键 | 图书ID |
| title | varchar(50) | 书名 |
| author | varchar(50) | 作者 |
| price | Double | 单价 |
| sales | Int | 销量 |
| stock | Int | 库存 |
| img_path | varchar(200) | 图片路径 |
表 14-3 t_order 表结构
| 字段 | 类型 | 说明 |
| order_id | int、自增主键 | 订单 ID |
| order_sequence | varchar(200) | 订单编号 |
| create_time | varchar(200) | 创建时间 |
| total_count | int | 总件数 |
| total_amount | double | 总价 |
| order_status | int | 订单状态(0:待发货 1:已发货 2:确认收货 3:已评价) |
| user_id | int | 订单所属用户 ID |
表 14-4 t_order_item 表结构
| 字段 | 类型 | 说明 |
| item_id | int、自增主键 | 订单项 ID |
| book_name | varchar(50) | 书名 |
| price | Double | 单价 |
| img_path | varchar(200) | 图片路径 |
| item_count | Int | 件数 |
| item_amount | Double | 金额 |
| order_id | Int | 订单项所属的订单 id |
14.1.3 项目搭建¶
在对尚硅谷书城项目及用到的数据库表进行了简单了解后,接下来进入项目开发。首先完成一些项目开发前的准备工作。
1. 导入建表和初始化表数据的 sql 语句¶
从项目资源素材中获取 bookManager.sql 文件,在 atguigu 数据库下执行该文件,创建对应表格,如图 14-4 所示。
2. 创建项目¶
打开 IDEA,创建一个 Project,设置好项目名称和存储位置等信息,最后单击 “Create” 按钮创建即可,如图 14-5 所示。

在项目上右键选择 “Add Framework Support” 进入新窗口,如图 14-6 所示。并在 Java EE 类目下选择 “Web Application” 选项为该项目添加 web 组件,最后单击 “OK” 按钮即可。如图 14-7 所示。



创建完后,项目目录会多出一个 web 组件,web 目录下的 index.jsp 删除即可,我们采用 Thymeleaf 进行视图渲染。BookManager 项目的目录结构如图 14-8 所示。
3. 添加数据库相关资源¶
接下来需要将一些工具的 jar 包,以及之前课程中封装过的工具类导入到项目内,清单如下。
- 相关 jar 包
- 工具类
- 配置文件:db.properties
下面依次将其添加到书城项目中。
(1) 添加 Tomcat 依赖。
单击菜单中的 “File”,然后选择 “Project Structure” 进入新窗口,如图 14-9 所示。选择 “Modules”,然后选中 “BookManager” 模块,单击右侧的 “Dependencies”,单击加号选择 “2 Library”,选中 “Tomcat 8.5.27”,再单击 “Add Selected”,最后单击 “OK” 按钮即可添加成功。
(2) 添加相关 jar 包。¶
在 WEB-INF 下创建 lib 目录,将相关 jar 包复制粘贴进去(从资料包中寻找),并右键 Add As Library 将其添加为项目的依赖,如图 14-10 所示。


(3) 创建配置文件。¶
在项目根目录下创建 resources 目录,并右键选择 “Mark Directory as”,标记该目录为 Resources Root 类型。这样项目编译时,会将该目录下的配置文件编译到类路径下。在 resources 目录下新建文件 db.properties,并添加如下配置信息。
需要注意,关于 MySQL 数据库的端口号、数据库名称,以及密码都需要设置成自己的。
(4)创建包名,添加工具类。¶
在 src 目录下将 package 准备好供后期使用。
将 JDBCTools、MD5Util、CommonResult 工具类复制到 util 包下,将 BaseDao 复制到 dao 包下,将 ViewBaseServlet 复制到 servlet.base 包下。
另外,在 web.xml 中设置 Thymeleaf 渲染视图的前缀和后缀。
(5) 拷贝静态资源。¶
将静态资源中 static 文件夹拷贝到项目的 web 目录下,将 pages 文件夹拷贝到 WEB-INF 目录下,将 index.html 拷贝到 WEB-INF/pages 目录下。
操作后的项目结构如图 14-11 所示。

14.2 首页的访问¶
书城项目使用 Thymeleaf 进行视图渲染,将页面都存放在 / WEB-INF/pages/ 目录下,因此首页的访问,需要先发请求到 Servlet,再由 Thymeleaf 进行渲染。步骤如下。
IndexServlet 代码如下。
index.html 页面代码如下。
添加 Tomcat 镜像服务器部署书城项目,如图 14-12 所示。然后启动服务器端,测试首页是否访问成功。打开浏览器通过 “http://localhost:8888/BookManager_war_exploded/index.html” 访问书城首页,如图 14-13 所示。


14.3 用户管理模块¶
用户管理模块主要包括三个功能,分别是用户注册、用户登录和用户注销。下面依次对这三个功能展开介绍。
14.3.1 用户注册¶
注册功能是用户的第一个操作,也是整个项目的第一个功能。重点理解按照 MVC 架构进行开发时,各层对应的代码结构及其调用关系。后面其他功能与此类似。
1. 开发实体类¶
在 bean 包下创建 User 类,对应数据库中的 t_users 表。示例代码如下。
2. 注册页面的访问¶
实现在首页中单击 “注册” 超链接跳转注册页面。
(1)创建 ToRegistPageServlet 类,实现跳转注册页面。
(2)修改 index.html 页面中注册对应的超链接,设置访问路径为 ToRegistPageServlet 类的映射路径。示例代码如下。
(3)修改 / WEB-INF/pages/user/ 目录下的 regist.html 页面,添加 Thymeleaf 的名称空间,实现页面渲染。
然后启动项目,单击首页的 “注册”,成功跳转注册页面,如图 14-14 所示。
接下来分别实现注册页面中涉及的验证码展示、表单正则验证,以及用户名唯一验证等功能,并且注册功能完善后进行统一测试。
3. 验证码图片动态展示¶
(1)在 web.xml 中配置 KaptchaServlet 的映射路径。

(2)修改 regist.html 页面,实现验证码动态展示功能。
在 regist.html 页面中修改 标签的访问路径,为 KaptchaServlet 的映射路径,并绑定单击事件。
在 regist.html 页面
标签内引入 vue.js 文件,并在 标签内添加最外层编写如下 Vue 代码。
4. 表单的正则验证¶
关于注册页面中的表单项,我们需要对注册用户提出一些数据格式要求,如用户名的组成部分、用户名的长度,密码的长度,以及邮箱的格式是否符合要求等。
首先,将表单以及提示内容和 Vue 的数据模型进行绑定。其次,在表单元素上分别添加事件:输入框添加 blur 失去焦点事件;表单上添加 submit 提交事件,并且在 Vue 中创建函数进行数据的正则验证。修改后的 regist.html 文件示例代码如下。
5. 用户名唯一性验证¶
关于用户名需要一个特殊的验证,即要求用户注册时使用的用户名是唯一的。在注册之前,需要根据用户输入的用户名去数据库查询,如果能查询到结果,就说明该用户名已被其他用户注册,并且不能重复使用;如果查询不到结果,就说明该用户名可用。这里,我们采用 AJAX 异步请求进行用户名唯一性的验证。具体步骤如下。
(1)在 regist.html 文件中引入 Axios 框架的支持文件。
(2)修改 checkUsername 函数,在用户名格式验证成功后,发送异步请求到服务器端。
(3)创建 CheckUsernameServlet 类,继承 HttpServlet,进行用户名验证的请求处理,示例代码如下。
(4)完成业务层和持久层相应操作。
业务层创建 UserService 接口,添加验证用户名是否重复的方法,示例代码如下。
业务层创建 UserServiceImpl 类,实现 UserService 接口,示例代码如下。
持久层创建 UserDao 接口,示例代码如下。
持久层创建 UserDaoImpl 类,实现 UserDao 接口,示例代码如下。
6. 单击注册按钮进行数据提交¶
前面已经对数据的格式进行了验证,也对用户名的唯一性进行了验证,接下来单击 “注册” 按钮进行表单的提交,将数据保存到数据库中完成注册功能。
(1)创建 RegistServlet 类,处理表单提交请求,注册成功跳转到注册成功页面,注册失败跳转到原页面,示例代码如下。
(2)将表单请求路径设置为 RegistServlet 的请求路径。
(3)完成业务层和持久层的相应操作。
在 UserService 接口中,添加将用户信息保存到数据库的方法,示例代码如下。
在 UserServiceImpl 实现类中,实现 UserService 接口的方法,示例代码如下。
在 UserDao 接口中,添加向数据库新增用户的方法,示例代码如下。
在 UserDaoImpl 实现类中,实现 UserDao 接口的方法,示例代码如下。
如果登录失败,就跳转到 regist.html 页面,需要实现数据回显及错误信息提示,在 Vue 的 data 中增加内容,示例代码如下。
下面对注册具体功能进行测试,如图 14-15 所示,填写注册信息。然后单击 “注册”,如图 14-16 所示,跳转至注册成功页面。


14.3.2 Servlet 的优化¶
至此,该项目的注册功能已经完成。不难发现,针对简单的注册功能已经创建了很多 Servlet,也就是说,后期在实现其他功能时,还会创建更多的 Servlet,因此我们需要对 Servlet 进行优化。保证让相同类型的请求都发送到同一个 Servlet 上,这样就大大减少了 Servlet 的个数。
首先,需要满足一个条件,即将请求路径进行规范化。回顾一下之前请求 Servlet 的路径:去注册页面的请求路径是 /regist.html;检查用户名唯一性的请求路径是 /checkUsername;注册的请求路径是 /regist。这里可以将三个 Servlet 合并成一个 UserServlet,统一处理和用户相关的请求,后面登录的相关请求也发送到 UserServlet。
假设 UserServlet 的访问路径是 /user,那么问题就是如何让一个 Servlet 处理多个不同的请求。解决方案就是,不同的请求都携带一个 key 值相同但 value 值不同的请求参数。例如,user?method=regist.html、user?method=checkUsername、user?method=regist,这样 Servlet 就可以获取 method 的请求参数值,根据 value 值的不同来调用不同的方法,进行不同请求的处理。下面对注册涉及的 Servlet 进行优化。
(1)修改请求路径携带 method 参数。
修改 index.html 页面中注册对应的超链接,示例代码如下。
修改 regist.html 页面中检查用户名唯一性的请求路径,示例代码如下。
修改 regist.html 页面中表单的请求路径,示例代码如下。
(2)创建 UserServlet,将 ToRegistPageServlet、RegistServlet、CheckUsernameServlet 三个合并到 UserServlet,示例代码如下。
本节完成了 Servlet 优化,大大减少了 Servlet 文件的个数,注册相关的 ToRegistPageServlet、RegistServlet、CheckUsernameServlet 就可以删除了。
14.3.3 用户登录¶
用户注册完后就会进行登录,接下来我们将实现登录功能,具体如下。
1. 单击 “登录” 按钮跳转登录页面¶
(1)修改 index.html 中的 “登录” 超链接,访问路径为 “user?method=login.html”,示例代码如下。 登录
(2)修改 UserServlet,新增一个分支(加粗部分),示例代码如下。
在 UserServlet 类中,新增 toLoginPage () 方法实现跳转登录页面,示例代码如下。
(3)修改 login.html 页面,示例代码如下。
重启项目进入首页,单击 “登录” 按钮,如图 14-17 所示,成功跳转登录页面。

2. 对登录页面表单进行非空校验¶
(3)在表单上绑定提交事件,修改之前
标签内的代码,具体如下。3. 实现登录功能¶
(1)修改登录表单的 action 属性值,示例代码如下。
(2)修改 UserServlet,新增处理登录请求的代码。
在 UserServlet 的 doPost () 方法中新增一个分支(加粗部分),代码如下。
在 UserServlet 中新增 login () 方法,处理登录请求,示例代码如下。
(3)完善业务层代码。另外,对于持久层,登录可以使用 UserDao 和 UserDaoImpl 中的 findUserByUsername (String username) 方法查询用户信息。
在 UserService 接口中新增 login () 登录方法,示例代码如下。
User login(String username, String password);
在 UserServiceImpl 实现类中实现 login () 方法,示例代码如下。
(4)完善登录和登录成功页面。
修改 login.html 页面中 Vue 代码的 data 内容,示例代码如下。
完善 login_success.html 登录成功页面,示例代码如下。
运行代码,输入已注册的用户信息进行登录,如图 14-18 所示,成功跳转登录成功页面。

4. index.html 页面的头信息完善¶
登录成功后,修改首页展示用户信息。首页的头信息根据 session 中是否有 user 对象判断是否处于登录状态,从而显示不同的内容,如果不处于登录状态就显示 “登录” 和 “注册” 的超链接,如果处于登录状态就显示 “欢迎:XXX” 和 “注销” 的超链接。
运行代码,重新登录用户信息,查看首页,如图 14-19 所示。

14.3.4 用户注销¶
登录完成后,首页会出现注销的超链接。注销功能,就是单击 “注销” 按钮后发送请求至后台 Servlet,然后实现将 session 中的 User 对象移除即可。
(1)修改首页的注销超链接,示例代码如下。
(2)修改 UserServlet,新增注销的相关代码。
在 UserServlet 的 doPost () 方法中新增一个分支(加粗部分),示例代码如下。
在 UserServlet 中新增 logout () 方法,示例代码如下。
运行代码,登录成功后,单击首页中 “注销” 按钮后成功注销。
14.4 后台管理模块¶
后台管理模块主要是对图书的管理,包括图书的查看、图书的添加、图书的修改、图书的删除操作,在首页有一个 “后台管理” 超链接,本项目内并没有涉及权限相关功能,因此该超链接是可以直接单击的,侧重点主要放在功能实现、知识点练习上。
14.4.1 图书列表展示¶
单击首页的 “后台管理” 超链接,将数据库 t_books 表中的图书数据显示在图书列表页面,暂时不考虑分页功能。
(1)创建 Book 实体类,示例代码如下。
(2)修改 index.html 首页中的 “后台管理” 超链接,示例代码如下。
需要注意的是,登录前和登录后对应的
(3)创建 BookServlet 类,并创建 findAll () 方法处理查询图书的请求,示例代码如下。
(4)完善业务层和持久层代码。
创建 BookService 接口,增添 findAll () 方法,示例代码如下。
创建 BookServiceImpl 实现类,实现 BookService 接口的 findAll () 方法,示例代码如下。
创建 BookDao 接口,增添 findAll () 方法,示例代码如下。
创建 BookDaoImpl 实现类,实现 BookDao 接口的 findAll () 方法,示例代码如下。
(5)修改 pages/manager/ 目录下的 book_manager.html 页面,示例代码如下。
运行代码,单击首页的 “后台管理”,如图 14-20 所示,成功实现图书列表展示功能。

14.4.2 添加图书¶
图书列表展示完成后,接下来实现添加图书功能,暂时不考虑图片添加的功能。
(1)修改 book_manager.html 页面的 “添加图书” 超链接,示例代码如下。
(2)在 BookServlet 中创建方法进行新增页面的渲染。
在 BookServlet 的 doPost () 方法中新增一个分支(加粗部分),示例代码如下。
在 BookServlet 中新增 toAddPage () 方法和 add () 方法,处理图书数据的保存请求,示例代码如下。
(3)修改 pages/manager/ 目录下的 book_add.html 页面,设置页面内表单的请求路径,示例代码如下。
(4)完善业务层和持久层代码。
在 BookService 接口中,新增 insert () 添加图书方法,示例代码如下。
在 BookServiceImpl 实现类中实现 insert () 方法,示例代码如下。
在 BookDao 接口中,新增 insert () 添加图书方法,示例代码如下。
在 BookDaoImpl 实现类中实现 insert () 方法,示例代码如下。
运行代码,单击图书管理页面的 “添加图书” 按钮并输入图书信息,如图 14-21 所示,成功添加一条记录,不过输入中文出现了乱码问题。

14.4.3 处理请求和响应中文乱码¶
在添加图书时,如果输入中文会出现乱码问题,可以创建 EncodingFilter 过滤器,处理请求和响应乱码,示例代码如下。
再次运行代码,添加图书信息,如图 14-22 所示,输入中文,无乱码问题。

14.4.4 修改图书¶
修改图书功能是单击修改超链接,跳转至修改页面,页面内显示原始数据,让用户在原始数据的基础上进行修改。修改完成后,用户单击 “保存” 按钮,进行数据的修改。和新增功能一样,暂时不考虑图片添加的功能。具体步骤如下。
(1)完善 “修改” 超链接的请求路径,示例代码如下。
(2)在 BookServlet 中新增代码,跳转到修改页面并展示原始数据。
在 BookServlet 的 doPost () 方法中增加两个分支(加粗部分),示例代码如下。
在 BookServlet 中新增 toEditPage () 方法和 update () 方法,示例代码如下。
(3)修改 pages/manager/ 目录下的 book_edit.html 页面,设置页面中表单的请求路径,示例代码如下。
(4)完善业务层和持久层代码。¶
在 BookService 接口中新增 getById () 方法和 update () 方法,示例代码如下。
在 BookServiceImpl 实现类中,实现 BookService 接口新增方法,示例代码如下。
在 BookDao 接口中,新增 getById () 方法和 update () 方法,示例代码如下。
在 BookDaoImpl 实现类中,实现 BookDao 接口新增方法,示例代码如下。
运行代码,修改前面出现中文乱码的图书,如图 14-23 所示,修改成功。

14.4.5 删除图书¶
删除图书的流程相对简单,单击 “删除” 超链接,将当前图书从数据库中移除即可。具体步骤如下。
(1)修改 “删除” 超链接,示例代码如下。
(2) BookServlet 新增处理删除功能的代码。
在 BookServlet 的 doPost () 方法中新增一个分支(加粗部分),示例代码如下。
在 BookServlet 中实现 delete () 方法,示例代码如下。
(3)完善业务层和持久层代码。
在 BookService 接口中新增 delete () 方法,示例代码如下。
在 BookServiceImpl 实现类中,实现 BookService 接口新增方法,示例代码如下。
在 BookDao 接口中新增 delete () 方法,示例代码如下。
在 BookDaoImpl 实现类中,实现 BookDao 接口新增方法,示例代码如下。
运行代码,单击最后一条图书记录对应的 “删除”,发现删除成功,表示成功实现该删除功能。
14.5 前台图书展示¶
同样在 index.html 首页中,展示数据库中真实的图书信息,接下来修改相关代码实现此功能。
(1)修改 IndexServlet 中的 doPost () 方法,查询图书数据,存放在 HttpServletRequest 请求域内。
(2)在 index.html 页面中,找到 class="list-content" 的
运行代码,查看首页,如图 14-24 所示,成功展示图书信息。

14.6 购物车功能¶
购物车中的数据我们选择存储在 session 中,以达到对 session 进行练习目的。购物车功能我们采用前后端分离的方式实现,也就是使用 Vue 框架发送异步请求。购物车功能包括加入购物车、查看购物车、购物车数量的修改、购物车删除商品、购物车清空,以及结账功能。
14.6.1 准备工作¶
(1)创建 CartItem 类,存储购物项数据,示例代码如下。
(2)创建 Cart 类,存储购物车数据,示例代码如下。
14.6.2 加入购物车¶
在首页单击商品下方的 “加入购物车” 按钮,发送异步请求,完成购物车的添加,具体步骤如下。
(1)修改 index.html 首页相关代码。
在首页中,引入 vue.js 和 axios.min.js 文件,示例代码如下。
在 “加入购物车” 按钮上绑定单击事件,示例代码如下。
并添加 Vue 组件,创建函数发送异步请求,示例代码如下。
(2)创建 CartServlet 类,处理加入购物车请求,示例代码如下。
(3)在 Cart 类中添加 addCart () 方法,将图书加入 Cart 对象的 Map 集合内,并编写代码计算购物车总
数量,示例代码如下。
(4)再次修改首页,右上角的 “购物车” 超链接上的数字显示为实际购物车数量。
注意,登录前后两个位置需要同步修改。然后运行代码,查看首页,如图 14-25 所示。

当前尚未单击 “加入购物车”,右上角显示数量为 0,然后单击 “解忧杂货店” 对应的 “加入购物车” 按钮,如图 14-26 所示,弹出提示框,表明添加成功。

单击 “确定” 按钮后,查看右上角购物车数量,由 0 变为 1,表明数量计算成功,如图 14-27 所示。

14.6.3 查看购物车¶
单击首页上 “购物车” 超链接,跳转至购物车展示页面,利用 Vue 钩子函数发送异步请求到服务器端,获取购物车的相关数据,再通过 Vue 渲染到页面上,具体步骤如下。
(1)修改首页中 “购物车” 超链接的请求路径,示例代码如下。
注意,登录前后两个位置需要同步修改。
(2)修改 CartServlet 类,编写代码处理购物车查看功能。
在 CartServlet 类的 doPost () 方法中新增以下两个分支(加粗部分),示例代码如下。
在 CartServlet 中新增方法,toCartPage () 方法实现去购物车页面;showCart () 方法实现展示购物车信息。示例代码如下。
(3)Cart 类中新增 getTotalAmount () 方法,获取购物车总金额,示例代码如下。
(4)修改 pages/Cart/ 目录下的 cart.html 购物车页面,示例代码如下。
运行代码,单击首页的 “购物车” 超链接,成功跳转购物车页面。如图 14-28 所示,由于尚未添加图
书到购物车,所以数据为空。然后回到首页,添加几本图书到购物车,如图 14-29 所示。


从图 14-29 中可知,添加购物车成功,并成功展示图书信息。
14.6.4 购物车中数量的加减和修改¶
在购物车页面,我们可以对购物项的数量进行增加或减少,也可以直接修改数量。实现思路是在加号 / 减号上绑定 click 事件,在数量的文本框上绑定 change 事件,然后创建对应的函数发送异步请求到服务器端进行数量的改变。具体步骤如下。
(1)修改 cart.html 页面代码。
在该页面,图书所对应的加号 / 减号,以及数量的文本框上绑定事件,示例代码如下。
修改 Vue 代码,在 methods 中创建如下函数,发送异步请求到服务器端,示例代码如下。
(2)修改 CartServlet 类,创建方法处理请求。
在 CartServlet 的 doPost () 方法中新增三个分支(加粗部分),示例代码如下。
在 CartServlet 中新增方法,addCount () 实现增加购物车数量;subCount () 实现减少购物车数量;changeCount () 实现修改购物车数量,示例代码如下。
(3)在 Cart 类中同样新增 addCount ()、subCount ()、changeCount () 方法,示例代码如下。
运行代码,如图 14-30 所示,测试购物车中图书数量的加减和修改,发现总数量和总金额随之改变,表明修改成功。

14.6.5 删除购物项和清空购物车¶
在购物车页面可以单击删除,将当前购物项从购物车中删除,单击清空购物车,将购物车对象直接从 session 中删除即可。具体步骤如下。
(1)修改 cart.html 文件相关代码。
在 “删除” 和 “清空购物车” 超链接上绑定单击事件,示例代码如下。
修改 Vue 代码,创建对应的函数,发送异步请求到 CartServlet,示例代码如下。
(2)在 CartServlet 中新增代码处理删除和清空购物车请求。
在 CartServlet 的 doPost () 方法中新增两个分支(加粗部分),示例代码如下。
并在 CartServlet 中创建 deleteCartItem () 和 clearCart () 两个方法,示例代码如下。
(3)在 Cart 类中同样创建 deleteCartItem () 方法,实现删除购物项操作。
// 删除购物项
运行代码,单击购物车页面的 “删除” 超链接发现对应图书信息被删除,然后单击 “清空购物车” 发现购物车为空。
14.7 结账功能¶
在购物车页面,可以单击 “去结账” 超链接进行订单的创建,由于付款功能没有介绍,所以暂且跳过付款功能,这里只创建订单即可,并且为了减少前端代码,结账功能默认针对购物车中的所有商品,省略选择商品的环节。
14.7.1 准备工作¶
针对订单表 t_order 和订单详情表 t_order_item,创建对应的两个实体类。
创建 Order 订单类,示例代码如下。
创建 OrderItem 订单详情类,示例代码如下。
14.7.2 登录状态检查¶
由于 “结账” 功能和 “我的订单” 功能都需要获取当前登录人的信息,如果不进行登录就单击 “结账” 或 “我的订单”,就会出现异常,因此我们创建一个过滤器,用于检查登录状态,如果处于登录状态就放行,如果不处于登录状态就跳转至登录页面,让用户进行登录。
同时,完善项目页面中涉及显示用户名的头信息,从 session 中获取数据进行展示。示例代码如下。
14.7.3 结账¶
单击 “去结账”,发送请求到服务器端,需要从 session 中获取购物车数据,创建订单项数据和订单数据,以及购物车清空操作。具体步骤如下。
(1)修改 cart.html 页面中 “去结账” 超链接,示例代码如下。
(2)创建 OrderServlet 类,并声明 checkout () 方法处理结账请求,示例代码如下。
(3)完善业务层和持久层代码。¶
创建 OrderService 接口,并声明 checkout () 方法,示例代码如下。
创建 OrderServiceImpl 实现类,实现 OrderService 接口中的方法,示例代码如下。
创建 OrderDao 接口,声明 getId () 和 insert () 方法,示例代码如下。
创建 OrderDaoImpl 实现类,并实现 OrderDao 接口,示例代码如下。
创建 OrderItemDao 接口,声明 insert () 方法,示例代码如下。
创建 OrderItemDaoImpl 实现类,并实现 OrderItemDao 接口,示例代码如下。
(4)修改 checkout.html 结算页面,进行数据渲染,示例代码如下。
运行代码,从首页添加几本图书到购物车,如图 14-31 所示,单击 “去结账” 按钮。

由于当前未登录,所以跳转登录页面,成功实现登录拦截。然后再次回到首页来到购物车,单击 “去结账” 按钮,如图 14-32 所示,生成订单编号。

如果在已登录的状态下,单击 “去结账” 按钮将直接跳转该页面,生成订单编号。
14.7.4 我的订单¶
在登录成功页面和购物车页面都有 “我的订单” 超链接,单击 “我的订单” 将当前账户的订单展示在页面上,具体步骤如下。
(1)修改 “我的订单” 超链接,示例代码如下。
(2)在 OrderServlet 的 doPost () 方法中增加一个分支(加粗部分),示例代码如下。
并在 OrderServlet 类中,创建 showOrder () 方法,示例代码如下。
//1. 获取到当前登录人的 User 对象
//2. 调用业务层处理业务
//3. 给响应
(3) 完善业务层和持久层代码。
在 OrderService 接口中,创建 showOrder () 方法,示例代码如下。
在 OrderServiceImpl 实现类中,实现 OrderService 接口的方法,示例代码如下。
在 OrderDao 接口中,创建 findOrderByUserId () 方法,示例代码如下。
在 OrderDaoImpl 实现类中,实现 OrderDao 接口的方法,示例代码如下。
运行代码,单击 “我的订单” 进入订单页面,如图 14-33 所示。

14.8 本章小结¶
本章主要介绍了尚硅谷书城项目,该项目整合了全书所有的技术知识,功能模块包括用户管理模块、后台管理模块、前台图书展示、购物车功能及结账功能等。通过本章的学习,巩固和提升对 JavaWeb 相关知识的掌握和综合应用,加深对项目的理解和开发能力。

