☰
J2EE企业级信息管理系统实战:招投标、资金与项目模块的流程设计与避坑指南
2026/10/10 1:53:25 网站建设 项目流程

简介:这份学士学位论文文档面向计算机与软件工程专业学生及企业信息化开发者,围绕中航天建设工程有限公司的综合信息管理系统展开,重点解决企业协同办公与信息集成问题。系统基于J2EE技术栈与Oracle数据库,采用B/S架构并融合移动平台开发技术,涵盖表单、工作流、公文、档案、知识及系统管理等模块,作者具体负责招投标管理、资金管理和项目管理三大模块的设计、测试与代码实现。资源包内含1个doc文件,约1.86MB,为完整论文正文,包含中英文摘要、目录及各章节论述,可帮助读者了解企业级信息系统的需求分析、架构选型与模块设计思路。目前已有106人学习,适合作为毕业设计选题参考或J2EE项目实践的学习材料。

1. 从一份 2013 年的 J2EE 毕设拆起:招投标、资金、项目三模块到底能不能跑

翻到这份《基于 Web 的中航天建设工程的综合信息管理系统》时,我第一反应是"又一个 XX 管理系统"。但把文档从头翻到尾,发现它跟那些只写"登录+增删改查"的毕设不太一样——作者明确说了自己负责的是招投标管理、资金管理、项目管理三个模块,而且系统本身是给一家工程建设公司做的真实业务系统,不是纯练手。技术栈是 J2EE + Oracle + B/S 架构,前端用 JSP + Struts2,开发工具 Eclipse,服务器 Tomcat,数据库操作走 PL/SQL。这套组合放在今天看确实老,但它的价值不在"新",而在于它把企业级信息管理里最麻烦的那块——分级审核 + 流程流转 + 数据复用——用一套可复现的方式讲清楚了。如果你正在做类似的企业管理系统、毕设选题,或者想理解传统 J2EE 项目怎么组织模块和权限,这份文档值得拆开看。它解决的不是"能不能跑起来",而是"业务规则怎么落到代码里"。

2. 方案选型:为什么是 J2EE + Oracle 而不是 LAMP 或 .NET

2.1 三套方案的对比逻辑

文档里花了整整一章做方案论证,把 LAMP、J2EE + Oracle、.NET 三套方案摆在一起比。这个做法在毕设里不多见,大部分毕设直接写"我选了 XX",不解释为什么。这里作者给的理由很实在:

对比维度LAMPJ2EE + Oracle.NET
开发效率PHP 快但框架约束弱Struts2 配置化,改参数不动代码语法兼容 ASP,上手快
数据复用弱,表结构绑定业务强,通过 f_TableType 字段区分表类型中等
数据库能力MySQL 百万级Oracle 支持集群、并行服务器依赖 SQL Server
跨平台Linux 为主全平台Windows 为主
安全性依赖配置HTTPS + SSL 加密层中等
成本开源免费开发工具免费,Oracle 需授权需 Windows Server 授权

作者最终选 J2EE + Oracle 的核心理由是数据复用性和安全性。具体来说,系统里有一张表被多个业务模块共用,通过f_TableType字段来区分不同业务类型的数据。调用时用 Filter 过滤表类型,一张物理表就能服务多个逻辑业务。这个设计思路在 2013 年算是比较务实的做法,放到今天看,其实就是一种轻量级的多租户/多业务共用表方案。

2.2 数据复用机制的具体实现

这个f_TableType机制值得展开说。传统做法是每个业务建一张表,招投标一张、项目管理一张、资金管理一张。但作者团队的做法是:建一张通用数据表,加一个f_TableType字段标记这条数据属于哪个业务。查询时带上过滤条件:

-- 查询招投标类型的数据 SELECT * FROM t_business_data WHERE f_TableType = 'BIDDING' AND f_OrgLevel IN ('本级', '下级'); -- 查询项目管理类型的数据 SELECT * FROM t_business_data WHERE f_TableType = 'PROJECT' AND f_OrgLevel IN ('本级', '下级');

逻辑说明:f_TableType是业务类型标识,f_OrgLevel是组织层级标识。这样设计的好处是新增业务类型时不需要建新表,只需要定义一个新的 Type 值。参数方面,f_TableType的取值需要在字典表里预先注册,否则前端下拉框里选不到。我一般会建议在字典表里加一个f_IsActive字段控制启用状态,避免废弃的业务类型还出现在选项里。

注意:这种共用表方案在数据量大了以后会有性能问题,因为所有业务的数据都堆在一张表里,索引设计要特别小心。如果单表超过 500 万行,建议按f_TableType做分区。

2.3 权限与审核流程的绑定方式

文档里反复强调"不同部门不同层级"的审核。具体实现上,系统把用户按组织层级划分,每个业务表单在提交时记录填报人的组织层级。审核人只能看到本级和下级的数据,不能向上越级或跨级查看。这个规则在 SQL 层面就是加一个f_OrgLevel的范围条件。

// Struts2 Action 中拼接查询条件 public String list() { String orgLevel = getCurrentUser().getOrgLevel(); // 本级和下级可见 List<String> visibleLevels = orgLevelService.getSelfAndSubLevels(orgLevel); queryParam.put("visibleLevels", visibleLevels); return SUCCESS; }

逻辑说明:getSelfAndSubLevels返回当前用户所在层级及其所有下级层级的列表。参数orgLevel从 Session 中取,不能从前端传,否则用户可以伪造层级越权查看。这是血泪经验——很多系统翻车就翻在把权限参数放在前端。

3. 招投标模块:从项目登记到中标的完整链路

3.1 招投标的业务流程拆解

文档里画了招投标管理的执行规则流程图,我把它翻译成可操作的步骤:

  1. 项目招标信息登记:录入拟投标项目的基本信息,同时在这个表单里完成项目可行性评价(作为标签页,不单独开功能)
  2. 项目可行性评价:对拟跟踪项目打分,分值可以为负,评价内容从"项目可行性评价字典"里取
  3. 项目投标阶段成本分析:只对已评审通过且未被终止的项目做,做过一次就不能再做
  4. 投标过程管理:从"项目投标作业字典"里引用作业项
  5. 投标结果登记:记录中标/未中标,未中标可以选择是否重新测算(二次测算)
  6. 工程项目信息:中标后自动导入,也可以手工录入不招标的工程项目

这个链路里有两个设计点值得注意:一是可行性评价不单独作为功能出现,而是嵌在招标信息登记的标签页里,减少用户操作步骤;二是工程项目信息与招标信息登记共用同一张数据库表,通过f_TableType区分。

3.2 共用表在招投标与项目管理中的具体用法

招投标模块和项目管理模块都涉及"工程项目信息",如果各建一张表,数据同步会很麻烦。共用一张表的做法是:

-- 表结构简化示意 CREATE TABLE t_project_info ( f_Id NUMBER PRIMARY KEY, f_TableType VARCHAR2(20), -- 'BIDDING' 或 'PROJECT' f_ProjectName VARCHAR2(200), f_OrgLevel VARCHAR2(50), f_CreateUser VARCHAR2(50), f_CreateTime DATE, f_Status VARCHAR2(20) -- 'DRAFT' / 'AUDITING' / 'DONE' );

逻辑说明:f_TableType区分这条记录是招标阶段的还是正式项目阶段的。当招标中标后,系统把f_TableType从'BIDDING'更新为'PROJECT',或者复制一条新记录。参数f_Status控制审核状态,只有'DONE'状态的记录才能被下游业务引用。

注意:共用表方案下,字段会越来越多,因为不同业务需要的字段不一样。我一般会预留 10-20 个扩展字段(f_Ext1到f_Ext20),避免频繁改表结构。

3.3 授权委托书管理的层级隔离

授权委托书这个功能看起来简单,但文档里特别强调了层级隔离:各组织层级只能对本级和下级的数据操作,不能越级。而且按照用户在授权委托书中的地位,分为"发出授权委托书"和"接收授权委托书"两种视角。

// 查询授权委托书列表 public String listEntrust() { User user = getCurrentUser(); // 本单位发出的 List<Entrust> sent = entrustService.findBySender(user.getOrgId()); // 本单位接收的 List<Entrust> received = entrustService.findByReceiver(user.getOrgId()); // 合并去重 return buildResult(sent, received); }

逻辑说明:findBySender和findByReceiver分别按发出方和接收方查询。参数user.getOrgId()从 Session 取,确保只能看到自己单位相关的委托书。这个设计避免了"张三能看到李四单位的委托书"这种越权问题。

4. 资金管理与项目管理:审核流怎么落到代码里

4.1 分级审核的状态机设计

文档里提到"不同部门和不同管理层的审核批准执行",但没有给出具体的状态机代码。根据这个场景,常见的做法是用一个状态字段加审核记录表来实现:

-- 审核记录表 CREATE TABLE t_audit_log ( f_Id NUMBER PRIMARY KEY, f_BusinessId NUMBER, -- 关联的业务单据 ID f_BusinessType VARCHAR2(20), -- 业务类型 f_Auditor VARCHAR2(50), -- 审核人 f_Action VARCHAR2(20), -- 'APPROVE' / 'REJECT' f_Comment VARCHAR2(500), -- 审核意见 f_AuditTime DATE );

逻辑说明:每次审核操作往t_audit_log插一条记录,业务单据的f_Status根据审核结果更新。参数f_BusinessType区分是招投标、资金还是项目管理的审核。这样设计的好处是审核历史可追溯,而且可以统计每个审核人的处理效率。

4.2 资金管理的预算与支出记录

资金管理模块涉及"基础设置"和"资金管理"两块。基础设置里通常放资金科目、预算科目这些字典数据。资金管理本身则记录每笔资金的流入流出。

// 资金流水记录 public class CapitalFlow { private Long id; private String projectId; // 关联项目 private String flowType; // 'IN' 或 'OUT' private BigDecimal amount; // 金额 private String category; // 资金科目 private Date flowDate; // 发生日期 private String auditStatus; // 审核状态 }

逻辑说明:projectId关联到项目管理模块,这样能按项目统计资金使用情况。flowType区分收入还是支出。auditStatus走和招投标一样的审核流程。参数category从基础设置的字典里取,不能自由输入,否则统计口径会乱。

4.3 项目管理的进度与合同关联

项目管理模块包含"招标管理、合同管理、进度管理"。其中合同管理和招投标模块的中标结果关联——中标后自动生成合同草稿,然后走合同审核流程。进度管理则是记录项目的里程碑节点。

-- 项目进度表 CREATE TABLE t_project_schedule ( f_Id NUMBER PRIMARY KEY, f_ProjectId NUMBER, f_Milestone VARCHAR2(200), -- 里程碑名称 f_PlanDate DATE, -- 计划完成日期 f_ActualDate DATE, -- 实际完成日期 f_Status VARCHAR2(20) -- 'PENDING' / 'DONE' / 'DELAYED' );

逻辑说明:f_PlanDate和f_ActualDate对比可以算出是否延期。f_Status为'DELAYED'时触发预警。参数f_ProjectId关联项目主表,确保进度记录不会挂到错误的项目上。

注意:进度管理的日期字段一定要用 DATE 类型而不是 VARCHAR2,否则排序和计算都会出问题。我见过有人用字符串存日期,结果"2024-1-1"排在"2024-10-1"后面,排查了半天。

5. 避坑与排查:这套老架构最容易翻车的五个地方

5.1 中文乱码:从 JSP 到 Oracle 的编码链路

现象:招投标信息登记时,项目名称里的中文存到数据库变成问号。

原因:JSP 页面编码、Struts2 编码、Tomcat 连接器编码、Oracle 字符集四层里有一层没对齐。常见的是 JSP 页面用了GBK,但 Oracle 是UTF-8。

解决:统一用 UTF-8。JSP 页面头部加<%@ page contentType="text/html;charset=UTF-8" %>,Struts2 配置里加<constant name="struts.i18n.encoding" value="UTF-8"/>,Tomcat 的server.xml连接器加URIEncoding="UTF-8",Oracle 建库时选AL32UTF8。

5.2 审核越权:前端传了不该传的参数

现象:A 部门的用户能看到 B 部门的数据。

原因:查询条件里的组织层级参数是从前端传过来的,用户改了 URL 参数就能越权。

解决:所有权限相关的参数必须从 Session 取,不能从前端传。在 Action 里加一层校验:

// 校验当前用户是否有权查看目标层级数据 public boolean canView(String targetOrgLevel) { String myLevel = getCurrentUser().getOrgLevel(); return orgLevelService.isSelfOrSubLevel(myLevel, targetOrgLevel); }

5.3 共用表查询慢:缺索引导致全表扫描

现象:招投标列表加载要十几秒。

原因:t_project_info表数据量大了以后,f_TableType和f_OrgLevel没有索引,每次查询都全表扫描。

解决:给f_TableType和f_OrgLevel建联合索引:

CREATE INDEX idx_project_type_level ON t_project_info(f_TableType, f_OrgLevel);

如果数据量超过千万,考虑按f_TableType做分区表。

5.4 审核状态不同步:并发操作导致状态覆盖

现象:两个审核人同时点"通过",后点的覆盖了先点的记录。

原因:没有加乐观锁,两个事务同时读到相同状态,各自更新。

解决:在业务表加版本号字段f_Version,更新时检查版本:

UPDATE t_project_info SET f_Status = 'DONE', f_Version = f_Version + 1 WHERE f_Id = ? AND f_Version = ?;

如果影响行数为 0,说明数据已被别人修改,提示用户刷新重试。

5.5 日期格式:Oracle 默认格式与 Java 不一致

现象:插入日期时报ORA-01861: 文字与格式字符串不匹配。

原因:Java 的Date转字符串格式和 Oracle 的NLS_DATE_FORMAT不一致。

解决:在 Java 里用SimpleDateFormat显式格式化,或者用PreparedStatement.setDate()直接传java.sql.Date。不要用字符串拼接 SQL 插日期。

6. 从这份毕设里能带走的三件事

第一件是共用表 + 类型字段的设计思路。虽然今天更流行微服务拆库,但在中小型系统里,一张表服务多个业务仍然是很务实的做法。关键是索引要跟上,扩展字段要预留。

第二件是权限参数必须从服务端取。这个教训不分技术栈,J2EE 也好、Spring Boot 也好、前端框架也好,把权限参数放前端就是给自己埋雷。从那以后我每次做权限相关的功能,都强制走一遍"参数来源检查"——凡是能决定数据可见范围的参数,一律从 Session 或 Token 里取。

第三件是审核流程要有独立的日志表。不要只靠业务表的状态字段,状态字段只能告诉你"现在是什么状态",日志表才能告诉你"谁在什么时候把它变成了这个状态"。出了问题要追溯的时候,日志表就是后悔药。

这份文档里的代码片段不算完整,但业务规则和流程设计讲得比较透。如果你要复现,建议先把招投标那条链路跑通——从项目登记到可行性评价到成本分析到结果登记,这条链路跑通了,资金管理和项目管理就是类似的套路。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询