ARTICLE DETAIL

资讯详情

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

SSM+JSP小工程预算系统毕业设计实战:环境配置、核心表设计与避坑指南

SSM+JSP小工程预算系统毕业设计实战:环境配置、核心表设计与避坑指南 简介这份资源是面向高校计算机专业学生与Java初学者的小工程预算系统毕业设计完整方案基于SSM框架与JSP技术开发采用B/S架构和MySQL数据库适合作为课程设计、毕业设计参考或SSM入门练手项目。压缩包共1272个文件约32.88MB涵盖120个Java源文件、109个JSP页面、364个JavaScript脚本、146个CSS样式及大量图片与前端资源另含SQL脚本、配置文件与项目说明结构完整、层次清晰。系统实现用户管理、装修材料管理、订单信息管理、工程信息管理、工程订单管理、材料分类管理等功能模块并附演示录像便于对照理解业务流程与代码逻辑。已有100人学习下载读者可借此掌握SSM整合开发、JSP页面交互与数据库设计的完整思路快速搭建可运行环境并完成二次开发或论文撰写。1. 小工程预算系统为什么还在用 SSMJSP一次讲清它的真实定位如果你正在找计算机毕业设计选题或者被分配了一个“小工程预算管理系统”的题目大概率会看到 SSMJSP 这套组合。SSM 是 Spring Spring MVC MyBatis 的缩写JSP 是 Java Server Pages这套技术栈在 2024 年听起来确实不算新但它依然是高校毕业设计里最稳的路线之一。原因很直接资料多、环境好配、导师熟悉、答辩时不会被追问“你这个技术选型有什么创新点”这种要命的问题。小工程预算系统本身解决的是施工队、装修公司、小型工程队对项目成本的事前估算和事后核算需求核心功能围绕预算单、材料清单、人工费用、项目进度款这几块展开。适合谁适合 Java 基础刚学完、想拿一个能跑通、能讲清楚、能自己改的毕业设计的人。不适合谁不适合想靠技术选型拿优秀论文的人因为这套东西的创新点只能从业务逻辑里找不能从框架里找。2. 把 SSMJSP 跑起来环境、依赖和最小可运行配置2.1 环境版本怎么选才不翻车毕业设计最怕的不是代码写不出来而是环境装不上。SSMJSP 这套东西对版本很敏感尤其是 JDK、Tomcat、MySQL 三者的搭配。我一般会推荐下面这套组合亲测在 Windows 和 macOS 上都能跑通组件推荐版本说明JDK1.8别用 11 或 17JSP 在老版本 Tomcat 上对高版本 JDK 支持不好Tomcat8.5.x9 也能用但 8.5 和 JDK 1.8 配合最稳MySQL5.78.0 的驱动类名和时区配置不一样新手容易在这里卡住Maven3.6用来拉 Spring、MyBatis 的依赖IDEIntelliJ IDEA 或 EclipseIDEA 对 Maven 项目支持更好Eclipse 对 JSP 页面预览更直观选 JDK 1.8 不是因为它新而是因为 JSP 的编译机制和 Tomcat 8.5 的类加载器对高版本 JDK 有兼容性问题。你如果用 JDK 17 跑 Tomcat 8.5启动时可能直接报Unsupported class file major version这个坑我见过太多人踩。MySQL 5.7 和 8.0 的区别主要在驱动包和连接 URL 上5.7 用com.mysql.jdbc.Driver8.0 用com.mysql.cj.jdbc.Driver而且 8.0 必须加时区参数serverTimezoneAsia/Shanghai否则连接直接失败。2.2 Maven 依赖与 web.xml 的最小配置新建一个 Maven Web 项目后pom.xml里至少要加下面这些依赖。注意 Spring 和 MyBatis 的整合包版本要对应不然会出现NoClassDefFoundError。!-- pom.xml 核心依赖 -- dependencies !-- Spring 核心 -- dependency groupIdorg.springframework/groupId artifactIdspring-context/artifactId version5.3.20/version /dependency !-- Spring MVC -- dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version5.3.20/version /dependency !-- MyBatis -- dependency groupIdorg.mybatis/groupId artifactIdmybatis/artifactId version3.5.10/version /dependency !-- MyBatis 与 Spring 整合 -- dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version2.0.7/version /dependency !-- MySQL 驱动5.7 用这个 -- dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version5.1.49/version /dependency !-- JSP 和 JSTL -- dependency groupIdjavax.servlet/groupId artifactIdjstl/artifactId version1.2/version /dependency !-- 数据库连接池 -- dependency groupIdcom.alibaba/groupId artifactIddruid/artifactId version1.2.8/version /dependency /dependenciesweb.xml里要配置 Spring 的监听器和 DispatcherServlet这是 SSM 整合的入口。很多教程只贴代码不说为什么这里我解释一下ContextLoaderListener负责启动 Spring 容器加载 Service 和 DAO 层的 BeanDispatcherServlet负责加载 Spring MVC 的配置处理 Controller 层的请求。两个容器是父子关系子容器能访问父容器的 Bean反过来不行。!-- web.xml 关键配置 -- web-app !-- Spring 容器启动 -- context-param param-namecontextConfigLocation/param-name param-valueclasspath:applicationContext.xml/param-value /context-param listener listener-classorg.springframework.web.context.ContextLoaderListener/listener-class /listener !-- Spring MVC 前端控制器 -- servlet servlet-namedispatcher/servlet-name servlet-classorg.springframework.web.servlet.DispatcherServlet/servlet-class init-param param-namecontextConfigLocation/param-name param-valueclasspath:spring-mvc.xml/param-value /init-param load-on-startup1/load-on-startup /servlet servlet-mapping servlet-namedispatcher/servlet-name url-pattern//url-pattern /servlet-mapping /web-appurl-pattern写/而不是/*这是 Spring MVC 的常见配置。写/*会拦截 JSP 页面请求导致页面返回源码而不是渲染结果。这个坑在答辩演示时如果出现基本等于当场翻车。2.3 数据库连接与 MyBatis 配置的四个必调参数applicationContext.xml里配置数据源和 MyBatis 的SqlSessionFactory。下面这四个参数是必须调的不调要么连不上要么查不出数据。!-- 数据源配置 -- bean iddataSource classcom.alibaba.druid.pool.DruidDataSource property namedriverClassName valuecom.mysql.jdbc.Driver/ property nameurl valuejdbc:mysql://localhost:3306/budget_db?useUnicodetrueamp;characterEncodingutf8/ property nameusername valueroot/ property namepassword value你的密码/ /bean !-- MyBatis 工厂 -- bean idsqlSessionFactory classorg.mybatis.spring.SqlSessionFactoryBean property namedataSource refdataSource/ !-- 实体类包别名XML 里可以直接写类名 -- property nametypeAliasesPackage valuecom.budget.entity/ !-- Mapper XML 位置 -- property namemapperLocations valueclasspath:mapper/*.xml/ /bean !-- Mapper 接口扫描 -- bean classorg.mybatis.spring.mapper.MapperScannerConfigurer property namebasePackage valuecom.budget.mapper/ /bean第一个必调参数是url里的characterEncodingutf8不写的话中文材料名称存进去就是乱码。第二个是typeAliasesPackage配了之后 Mapper XML 里resultType可以直接写Budget而不是全限定类名。第三个是mapperLocations路径写错的话启动时报Invalid bound statement这个错误本质是 MyBatis 找不到 XML 映射文件。第四个是MapperScannerConfigurer的basePackage它负责把 Mapper 接口自动注册成 Bean不配的话 Service 里注入 Mapper 会报NoSuchBeanDefinitionException。3. 小工程预算系统的核心表设计与 JSP 页面落地3.1 预算单、材料、人工三张表的字段设计小工程预算系统的数据模型不复杂但字段设计要考虑实际业务。我一般会设计这几张核心表表名关键字段说明projectid, name, address, start_date, status工程项目主表budgetid, project_id, total_amount, create_time, status预算单一个项目可以有多版预算material_itemid, budget_id, name, unit, quantity, unit_price材料明细单价和数量相乘得小计labor_itemid, budget_id, work_type, days, daily_wage人工明细工种、天数、日工资userid, username, password, role用户表区分管理员和普通录入员budget表里的status字段用来标记预算单是草稿、已提交还是已审核这个状态机在答辩时是个加分项因为你可以讲清楚业务流转。material_item和labor_item通过budget_id关联到预算单删除预算单时要级联删除明细这个在 MyBatis 里可以用collection做嵌套查询也可以手动在 Service 层删两次。3.2 用 MyBatis 实现预算单的增删改查Mapper 接口定义方法XML 里写 SQL。下面以预算单查询为例展示一个带项目名称的联表查询。// BudgetMapper.java public interface BudgetMapper { // 查询所有预算单带项目名称 ListBudgetVO selectAllWithProject(); // 根据 ID 查预算单 Budget selectById(Integer id); // 插入预算单返回自增主键 int insert(Budget budget); // 更新预算单 int update(Budget budget); // 删除预算单 int deleteById(Integer id); }!-- BudgetMapper.xml -- mapper namespacecom.budget.mapper.BudgetMapper !-- 联表查询把项目名称带出来 -- select idselectAllWithProject resultTypecom.budget.vo.BudgetVO SELECT b.*, p.name AS projectName FROM budget b LEFT JOIN project p ON b.project_id p.id ORDER BY b.create_time DESC /select !-- 插入后返回主键keyProperty 对应实体类属性 -- insert idinsert useGeneratedKeystrue keyPropertyid INSERT INTO budget(project_id, total_amount, create_time, status) VALUES(#{projectId}, #{totalAmount}, NOW(), #{status}) /insert /mapperuseGeneratedKeystrue和keyPropertyid这两个属性是配套用的插入之后 MyBatis 会把数据库生成的自增 ID 回填到实体对象的id属性里。如果你在 Service 层插入预算单后还要插入明细就必须拿到这个 ID否则明细的budget_id没法赋值。resultType写的是 VO 类因为联表查询的结果字段比实体类多一个projectName直接映射到实体类会丢字段。3.3 JSP 页面怎么展示预算明细和计算小计JSP 页面用 JSTL 标签遍历明细列表并在页面上直接计算小计。下面是一个材料明细表格的写法。!-- material_list.jsp -- % taglib prefixc urihttp://java.sun.com/jsp/jstl/core % % taglib prefixfmt urihttp://java.sun.com/jsp/jstl/fmt % table border1 tr th材料名称/th th单位/th th数量/th th单价/th th小计/th /tr c:forEach items${materialList} varitem tr td${item.name}/td td${item.unit}/td td${item.quantity}/td tdfmt:formatNumber value${item.unitPrice} pattern#,##0.00//td tdfmt:formatNumber value${item.quantity * item.unitPrice} pattern#,##0.00//td /tr /c:forEach /tablec:forEach的items属性对应后端 Model 里放的materialListvar是循环变量名。fmt:formatNumber用来格式化金额保留两位小数并加千分位。JSP 里直接写${item.quantity * item.unitPrice}做乘法是允许的EL 表达式支持基本运算。但要注意如果quantity或unitPrice是 null页面会报错所以后端查询时要保证这两个字段不为空或者在数据库里设默认值 0。4. 避坑与排查SSMJSP 毕业设计里最容易翻车的五件事4.1 中文乱码从数据库到 JSP 页面全链路排查现象材料名称存进数据库变成问号或者 JSP 页面显示乱码。原因通常有三个地方没配好。第一数据库连接 URL 没加characterEncodingutf8。第二web.xml里没配CharacterEncodingFilter。第三JSP 页面头部没写% page contentTypetext/html;charsetUTF-8 %。解决方法是三处都检查一遍缺哪个补哪个。CharacterEncodingFilter的配置如下filter filter-nameencodingFilter/filter-name filter-classorg.springframework.web.filter.CharacterEncodingFilter/filter-class init-param param-nameencoding/param-name param-valueUTF-8/param-value /init-param init-param param-nameforceEncoding/param-name param-valuetrue/param-value /init-param /filter filter-mapping filter-nameencodingFilter/filter-name url-pattern/*/url-pattern /filter-mappingforceEncoding设为true表示强制请求和响应都用 UTF-8不设的话只对请求生效响应还是可能乱码。4.2 404 和 500DispatcherServlet 拦截路径写错的表现现象访问 Controller 返回 404或者 JSP 页面直接下载而不是渲染。原因通常是web.xml里url-pattern写成了/*。/*会拦截所有请求包括 JSP导致 JSP 被当成静态资源处理。解决方法是改成/然后在spring-mvc.xml里配置静态资源放行!-- spring-mvc.xml 静态资源放行 -- mvc:default-servlet-handler/ mvc:annotation-driven/mvc:default-servlet-handler/的作用是把找不到映射的请求交给 Tomcat 默认的 Servlet 处理这样 CSS、JS、图片才能正常加载。不配这个的话页面样式全丢答辩时看起来很业余。4.3 MyBatis 的 Invalid bound statementXML 没被扫描到现象启动不报错但调用 Mapper 方法时报Invalid bound statement (not found)。原因通常是mapperLocations路径写错或者 Maven 没有把src/main/java下的 XML 文件打包到target/classes。解决方法是两个第一检查applicationContext.xml里mapperLocations的值是不是classpath:mapper/*.xml并且 XML 文件确实放在resources/mapper目录下。第二在pom.xml里加资源目录配置build resources resource directorysrc/main/java/directory includes include**/*.xml/include /includes /resource resource directorysrc/main/resources/directory /resource /resources /buildMaven 默认只把src/main/resources下的文件复制到target/classessrc/main/java下的 XML 会被忽略。加上这段配置后Mapper XML 才能被正确打包。4.4 事务不生效Service 类没被 Spring 管理现象插入预算单和明细时明细插入失败但预算单已经写进数据库了。原因是 Service 类没有加Service注解或者事务注解Transactional加在了 Controller 层。Spring 的事务管理基于 AOP 代理只有被 Spring 容器管理的 Bean 才能被代理。解决方法是确保 Service 实现类上有Service事务方法上有Transactional并且在applicationContext.xml里开启事务注解驱动tx:annotation-driven transaction-managertransactionManager/ bean idtransactionManager classorg.springframework.jdbc.datasource.DataSourceTransactionManager property namedataSource refdataSource/ /bean另外注意Transactional默认只对RuntimeException回滚如果捕获了异常没抛出事务不会回滚。这个坑在毕业设计里很常见因为很多人喜欢在 Service 里 try-catch 然后返回错误信息。4.5 JSP 页面取不到 Model 数据EL 表达式被忽略现象Controller 里model.addAttribute(budget, budget)放了数据但 JSP 页面${budget.totalAmount}显示空白。原因通常是 JSP 页面的web.xml版本太低或者isELIgnored设成了true。解决方法是检查 JSP 页面头部有没有% page isELIgnoredfalse %以及web.xml的version是不是 2.4 以上。如果用的是 Servlet 2.3 的web.xmlEL 表达式默认不解析页面会直接把${budget.totalAmount}当文本输出。5. 让预算系统在答辩时多拿几分三个可验证的进阶技巧5.1 用拦截器做登录校验而不是在每个 Controller 里写 if毕业设计里最常见的登录校验写法是在每个 Controller 方法开头写if (session.getAttribute(user) null) return redirect:/login;这种写法重复且容易漏。更好的做法是用 Spring MVC 的拦截器在spring-mvc.xml里配置拦截路径在拦截器类里统一判断 Session。// LoginInterceptor.java public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行登录页和登录接口 String uri request.getRequestURI(); if (uri.contains(/login) || uri.contains(/doLogin)) { return true; } // 检查 Session Object user request.getSession().getAttribute(user); if (user null) { response.sendRedirect(request.getContextPath() /login); return false; } return true; } }!-- spring-mvc.xml 拦截器配置 -- mvc:interceptors mvc:interceptor mvc:mapping path/**/ mvc:exclude-mapping path/login/ mvc:exclude-mapping path/doLogin/ mvc:exclude-mapping path/static/**/ bean classcom.budget.interceptor.LoginInterceptor/ /mvc:interceptor /mvc:interceptorspreHandle返回false表示中断请求返回true表示放行。exclude-mapping用来排除登录页和静态资源不然登录页自己也被拦截会陷入死循环。这个拦截器在答辩时可以讲清楚 AOP 思想比在每个方法里写 if 显得专业得多。5.2 预算金额用 BigDecimal别用 double材料单价和数量相乘如果用double会出现精度丢失比如0.1 * 3结果是0.30000000000000004。预算系统涉及金额必须用BigDecimal。实体类里金额字段用BigDecimalMyBatis 会自动映射数据库的DECIMAL类型。计算时用BigDecimal的multiply方法并且指定保留两位小数// 计算材料小计 BigDecimal quantity new BigDecimal(3); BigDecimal unitPrice new BigDecimal(0.1); BigDecimal subtotal quantity.multiply(unitPrice).setScale(2, RoundingMode.HALF_UP); // 结果是 0.30setScale(2, RoundingMode.HALF_UP)表示保留两位小数四舍五入。RoundingMode还有DOWN、UP等模式预算系统一般用HALF_UP符合财务习惯。这个细节在答辩时如果被问到“金额精度怎么保证”你能答上来就是加分项。5.3 用 PageHelper 做分页别在 JSP 里手动算页码预算单列表数据多了要分页手动写LIMIT和计算总页数很麻烦。用 PageHelper 插件可以一行代码搞定// Service 层分页查询 public PageInfoBudgetVO getBudgetPage(int pageNum, int pageSize) { PageHelper.startPage(pageNum, pageSize); ListBudgetVO list budgetMapper.selectAllWithProject(); return new PageInfo(list); }PageHelper.startPage只对紧接着的第一条查询生效所以必须放在查询方法的前一行。PageInfo封装了总记录数、总页数、当前页数据JSP 页面直接遍历pageInfo.list就行。这个插件在pom.xml里加pagehelper依赖即可版本选 5.3.x 和 MyBatis 3.5.x 兼容。5.4 答辩前必做的三个验证动作第一个验证把数据库清空从注册用户开始走一遍完整流程确保没有依赖测试数据的隐藏逻辑。第二个验证把项目打包成 WAR 丢到干净的 Tomcat 里跑确保不是靠 IDEA 的自动配置才能启动。第三个验证把applicationContext.xml里的数据库密码改成错误密码看启动时报什么错这样答辩时老师问“如果数据库连不上怎么办”你能答出具体错误信息。这三个动作做完基本不会在演示环节翻车。我自己的习惯是每次改完 Mapper XML 都重启一次 Tomcat不靠热部署因为 JSP 和 MyBatis 的热加载经常有玄学问题重启虽然慢但能避免很多莫名其妙的报错。希望帮到你。本文还有配套的精品资源点击获取
返回列表