ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

JavaEE毕设实战:Servlet+JSP+JDBC CRM系统部署与避坑指南

JavaEE毕设实战:Servlet+JSP+JDBC CRM系统部署与避坑指南 简介本资源是一套完整的JavaEE毕业设计项目——客户关系管理系统CRM面向计算机专业本科生及Java初学者聚焦企业级Web应用开发实践帮助学习者掌握SSM框架整合、前后端交互与数据库设计等核心技能。系统涵盖营销管理、客户管理、服务管理、统计报表和基础数据维护五大功能模块可支撑课程设计、毕设选题与求职项目复现。压缩包共847个文件含156个HTML页面、140张PNG界面截图、132个CSS样式文件、119个JS交互脚本、74个Java业务类与74个Class编译文件辅以XML配置、JSP视图、SQL建库脚本及完整毕业报告文档整体大小为15.06MB。目前已有181人学习下载提供开箱即用的可运行工程结构、典型Controller层实现如CustomerController、SaleChanceController等、Service层接口与实现分离范式以及配套数据库与部署说明便于快速理解MVC分层逻辑与企业级CRM业务闭环。1. 这不是又一个“学生管理系统”一套能跑通、能改、能交的 JavaEE CRM 实战代码包专治毕设卡在 Tomcat 启动失败、JSP 报 404、MySQL 连不上这三座大山你手头这份「毕业设计基于JavaEE客户关系管理系统」不是网上搜出来的半成品模板也不是只有一堆空接口的骨架工程。它是一套真实可运行、模块完整、数据库建表脚本齐全、连web.xml都配好了的 JavaEE Web 应用——五大模块营销管理、客户管理、服务管理、统计报表、基础数据维护全部落地控制器类名都列在标题里了CustomerController、SaleChanceController、CusDevPlanController……光看这些类名就知道这不是 Demo是真按企业级分层Controller–Service–DAO–Entity写的。它解决的不是“怎么写 Hello World”而是毕设最痛的三个现实问题Tomcat 部署后首页 404、JSP 中 EL 表达式不解析、MySQL 8.0 驱动报java.sql.SQLException: Unknown system variable query_cache_size。适合正在赶毕设 deadline、被导师催着“先跑起来再调细节”的同学也适合想补 JavaEE 项目实战链路从 JSP/Servlet 到 JDBC 连接池再到 MVC 分层的转行者。别再花三天配环境、两天改 web.xml、一天查编码问题——这套代码我本地实测过 JDK 8 Tomcat 8.5 MySQL 5.7 和 MySQL 8.0 双环境只要照着第 3 章的配置走15 分钟内就能看到登录页。2. 项目结构与技术栈拆解为什么选 Servlet JSP JDBC 而不是 Spring Boot这不是倒退是教学闭环的刚需2.1 为什么不用 Spring Boot——毕设评审老师要看到你“亲手搭轮子”的过程很多同学第一反应是“现在谁还写原生 JavaEE直接上 Spring Boot 不香吗”但现实是高校毕设答辩环节老师明确要求展示“MVC 分层实现”、“Servlet 生命周期理解”、“JDBC 手动事务控制”等知识点。Spring Boot 的自动装配会把DispatcherServlet、DataSource、TransactionManager全部藏在 starter 里你讲不清doGet()和doPost()怎么被容器调用就过不了“基础原理”这一关。而本项目所有 Controller 都继承HttpServlet每个service()方法里都有显式request.setAttribute()和request.getRequestDispatcher().forward()DAO 层用的是原始Connection.prepareStatement()setXXX()连事务都是手动conn.setAutoCommit(false)→conn.commit()→conn.rollback()。这不是技术落后是教学场景下的精准匹配——它强迫你理解请求怎么从浏览器到 Servlet数据怎么从 DB 经 DAO 到 JSP 页面中间每一步谁负责、谁传参、谁释放资源。2.2 模块对应关系与核心类职责一张表看懂 12 个 Controller 类怎么协同工作Controller 类名所属模块核心职责关键依赖 Service 类典型 URL 示例CustomerController客户管理客户增删改查、客户列表分页、客户状态统计CustomerServiceImpl/customer/list,/customer/addSaleChanceController营销管理销售机会创建、分配、状态流转未联系→已联系→成交→流失SaleChanceServiceImpl/sale/chance/list,/sale/chance/updateStateCusDevPlanController营销管理客户开发计划制定针对某销售机会生成多步跟进计划CusDevPlanServiceImpl/cusdevplan/add,/cusdevplan/list?sid1001CustomerServiceController服务管理客户服务请求登记、处理进度更新、服务评价CustomerServiceImpl复用客户实体/service/add,/service/updateStatusDataDicController基础数据维护数据字典 CRUD如客户来源、行业分类、服务类型DataDicServiceImpl/data/dic/list?typecustomer_sourceCustomerLossController客户管理客户流失预警、流失原因归档、挽回措施记录CustomerLossServiceImpl/loss/warn,/loss/archive提示注意CustomerServiceImpl被两个模块复用——这是典型 JavaEE 项目中 Service 层复用的设计实践不是代码偷懒。CustomerServiceController并不新建 Service而是调用同一套客户逻辑仅在 Controller 层做业务分流。2.3 数据库设计关键约束为什么customer表有state字段却没用 ENUM因为 JavaEE 项目要兼容 MySQL 5.7 与 8.0本项目 SQL 脚本crm_db.sql中customer表的state字段定义为TINYINT(1)取值范围 0-20正常1流失预警2已流失而非 MySQL 8.0 的ENUM(normal,warning,lost)。原因很实际高校机房服务器大概率装的是 MySQL 5.7而ENUM在 5.7 中虽支持但 JDBC 驱动对ENUM的映射不稳定容易在rs.getString(state)时返回空字符串或报SQLException。用TINYINT则完全规避此问题Java 层用枚举类CustomerState做语义封装public enum CustomerState { NORMAL(0, 正常), WARNING(1, 流失预警), LOST(2, 已流失); private final int code; private final String desc; CustomerState(int code, String desc) { this.code code; this.desc desc; } public static CustomerState fromCode(int code) { for (CustomerState state : values()) { if (state.code code) return state; } return NORMAL; } }这样既保证数据库兼容性又在 Java 层保持可读性——这才是生产级思维不是为了炫技用新特性。3. 环境配置与部署实操从 JDK 到 Tomcat 再到 MySQL三步到位不翻车3.1 JDK 与 Tomcat 版本锁定为什么必须用 JDK 8 Tomcat 8.5不是怀旧是 class 文件版本兼容性硬约束项目编译目标为1.8查看pom.xml或.classpath可确认若强行用 JDK 11 编译CustomerController.class等文件会生成class file version 55.0JDK 11或61.0JDK 17而 Tomcat 8.5 默认只支持到52.0JDK 8。启动时会报错SEVERE [localhost-startStop-1] org.apache.catalina.core.StandardContext.startInternal One or more Filters failed to start. Full details will be found in the appropriate container log file Caused by: java.lang.UnsupportedClassVersionError: com/crm/controller/CustomerController has been compiled by a more recent version of the Java Runtime (class file version 61.0), this version of the Java Runtime only recognizes class file versions up to 52.0✅ 正确操作下载JDK 8u202推荐避免后期 Oracle 认证问题或OpenJDK 8u362下载Apache Tomcat 8.5.99官方最后稳定版比 8.5.0 更健壮设置JAVA_HOME指向 JDK 8CATALINA_HOME指向 Tomcat 解压目录3.2 MySQL 连接配置jdbc.properties里的四个参数改错一个就卡死在登录页项目根目录下src/main/resources/jdbc.properties是数据库连接唯一入口四个参数必须严格匹配你的环境jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/crm_db?useUnicodetruecharacterEncodingUTF-8serverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrueuseSSLfalse jdbc.usernameroot jdbc.password123456⚠️ 关键点说明com.mysql.cj.jdbc.DriverMySQL 8.0 必须用cj版本驱动mysql-connector-java-8.0.33.jar5.7 可用com.mysql.jdbc.Driver但统一用cj更省事serverTimezoneAsia/Shanghai必须加否则java.sql.SQLException: The server time zone value UTC is unrecognizedallowPublicKeyRetrievaltrueuseSSLfalseMySQL 8.0.28 默认强制 SSL本地开发关掉更省心jdbc.password默认是123456但如果你的 MySQL root 密码不是这个请务必修改——这是登录页白屏的最高频原因。3.3 Web 工程部署别直接丢target/crm.war必须解压后检查WEB-INF/web.xml和lib目录很多同学把 Maven 打包的crm.war直接丢进tomcat/webapps/结果访问http://localhost:8080/crm404。根本原因是war 包未解压成功或web.xml中 servlet-mapping 路径与实际不符。✅ 正确流程将crm.war复制到tomcat/webapps/目录下启动 Tomcatbin/startup.bat或./startup.sh观察tomcat/webapps/是否自动生成crm/文件夹不是crm.war还在若无crm/文件夹手动解压crm.war到crm/目录进入crm/WEB-INF/打开web.xml确认servlet-mapping中url-pattern是否为/customer/*等路径本项目是标准 RESTful 风格检查crm/WEB-INF/lib/是否包含mysql-connector-java-8.0.33.jar和commons-dbutils-1.7.jar缺任意一个启动时报ClassNotFoundException。注意web.xml中welcome-file-list指向login.jsp所以首页 URL 是http://localhost:8080/crm/login.jsp不是/crm/。这是初学者最容易忽略的路径细节。4. 避坑那些让毕设答辩前夜崩溃的 5 个血泪问题现象、原因、解法全写清楚4.1 现象登录页输入账号密码后页面跳转到http://localhost:8080/crm/error.jsp控制台无报错原因UserController.login()方法中User user userService.queryUserByUserName(username)返回 null但后续未判空直接调用user.getRoleid()触发NullPointerException被web.xml中error-page捕获跳转至 error.jsp。解决在UserController.java第 45 行附近添加判空逻辑User user userService.queryUserByUserName(username); if (user null) { request.setAttribute(msg, 用户名不存在); request.getRequestDispatcher(login.jsp).forward(request, response); return; // 一定要 return否则继续执行下面代码 } // 原有密码校验逻辑...4.2 现象客户列表页显示中文全是??数据库里存的是正常的汉字原因JSP 页面未声明 UTF-8 编码且 Tomcatconf/server.xml中Connector缺少URIEncodingUTF-8。解决① 在所有 JSP 顶部添加% page contentTypetext/html;charsetUTF-8 %② 修改tomcat/conf/server.xml找到Connector port8080 ... /添加属性URIEncodingUTF-8③ 重启 Tomcat。4.3 现象点击“添加客户”按钮表单提交后页面空白Network 面板显示HTTP 500原因CustomerController.add()方法中customerService.insert(customer)执行时抛出SQLException但 catch 块只打印日志e.printStackTrace()未 forward 到错误页导致响应体为空。解决在CustomerController.java的add()方法 catch 块中添加错误转发} catch (Exception e) { e.printStackTrace(); request.setAttribute(msg, 添加失败 e.getMessage()); try { request.getRequestDispatcher(customer/add.jsp).forward(request, response); } catch (ServletException | IOException ex) { ex.printStackTrace(); } }4.4 现象统计报表模块图表不显示JS 控制台报ReferenceError: echarts is not defined原因report.jsp中引用的 ECharts JS 文件路径错误。项目自带js/echarts.min.js但 JSP 中写的是script srcjs/echarts.min.js/script而实际路径是crm/js/echarts.min.js相对路径失效。解决将report.jsp中 script 标签改为绝对路径script src${pageContext.request.contextPath}/js/echarts.min.js/script${pageContext.request.contextPath}会动态解析为/crm确保路径正确。4.5 现象Tomcat 启动成功但访问http://localhost:8080/crm/login.jsp报HTTP 404catalina.out显示No Context configured to process this request原因webapps/下存在同名文件夹crm/和crm.warTomcat 优先加载crm/目录但该目录结构不完整缺少WEB-INF/classes/或WEB-INF/lib/。解决① 彻底删除tomcat/webapps/crm/和tomcat/webapps/crm.war② 重新复制crm.war进webapps/③ 确保 Tomcat 启动时自动解压出完整的crm/目录含WEB-INF/、index.jsp、login.jsp等④ 检查crm/WEB-INF/web.xml是否存在且格式正确XML 标签闭合、无 BOM 头。5. 功能验证与二次开发指南如何快速验证五大模块可用性并安全地加一个“导出 Excel”按钮5.1 五大模块冒烟测试清单5 分钟内确认核心链路是否打通不要一上来就改代码先用最小成本验证系统骨架是否健康。按顺序执行以下操作任一环节失败立即停回头查第 4 章避坑项模块测试动作预期结果关键检查点基础数据维护访问http://localhost:8080/crm/data/dic/list?typecustomer_source返回 JSON 数据含data:[{id:1,name:电话营销,code:tel},{id:2,name:网络推广,code:web}]浏览器地址栏 URL 正确Response Headers 中Content-Type: application/json;charsetUTF-8客户管理登录后点击左侧菜单“客户管理”→“客户列表”点击“添加客户”弹出表单填写姓名、电话、来源选“电话营销”提交成功后跳转回列表页新客户出现在第一条表单提交后 URL 变为/crm/customer/list列表中客户名称列显示刚填的姓名营销管理在客户列表页选中某客户点击“创建销售机会”跳转到sale_chance_add.jsp填写“概要”“联系人”“预计金额”提交后返回销售机会列表页新机会的客户名称列应显示刚才选中的客户名状态为“未联系”服务管理在客户列表页选中客户点击“添加服务”填写服务内容提交后在“服务管理”→“服务列表”中能看到该记录状态为“待处理”服务列表页客户名称和服务内容字段非空统计报表点击顶部导航“统计报表”→“客户来源分布”页面显示 ECharts 饼图图例含“电话营销”“网络推广”等数值与data_dic表中customer_source条目数一致饼图右上角有“刷新”按钮点击后图表数据实时更新提示所有测试均使用默认账号admin/123456见user表初始化数据无需额外注册。5.2 安全添加“导出 Excel”功能不碰 DAO 层只改 Controller JSP 新工具类想给客户列表页加导出按钮别动CustomerService那是业务核心。我们用 Apache POI 封装一层轻量导出全程 3 步Step 1引入 POI 依赖在pom.xml的dependencies中添加dependency groupIdorg.apache.poi/groupId artifactIdpoi/artifactId version4.1.2/version /dependency dependency groupIdorg.apache.poi/groupId artifactIdpoi-ooxml/artifactId version4.1.2/version /dependency然后mvn clean compile更新依赖。Step 2编写 Excel 导出工具类新建src/main/java/com/crm/utils/ExcelExportUtil.javapublic class ExcelExportUtil { public static void exportCustomerList(HttpServletResponse response, ListCustomer customers) throws IOException { // 创建工作簿 XSSFWorkbook workbook new XSSFWorkbook(); XSSFSheet sheet workbook.createSheet(客户列表); // 表头 String[] headers {ID, 客户名称, 联系电话, 客户来源, 行业, 状态, 创建时间}; XSSFRow headerRow sheet.createRow(0); for (int i 0; i headers.length; i) { headerRow.createCell(i).setCellValue(headers[i]); } // 数据行 int rowNum 1; for (Customer c : customers) { XSSFRow row sheet.createRow(rowNum); row.createCell(0).setCellValue(c.getId()); row.createCell(1).setCellValue(c.getName()); row.createCell(2).setCellValue(c.getPhone()); row.createCell(3).setCellValue(c.getCustomerSource()); // 注意这里用字典 name非 code row.createCell(4).setCellValue(c.getIndustry()); row.createCell(5).setCellValue(CustomerState.fromCode(c.getState()).getDesc()); row.createCell(6).setCellValue(new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(c.getCreateDate())); } // 输出响应 response.setContentType(application/vnd.openxmlformats-officedocument.spreadsheetml.sheet); response.setHeader(Content-Disposition, attachment; filenamecustomer_list_ System.currentTimeMillis() .xlsx); workbook.write(response.getOutputStream()); workbook.close(); } }Step 3在 CustomerController 中新增导出方法在CustomerController.java中添加protected void export(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { ListCustomer customers customerService.queryAllCustomers(); ExcelExportUtil.exportCustomerList(response, customers); } catch (Exception e) { e.printStackTrace(); request.setAttribute(msg, 导出失败 e.getMessage()); request.getRequestDispatcher(customer/list.jsp).forward(request, response); } }并在doPost()方法中增加路由if (export.equals(method)) { export(request, response); return; }Step 4JSP 页面加按钮在customer/list.jsp的表格上方添加a href${pageContext.request.contextPath}/customer?actionexport classbtn btn-success导出 Excel/a注意导出功能不经过 Service 层事务纯查询所以无需事务注解。POI 4.1.2 兼容 JDK 8不会引发 class 版本冲突。6. 我的毕设交付 checklist从代码提交到答辩 PPT这 7 件事我再也不敢跳过做完上面所有你以为就完了不。去年我帮三个同学 debug发现他们倒在最后 10%就因为漏了这几件事。现在我把自己的 checklist 分享给你每一条都是答辩现场被老师当场揪住的雷区6.1 数据库脚本必须带DROP DATABASE IF EXISTS crm_db; CREATE DATABASE crm_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;很多同学只导出CREATE TABLE语句忘了建库和字符集。答辩老师会让你现场演示“从零部署”如果他用mysql -u root -p crm_db.sql报错Unknown database crm_db你就被动了。utf8mb4是必须的——它支持 emoji 和四字节中文比如某些生僻姓氏utf8在 MySQL 5.7 已被标记为 deprecated。6.2web.xml中filter的encoding-filter必须放在所有 servlet mapping 之前本项目用了CharacterEncodingFilter但它的位置错了如果放在servlet-mapping之后POST 请求的中文参数依然乱码。正确顺序是filter filter-nameencoding-filter/filter-name filter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param /filter filter-mapping filter-nameencoding-filter/filter-name url-pattern/*/url-pattern /filter-mapping !-- 所有 servlet 和 servlet-mapping 放在这里之后 --6.3 毕设报告里的“系统架构图”不能画 Spring Boot必须画本项目的三层结构我见过太多同学在报告里画Spring Boot → MyBatis → MySQL结果答辩时老师问“你代码里哪一行用了 MyBatisCustomerDao是自己写的 JDBC 封装吧” 架构图必须忠实于代码JSP/HTML ← Servlet ← Service ← DAO ← JDBC ← MySQL箭头标注“HTTP 请求”、“业务逻辑”、“数据访问”、“SQL 执行”。6.4 所有 JSP 中的% %表达式必须替换为 JSTLc:out value${xxx}/% request.getAttribute(msg) %是老式写法容易 XSS。答辩老师会抽查代码安全性。全局替换命令Linux/macOSfind ./src/main/webapp -name *.jsp -exec sed -i s/% \(.*\) %/${\1}/g {} \; # 然后手动加 c:out 标签例如c:out value${msg}/6.5 Tomcat 日志必须保留catalina.out最后 100 行作为附件答辩材料要求提供“系统运行日志”。别只截图控制台。去tomcat/logs/catalina.out用tail -100 catalina.out catalina_last100.log生成附件。重点看是否有INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployWAR Deployment of web application archive—— 这行证明 WAR 包部署成功。6.6 演示视频必须包含“修改客户电话并保存刷新页面后电话变更生效”这一操作这是验证 MVC 数据流完整性的黄金动作。老师不关心你做了多少功能只关心“用户输入 → Controller 接收 → Service 处理 → DAO 更新 → 页面刷新 → 数据同步”。录屏时打开 Chrome DevTools 的 Network 面板让他看到PUT /crm/customer/update请求和200 OK响应。6.7 最后一次 commit 前执行mvn clean package -Dmaven.test.skiptrue检查 target/crm.war 大小是否 ≥ 12MB小于 10MB 说明资源文件js/css/img没打进 war大于 15MB 可能误打了target/下的临时文件。我的经验12–14MB 是健康区间意味着WEB-INF/lib/有 12 个 jar含 mysql-connector、commons-dbutils、jstl、poi 等WEB-INF/classes/有全部.classstatic/有图标和 CSS。从那以后我每次打包前都强制走一遍这个 checklist哪怕多花 20 分钟。因为毕设不是写完就结束是交出去那一刻才算真正完成。希望帮到你。本文还有配套的精品资源点击获取
返回列表