☰
JavaWeb课设实战:JSP+Servlet购物系统导入部署与答辩指南
2026/10/7 10:40:37 网站建设 项目流程

简介:这份JavaWeb期末课程设计资源基于JSP+Servlet与MySQL构建网上在线购物系统,主要面向计算机相关专业需要提交期末作业或进行课程实践的学生。项目涵盖用户注册登录、商品分类展示、购物车管理、订单结算、后台商品维护等典型电商模块,代码采用MyEclipse工程组织,导入后即可运行。压缩包共2000个文件,前端以484个HTML、436个CSS、342个JS为主,服务端由JSP页面、Java源文件与class文件构成,另含SQL脚本、XML配置及JAR包,整体约33.8MB,目录结构清晰便于检索。当前已有99人学习下载,资源拿来即用,只需将课程报告中的学号姓名等信息稍作修改即可提交,代码无需改动。从登录验证、购物车增删到订单生成,可逐步对照Controller类与JSP页面理解Servlet的请求处理、转发跳转及MySQL交互写法,既能快速完成课设,也能巩固JavaWeb核心开发技能。

1. 期末课设拿到JSP+Servlet购物系统:先搞清楚你手里是什么

JavaWeb期末课程设计(JSP+Servlet)(mysql)-网上在线购物系统SSM+MyEclipse.rar这个标题读起来绕,是因为它在同一行里混了两代技术写法:JSP+Servlet 是传统的两层 Web 开发方式,而 SSM 是 Spring + SpringMVC + MyBatis 的组合。这个矛盾就是你的第一个坑——你手里的包大概率是 JSP + Servlet + JDBC 写的传统架构,SSM 三个字母是卖家或同学写上去的关键词。本篇笔记要解决的问题很直接:把这份 .rar 里的工程导进 MyEclipse 跑起来、看懂购物系统的表结构和请求链路、改出一两个能应付答辩的功能点,然后把老师可能问的问题提前堵住。读者就是正在做 JavaWeb 课设、手里有一个打不开或跑不动的购物系统、且两周内要交的学生。

2. 网上在线购物系统的技术构图:目录、架构与三层边界

2.1 先看目录结构:用tree命令识别项目骨架

拿到 .rar 解压之后,先别急着 double click 导入 IDE,按下面这个命令看一眼工程根目录长什么样:

tree /F # Windows 下递归列出文件;Mac/Linux 去掉 /F,用 find . -type f 效果类似

一个典型的 JSP+Servlet+MySQL 课设购物系统,目录结构基本长这样:

src com.xxx.entity -- User.java, Goods.java, CartItem.java 等数据类 com.xxx.dao -- UserDao.java, GoodsDao.java,直连 JDBC com.xxx.service -- UserService.java, GoodsService.java,业务逻辑 com.xxx.servlet -- LoginServlet.java, CartServlet.java, OrderServlet.java com.xxx.util -- DBUtil.java / JdbcUtil.java,只有一个工具类管连接 db.properties -- 数据库连接配置文件 WebRoot WEB-INF web.xml -- 项目部署描述符,3.0 规范以下全靠它配 Servlet lib -- mysql-connector-java-5.1.47.jar 一般在这里 index.jsp login.jsp register.jsp cart.jsp goods_list.jsp goods_detail.jsp order_confirm.jsp

看这个结构,你要先回答一个问题:这是JSP -> Servlet -> Service -> DAO -> MySQL的经典链路,还是 Spring 容器管的SpringMVC -> Controller -> Service -> MyBatis?区别方法非常简单:打开WEB-INF/lib看有没有 spring-webmvc、mybatis 这类 jar 包;再打开 web.xml 看有没有ContextLoaderListener或一堆<servlet>标签。有 Spring 相关的 jar 才是 SSM,只有<servlet>和<servlet-mapping>就是纯 JSP+Servlet。

2.2 JSP+Servlet 与 SSM 的分叉点:Spring 容器到底给你带来了什么

很多课设项目的题目里写着 SSM,实际代码却是 Servlet 里直接new UserService(),Service 里自己DriverManager.getConnection()。这不算造假,因为很多机房电脑、老教材、教学视频就是这套两代混着的写法。但如果答辩老师较真,你要能说清楚两者的核心区别:JSP+Servlet 时代,你通过@WebServlet或 web.xml 手动管理 URL 映射;SSM 时代,SpringMVC 的@Controller加@RequestMapping注解帮你把请求分发这件事干了,@Autowired又帮你把对象的创建和注入接管了。

// SSM 中常见的三层写法:注解替代了 web.xml 和 new 对象 @Controller @RequestMapping("/user") public class UserController { @Autowired private UserService userService; // Spring 容器注入,不需要 new @RequestMapping("/login") public String login(String username, String password, HttpSession session) { User user = userService.login(username, password); session.setAttribute("loginUser", user); return "redirect:/index.jsp"; } }

这段代码不用照抄进你的课设,而是用来对照。你的项目如果没引入 Spring 依赖,写@Autowired会直接编译失败,所以别一上来就把两种架构混在一起改。理解这个分叉点的价值在于:答辩时老师问“你这个项目是 SSM 吗”,你至少能诚实地说“我的课程设计基于 JSP+Servlet 实现,按 Servlet/Service/DAO 三层组织,在标题中提及 SSM 是因为分层思想与 SSM 一致”。这是一个可以救命的回答模板。

2.3 为什么课设也要分层:一个购物系统的三层边界

我见过太多同学把 SQL 写在 Servlet 里,最后整个项目只有两个文件:index.jsp和conn.jsp(页面上直接建连接)。这种写法不是不能交,而是无法扩展,答辩时也讲不出东西。常见做法是坚持把项目按三层职责切开:Servlet 只接收参数和返回页面,Service 只做拼装逻辑(比如下单时先查库存再扣库存),DAO 只执行 SQL。每层之间通过实体类传值,例如User、Goods、CartItem。

// Service 层的一个典型方法:参与事务的代码放在业务层,而不是 DAO public boolean submitOrder(int userId, int goodsId, int buyNum) { conn = DBUtil.getConnection(); try { conn.setAutoCommit(false); // 关闭自动提交,保证两条 SQL 在同一事务里 orderDao.insertOrder(conn, userId, goodsId, buyNum); goodsDao.deductStock(conn, goodsId, buyNum); conn.commit(); // 减库存失败则抛异常回滚 return true; } catch (Exception e) { conn.rollback(); return false; } finally { DBUtil.closeAll(conn, null, null); } }

这个方法的逻辑说明:setAutoCommit(false)是关键,网上购物系统最容易出的一类 bug 是“订单生成了但库存没减”,不关事务就会出现这种半成品数据。参数上,buyNum是你页面提交的数量,deductStock里的 SQL 建议写成UPDATE goods SET stock = stock - ? WHERE id = ? AND stock >= ?,这样数据库在更新时自己会做一次库存保护,比先查再更新更安全。

3. 在 MyEclipse 里把项目跑起来:JDK、Tomcat、MySQL 的铁三角

3.1 本地环境版本怎么配:这组组合最稳

JavaWeb 课设项目对环境最敏感。我在帮别人看这种购物系统的时候,第一句话永远是:先对版本,再看代码。最不会翻车的一组组合是MyEclipse 2017/2019 + JDK 1.8 + 内置 Tomcat 8.x + MySQL 5.7.44 + mysql-connector-java-5.1.47.jar。MySQL 5.7.44 是目前课设里最省心的版本,原因有两点:一是它的驱动类名还是com.mysql.jdbc.Driver,和老代码完全匹配;二是没有 MySQL 8.0 那套serverTimezone时区强制要求。如果你的电脑装的 MySQL 8.0,那db.properties里的驱动类名要换成com.mysql.cj.jdbc.Driver,URL 后面追加?serverTimezone=Asia/Shanghai&useSSL=false,否则启动必报时区错误。

// 驱动类名的两种写法,注意版本对应,写反了直接 ClassNotFoundException Class.forName("com.mysql.jdbc.Driver"); // MySQL 5.x 及更早的写法 Class.forName("com.mysql.cj.jdbc.Driver"); // MySQL 8.x 必须用这个新类名

这个选择背后有个现实原因:很多同学用 MySQL 8.0 安装教程装完后,项目里 jar 包还是 5.x 的,类名对不上,一启动就翻车。如果课程设计本身没有强制用 MySQL 8,我建议你直接装 MySQL 5.7.44,能少踩一半的坑。如果已经装好 8.0,那就老老实实把 URL 后面加时区和关闭 SSL 的参数,同时把 jar 换成 8.x 的版本,这两个参数缺一不可。

3.2 数据库导入与连接配置:db.properties 逐项拆开讲

购物系统都带一个 sql 脚本,通常在项目根目录或数据库文件夹下,找到后先导入 MySQL。不要双击 excel 那样打开 sql 文件,建议在命令行里执行:

mysql -uroot -p123456 < D:/shopping.sql # 参数说明:-u 指定用户 root,-p 后直接跟密码 123456(无空格) # 也可以先登录 mysql,再执行 source D:/shopping.sql,效果一样

导入完成后,打开src/db.properties,这是整个项目唯一需要你手动改的连接配置:

jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/shopping?characterEncoding=utf-8 jdbc.username=root jdbc.password=123456

逐个解释这四个参数:jdbc.driver是驱动类名,取决于你 lib 里 jar 包的版本;jdbc.url里shopping是数据库名,要和 sql 文件建库时的名字一致,characterEncoding=utf-8解决中文乱码问题;jdbc.username和jdbc.password是你 MySQL 自己的账号密码,很多课设代码默认写root/root,你按自己的实际情况改。另外,注意看DBUtil.java里读配置文件的方式,常见做法是Properties.load(类名.class.getClassLoader().getResourceAsStream("db.properties")),这意味着db.properties必须在src下,放错位置就报空指针。

3.3 在 MyEclipse 中部署到 Tomcat 的 7 个步骤

如果是已经交付过多次的项目,部署姿势基本固定。我一般按这个顺序操作,每一步做完都重启一次 Tomcat,不要攒到最后一起验证:

第一,File -> Import -> General -> Existing Projects into Workspace,选择解压后的项目根目录,注意勾选Search for nested projects。第二,右键项目Properties -> Java Compiler,把编译级别改为 1.8,和你的 JDK 对应。第三,Properties -> Project Facets,确认Dynamic Web Module版本是 3.0 或 2.5,版本太高会报cannot be set。第四,把WebRoot或WebContent设为 web 根目录。第五,Window -> Preferences -> Tomcat,配置你的 Tomcat 8.x 的安装目录。第六,右键项目Run As -> MyEclipse Server Application,选 Tomcat 启动。第七,启动后控制台会打印Mapped URL或部署路径,打开浏览器访问http://localhost:8080/项目名/。

这里你要重点检查的是第五步和第六步。很多项目一到Run As菜单里没有MyEclipse Server Application,那是因为Project Facets没勾对,Dynamic Web Module没打开。右键项目的Properties -> Targeted Runtimes里把 Tomcat 勾上,这个菜单才会出现。这个操作在答辩前一定要自己走通一遍,因为机房电脑的环境往往比你自己电脑更老。

3.4 表结构:先读懂购物系统的五张核心表

购物系统换一百个名字,表结构都逃不出这五张表。打开 sql 脚本,找到建表语句,对照下面这张清单确认你的项目有哪些表:

表名(常见命名)核心字段备注
user / t_userid, username, password, nickname, phone用户表,密码建议在 insert 时就存 MD5 后的值
goods / productid, goods_name, price, stock, img_url, description商品表,注意 stock 不能为负数
cart_itemid, user_id, goods_id, buy_num购物车明细表,很多课设把购物车放进 session 就不建这张表
orders / order_infoid, user_id, total_price, create_time, status订单主表,status 可用 0 未支付 1 已支付 2 已发货
order_itemid, order_id, goods_id, buy_num, price订单明细表,保存下单时的商品快照

为什么要先看表结构?因为如果你要继续在别人的项目上加功能,最常改的就是表和对应 DAO。比如想加一个“收货地址”字段,你要在 user 表加一个address字段,然后在User.java加属性、在UserDao.java改insert和select语句、在register.jsp加输入框,一条线贯穿三层。这一章把表看明白,后面喊你改代码就不会手忙脚乱。

4. 五分钟学会改功能:登录、购物车、个人信息页面的串联改造

4.1 登录模块的请求链:LoginServlet 是怎么一步步处理表单的

登录是购物系统最基本也最爱在答辩时被问的模块。打开LoginServlet.java,正常课设项目的写法长这样:

@WebServlet("/loginServlet") public class LoginServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); // 1. 处理 POST 请求中文乱码 String username = request.getParameter("username"); String password = request.getParameter("password"); UserService userService = new UserService(); User user = userService.login(username, password); // 2. 业务方法返回 User 或 null if (user == null) { request.setAttribute("msg", "用户名或密码错误"); request.getRequestDispatcher("/login.jsp").forward(request, response); } else { HttpSession session = request.getSession(); session.setAttribute("loginUser", user); // 3. 关键一步:把用户放进 session response.sendRedirect(request.getContextPath() + "/index.jsp"); } } }

逻辑说明:第一步的setCharacterEncoding("UTF-8")必须放在读参数之前,否则request.getParameter拿到的是乱码。第二步userService.login内部一般调用UserDao.findByUsername(username),再用返回的 user 对象比对密码,你可以改成用MD5加密后再比对,这是一个非常容易被答辩老师认可的改动点。第三步把 user 放进 session,后续所有页面通过${loginUser.nickName}直接展示用户名,靠的就是这个对象。forward与sendRedirect的区别你必须能讲:forward 是请求转发,浏览器 URL 不变、跳转发生在服务端;sendRedirect 是重定向,浏览器重新发起一次请求,URL 会变成目标地址。登录成功用重定向,避免刷新页面时重复提交表单。

4.2 购物车加减购:只用 Session 就能实现的最小方案

很多课设没有购物车表,直接把数据放在 session 里,这是最简单的实现,也足以支撑答辩。核心代码在CartServlet.java:

@WebServlet("/cartServlet") public class CartServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); Map<Integer, Integer> cart = (Map<Integer, Integer>) session.getAttribute("cart"); if (cart == null) { cart = new HashMap<>(); // key 是商品 id,value 是购买数量 session.setAttribute("cart", cart); } String op = request.getParameter("op"); int goodsId = Integer.parseInt(request.getParameter("goodsId")); if ("add".equals(op)) { cart.put(goodsId, cart.getOrDefault(goodsId, 0) + 1); } else if ("remove".equals(op)) { cart.remove(goodsId); } else if ("clear".equals(op)) { cart.clear(); } else if ("changeNum".equals(op)) { int num = Integer.parseInt(request.getParameter("num")); cart.put(goodsId, num); // 页面传来的新数量直接覆盖 } response.sendRedirect(request.getContextPath() + "/cart.jsp"); } }

这段代码里有两个容易忽略的地方。Map<Integer, Integer>的购物车有个天然问题:它不区分过期时间和用户,只认 session,用户关掉浏览器购物车就没了,这是 session 方案的白板缺陷,你在答辩时如实说“这是基于 session 的临时购物车,真实项目会落到数据库表”,反而显得你清楚技术边界。getOrDefault是 Java 8 以后才有的方法,如果你在 JDK 1.7 的环境下编译这段代码会报错,服务器端编译级别低于 1.8 时请换成cart.containsKey(goodsId) ? cart.get(goodsId) : 0的三目写法。

4.3 个人信息展示页面:用 EL 表达式替换掉又长又丑的 Java 代码

课设里一定会有一个userInfo.jsp个人中心页面,很多同学的写法是<% %>里面 Java 和 HTML 混排,看得老师头皮发麻。改造成本极低,把业务代码删掉,只留 EL 表达式:

<%-- 如果登录时设置了 session.setAttribute("loginUser", user),EL 可以直接取 --%> <div class="user-card"> <p>昵称:${loginUser.nickName}</p> <p>手机号:${loginUser.phone}</p> <p>注册时间:<fmt:formatDate value="${loginUser.regTime}" pattern="yyyy-MM-dd" /></p> </div> <div class="avatar-area"> <%-- jsp 图片定位常见做法:外层 div 设置 position:relative,图片用绝对定位控制偏移 --%> <div class="avatar-box" style="position:relative; width:100px; height:100px;"> <img src="upload/${loginUser.avatar}" alt="头像" style="position:absolute; left:10px; top:10px; width:80px; height:80px; border-radius:50%;" /> </div> </div>

这里要注意两点。第一,fmt:formatDate需要引入 JSTL 标签库,在 jsp 顶部写<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>,如果项目 lib 里没有jstl.jar和standard.jar,就去下载放进WEB-INF/lib,否则页面上这个标签会直接报错。第二,EL 表达式取不到值时页面会显示空字符串,不会报错,所以如果图片路径显示不出来,先检查upload/目录是否存在,再检查loginUser.avatar是否真的存了文件名。图片坐标定位那个坑我见过太多次:本地图片能显示,部署到机房电脑上就裂了,十有八九是路径里用了绝对盘符,改成相对路径上传目录是最稳妥的。

5. 避坑:运行这种课设项目最常见的 5 个翻车点

5.1 现象:8080 端口被占用,Tomcat 启动报 Address already in use

原因:你机器上某程序(常见是另一个 Tomcat、Oracle、或者别的开发工具)抢先占用了 8080。解决:先看是谁占的端口,再决定杀掉进程还是改 Tomcat 端口。

netstat -ano | findstr 8080 taskkill /PID 12345 /F # 不想杀进程就改 Tomcat 端口:在 server.xml 中把 <Connector port="8080"> 改成 8088

改端口后访问地址要跟着变:http://localhost:8088/项目名/。这个坑几乎每次答辩前都会发生在机房电脑上,因为机房很多机器装了多个版本 Tomcat 或者有后台服务占用 8080,提前确认这条能省五分钟。

5.2 现象:页面所有中文变成问号,或者登录提交后用户名乱码

原因分三种:JSP 文件本身的编码不是 UTF-8;POST 请求没设置request.setCharacterEncoding("UTF-8");GET 请求在 Tomcat 8 以下版本默认 ISO-8859-1。最省心的解决方式是写一个过滤器统一处理,这段代码可以直接抄:

@WebFilter("/*") public class EncodingFilter implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { req.setCharacterEncoding("UTF-8"); resp.setCharacterEncoding("UTF-8"); chain.doFilter(req, resp); // 放行到目标 Servlet/JSP } }

加了过滤器之后,登录 Servlet 里那行setCharacterEncoding留着也不会冲突。检查每个 JSP 头部是不是都有<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>。用记事本打开 jsp 文件另存为时如果编码不对,也会导致中文乱码,这一步是纯玄学级别的坑,排查顺序永远是:JSP 编码 -> 过滤器 -> MySQL 连接 URL。

5.3 现象:启动项目后第一次访问数据库就抛 ClassNotFoundException: com.mysql.jdbc.Driver

原因:WEB-INF/lib里根本没有 mysql 驱动 jar,或者驱动版本与类名不匹配。解决:下载mysql-connector-java-5.1.47.jar放进WEB-INF/lib,然后右键项目Properties -> Java Build Path -> Libraries -> Add JARs把它加进去。如果你用的是 MySQL 8.0,把驱动类名改成com.mysql.cj.jdbc.Driver,同时换用 8.x 的驱动 jar。很多同学把 jar 放进 lib 就以为完事了,结果 Build Path 里没有勾选,Tomcat 部署时还是没有这个类,注意这个细节。

5.4 现象:数据库连接时报 Communications link failure 或 Access denied for user

原因:前者通常是 MySQL 服务没启动,或者 URL 里的数据库名写错;后者是用户名密码不对。解决:先确认 MySQL 服务启动了没有,Windows 下Win + R输入services.msc,找到 MySQL 服务右键启动;再确认db.properties里的账号密码和本地 MySQL 一致,命令行mysql -uroot -p你的密码能进去才行。还有一个坑:MySQL 5.7 默认密码加密方式是mysql_native_password,而 8.0 默认caching_sha2_password,老驱动连 8.0 会报Unable to load authentication plugin,需要给连接加上校验方式或者换驱动,这个属于 MySQL 版本压迫你升级配置的场景,尽量按 3.1 节的组合来避免。

5.5 现象:导入项目后满屏红叉,右键没有 Run As Server 选项

原因:项目里的 JDK 编译级别和你本地不一致,或 Dynamic Web Module 版本号冲突。解决:右键项目Properties -> Targeted Runtimes,勾选你配好的 Tomcat 版本;再检查Properties -> Java Compiler是否勾了Enable project specific settings且版本为 1.8;最后到Project Facets里把 Java 版本调成 1.8、Dynamic Web Module 调到 3.0,改完保存后项目会自动重新编译。如果红叉还在,打开Problems窗口看具体错误,绝大多数是一个个 jar 引用不到的报错,右键Build Path -> Configure Build Path修复即可。这五个坑几乎能覆盖课设项目运行期 90% 的问题,剩下 10% 是 Tomcat 部署路径和 JDK 版本这种磁盘级问题,通常重开一次 IDE 就好。

6. 答辩前把项目“讲明白”:一份可当场的演示验证清单

答辩这种事,项目烂不烂不是最重要的,能不能讲清楚才是。我建议你提前压一遍这条演示动线:先注册一个新用户,再登录,然后选两件商品加购物车,改一下数量,下单后去订单列表页看结果。走完这一步,你嘴里要能脱口而出这条链路里的每个请求去了哪个 Servlet、哪一步用了 forward 哪一步用了 redirect、userId 和 goodsId 在参数里是怎么传的。如果老师问“购物车数据存在哪里”,你就说存在 session 里,并补一句“生产环境会用 Redis 或购物车表持久化”——这句话就够表明你思考过技术边界。

如果你是拿别人的项目改的,答辩前必须动手改一个小点,否则很容易被拆穿。改动成本最低的几个方案:注册页面加一个 AJAX 校验用户名是否重复;登录密码加密后入库;商品列表页按价格排序。任何一个都能让你在“你做了哪些工作”这个问题上站得住脚。另外现在很多同学的电脑只有 IDEA,没有 MyEclipse,我遇到过 IDEA 环境跑 MyEclipse 项目跑不起来的案例,正确姿势是:导入时选择 Eclipse 项目选项,然后在Project Structure -> Artifacts里新建Web Application: Exploded,Artifact 里加入 lib 依赖,再配置 Tomcat 后重新部署。版本兼容问题这里就不展开了,我的建议是答辩前一周就要在自己的电脑上用和学校机房一致的软件组合跑通一遍。

最后说我自己的血泪经验:当年课设答辩,我把登录模块背得滚瓜烂熟,结果老师打开我的项目点了一下“商品详情页的图片”,图片裂了,那一刻我花了三十秒才反应过来是图片相对路径的问题。从那以后我做任何课设,都会先检查静态资源路径和数据库连接配置,再用浏览器逐页点一遍。这份清单不是让你背的,是让你照着做一遍,做完你会发现面前这台电脑上的项目,你已经知道你改过哪一行、为什么改,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询