首页 / 资讯中心 / 文章详情

JSP超市管理系统课程设计实战:环境搭建、数据库设计与答辩避坑

JSP超市管理系统课程设计实战:环境搭建、数据库设计与答辩避坑 ★ FEATURED ARTICLE
简介面向JSP与Java Web初学者及课程设计需求这份资源提供一套基于B/S模式的超市管理系统完整源码与数据库。系统采用JSP、Servlet等Java技术在MyEclipse8.5和Tomcat7.0环境下开发数据库使用MySQL5.0功能涵盖职工信息查询与更新、供应商管理、商品销售盘点、进货管理、库存维护、客户密码修改等各模块完整呈现了从页面交互到数据库操作的典型Java Web分层实现页面与业务逻辑代码分离结构清晰便于阅读。资源包仅1.06MB内含可直接导入的源代码、jspsupermarket.sql数据库文件以及初始化脚本修改DBO.java中的连接参数并部署至Tomcat即可运行系统默认管理员账号为admin/admin登录页面完整便于快速体验和二次开发。目前已有1023人学习下载适合用于课程设计、理解B/S架构开发流程也可作为JSP项目的基础框架进行扩展。1. JSP超市管理系统Java Web课设里的“全家桶”项目JSP超市管理系统是Java Web课程设计里出现率最高的一类题目MyEclipse做开发环境Tomcat做运行容器MySQL存数据整个系统是标准的B/S Web结构。代码量不算大却把超市的进销存闭环完整串了起来——用户登录、商品管理、供应商、入库、销售、库存查询。如果你正准备动手写这样一个web项目或者手里有个半成品不知道怎么继续写这篇笔记把从建工程到答辩演示的完整路径讲清楚。为什么这套老技术栈到今天还有人在写因为JSPServletJDBC把Web请求的完整链路暴露在最底层浏览器发请求、Servlet接参数、JDBC连库、JSP渲染。框架把这些都藏起来了而课程设计恰恰需要你亲手搭一遍。做这个项目等于把java基础里的面向对象、集合、异常处理全用了一遍。适合正在准备课程设计答辩的学生也适合刚学完JavaSE想补Web开发第一课的初学者如果你已经有Spring Boot的经验同样值得当“原理解剖”看框架里很多约定在这套老代码里都是显式写出来的。2. 开发环境搭建MyEclipse、Tomcat与MySQL的版本匹配是关键这套项目最容易出问题的不是代码本身而是开发环境版本不匹配导致的玄学报错。我在给多个课设项目排错时发现把环境固定成一套成熟组合后面能省掉一半排查时间。2.1 版本匹配是课程设计的第一道门最省心的组合是JDK 1.8 MyEclipse 2015/2016 Tomcat 8.5 MySQL 5.7。这个组合下数据库驱动用mysql-connector-java 5.x驱动类名是com.mysql.jdbc.Driver运行时几乎不用额外处理连接参数。组件推荐版本注意点JDK1.8MyEclipse对JDK 11以上支持较差容易编译报错MyEclipse2015 / 2016自带Web项目部署管理对老项目最友好Tomcat8.5与JDK 1.8兼容性好稳定无坑MySQL5.7驱动5.x直接可用避开SSL与时区报错mysql-connector-java5.1.49手动拷进WEB-INF/lib别漏为什么不推荐MySQL 8因为新手很容易在驱动类名和serverTimezone参数上翻车。MySQL 8的驱动类名从com.mysql.jdbc.Driver改成了com.mysql.cj.jdbc.DriverURL里还必须追加serverTimezone否则连库直接异常。这个在第5章会单独展开说。MySQL安装时也有一点要注意字符集务必选utf8mb4。安装教程里如果用了默认的latin1建表之后再改库字符集要动的地方非常多中文乱码会一直跟到答辩现场。我在安装向导那一步会直接勾选“Use UTF-8 as default server’s character set”后面所有表默认继承这个字符集少踩一个坑。2.2 在MyEclipse里挂上Tomcat三步把工程跑起来在MyEclipse里部署Web项目核心是把Tomcat注册成运行环境再把项目发布到它上面。具体三步Window - Preferences - Server - Runtime Environments点Add选择Tomcat版本并指定安装目录。在底部Servers视图右键 - New - Server把当前项目Add到右侧列表。右键项目 - Run As - Run On Server浏览器会自动打开http://localhost:8080/项目名。第一步里JRE必须选JDK 1.8的目录不要用默认的JRE否则JSP动态页面编译时会找不到javac报一堆ClassNotFoundException。第二步里项目名建议用全英文比如supermarket不要带中文和空格否则访问URL里会出现转义符。第三步启动后MyEclipse会先把项目编译并发布到Tomcat的webapps目录控制台出现“INFO: Server startup in …”字样才算成功。如果Tomcat默认页能打开但项目404先去看Tomcat安装目录的webapps下有没有生成项目文件夹没有就去Servers视图右键Clean清理再重新Deploy。这是web项目部署的基本排查思路不是黑匣子多走两遍就熟了。2.3 工程结构WebRoot里谁管页面、谁管请求MyEclipse创建的Dynamic Web Project默认目录是WebRoot不是Eclipse里的WebContent。一个标准课设项目的目录结构大致如下supermarket/ ├── src/ │ ├── com/supermarket/servlet/ │ ├── com/supermarket/dao/ │ ├── com/supermarket/entity/ │ └── com/supermarket/util/ ├── WebRoot/ │ ├── css/ │ ├── js/ │ ├── images/ │ ├── login.jsp │ ├── index.jsp │ └── WEB-INF/ │ └── web.xmlsrc下面放Java源码WebRoot是浏览器可以直接访问的根路径。JSP页面放在WebRoot下面CSS和JS也在这里。WEB-INF目录比较特殊浏览器不能直接访问里面的文件所以登录页不要放WEB-INF里除非你想用Servlet转发才能打开。WEB-INF/web.xml是web项目的配置文件欢迎页在这里设置welcome-file-list welcome-filelogin.jsp/welcome-file /welcome-file-list这段配置的意思是访问项目根路径时服务器自动把请求转发到login.jsp所以启动后直接敲http://localhost:8080/supermarket/就能看到登录页。WEB-INF/lib里要放mysql-connector-java.jar和jstl.jarMyEclipse有时候不会自动把外部jar发布到Tomcat部署后要检查一下发布目录的WEB-INF/lib里有没有这些jar没有就手动补。3. MySQL端设计6张表把进销存串成闭环超市管理系统的核心不是商品表而是“进、销、存”三条线。很多课设做成了单表增删改查看起来功能很多但评委一问数据关系就露馅。把表设计成闭环演示时才能讲出完整的故事。3.1 表结构与字段拆解我一般会用6张表来支撑这套系统用户表、供应商表、商品表、库存表、入库单表、销售记录表。每张表的职责如下表名作用关键字段t_user登录用户与角色username, password, rolet_supplier供应商档案name, contact, phonet_goods商品信息goods_name, price, cost_price, supplier_idt_stock商品库存goods_id, quantityt_inbound入库单goods_id, quantity, price, operator_idt_sale销售记录goods_id, quantity, total_price, operator_id把供应商单独建表而不是在商品表里填一个文本字段是为了以后按供应商查进货金额、做报表。销售记录单独建表是为了收银历史可查、库存变动有据可依。这比单纯做增删改查更像一套“系统”也是答辩时能讲出深度的分水岭。角色字段role建议直接存字符串“管理员”或“收银员”课程设计阶段不要引入权限表过度设计反而增加工作量。用户表放管理员和收银员两种角色就够了演示时切换账号能看到不同菜单这就是角色权限的体现。3.2 建表SQL引擎、字符集与金额字段建表的几个关键点直接决定后面会不会返工。用一段SQL说明CREATE DATABASE supermarket_db DEFAULT CHARSET utf8mb4; CREATE TABLE t_goods ( id INT PRIMARY KEY AUTO_INCREMENT, goods_name VARCHAR(64) NOT NULL, category VARCHAR(32), price DECIMAL(10,2) NOT NULL, cost_price DECIMAL(10,2) NOT NULL, supplier_id INT NOT NULL, status TINYINT DEFAULT 1, CONSTRAINT fk_goods_supplier FOREIGN KEY (supplier_id) REFERENCES t_supplier(id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;先说datawarehouse名字supermarket_db字符集直接指定utf8mb4后续所有表都继承这个字符集中文存储不会有问题。价格字段用DECIMAL(10,2)而不是FLOAT因为浮点计算会累积精度误差对账时小数点对不上非常头痛。DECIMAL(10,2)表示整数部分8位、小数部分2位超市场景完全够用。引擎写InnoDB是必须的MyISAM不支持外键也不支持事务。外键约束保证商品引用供应商时供应商不会被随意删除。status字段做逻辑删除默认1表示上架0表示下架这个字段在后面删除商品时非常有用。其他表的字段风格一样数量用INT金额用DECIMAL(10,2)时间字段用DATETIME。如果做生鲜超市需要支持半斤称重可以把quantity改成DECIMAL(8,2)再配合单位字段按业务需要扩展即可。3.3 准备演示数据先供应商后商品顺序别反演示数据是答辩的生命线。INSERT语句的执行顺序必须遵守外键依赖先用户和供应商再商品最后进货和库存。这个顺序反了数据库直接报外键约束失败。INSERT INTO t_user (username, password, realname, role) VALUES (admin, 123456, 系统管理员, 管理员), (cashier, 123456, 收银员01, 收银员); INSERT INTO t_supplier (name, contact, phone) VALUES (本地粮油批发, 王老板, 13800000000); INSERT INTO t_goods (goods_name, category, price, cost_price, supplier_id) VALUES (农夫山泉550ml, 饮料, 2.00, 1.20, 1), (可口可乐500ml, 饮料, 3.50, 2.10, 1); INSERT INTO t_stock (goods_id, quantity) VALUES (1, 100), (2, 80); INSERT INTO t_inbound (goods_id, quantity, price, operator_id) VALUES (1, 100, 1.20, 1), (2, 80, 2.10, 1);这段演示数据的逻辑要顺一遍t_stock里的初始库存和最后一次入库数量保持一致都是100和80避免答辩时被“为什么库存和进货对不上”问住。t_inbound里的price存的是进价1.20t_goods里的price是售价2.00进价和售价的差价就是毛利后面做销售统计时有据可算。外键依赖的顺序问题在数据库设计里非常常见不只是插入受限制删除同样受限制。t_sale和t_stock都引用t_goods的id所以删除商品前必须先清理引用记录这个坑会在第5章详细讲。4. 代码分层与三个必调参数JSP、Servlet、DAO的分工代码结构决定了这个项目是“能跑”还是“能讲”。用传统的JSPServletDAO三层结构每一层职责清晰代码量适中也符合课程设计对java基础的考察要求。4.1 三层架构一个登录请求从浏览器到数据库的路径JSP负责页面展示和表单收集Servlet负责接收参数和页面跳转DAO负责拼SQL访问MySQLentity是JavaBean对应表字段。这个结构就是轻量MVC完整请求路径是这样的浏览器提交登录表单 - Tomcat根据web.xml或注解找到LoginServlet - Servlet调用UserDao操作数据库 - 结果存进request或session - 转发或重定向到JSP页面。登录Servlet的核心逻辑长这样WebServlet(/login) public class LoginServlet extends HttpServlet { private UserDao userDao new UserDao(); protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.setCharacterEncoding(UTF-8); String username req.getParameter(username); String password req.getParameter(password); User user userDao.findByUsernameAndPassword(username, password); if (user ! null) { req.getSession().setAttribute(loginUser, user); resp.sendRedirect(req.getContextPath() /index.jsp); } else { req.setAttribute(error, 用户名或密码错误); req.getRequestDispatcher(/login.jsp).forward(req, resp); } } }这段代码里有几个关键点。登录成功后把User对象放进session后续页面通过session判断用户是否登录、是什么角色失败时用forward而不是sendRedirect因为forward能把error属性带到JSP页面并显示在表单上方。这里用了WebServlet注解就不需要在web.xml里重复配置servlet-mapping了两处都写会重复映射启动时报错。MyEclipse太老的版本不支持注解时再退回web.xml配置。4.2 数据库连接工具类驱动加载与连接参数数据库连接是整套系统的地基。一个精简的连接工具类如下public class DBUtil { private static final String DRIVER com.mysql.jdbc.Driver; private static final String URL jdbc:mysql://localhost:3306/supermarket_db ?useUnicodetruecharacterEncodingutf8; private static final String USER root; private static final String PASSWORD 123456; static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { throw new RuntimeException(找不到MySQL驱动检查WEB-INF/lib, e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } }URL里两个参数最关键useUnicodetrue与characterEncodingutf8作用是让中文参数以UTF-8编码传入数据库和建库时指定的utf8mb4对应。驱动类名com.mysql.jdbc.Driver对应MySQL 5.x的驱动jar如果换成MySQL 8驱动类名要改成com.mysql.cj.jdbc.DriverURL还要追加serverTimezoneAsia/Shanghai和useSSLfalse否则连接直接报时区错误或SSL错误。密码直接写在Java类里只适合课程设计生产环境必须使用配置文件和连接池。这个点经常作为java面试题出现在数据库连接池话题里能答清楚“为什么DriverManager不适合生产”反而能加分。4.3 三个必调参数编码过滤器、事务与分页第一个必调参数是编码过滤器。没有它每个Servlet都要写一遍setCharacterEncoding漏一个就乱码一个页面。定义一个过滤器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里就不再重复写编码设置代码。注意过滤器的url-pattern写“/*”别写成“/”后者只匹配根路径登录请求根本走不到过滤器。第二个必调参数是事务提交。入库操作要同时更新入库单和库存表两步必须一起成功或一起失败。JDBC默认自动提交两条SQL之间一旦第二条失败库存就和入库单对不上。手动控制事务的写法是Connection conn DBUtil.getConnection(); try { conn.setAutoCommit(false); inboundDao.insert(conn, inbound); // 插入入库单 stockDao.increase(conn, goodsId, quantity); // 更新库存 conn.commit(); } catch (Exception e) { conn.rollback(); throw new RuntimeException(入库失败已回滚, e); } finally { conn.setAutoCommit(true); conn.close(); }这里的关键是Connection对象必须从外面传进DAO而不是每个DAO再去DBUtil里拿一个新连接。只有共享同一个连接事务才有效。Spring的Transactional本质就是把这套模板封装起来理解了这段代码框架原理就不再神秘。第三个必调参数是分页。商品列表和销售记录列表都要分页SQL用“LIMIT ?, ?”第一个参数是起始行号第二个是每页条数。在DAO里定义findPage(int pageNo, int pageSize)pageNo由JSP页面传入pageSize在常量类里定义成20。不要在SQL里写死LIMIT 5数据一多就露馅。页面上“上一页/下一页”只是把pageNo加一减一注意pageNo小于1时取1否则查出来是空页。5. 避坑与排查这5个坑让JSP课程设计集体翻车这一章是整个项目里最容易卡住人的地方。每一条都是真实项目里反复出现的问题按“现象 - 原因 - 解决”来看能少走很多弯路。5.1 中文乱码页面、请求、数据库三层都写UTF-8现象登录后首页的欢迎语和商品名显示成“????”或“æ°´”这样的乱码。这是JSP课设里出现率最高的问题没有之一。原因是三层编码不一致JSP页面本身的pageEncoding是GBK浏览器提交参数是UTF-8数据库表又是latin1三层只要有一处不一样最终展示就是乱码。解决思路是统一成UTF-8。JSP头部同时写pageEncodingUTF-8和contentTypetext/html; charsetUTF-8建表时确认DEFAULT CHARSETutf8mb4连接URL带useUnicodetruecharacterEncodingutf8再配上4.3里的编码过滤器。改完要重启Tomcat并重新部署浏览器缓存会让你误以为没改生效。这个问题的排查顺序是从页面到数据库逐层验证不要上来就改代码。5.2 登录请求404Servlet映射与编译产物现象login.jsp能正常打开点登录按钮后地址栏变成/login但页面返回404。原因是web.xml里的servlet-name或url-pattern写错找不到映射或者Servlet类没有编译进WEB-INF/classes目录Tomcat部署的是一个残缺项目。解决时先确认url-pattern是/login而不是/login.jsp再用WebServlet注解时不要在web.xml里重复配置重复映射会启动报错最后检查部署目录下WEB-INF/classes里有没有LoginServlet.class没有就Build Project强制重新编译。我一般会打开浏览器开发者工具看网络标签页404请求的路径和Servlet映射一对比就能定位比瞎猜快得多。5.3 Tomcat启动失败8080端口占用与重复发布现象启动服务时控制台报“Port 8080 required by Tomcat v8.0 Server is already in use”。原因是上一个Tomcat进程没杀干净或者其它程序占用了8080端口。直接在MyEclipse里反复重启没用因为旧进程还挂在系统里。解决方法是打开任务管理器结束java.exe进程或者换端口修改server.xml里的HTTP Connector端口为8081同时shutdown端口也要改成别的值。改完端口后访问地址要跟着变很多同学改完端口还输8080这是不该犯的低级错误。换端口还有一个好处可以同时开两套环境对比测试。5.4 MySQL 8驱动报SSL与时区错误把版本认知对齐现象驱动jar明明放在lib里连接数据库却报“The server time zone value … is unrecognized”或者SSL连接错误。原因是MySQL 8的驱动类和连接参数都变了。老代码里com.mysql.jdbc.Driver这个类在新版驱动中已经移除连带URL也需要追加时区参数。解决方式有两种。不想折腾就直接用MySQL 5.7这是课设最稳的路线坚持MySQL 8就把驱动类名改成com.mysql.cj.jdbc.DriverURL追加serverTimezoneAsia/Shanghai和useSSLfalse。这个问题的根源是MySQL大版本和驱动小版本必须配套别只看“驱动能加载”就以为能连上库。5.5 删除商品外键约束失败先清引用再删主表现象在商品管理里点删除控制台报“Cannot delete or update a parent row: a foreign key constraint fails”。原因是t_stock或t_sale里有记录引用商品id外键的RESTRICT行为阻止了删除。解决时要按依赖顺序清理先删除子表记录再删商品主表。SQL顺序是DELETE FROM t_stock WHERE goods_id1然后清理t_sale和t_inbound里的关联记录最后DELETE FROM t_goods WHERE id1。但要注意如果销售记录有保留价值就不要物理删除商品而是在t_goods里把status字段改成0代表下架列表只查status1。这就是前面建表时设计status字段的真正用途很多答辩现场就是在这个操作上翻车的。6. 验收与答辩把演示流程跑通比堆功能更要紧功能做得再多演示时逻辑对不上评委的追问就会越来越多。我的习惯是先准备一套完整的演示剧本再考虑加功能。6.1 一组能自圆其说的演示数据把演示顺序定成管理员登录 - 建供应商 - 建商品 - 做一笔入库 - 切换收银员 - 卖出3瓶水 - 回查库存和销售记录。每一步的数据变化要能对上账库存100卖3剩余97销售额是3乘以售价2元等于6元毛利是3乘以售价减进价即0.8元等于2.4元。这个口算能算清楚比多写十个按钮更能说服评委因为这套数字证明业务逻辑是通的。6.2 把项目导出成war包右键项目 - Export - WAR file选择导出目录MyEclipse会打包整个WebRoot和src下的源码。很多同学问“MyEclipse怎么打包成exe可执行文件”方向从一开始就错了web项目最后交付的是war包不是exe。war包丢进Tomcat的webapps目录会自动解压部署这才是web结构的标准交付方式。导出后可以用命令检查一下内容jar tf supermarket.war看到WEB-INF/classes下编译好的.class、web.xml和所有jsp都齐全就可以拷到另一台机器演示了。部署后的访问路径可能是http://localhost:8080/supermarket/和MyEclipse里Run On Server的路径会有差别提前确认。6.3 答辩时先讲清楚三条线数据线登录表单怎么从JSP走到Servlet再到DAO最后落到MySQL查询结果又怎么回到JSP页面展示状态线session怎么保存登录态库存数量怎么随入库和销售变化角色线管理员和收银员分别看到哪些菜单、能操作哪些功能。我的经验是拿一张A4纸写演示脚本每个操作对应哪张表、改哪个字段评委问任何一个数字都能答上来。演示前把脚本完整跑三遍尤其是中文乱码和库存对账这两条跑顺了心里就有底。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站