ARTICLE DETAIL

资讯详情

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

Jsp1016科研成果申报系统:JSP+Servlet+JavaBean三层架构实战

Jsp1016科研成果申报系统:JSP+Servlet+JavaBean三层架构实战 简介一份关于科研成果申报管理系统设计与实现的完整分析文档面向高校计算机专业学生、毕业设计者以及科研管理系统开发人员帮助理解基于JSPJavaBean与SQL Server 2000的申报平台如何完成从需求分析、数据库设计到编码调试的整个流程。文档以实际系统为蓝本详细展开开发背景、设计目标、技术选型、系统模型与可行性分析并对申报管理、审批管理、用户管理等核心功能模块进行划分辅以数据流图、实体关系图和数据表结构设计能够为同类系统的课程设计或论文写作提供直接参照。运行效果方面还给出系统主界面、科研申报、登录、课题申报、个人信息修改、科研审批等页面的实现与截图并包含关键源代码分析便于读者按图索骥复现模块逻辑。整个资源为1个doc文档压缩包约516KB内容紧凑、章节清晰目前已有62人学习下载适合需要快速掌握JSP科研管理项目完整设计思路的开发者和学生。1. 科研成果申报这事Jsp1016 想把它做成一个闭环科研成果申报管理系统的难点不在页面多而在状态多申报人填到一半可以存草稿提交后要等审核审核不通过又要退回修改等主管部门签收后还得归档。这个过程如果只用 Excel 加邮箱十个申报项目就能把人耗干。Jsp1016 这个编号看起来像某个课题的代码实际上它代表的是一个典型的 JSP Web 工程——用 JSP 做展示层Servlet 当控制层JavaBean 承载业务数据。这套组合放在今天的 Java 生态里不算新潮但它非常适合内部管理类系统结构简单、部署成本低、招人容易。这篇文章把这类系统的“设计—实现—上线”拆开讲。先说为什么分三层是合理的再拿一个申报表单跑通 JSP 与 Tomcat 的调试链路接着处理权限和重复提交最后给一个能减少线上故障的预编译技巧。中间涉及的每一步都是实际开发里容易踩坑、也值得抠细节的地方。2. Jsp1016 科研成果申报管理系统的分层设计与数据模型2.1 JSP、Servlet、JavaBean谁的代码放哪里我见过不少 JSP 项目把 SQL 直接写在 JSP 的%! %声明里当时写起来痛快等申报规则改到第三版时改一个字段要同时动页面、清缓存、重新部署。Jsp1016 这类系统最稳的分层方式还是 Servlet JSP JavaBean 的经典组合JSP 只负责渲染页面Servlet 做参数接收和流程跳转JavaBean 或 Service 类做数据访问。以申报人信息为例我会定义一个表单对象让 Servlet 从 request 里把参数一次性填充进来public class ApplyInfoBean { private Long id; private String applyUserId; private String achieveType; private String projectName; private String status; // 字段对应的 getter/setter 省略 }这个类不依赖 HttpServletRequest所以后续做单元测试时不用启动 Tomcat。Servlet 里用BeanUtils.populate(bean, request.getParameterMap())就能把表单参数映射进对象省掉一堆重复的getParameter调用。这里的边界必须清楚JavaBean 里不写out.println()JSP 里不 new DAOServlet 里不拼 HTML。一旦有人跨过这条线后面的权限控制和状态流转都会开始乱套。2.2 申报流程的状态机从填报到结题的页面流科研成果申报系统里我一般会把流程状态收敛成五种草稿、待审核、退回修改、已通过、已结题。数据库里只存状态值页面跳转规则集中放在 Servlet 里不要让每个 JSP 自己判断“下一步该去哪”。否则审核员换一个浏览器就可能迷路。当前状态可执行操作跳转目标页面流转后状态草稿提交申报/jsp/apply/review.jsp待审核待审核审核通过/jsp/manager/approve_result.jsp已通过待审核审核退回/jsp/manager/back_reason.jsp退回修改退回修改重新提交/jsp/apply/edit.jsp?fromback待审核已通过结题登记/jsp/manager/close_project.jsp已结题这张表既是需求文档也是测试用例。写代码时我会额外存一个update_user字段每次变更都记下操作人科研处如果要追溯“这个成果为什么从已通过变回待审核”有字段就能查。表单提交时注意要使用response.sendRedirect()而不是forward()。如果用 forward用户按下 F5 就会把同一个申报动作执行两次评审记录出现重复。重定向是 302 跳转再刷新也只是重新请求目标页面不会重放提交动作。2.3 数据表设计以成果申报主表和附件表为例申报系统的核心表不多但每张表都要为状态流转服务。我一般会先建主表和附件表附件表单独拆出来避免一个申报人传三份 PDF 就得在主表里塞三个字段。CREATE TABLE research_achievement ( id BIGINT PRIMARY KEY AUTO_INCREMENT, form_no VARCHAR(32) NOT NULL, applicant_name VARCHAR(50) NOT NULL, achieve_type VARCHAR(20) NOT NULL, project_name VARCHAR(200), apply_status TINYINT NOT NULL DEFAULT 0, submit_time DATETIME, update_time DATETIME, KEY idx_status (apply_status) ); CREATE TABLE achievement_attachment ( id BIGINT PRIMARY KEY AUTO_INCREMENT, achievement_id BIGINT NOT NULL, file_name VARCHAR(255) NOT NULL, file_path VARCHAR(255) NOT NULL, upload_time DATETIME, KEY idx_achievement_id (achievement_id) );主表里apply_status我用TINYINT而不是VARCHAR因为状态值要参与排序和索引form_no保留可读的单号比如GG-2025-0001方便科研处在线下核对。附件表通过achievement_id关联主表删除申报记录时要先清附件数据库虽然没建外键约束但应用层必须保证删除顺序。这里提醒一句不要因为现在申报字段少就把所有信息堆在一张表里。论文有期刊号专利有专利号软著有登记号字段完全不同。等系统上线半年再拆表已有的申报数据迁移会非常痛苦。3. 从零跑通 JSP 申报页工程搭建、页面渲染与 Tomcat 排错3.1 IntelliJ IDEA 创建 JSP 文件和 Tomcat 运行目标多数人第一次遇到 JSP 是在 IntelliJ IDEA 里最容易卡住的是创建工程后找不到 JSP 文件入口。IDEA 加 Web 项目有两种常见方式新建工程时选 Java Enterprise 并勾选 Web Application或者在已有项目中手工添加 Web Facet。创建 JSP 文件时可以新建apply_list.jsp只要能编译通过文件放webapp/jsp/apply/还是webapp/下区别不大但建议按角色分目录后面做权限拦截会省事得多。Tomcat 的启动配置里有几个参数值得固定下来配置项推荐值说明Application context/避免 JSP 地址里出现上下文名action 路径更好维护JVM 参数-Dfile.encodingUTF-8防止 JSP 页面中文乱码也影响日志输出On frame deactivationUpdate classes and resources修改 JSP 后切出 IDEA 界面时自动同步到 Tomcat把 Application context 配成/是我个人偏好因为 JSP 里的form action/jsp/apply/save就不需要再拼 contextPath。如果项目要挂在二级路径下则所有 form action 和 sendRedirect 路径都必须带 context 前缀。3.2 用 JSTL 在申报页面渲染成员列表JSP 页面里禁用 scriptlet 后展示列表要靠 JSTL。以“课题组成员”为例Servlet 把成员列表放进request.setAttribute(memberList, list)页面里这样输出% taglib prefixc urihttp://java.sun.com/jsp/jstl/core % table classmember-table trth姓名/thth所在部门/thth成员类型/th/tr c:forEach items${memberList} varmember varStatusidx tr td${member.userName}/td td${member.department}/td td${member.memberType}/td /tr /c:forEach /tablevarStatusidx能拿到循环序号生成复选框的 name 属性时很方便。JSTL 标签库的核心作用是把 Java 代码从 JSP 里挤出去页面变成纯模板前端工程师和后端工程师改同一个文件时冲突概率会小很多。3.3 在 Tomcat work 目录里查看 JSP 编译后的 Java 类JSP 本质上是会被 Tomcat 编译成 Servlet 的编译产物落在 Tomcat 的work目录。遇到 JSP 报 500 错误并且日志只给出行号不要对着 JSP 猜直接在编译后的 Java 类里找答案。定位命令一般是find $CATALINA_HOME/work/Catalina/localhost/jsp1016 -name *.java | grep applywork是 Tomcat 存放运行期临时文件的位置Catalina/localhost表示引擎和虚拟主机名称jsp1016是 context 名。找到apply_list_jsp.java后打开搜索异常堆栈里给的行号那一行往往是out.write(...)或response.getWriter()的调用。改完 JSP 后如果想强制重新编译删掉work/Catalina/localhost/jsp1016/org/apache/jsp目录再重启即可。这个方法也适用于排查 JSP 变量作用域写错导致的空指针比在编辑器里干瞪眼要快。4. 申报系统上线前要处理的 JSP 访问控制与重复提交问题4.1 用 Filter 堵住未登录用户的 JSP 直接访问科研申报系统里最容易被绕过的不是 Servlet而是 JSP 文件。如果有人把审核页面的完整 URL 复制给别人对方不需要登录就能打开页面看到申报列表。常见做法是把管理员相关 JSP 放在/jsp/manager/下然后写一个 Filter把这个路径下的请求全部拦下来。WebFilter(/jsp/manager/*) public class LoginFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req (HttpServletRequest) request; HttpServletResponse resp (HttpServletResponse) response; Object userId req.getSession().getAttribute(loginUserId); if (userId null) { resp.sendRedirect(req.getContextPath() /login.jsp); return; } chain.doFilter(request, response); } }WebFilter(/jsp/manager/*)这个注解决定拦截范围。/jsp/apply/*下同样可以挂一个只判断“是否登录”的过滤器。注意 Filter 里别做太重的数据库查询每次请求都查一遍用户权限会让申报页面明显变慢。如果系统权限较细还是把角色判断放到 Servlet 里Filter 只负责拦截未登录状态。4.2 用一次性 Token 拦截表单重复提交科研成果申报的提交按钮通常位于表单底部用户点了没反应习惯性再点一次两次请求就会生成两条申报记录。防重复提交最简单的方式是一次性 Token页面第一次加载时生成随机数放进 session同时放一个隐藏域提交时比较两者处理完立刻把 session 里的值清掉。JSP 表单里放一个隐藏域input typehidden nameformToken value${sessionScope.applyToken} /Servlet 中校验逻辑String token req.getParameter(formToken); String sessionToken (String) req.getSession().getAttribute(applyToken); if (token null || !token.equals(sessionToken)) { resp.sendRedirect(req.getContextPath() /duplicate.jsp); return; } req.getSession().removeAttribute(applyToken);这里我刻意用 session 而不是 cookie因为 cookie 里的 Token 容易被浏览器扩展自动带上导致第一次提交就校验失败。处理成功后再移除 session 属性用户后退重新提交时参数存在但 session 里已经没有 Token系统依然会拒绝。这个方案不用引入 Redis适合 Jsp1016 这种没有独立缓存的内部系统。4.3 屏蔽 JSP 离开页面提示顺手解决 IDEA 的 JSP 配色缺失部分申报页会注册window.onbeforeunload防止用户误关浏览器丢失表单。这个提示一旦出现就非常干扰用户只是点“保存并继续”浏览器也要弹一遍“确定要离开吗”。正确做法不是全局禁用事件而是在表单提交时先把事件置空再执行提交。function doSubmit() { window.onbeforeunload null; document.getElementById(applyForm).submit(); } window.onbeforeunload function () { return 申报数据尚未保存确定离开吗; };代码逻辑很直白只有真正离开页面时才弹提示点击提交按钮则静默发送请求。顺便提一个 IntelliJ IDEA 的问题有时候新建的 JSP 文件没有任何高亮在Settings Editor Color Scheme里也找不到 JSP 选项。这种大概率是文件类型识别错了。打开Settings Editor File Types找到 JSP 文件类型确认*.jsp扩展名被关联上如果已经关联但没有配色检查 JavaScript 插件是否被禁用。JSP 高亮依赖 JavaScript 支持插件关闭后页面会退化成普通文本。5. 上线前把 JSP 全部预编译一次顺便解决冷启动卡顿Jsp1016 这类 JSP 项目在 Tomcat 上最常见的故障是首次访问某页面时 Jasper 编译器才把 JSP 编译成 Servlet遇到语法问题直接 500而且第一个请求会比后续请求慢好几倍。解决思路是在上线前用 Tomcat 自带的 JspC 把所有 JSP 预编译一遍提前暴露错误同时把编译产生的 class 文件随应用一起发布。预编译命令可以写成java -classpath $CATALINA_HOME/lib/* \ org.apache.jasper.JspC \ -webapp /opt/workspace/jsp1016/src/main/webapp \ -uribase /opt/workspace/jsp1016/src/main/webapp \ -d /opt/workspace/jsp1016/precompile \ -compile-webapp指定 Web 应用根目录JspC会递归扫描目录下所有.jsp文件-d指定编译结果输出目录生成的_jsp.java和.class文件会按包路径排列-compile表示把 Java 源码再编译成 class。命令跑完后检查输出目录是否存在org/apache/jsp不存在就说明 JSP 全部通过存在则从里面的报错日志能直接定位是哪个 JSP 写错了。预编译完成后还有一个参数要配合改。Tomcat 的 JSP Servlet 默认开启development模式每次请求都要检查 JSP 源文件是否更新过这个检查在生产环境毫无意义。在应用自己的web.xml里覆盖同名 Servlet 配置servlet servlet-namejsp/servlet-name servlet-classorg.apache.jasper.servlet.JspServlet/servlet-class init-param param-namedevelopment/param-name param-valuefalse/param-value /init-param init-param param-namecheckInterval/param-name param-value0/param-value /init-param /servletdevelopmentfalse会让 Jasper 不再动态编译 JSPcheckInterval0表示关闭源文件修改时间检查。这两个参数生效后线上 JSP 文件即使被误改也不会立刻触发重编译修改任何页面都必须走一次预编译加替换 class 的流程。对 Jsp1016 这类申报系统来说提前把编译这一步放在发布管道里比等到申报窗口期首日再让第一个用户帮你触发编译要稳妥得多。本文还有配套的精品资源点击获取
返回列表