ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

基于SSH框架的Java固定资产管理系统设计与实现

2026/9/19 14:50:28 拓冰建站 浏览量
基于SSH框架的Java固定资产管理系统设计与实现 简介基于Java的固定资产管理系统毕业设计文档是一份完整的论文资料面向计算机专业学生、毕业设计者及希望掌握SSH框架的开发者。文档以某公司固定资产管理为背景采用浏览器/服务器模式运用JSP、Struts、Hibernate、Spring技术栈详细阐述了系统需求分析、架构设计、功能实现与权限管理涵盖资产增删改查、报表打印、职工信息管理及员工权限分配等核心模块并给出了清晰的数据库与界面设计思路。包体仅含1个doc文档大小2.72MB内容充实目录结构完整从摘要、Abstract、绪论到系统分析、详细设计等章节一应俱全便于直接参考论文框架或提炼技术要点。目前已有45人学习对于准备毕业设计或课程项目的读者具有较高参考价值可帮助理解SSH整合原理、资产管理业务流程以及论文撰写规范也能为实际信息系统开发提供切实可行的设计思路。1. 为什么毕业设计都爱选SSH做固定资产管理做管理系统类毕业设计时固定资产管理是一个被反复验证过的好题目业务边界清晰、角色分明、增删改查覆盖完整还能带出报表和权限这类“加分项”。这个基于Java的公司固定资产管理系统就是典型的SSH组合——JSP负责页面展示Struts接住请求Spring管对象Hibernate做持久化。整套代码对初学者最友好的地方在于它把MVC的每个环节都摆在了明面上你在Action里写业务逻辑在Service里调DAO在Hibernate映射文件里定义表和对象的关系每一步都能找到对应位置。这套系统对应的是龙成公司的实际管理场景资产从入库到借出、归还、维护都有记录管理员的权限高于操作员。对于准备java毕业设计的人它既是能直接跑的完整项目也是一份看得懂的分层教材。适合两类人第一是计算机专业学生拿它理解SSH整合流程第二是刚工作的Java工程师想复盘传统B/S系统里数据流和控制流的组织方式。下面直接从架构选型说起。2. 固定资产系统的SSH架构分层与B/S选型逻辑2.1 为什么选JSPStruts而不是Servlet这个项目是2019年的毕业设计但它背后的技术选型逻辑到现在仍然适用。先用一张图理解请求流转路径浏览器发出HTTP请求Tomcat根据web.xml把请求交给Struts的ActionServletActionServlet读取struts-config.xml找到对应ActionAction调用Spring管理的ServiceService调用Hibernate的DAO接口最终通过Hibernate模板操作MySQL数据库。数据返回时逆向走一遍JSP负责渲染。相比直接写ServletStruts的核心价值在于把请求分发和业务逻辑解耦。比如资产查询和资产删除是两个不同的Action但它们的公共逻辑比如字符编码过滤、权限校验可以在Struts的拦截器或过滤器里集中处理。实际开发中我一般会建议在Action里只做参数收集和视图跳转真正的业务判断放到Service层这样便于用Spring的AOP做事务控制。代码层面的跳转配置如下action path/asset/add typecom.company.sshaction.AssetAction nameassetForm scoperequest validatetrue parametermethod forward namesuccess path/asset/list.jsp/ forward nameerror path/asset/add.jsp/ /action参数说明path是浏览器访问的URL路径type是对应的Action全类名name引用表单BeanStruts会自动把请求参数封装进AssetForm对象parametermethod是常用的DispatchAction技巧同一个Action类可以通过?methodadd或?methoddelete调用不同方法减少Action类的数量。2.2 Spring在系统中的角色不只是粘合剂很多人初学SSH时会把Spring当成一个“注册中心”其实它在固定资产系统里承担了三件事依赖注入、事务管理和AOP权限校验。比如资产借出时需要同时更新资产状态表和新增借还记录这两步要么都成功要么都回滚Spring声明式事务就能保证bean idassetService classcom.company.service.AssetService property nameassetDao refassetDao/ property nameborrowDao refborrowDao/ /bean bean idtransactionManager classorg.springframework.orm.hibernate3.HibernateTransactionManager property namesessionFactory refsessionFactory/ /bean aop:config aop:pointcut idserviceMethods expressionexecution(* com.company.service.*.*(..))/ aop:advisor advice-reftxAdvice pointcut-refserviceMethods/ /aop:config这里有个关键点AssetService里同时注入了assetDao和borrowDao事务切面拦截所有com.company.service包下的方法。当一个Service方法内部多次调用DAO时它们共享同一个数据库连接如果中间抛出运行时异常事务自动回滚不需要手写try-catch。2.3 Hibernate映射文件的设计细节资产表和员工表是Hibernate的核心映射对象。早期SSH项目习惯用.hbm.xml文件而不是注解因为这种方式可以更精细地控制字段类型和关联关系。看资产表的一个映射片段class namecom.company.entity.Asset tablet_asset id nameid typejava.lang.Integer column nameid/ generator classnative/ /id property nameassetNo typejava.lang.String column nameasset_no length50 not-nulltrue/ /property property nameassetName typejava.lang.String column nameasset_name length100 not-nulltrue/ /property property namestatus typejava.lang.Integer column namestatus/ /property !-- status字段含义0在库1已借出2维修中3报废 -- many-to-one nameemployee classcom.company.entity.Employee fetchselect column nameemployee_id/ /many-to-one /class映射文件里最容易被忽略的是many-to-one关系。资产表通过employee_id外键关联员工表表示“当前保管人”。实际查询时如果直接访问asset.getEmployee().getName()会触发Hibernate的懒加载在Session关闭后报LazyInitializationException。解决办法是在Service层内把需要展示的数据查询完成或者将关联对象设为fetchjoin这要根据业务场景权衡。3. 数据库设计与核心功能模块实现3.1 数据表结构设计要点固定资产管理的数据模型并不复杂但表之间的关系值得拆解。从论文中的功能描述看系统至少需要五张核心表用户表、员工表、资产表、资产借还表、资产维护表。下面给出资产和借还表的基本设计字段名类型约束说明idint主键自增资产IDasset_novarchar(50)非空唯一资产编号asset_namevarchar(100)非空资产名称categoryvarchar(50)可空资产分类如电子设备、家具pricedecimal(10,2)非空资产原值statusint默认00在库 1借出 2维修 3报废employee_idint外键当前保管人IDbuy_datedatetime可空购入日期remarkvarchar(255)可空备注注意status字段设计了枚举值查询时不需要关联表就能知道资产状态。asset_no加唯一约束可以防止重复录入。员工表和用户表是分离的用户表存登录账号密码和角色员工表存姓名、部门等基本信息这种设计保证了操作员账号被删除时员工历史记录仍保留。3.2 资产录入的Action实现流程资产入库是整个系统的操作入口。前端JSP表单通过AssetForm收集参数Struts负责参数校验校验通过后交给Service。看一个简化的Action方法public ActionForward add(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { AssetForm assetForm (AssetForm) form; Asset asset new Asset(); asset.setAssetNo(assetForm.getAssetNo()); asset.setAssetName(assetForm.getAssetName()); asset.setCategory(assetForm.getCategory()); asset.setStatus(0); // 新入库资产默认在库 // 用SimpleDateFormat处理日期字符串避免中文环境下的格式问题 SimpleDateFormat sdf new SimpleDateFormat(yyyy-MM-dd); try { asset.setBuyDate(sdf.parse(assetForm.getBuyDate())); } catch (ParseException e) { e.printStackTrace(); return mapping.findForward(error); } // 保存人从Session中获取保证操作可追溯 User operator (User) request.getSession().getAttribute(currentUser); asset.setCreateUser(operator.getUsername()); assetService.addAsset(asset); return mapping.findForward(success); }这段代码里有两个工程习惯值得学习一是保存操作人信息到数据表而不是只靠日志后续审计时能直接从数据库查出谁在什么时间录入了哪些资产二是日期解析单独处理Hibernate的日期类型与MySQL的datetime字段对应时容易产生时区偏移统一使用SimpleDateFormat并明确格式可以减少这类问题。实际项目中AssetForm里还应该加ActionErrors做必填项校验比如资产编号为空时返回错误信息而不进入Service层。3.3 管理员与操作员的权限控制论文中提到“操作员只可对资产和用户进行基本操作管理员可以为每位员工赋权限”这就是典型的基于角色的访问控制。Struts中实现权限控制有两种常见做法在Action执行前用Servlet过滤器拦截或者在Spring的AOP里做方法级拦截。更推荐的是在Struts的RequestProcessor里做统一校验这样不需要在每个Action中重复写权限判断逻辑public class SecurityProcessor extends RequestProcessor { Override protected boolean processPreprocess(HttpServletRequest request, HttpServletResponse response) { String path request.getServletPath(); // 登录和公共页面直接放行 if (/login.jsp.equals(path) || /login.do.equals(path)) { return true; } HttpSession session request.getSession(); User user (User) session.getAttribute(currentUser); if (user null) { try { response.sendRedirect(request.getContextPath() /login.jsp); } catch (IOException e) { e.printStackTrace(); } return false; } // 管理员角色可以访问以manage开头的路径 if (/manage_.contains(path) !admin.equals(user.getRole())) { try { response.sendRedirect(request.getContextPath() /error.jsp); } catch (IOException e) { e.printStackTrace(); } return false; } return true; } }注意这个类实现的processPreprocess是Struts1.2之后提供的方法相比直接继承ActionServlet它更轻量。配置时需要在struts-config.xml里替换controller属性controller processorClasscom.company.security.SecurityProcessor/这样做的好处是权限逻辑集中且可测试。如果项目里再引入Spring Security思路也是类似的定义资源与角色的映射关系在请求进入控制器之前完成认证和授权。4. 资产借还、报表打印与中文乱码实战4.1 借出与归还的状态管理资产借还模块最容易出现的数据问题是不一致资产记录显示在库但借还表里没有对应记录。为了避免这种情况借出操作必须在一个事务里完成两件事插入一条借还记录同时更新资产表的status和employee_id。对应的Service方法public void borrowAsset(Integer assetId, Integer employeeId, Date borrowDate) { Asset asset assetDao.findById(assetId); // 校验资产当前状态已借出或维修中的资产不能再借 if (asset null || asset.getStatus() ! 0) { throw new BusinessException(资产不存在或当前状态不可借出); } BorrowRecord record new BorrowRecord(); record.setAsset(asset); record.setEmployee(employeeDao.findById(employeeId)); record.setBorrowDate(borrowDate); borrowDao.save(record); asset.setStatus(1); asset.setEmployee(employeeDao.findById(employeeId)); assetDao.update(asset); }这里有一个容易被忽略的坑asset是Hibernate的持久化对象在事务内修改它的属性后即使不显式调用update事务提交时也会自动更新数据库。但为了明确表达意图代码里还是保留了assetDao.update(asset)。借出时校验状态是必须的如果不校验同一台设备可能被借给两个人。HQL查询借出记录时我一般使用以下写法String hql from BorrowRecord r where r.returnDate is null; Query query session.createQuery(hql); ListBorrowRecord list query.list();这个HQL只查询尚未归还的借出记录。returnDate为空表示还在借出状态这是最直观的状态标记。实际运行中要注意HQL中的类名和属性名大小写BorrowRecord对应Java类名returnDate对应属性名而不是数据库的return_date列名写错会直接抛QuerySyntaxException。4.2 使用JavaReport生成打印报表论文中提到的外部包JavaReport-V3-Enterprise-Released.jar是当时的报表组件。打印报表的流程可以拆成四个步骤从数据库查出要打印的数据集合把数据填充到报表模板设置输出格式最后通过Response输出流写回浏览器。public void printAssetList(HttpServletRequest request, HttpServletResponse response) { ListAsset assets assetService.findAllAssets(); request.setAttribute(assets, assets); // 报表组件通过JSON或XML接收数据这里用字符串拼接简化 StringBuilder json new StringBuilder(); json.append([); for (Asset a : assets) { json.append(String.format( {\assetNo\:\%s\,\assetName\:\%s\,\price\:\%.2f\,\status\:\%s\},, a.getAssetNo(), a.getAssetName(), a.getPrice(), a.getStatus())); } if (assets.size() 0) { json.deleteCharAt(json.length() - 1); } json.append(]); // 转换JSON为报表组件需要的DTO response.setContentType(application/pdf); response.setCharacterEncoding(UTF-8); // 调用JavaReport的ReportManager输出PDF // ReportManager.createReport(json.toString()).exportPDF(response.getOutputStream()); }实际项目中不建议手写JSON可以用fastjson或Gson替代。报表打印的注意点在于中文显示PDF报表引擎默认字体可能不支持中文需要在报表模板或代码里指定中文字体比如STSong-Light否则导出的PDF中文会是乱码或方块。4.3 中文乱码的三层过滤方案中文乱码是所有老Java Web项目绕不开的话题这个系统也不例外。乱码会产生在三个位置页面显示乱码、请求参数乱码、数据库存储乱码。工程上常用的做法是统一编码为UTF-8。第一层在JSP页面顶部声明% page contentTypetext/html; charsetUTF-8 pageEncodingUTF-8 %第二层使用过滤器统一处理POST请求编码public class EncodingFilter implements Filter { private String encoding UTF-8; Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding(encoding); response.setCharacterEncoding(encoding); chain.doFilter(request, response); } }第三层修改MySQL连接URL和环境变量这是最容易被忽略的环节jdbc:mysql://localhost:3306/assetdb?useUnicodetruecharacterEncodingUTF-8useUnicodetrue和characterEncodingUTF-8必须同时出现否则Hibernate连接MySQL时中文写入会变??。另外如果使用的是MySQL 5.7及以上版本还需要在my.ini中设置character-set-serverutf8mb4因为utf8mb4才是完整的四字节UTF-8支持。5. 从论文到可演示系统复现与答辩的实操技巧5.1 将MyEclipse项目迁移到IDEA论文指定的开发环境是MyEclipse 8.0和Tomcat 6.0如果你现在打开这个项目很可能会遇到编译不兼容的问题。我的建议是迁移到IntelliJ IDEA和Tomcat 8.5以上版本。迁移时重点检查三处项目结构是否为src/main/java布局.classpath中是否残留MyEclipse的容器引用web.xml中servlet版本是否与Tomcat匹配。Struts1和Spring3在Tomcat 8上运行没有问题但要注意删除xercesImpl.jar这类可能引起冲突的XML解析包。5.2 功能测试的关键数据准备测试这个系统时不要只登录管理员账号随便点两下。建议按照真实流程准备三组数据第一组是正常数据比如“笔记本-001”从入库到借出再到归还第二组是边界数据比如资产编号为空、价格超过百万、员工姓名为生僻字第三组是异常操作比如重复删除已报废资产、操作员尝试访问管理员页面。验收时重点观察三件事操作是否产生预期记录、借出后资产状态是否变化、错误提示是否清晰定位到具体字段。5.3 答辩时把三个技术点讲透面试官或答辩老师通常不会只问“你做的是什么”而是追问“为什么这么设计”。这个固定资产系统有三个技术点可以提前准备。第一个是Hibernate的一级缓存和懒加载。回答时要说到Session范围内的缓存机制以及打开懒加载后Session关闭导致LazyInitializationException的解决方案。第二个是Spring的事务管理粒度问题。你可以在答辩时说不是所有方法都需要事务查询方法设置只读事务readOnlytrue可以提升性能而borrowAsset这样涉及两次写操作的方法必须开启默认的REQUIRED传播行为。第三个是权限控制的边界。只在前端隐藏“管理员管理”按钮是不够的因为请求还是可以直接发到后台。你的SecurityProcessor在服务端做了二次校验这才是安全的做法。把这一点讲清楚整个项目的技术深度会立刻提升一个档次。本文还有配套的精品资源点击获取