
简介面向JavaWeb初学者及毕业设计学生这套商品管理系统提供了从用户登录到后台管理的完整闭环。系统涵盖用户注册登录与角色权限区分管理员可维护商品信息、商品分类、库存数量及订单状态用户端支持购物车下单后台还能对销售数据进行统计分析是一个可用于实战的电商管理基础框架。前端采用Vue构建页面后端基于JavaWeb分层实现代码耦合度适中便于二次扩展。资源压缩包共163个文件总体仅3.29MB。其中包含26个Java源码、34个XML配置、12个JS、4个HTML和4个CSS构成的界面资源6个JAR依赖库以及1个SQL数据库脚本同时附带class编译文件与字体文件。文件类型覆盖了编码、配置、样式、脚本、数据导入等完整开发环节。已有1123人学习/下载该资源。其价值在于提供了可运行的增删改查范例结合订单处理、库存更新等业务场景可帮助读者快速掌握JavaWeb项目的分层架构与数据流转逻辑也可作为毕业设计初稿进一步添加促销、轮播等特色模块。 做JavaWeb开发这些年我见过太多新手一上来就问“第一个项目做什么好”我的答案从来没变过做一个商品管理系统。它不花哨、不烧脑但麻雀虽小五脏俱全——登录认证、增删改查、分页搜索、图片上传、打包部署这些Web开发里最核心、最高频的技能点它全都占了。你把这一个项目从头到尾跟完JavaWeb这条线基本就打通了。这篇文章我会从一个完整的项目视角来拆解包含技术选型、数据库设计、核心功能实现、部署发布还有我在实操中踩过的一些坑。这篇内容不是给你贴一堆代码让你去抄而是告诉你每一步为什么要这么做遇到问题该往哪个方向排查。不管你是准备做课程设计、毕业设计还是纯粹想通过项目把JavaWeb串起来这篇文章都值得你跟着走一遍。1. 整体设计与技术选型1.1 为什么还在用 Servlet JSP现在Spring Boot已经成为主流新项目很少再从Servlet JSP起步。但作为教学和课设项目Servlet JSP依然是最好的入门组合没有之一。原因是Spring Boot帮你把Tomcat内嵌了、把请求分发封装了、把依赖管理做好了你写起来很爽但很多底层机制你根本没机会接触。而商品管理系统这种体量正好适合用Servlet JSP把一条请求的完整链路走明白浏览器发起HTTP请求请求到达Tomcat容器容器根据web.xml或注解找到对应的ServletServlet调用Service处理业务逻辑Service再调DAO完成数据库操作最后把结果页面转发或者重定向回浏览器。这个过程你要是亲手用Servlet写一遍你对HTTP协议、请求响应模型、会话机制的理解会彻底不一样。技术栈我建议这么定Servlet 4.0 JSP JSTL MySQL 8.0 Tomcat 9/10 JDBC前端用BootStrap或者纯CSS手写都行不引入复杂框架。这样做的好处是整条链路里的每一个组件你都能看到、能控制排查问题时思路是清晰的。1.2 三层架构与包结构设计既然是练手项目项目结构就必须规范不然代码一多就乱。我习惯把包结构按三层架构来分这也是JavaWeb项目最经典的组织方式。com.example.shop ├── bean // 实体类User、Product ├── dao // 数据访问层UserDao、ProductDao ├── service // 业务逻辑层UserService、ProductService ├── servlet // 控制器层LoginServlet、ProductServlet... ├── filter // 过滤器LoginFilter、EncodingFilter └── util // 工具类DBUtil、PageUtil实体类对应数据库表结构DAO只负责增删改查Service处理业务规则Servlet接收请求、调用Service、控制页面跳转Filter统一处理编码和登录拦截。各层之间单向依赖Controller - Service - DAO不要反向调用也不要出现Servlet里直接拼SQL的情况。这种分层的价值在于你后续想给某个功能加逻辑非常清晰该去哪个类里改。比如你想在删除商品前检查它是否还有库存只需要在Service层加一个判断不用动Servlet和DAO。2. 环境准备与项目搭建2.1 2023版IDEA创建JavaWeb项目的两种方式如果你用的是2023版的IDEA按下New Project的时候会发现以前的Java Enterprise里找“Web Application”选项的路径变了很多教程里的截图已经对不上。这里我给两个亲测可行的方案。方案一推荐直接创建Maven项目然后手动变成Web项目。新建Project时选择Maven不勾选任何骨架archetypeJDK选1.8或者11。创建完之后在src/main下新建webapp目录再在webapp下建WEB-INF目录放一个web.xml。然后改pom.xml打包方式设为warpackagingwar/packaging再补上Servlet、JSP、JSTL、MySQL驱动这几个依赖。配置Tomcat时打开Run - Edit Configurations点加号找到Tomcat Server - Local配置好Tomcat路径后在Deployment页签里把当前项目以/shop为上下文路径部署上去。这个上下文路径就是你以后访问项目的根路径访问首页就是http://localhost:8080/shop/index.jsp。方案二用IDEA的Jakarta EE模板创建。新建Project时选择Jakarta EE勾选Web ApplicationIDEA会帮你生成一个带web.xml的标准Web项目。不过这个方式生成的模板依赖是较新的Jakarta命名空间和传统javax命名空间有区别如果你用的教程是旧版的代码里javax和jakarta混着来会非常痛苦。所以更稳妥的还是自己手搭。2.2 数据库设计与初始化脚本商品管理系统的核心表就两张用户表和商品表。如果你要做订单再加一张订单表和订单明细表但课设项目通常做到商品管理加登录就够了。用户表我建议至少包含这几个字段CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;商品表是核心设计时要考虑实际场景CREATE TABLE t_product ( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100) NOT NULL COMMENT 商品名称, price DECIMAL(10,2) NOT NULL COMMENT 单价单位元, stock INT NOT NULL DEFAULT 0 COMMENT 库存, image VARCHAR(255) DEFAULT NULL COMMENT 图片路径, description TEXT COMMENT 描述, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这里有个小细节价格字段一定要用DECIMAL而不是FLOAT浮点数在计算金额时会出现精度丢失这是经典问题。另外表和字段的字符集统一用utf8mb4不然存emoji或者一些特殊字符会乱码。2.3 JDBC基础封装与连接管理如果你用的是纯JDBC不建议每个DAO里都写一遍Class.forName和getConnection太啰嗦而且连接用完不关会直接把数据库连接池耗尽。最好封装一个DBUtil工具类把连接获取和关闭统一管理。public class DBUtil { private static final String URL jdbc:mysql://localhost:3306/shop?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8; private static final String USER root; private static final String PASSWORD 123456; static { try { Class.forName(com.mysql.cj.jdbc.Driver); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }注意MySQL 8.0以上驱动类名是com.mysql.cj.jdbc.Driver老教程里的com.mysql.jdbc.Driver已经过时了。连接串里的serverTimezoneAsia/Shanghai也不能少否则会报时区错误。如果是学习用途这样写完全够用生产环境得换Druid或HikariCP连接池原理其实一样都是管好连接的创建和复用。3. 核心功能实现与踩坑记录3.1 登录认证与权限拦截登录逻辑本身不难页面提交用户名密码Servlet里查数据库比对成功就把用户信息放进Session失败就回登录页提示错误。但有一个关键点登录成功之后不能只做跳转还得考虑权限控制——也就是不能让用户跳过登录直接访问商品管理页面。实现思路很简单写一个Filter拦截所有/admin/*路径每次请求进来先检查Session里有没有登录标记WebFilter(/admin/*) public class LoginFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; Object user request.getSession().getAttribute(loginUser); if (user null) { response.sendRedirect(request.getContextPath() /login.jsp); } else { chain.doFilter(request, response); } } }这里建议用WebFilter注解省去了web.xml里一堆配置。但要注意2023版IDEA创建项目时如果你选了新模板注解包名是jakarta.servlet而Servlet包版本又可能不一样最容易报“找不到注解”或者ClassNotFoundException排查时先看依赖里实际引入的是javax还是jakarta。3.2 商品列表、条件查询与分页商品列表是系统的门面也是功能最密集的一块。除了把所有商品查出来循环展示通常还要支持按名称模糊搜索和分页。分页的实现逻辑是这样的前端传入当前页码currentPage和每页条数pageSize后端查两次数据库第一次查总记录数算出总页数第二次用LIMIT查当前页的数据SELECT * FROM t_product ORDER BY id DESC LIMIT ?, ?这里第一个问号是偏移量计算方式是(currentPage - 1) * pageSize第二个问号是每页条数。LIMIT的偏移量不能在前端直接拼进去否则就是SQL注入漏洞必须用PreparedStatement的setInt设定参数。这个点是面试常问也是实际项目中容易忽略的地方。我在做分页时遇到过一个小坑用了request.getParameter(page)但如果用户首次进入页面page参数是null直接用Integer.parseInt就会报NumberFormatException。所以一定要做空值判断默认第一页。这个小问题排查了我好一会儿报错信息还不直观。列表页的展示我建议配合JSTL的c:forEach来遍历数据Java代码只在Servlet里写JSP页面里不要出现% %代码块既丑又难维护。逻辑和页面分离之后后续改样式、改展示逻辑都方便很多。3.3 新增、编辑、删除的注意事项新增和编辑可以共用一个表单页面通过URL参数区分是新增还是修改。Servlet里先判断参数里有没有商品ID有就是编辑需要把商品原数据查出来回显到表单没有就是新增提交后执行insert。表单提交过来的数据第一件事是设置编码。在Servlet里POST请求最稳妥的做法是在读取任何参数之前先执行request.setCharacterEncoding(UTF-8);这个代码必须在第一次调用request.getParameter()之前执行否则中文必乱码。我之前在Filter里统一处理编码后来发现某些Servlet里又手动设置了导致重复设置其实没有大问题但为了省心我还是建议写一个EncodingFilter统一处理所有请求的编码这样就不会漏。删除操作有个容易被忽视的点建议用POST方式提交删除请求不要用简单的a hrefdelete?id1。因为GET请求会被浏览器预加载搜索引擎爬虫也可能访问如果误爬删除链接数据就没了。更保险的做法是在页面上用表单包裹点击时弹窗确认。3.4 商品图片上传与回显图片上传是很多课设项目里的加分项但也是坑最多的地方。我用的是Apache的commons-fileupload组件配置很简单但要注意保存路径的问题。很多教程会写用request.getServletContext().getRealPath(/upload)获取上传目录这样项目部署后文件会保存在Tomcat的webapps目录下。但如果你用IDEA开发时Tomcat会以Exploded方式部署项目每次重新构建项目之前上传的图片可能就丢了。这个问题坑了好多人我以为文件丢了其实是项目目录被重新生成上传文件跟着被清理了。后来我改成了把图片保存到服务器固定目录比如Windows下的D:/upload或者Linux下的/data/upload然后通过配置Tomcat的虚拟路径映射来访问。在Tomcat的conf/server.xml的Host标签里加Context path/upload docBaseD:/upload /这样商品图片的URL就是http://localhost:8080/upload/xxx.jpg文件不会因为重新部署而丢失。如果你是发布到生产环境这种方案也更可靠。4. 发布部署与高频问题排查4.1 本地打War包与Tomcat发布项目做得差不多了就要考虑打包发布。Maven项目直接双击package或者命令行执行mvn clean package在target目录下就会生成一个shop.war。把这个war包复制到Tomcat的webapps目录下启动Tomcat它会自动解压并部署。这里有个细节war包的名字决定了访问路径。shop.war对应的是http://localhost:8080/shop/如果你改名叫abc.war访问路径就变成/abc/。有时候我为了先快速验证功能直接改war包名再重启比在IDEA里改配置快很多。启动之后第二件事是看日志。Tomcat的logs目录下有个localhost.log里面是应用启动的详细日志。页面报错时大部分情况下这个日志里已经写清楚了异常堆栈比你在浏览器里盯着那个500页面有用得多。4.2 Windows Server 环境部署要点如果你需要部署到Windows Server上有几个点是客户端环境不会遇到的容易卡住。第一防火墙必须放行8080端口否则服务器本机访问正常外部IP死活访问不了。第二把Tomcat注册成Windows服务比如用service.bat install这样服务器重启后Tomcat能自动启动不用手动去点startup.bat。如果要和Apache共存常见做法是Apache监听80端口处理静态资源动态请求转发给Tomcat。最古老的方案是通过mod_jk走AJP协议集成起来稍复杂。现在更常见的是直接用Apache的mod_proxy做反向代理ProxyPass /shop/ http://localhost:8080/shop/ ProxyPassReverse /shop/ http://localhost:8080/shop/另外Windows Server上部署还要注意JDK环境变量是否配好。Tomcat启动脚本依赖JAVA_HOME如果系统装了多个JDK版本要确认用的是哪个。这些看起来都是小事但实际部署时80%的问题是环境问题不是代码问题。4.3 高频问题排查速查表做JavaWeb项目几乎每个人都会遇到下面这些老问题。我把排查思路整理成一张表遇到问题先照着查一遍能省很多时间。现象可能原因解决方向访问项目路径404上下文路径或war包名不对检查IDEA Deployment配置或看Tomcat webapps下实际解压的目录名页面报500日志有ClassNotFoundException依赖冲突或没打包进去检查Maven依赖里javax/jakarta是否混用清理target后重新package数据库中文乱码连接串编码或表字符集问题连接串加characterEncodingutf8表用utf8mb4驱动加载失败MySQL版本与驱动不匹配MySQL 8.x必须用com.mysql.cj.jdbc.Driver8080端口被占用其他程序占用了Tomcat端口用netstat -ano查占用进程改Tomcat端口或杀掉进程上传的图片重启后消失文件存在项目部署目录被覆盖改存服务器固定目录配置虚拟路径映射Invalid date或时间格式异常数据库时区问题连接串加serverTimezoneAsia/Shanghai这里面我特别想强调第一项。404有相当一部分是IDEA的Artifact配置问题或者war包没成功部署。你去看Tomcat的webapps目录如果看不到解压后的项目文件夹那问题出在部署环节不用在代码里浪费时间。至于端口占用我常用的命令是netstat -ano | findstr 8080查到进程PID后用tasklist /fi pid eq 进程号看是什么程序确认是残留的Java进程就杀掉。这个商品管理系统做完之后你可以继续往上面加功能比如加一个购物车模块把订单关联上用户或者把列表页的图标数量统计做成一个简单的后台仪表盘。每一步扩展都是对现有代码的一次重构练习。我个人做完这个项目最大的体会是报错不可怕真正让你进步的是学会读异常堆栈学会根据现象定位问题所在的那一层。把这次部署中遇到的问题和解决办法记下来下一回再做其他Web项目你会发现自己比预想的要从容得多。本文还有配套的精品资源点击获取