简介:这是一套面向Java Web初学者与课程设计者的花店管理系统完整源码,采用JSP+Servlet+JavaBean的经典架构,适合作为毕业设计、课程大作业或Java Web入门练手项目。压缩包共98个文件,约2.56MB,其中27个java文件承载后台业务逻辑,16个jsp页面负责前台展示与交互,另有9个css、6个js及21张jpg图片用于界面美化,并附带数据库脚本与Eclipse工程配置,导入后即可运行调试。系统覆盖管理员与普通用户双角色,包含登录注册、订单管理、员工管理、用户管理、密码修改等核心模块,目录结构清晰,便于按功能模块阅读与二次开发。目前已有636人学习下载,可作为理解MVC分层、JSP页面跳转与数据库增删改查的实战参考,帮助读者快速搭建可运行的花店管理原型并掌握Java Web项目的基本开发流程。
1. 花店管理系统从源码到跑通:一套 Java 课设的真实落地路径
花店管理系统源码加数据库这套东西,在 Java 课程设计和毕业设计里出现的频率极高。它表面是个“卖花”的增删改查,实际是一套标准的 JavaWeb 分层架构练习:用户登录、鲜花分类、库存管理、订单处理、数据统计,一个都不少。很多人拿到压缩包后卡在第一步——数据库连不上、Tomcat 起不来、页面 404,然后就放弃了。这篇笔记不讲空话,直接按“拿到源码后怎么在本地跑通、每个参数怎么改、哪里最容易翻车”的顺序走一遍。适合正在做 Java 课程设计、需要一套能跑的后端案例、或者想拿它练手 MyBatis 和数据库增删改查的人。读完你能独立完成环境搭建、数据导入、配置修改和基础排错,而不是对着报错发呆。
2. 先看清这套源码的技术栈与目录结构
2.1 典型花店管理系统的分层与依赖
拿到一个 JavaWeb 项目压缩包,别急着导入 IDE。先解压,看根目录有没有pom.xml或lib文件夹,这决定了它是 Maven 项目还是传统 Web 项目。花店管理系统这类课设案例,常见组合是 Servlet + JSP + JDBC,或者 Spring Boot + MyBatis。两种结构的启动方式完全不同,搞错了会浪费一整天。
如果是 Maven 项目,根目录会有pom.xml,依赖写在里面,包括 MySQL 驱动、连接池、JSTL 标签库等。传统项目则会把 jar 包放在WebContent/WEB-INF/lib或web/WEB-INF/lib下。先确认这一点,再决定用 Maven 导入还是手动配置构建路径。
目录结构上,标准分层一般是这样:
src/main/java或src:存放实体类、DAO、Service、Servlet/Controllersrc/main/resources:数据库配置文件、MyBatis 映射文件web或WebContent:JSP 页面、CSS、JS、WEB-INFsql或db:数据库脚本,通常是.sql文件
实体类通常叫Flower、Order、User、Category,DAO 层负责 SQL,Service 层做业务组合,Controller 接收请求。看懂这个分层,后面改代码才知道该动哪个文件。
2.2 数据库脚本里必须确认的四张核心表
数据库脚本是这套源码能不能跑起来的命门。打开.sql文件,先找CREATE TABLE语句,确认这几张表存在:
| 表名 | 作用 | 关键字段 |
|---|---|---|
| user | 登录与权限 | id, username, password, role |
| flower | 鲜花信息 | id, name, price, stock, category_id |
| category | 分类 | id, name |
| orders | 订单 | id, user_id, total, status, create_time |
有些版本还会加order_item做订单明细,或者cart做购物车。字段类型要注意:价格用DECIMAL(10,2),时间用DATETIME,状态用INT或VARCHAR。如果脚本里用了AUTO_INCREMENT,插入数据时不要手动指定主键。
导入数据库的命令很直接:
mysql -u root -p CREATE DATABASE flower_shop DEFAULT CHARACTER SET utf8mb4; USE flower_shop; SOURCE /path/to/flower_shop.sql;utf8mb4是为了支持中文和特殊字符,很多课设脚本默认utf8,遇到 emoji 或生僻字会报错。导入完成后用SHOW TABLES;确认表都建好了,再用SELECT COUNT(*) FROM flower;看有没有初始数据。如果表是空的,登录都进不去,因为用户表没数据。
2.3 用 IDEA 导入项目并配好 JDK 与 Tomcat
导入项目时,Maven 项目直接Open根目录,等依赖下载完。传统项目选Import Module,指定web/WEB-INF/web.xml所在目录。JDK 版本看pom.xml里的maven.compiler.source,常见是 1.8 或 11。JDK 版本不匹配会报Unsupported class file major version,这时候换 JDK 或者改编译级别。
Tomcat 配置在Run/Debug Configurations里加Tomcat Server > Local,指定 Tomcat 安装目录,然后在Deployment标签页加Artifact。如果是 Maven 项目,选war exploded;传统项目选web:war exploded。Application context建议设成/flower,这样访问地址就是http://localhost:8080/flower/。
启动前检查端口占用:
netstat -ano | findstr 8080如果 8080 被占,要么改 Tomcat 端口,要么杀掉占用进程。启动后控制台没有SEVERE级别报错,并且出现Server startup in xxx ms,才算部署成功。
3. 数据库连接与配置文件的参数怎么改
3.1 JDBC 配置文件的四个必改项
数据库配置文件通常叫db.properties、jdbc.properties或application.yml。打开后重点看四个参数:
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/flower_shop?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false jdbc.username=root jdbc.password=你的密码driver这一项,MySQL 8.x 用com.mysql.cj.jdbc.Driver,5.x 用com.mysql.jdbc.Driver。写错了会报ClassNotFoundException。url里的serverTimezone必须加,否则 MySQL 8 会报时区错误。useSSL=false是关掉 SSL 警告,本地开发不需要加密连接。username和password改成你本机 MySQL 的实际账号密码。
如果配置文件里用的是&而不是&,在 XML 里会解析出错,但在.properties文件里直接写&没问题。这一点很多人搞混。
3.2 连接池参数与常见超时设置
如果项目用了 Druid 或 HikariCP,配置文件里还会有连接池参数:
druid.initialSize=5 druid.minIdle=5 druid.maxActive=20 druid.maxWait=60000initialSize是启动时建立的连接数,maxActive是最大连接数。课设项目并发低,maxActive=20足够。maxWait=60000表示获取连接最长等 60 秒,超时会抛GetConnectionTimeoutException。如果启动时报连接池初始化失败,先检查数据库服务有没有启动,再检查用户名密码。
连接池的validationQuery建议设成SELECT 1,这样能自动检测断开的连接。MySQL 默认 8 小时空闲断开,不设这个参数,第二天再跑项目就会报Communications link failure。
3.3 用一条 SQL 验证数据库连通性
配置改完后,别急着启动 Web 项目。先在 IDE 的数据库工具里建连接,或者用命令行跑一条查询:
SELECT u.username, u.role, COUNT(o.id) AS order_count FROM user u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.id, u.username, u.role;这条 SQL 同时验证了三件事:用户表能读、订单表能关联、聚合函数正常。如果报Table 'flower_shop.user' doesn't exist,说明数据库选错了或者脚本没导入完整。如果报Access denied,说明账号密码不对。如果返回空结果但没报错,说明表存在但没数据,需要手动插入一条管理员账号:
INSERT INTO user (username, password, role) VALUES ('admin', '123456', 'admin');密码如果是明文存储,直接写;如果是 MD5,需要先算好哈希值再插入。很多课设源码用明文,方便调试,但实际项目里必须加密。
4. 核心功能模块的代码走读与二次修改
4.1 登录模块:从 Servlet 到 Session 的完整链路
登录是第一个要跑通的功能。典型流程是:JSP 提交表单到LoginServlet,Servlet 调用UserDao.findByUsername(),查到用户后比对密码,成功则把用户信息放进HttpSession,然后重定向到首页。
// LoginServlet.java 核心逻辑 String username = request.getParameter("username"); String password = request.getParameter("password"); User user = userDao.findByUsername(username); if (user != null && user.getPassword().equals(password)) { request.getSession().setAttribute("currentUser", user); response.sendRedirect("index.jsp"); } else { request.setAttribute("msg", "用户名或密码错误"); request.getRequestDispatcher("login.jsp").forward(request, response); }这里要注意sendRedirect和forward的区别:重定向会改变浏览器地址,转发不会。登录成功用重定向,防止刷新重复提交;登录失败用转发,保留错误信息。Session 超时时间在web.xml里配置:
<session-config> <session-timeout>30</session-timeout> </session-config>单位是分钟。课设项目设 30 分钟够用,太长会占内存,太短会频繁掉登录。
4.2 鲜花管理:分页查询与模糊搜索的实现
鲜花列表通常需要分页和搜索。DAO 层写两个方法:countFlowers(keyword)和findFlowers(keyword, page, pageSize)。SQL 用LIMIT做分页:
SELECT * FROM flower WHERE name LIKE CONCAT('%', #{keyword}, '%') ORDER BY id DESC LIMIT #{offset}, #{pageSize}offset = (page - 1) * pageSize。如果搜索关键字为空,LIKE '%%'会匹配所有记录,所以不需要额外写if判断。MyBatis 里用#{}是预编译参数,能防 SQL 注入;用${}是字符串拼接,有注入风险,搜索框千万别用。
分页逻辑在 Service 层算总页数:
int total = flowerDao.countFlowers(keyword); int totalPages = (int) Math.ceil((double) total / pageSize);Math.ceil向上取整,避免最后一页数据被截断。如果总数为 0,totalPages为 0,前端要处理这种情况,显示“暂无数据”。
4.3 订单模块:事务控制与库存扣减的坑
下单是最容易出 bug 的地方。正确流程是:开启事务 → 插入订单 → 插入订单明细 → 扣减库存 → 提交事务。任何一步失败都要回滚。
Connection conn = null; try { conn = DBUtil.getConnection(); conn.setAutoCommit(false); orderDao.insertOrder(conn, order); for (OrderItem item : items) { orderItemDao.insert(conn, item); flowerDao.reduceStock(conn, item.getFlowerId(), item.getQuantity()); } conn.commit(); } catch (Exception e) { conn.rollback(); throw new RuntimeException("下单失败", e); } finally { DBUtil.close(conn); }关键点是所有 DAO 方法必须接收同一个Connection对象,不能用各自从连接池拿的连接,否则事务不生效。库存扣减的 SQL 要加条件:
UPDATE flower SET stock = stock - #{qty} WHERE id = #{id} AND stock >= #{qty}AND stock >= #{qty}防止超卖。如果返回影响行数为 0,说明库存不足,要抛异常触发回滚。这个细节很多课设源码没做,答辩时容易被问住。
4.4 用 MyBatis 映射文件替代手写 JDBC
如果项目用的是 MyBatis,DAO 实现类可以省掉,直接写接口和 XML:
<select id="findByUsername" resultType="com.flower.entity.User"> SELECT * FROM user WHERE username = #{username} </select>接口里定义User findByUsername(String username);,MyBatis 会自动映射。resultType写全限定类名,字段名和属性名不一致时用resultMap手动映射。比如数据库字段create_time对应实体属性createTime,需要开mapUnderscoreToCamelCase或者在resultMap里写<result column="create_time" property="createTime"/>。
MyBatis 配置文件里记得注册映射文件:
<mappers> <mapper resource="mapper/UserMapper.xml"/> <mapper resource="mapper/FlowerMapper.xml"/> </mappers>漏注册会报Invalid bound statement (not found),这个错误排查起来很费时间,因为 IDE 不会提示。
5. 部署上线前必须排查的五个翻车点
5.1 现象:启动报 ClassNotFoundException 原因:驱动 jar 没打进 lib 解决:补依赖
传统 Web 项目最容易出这个问题。IDE 里编译通过了,但 Tomcat 启动时报ClassNotFoundException: com.mysql.cj.jdbc.Driver。原因是 MySQL 驱动 jar 只加到了 IDE 的构建路径,没有复制到WEB-INF/lib目录。Tomcat 运行时只认WEB-INF/lib下的 jar。
解决办法:在 IDEA 的Project Structure > Artifacts里,确认Available Elements中的依赖都双击加到了WEB-INF/lib下。或者手动把 jar 复制进去。Maven 项目一般不会出这个问题,因为mvn package会自动打包依赖。
5.2 现象:页面 404 原因:Application context 配错 解决:核对访问路径
部署成功但访问http://localhost:8080/显示 404,多半是Application context没设或者设错了。在 Tomcat 配置的Deployment标签页,看Application context的值。如果是/flower,访问地址就是http://localhost:8080/flower/login.jsp。如果设成/,就是http://localhost:8080/login.jsp。
还有一种情况是web.xml里welcome-file配的是index.html,但项目里只有index.jsp。改web.xml或者加一个index.html跳转页。
5.3 现象:中文乱码 原因:编码链没统一 解决:三处都设 UTF-8
中文乱码分三种:请求乱码、响应乱码、数据库乱码。请求乱码在 Servlet 里加request.setCharacterEncoding("UTF-8");,必须写在getParameter之前。响应乱码加response.setContentType("text/html;charset=UTF-8");。数据库乱码检查连接 URL 里的characterEncoding=utf8和数据库本身的字符集。
JSP 页面头部也要加:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>三处都设了还乱码,检查 Tomcat 的server.xml里Connector有没有URIEncoding="UTF-8"。老版本 Tomcat 默认 ISO-8859-1,不改会出问题。
5.4 现象:连接池报连接泄漏 原因:DAO 里没关连接 解决:finally 块统一关闭
项目跑一段时间后报Connection leak detection或者Too many connections。原因是某个 DAO 方法里Connection、Statement、ResultSet没关。手写 JDBC 时必须在finally块里依次关闭:
finally { if (rs != null) try { rs.close(); } catch (SQLException e) {} if (ps != null) try { ps.close(); } catch (SQLException e) {} if (conn != null) try { conn.close(); } catch (SQLException e) {} }用连接池时,conn.close()不是真的关闭物理连接,而是归还给池子。不调用close(),连接永远不会归还,池子很快耗尽。用 MyBatis 的话,SqlSession也要在finally里close()。
5.5 现象:修改代码后页面没变化 原因:Tomcat 缓存了旧类 解决:清理并重新部署
改了 Java 代码,重启 Tomcat 后页面还是旧逻辑。原因是 Tomcat 的work目录缓存了编译后的 JSP 和类文件。解决办法:在 Tomcat 配置里勾选On 'Update' action: Update classes and resources,或者手动删除work/Catalina/localhost/项目名目录,然后重新部署。
JSP 修改一般不需要重启,但 Java 类修改必须重新编译部署。IDEA 里按Ctrl+F9重新构建,再点Redeploy。
6. 把这套源码改造成能写进简历的项目
6.1 从课设到简历项目的三个改造方向
直接拿课设源码写简历,面试官一眼就能看出来。想让它有说服力,至少做三个改造。第一,把明文密码改成 BCrypt 加密,登录时用BCrypt.checkpw()比对。第二,给订单模块加状态机,从“待支付”到“已支付”到“已发货”到“已完成”,每个状态变更记录操作日志。第三,把重复的 JDBC 代码抽成BaseDao泛型类,用反射做通用查询。
public <T> List<T> queryList(String sql, Class<T> clazz, Object... params) { // 反射设置属性,通用查询 }这三个改造不需要重写整个项目,但能让面试官看到你懂安全、懂业务、懂抽象。改造完把代码传到代码托管平台,简历里写清楚你改了什么、为什么改。
6.2 用 Postman 做接口自测的固定套路
改造过程中要频繁验证接口。用 Postman 建一个集合,把登录、查询鲜花、下单、取消订单四个接口存进去。登录接口用Tests脚本自动提取 Session:
pm.test("Login success", function() { pm.response.to.have.status(200); pm.response.to.have.jsonBody("code", 0); });下单接口在Pre-request Script里带上 Cookie:
pm.request.headers.add({ key: "Cookie", value: "JSESSIONID=" + pm.globals.get("sessionId") });这样每次改完代码,跑一遍集合就知道有没有破坏原有功能。比手动点页面快得多,也更容易发现回归问题。
6.3 数据库备份与版本迁移的后悔药
改表结构之前一定要备份。用mysqldump导出:
mysqldump -u root -p flower_shop > flower_shop_backup_20250101.sql改坏了直接SOURCE回去。如果项目要长期维护,建议用 Flyway 或 Liquibase 做版本迁移,每次改表写一个 SQL 脚本,按版本号命名,启动时自动执行。课设项目用不上,但面试时提一句“我用 Flyway 管理数据库版本”,比说“我手动改表”高一个档次。
我自己的习惯是:每次动数据库之前先mysqldump,改完再导出一份新的,文件名带日期和改动说明。这个习惯帮我省过至少三次通宵重做的悲剧。花店管理系统这套源码本身不复杂,但把它跑通、改好、讲清楚,足够撑起一个初级 Java 后端的面试话题。希望帮到你。
本文还有配套的精品资源,点击获取