news 2026/9/28 11:57:14

JavaWeb原生开发实战:JSP+Servlet人事系统部署与调试指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaWeb原生开发实战:JSP+Servlet人事系统部署与调试指南

简介:这是一套基于JSP+Servlet+Tomcat+MySQL实现的完整人事管理系统源码,面向计算机、数学、电子信息等专业的本科生及初学者,适用于课程设计、期末大作业与毕业设计参考。系统涵盖员工信息管理、部门维护、考勤统计、权限控制等核心模块,采用经典B/S架构与MVC分层思想,便于理解Web开发全流程与数据库交互逻辑。压缩包共2000个文件,主体为49个Java后端类、42个JSP页面、1294个JS脚本及404个CSS样式文件,辅以SQL建表语句、配置文件与说明文档,整体73.74MB,结构清晰、注释较全,适合作为Java Web入门到进阶的实践范例。目前已有205人学习下载,资源提供开箱即用的可运行环境(含adminLTE前端框架),并附带详细部署说明与常见问题提示,有助于快速掌握项目搭建、代码调试与功能扩展方法。

1. 这不是“老古董”,而是能跑通、能调试、能交差的 JavaWeb 实战基线:一个完整人事管理系统源码包,为什么值得你花 20 分钟解压、配环境、跑起来?

你可能刚在头歌实训里卡在HttpServlet的doGet和doPost区分上,也可能正被毕设选题折磨——导师说“别用 Spring Boot,得体现 Servlet 基础”,而你搜到的所谓“JSP 项目”点开全是空文件夹或报错 404。这个基于jsp+servlet+tomcat+mysql的人事管理系统源码.zip不是教学幻灯片,也不是阉割版 demo,它是一套真实可运行、结构清晰、有登录鉴权、有增删改查、有前端 AdminLTE 界面、有 MySQL 表结构脚本、有 Tomcat 部署路径约定的完整工程。它解决的不是“怎么写 HelloWorld.jsp”,而是“如何把用户登录、部门管理、员工档案录入、离职状态更新、权限跳转这些业务逻辑,用原生 JSP+Servlet 串成一条不崩的链路”。适合计算机/软工专业大三学生做课程设计,也适合想补全 JavaWeb 底层链路(从请求进 Filter 到 Servlet 处理再到 JSP 渲染)的转岗者。它不炫技,但每一步都踩在 JavaWeb 开发的真实断点上:比如web.xml里 servlet-mapping 的/emp/*路径匹配规则、context.xml中 JNDI 数据源配置、WEB-INF/web.xml与META-INF/MANIFEST.MF的协同作用——这些不是考点,是部署时真正会卡住你的地方。


2. 从解压到首页渲染:五步走通整个部署链路,每一步都对应一个真实环境变量

2.1 解压后先看目录结构:识别核心模块与“非装饰性”文件

解压后你会看到类似这样的层级(实际以 ZIP 内容为准,但典型结构如下):

hrms/ ├── src/ # Java 源码根目录 │ ├── main/ │ │ ├── java/ # Servlet 类、DAO、Service 层 │ │ │ └── com/hrms/ # 包名前缀,含 LoginServlet.java, EmpServlet.java 等 │ │ └── resources/ # db.properties 或 jdbc.properties(关键!) │ └── webapp/ # Web 资源根目录(等同于传统 WebContent) │ ├── WEB-INF/ │ │ ├── web.xml # 核心配置:servlet 定义、filter、welcome-file-list │ │ └── lib/ # jar 包:mysql-connector-java-x.x.jar 必须存在 │ ├── static/ # CSS/JS 静态资源(注意:adminlte.css 在此目录下) │ └── jsp/ # 所有 .jsp 页面:login.jsp, index.jsp, emp_list.jsp 等 ├── sql/ # 数据库脚本:hrms.sql 或 init.sql(建库建表+初始数据) └── README.md # (如有)说明数据库用户名密码、默认账号

提示:adminlte.css等文件出现在static/下而非WEB-INF/,是因为WEB-INF是受保护目录,外部无法直接访问。所有 CSS/JS 必须放在webapp/static/或webapp/根下才能被浏览器加载。这是新手第一次启动页面空白的最常见原因。

2.2 数据库初始化:执行 SQL 脚本前必须确认三件事

不要直接双击.sql文件用 Navicat 执行——很多脚本依赖CREATE DATABASE IF NOT EXISTS hrms CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;这类语句,而 Navicat 默认不启用“执行多条语句”选项。

正确做法(命令行优先,避免 GUI 陷阱):

# 1. 登录 MySQL(假设 root 密码为 123456) mysql -u root -p123456 # 2. 手动创建数据库(确保字符集) CREATE DATABASE hrms CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; # 3. 退出后执行脚本(关键:-e 参数让 mysql 客户端执行完即退出) mysql -u root -p123456 hrms < /path/to/hrms/sql/hrms.sql

参数说明:

  • utf8mb4:支持 emoji 和四字节 UTF-8 字符,避免中文乱码(尤其姓名字段含生僻字时);
  • -e:避免交互式等待,适合自动化部署;
  • hrms.sql中应包含USE hrms;和完整的CREATE TABLE语句,若无USE,需在脚本开头手动加。

2.3 Tomcat 配置:context.xml与web.xml的双重绑定

该系统大概率使用 JNDI 数据源(比硬编码 URL 更安全),因此src/main/webapp/META-INF/context.xml是必查文件:

<!-- META-INF/context.xml --> <?xml version="1.0" encoding="UTF-8"?> <Context> <Resource name="jdbc/hrms" auth="Container" type="javax.sql.DataSource" factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" driverClassName="com.mysql.cj.jdbc.Driver" url="jdbc:mysql://localhost:3306/hrms?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=Asia/Shanghai" username="root" password="123456" maxActive="20" minIdle="5" maxWait="10000"/> </Context>

关键点解析:

  • name="jdbc/hrms":JNDI 名称,必须与web.xml中<resource-ref>的res-ref-name一致;
  • url中serverTimezone=Asia/Shanghai:MySQL 8.0+ 强制要求,否则报The server time zone value '...' is unrecognized;
  • &amp;:XML 中&必须转义,写成&amp;,否则 Tomcat 启动失败。

同时检查WEB-INF/web.xml是否声明了该资源:

<!-- WEB-INF/web.xml --> <resource-ref> <description>HRMS Database Connection</description> <res-ref-name>jdbc/hrms</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Container</res-auth> </resource-ref>

2.4 IDE 配置:IntelliJ IDEA 中让 JSP 正确编译的三个隐藏开关

即使你已配置好 Tomcat Server,JSP 仍可能报java.lang.ClassNotFoundException: org.apache.jsp.index_jsp——这不是类路径问题,而是 IDEA 未启用 JSP 编译器。

必须操作:

  1. File → Project Structure → Modules → [你的模块] → Sources:确认src/main/webapp已标记为Web Resources Root;
  2. File → Settings → Build → Compiler → Java Compiler:勾选"Use compiler: javac in-process"(避免 JDK 版本冲突);
  3. File → Settings → Build → Compiler → Compiler → Java Compiler:设置Target bytecode version = 8(JSP 编译依赖 Java 8 兼容性);
  4. 最关键一步:File → Settings → Build → Compiler → Annotation Processors→ 勾选"Enable annotation processing",并设置Processor path为tomcat/lib/jasper.jar(路径需指向你本地 Tomcat 的lib目录)。

血泪经验:很多教程漏掉第 4 步,导致 JSP 页面始终 500 错误,日志只显示org.apache.jasper.JasperException: Unable to compile class for JSP,根本原因就是jasper.jar未参与编译过程。

2.5 启动验证:用 curl 命令绕过浏览器,直击 Tomcat 响应头

不要一上来就打开http://localhost:8080/hrms/login.jsp——先用命令行确认服务是否真正响应:

# 发送 GET 请求,只看 HTTP 状态码和 Content-Type curl -I http://localhost:8080/hrms/login.jsp # 预期返回(关键看 200 OK 和 text/html) HTTP/1.1 200 OK Content-Type: text/html;charset=UTF-8 Content-Length: 2345 Date: Mon, 15 Apr 2024 08:22:17 GMT

如果返回HTTP/1.1 404 Not Found:

  • 检查 WAR 包是否部署成功($TOMCAT_HOME/webapps/下是否有hrms/目录);
  • 检查web.xml中<welcome-file-list>是否包含login.jsp;
  • 检查login.jsp是否真在webapp/jsp/下(而非webapp/根目录)。

如果返回HTTP/1.1 500 Internal Server Error:

  • 查catalina.out日志末尾,定位Caused by:行;
  • 最常见是ClassNotFoundException: com.mysql.cj.jdbc.Driver(jar 包没放对位置)或SQLException: Access denied for user 'root'@'localhost'(数据库密码错误)。

3. Servlet 生命周期与请求流转:从 login.jsp 提交到 LoginServlet 的七层调用链

3.1 表单提交路径:action属性如何触发正确的 Servlet 映射

login.jsp中的表单通常长这样:

<form action="login" method="post"> <input type="text" name="username" /> <input type="password" name="password" /> <button type="submit">登录</button> </form>

注意action="login"是相对路径,它会被浏览器解析为http://localhost:8080/hrms/login。而web.xml中必须有对应映射:

<servlet> <servlet-name>LoginServlet</servlet-name> <servlet-class>com.hrms.servlet.LoginServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>LoginServlet</servlet-name> <url-pattern>/login</url-pattern> <!-- 关键:必须与 action 值完全一致 --> </servlet-mapping>

玄学细节:/login是精确匹配;/login/*是路径前缀匹配;*.do是扩展名匹配。本项目用前者,意味着只有POST /login才会进入LoginServlet,GET /login会 405 错误(除非doGet()也实现)。

3.2 LoginServlet 的标准处理流程:request.getParameter() 到 request.getRequestDispatcher() 的闭环

典型LoginServlet.java代码片段:

public class LoginServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 获取表单参数(注意:name 属性值必须与 getParameter() 一致) String username = request.getParameter("username"); // 来自 <input name="username"> String password = request.getParameter("password"); // 2. 调用 Service 层验证(此处简化为硬编码校验) if ("admin".equals(username) && "123456".equals(password)) { // 3. 设置 session 属性(登录态) request.getSession().setAttribute("user", username); // 4. 转发到主页(注意:/index.jsp 是相对于 webapp 的路径) request.getRequestDispatcher("/jsp/index.jsp").forward(request, response); } else { // 5. 转发回登录页,并带错误信息 request.setAttribute("error", "用户名或密码错误"); request.getRequestDispatcher("/jsp/login.jsp").forward(request, response); } } }

参数说明:

  • request.getRequestDispatcher():服务器端内部跳转,URL 地址栏不变,request对象可传递属性;
  • response.sendRedirect():客户端重定向,URL 变化,request属性丢失(本项目登录成功后用forward,避免刷新重复提交);
  • request.getSession().setAttribute():将用户信息存入 Session,后续所有 Servlet 可通过request.getSession().getAttribute("user")获取。

3.3 Filter 拦截器:如何实现未登录用户访问员工列表自动跳转

web.xml中定义的LoginFilter是权限控制核心:

<filter> <filter-name>LoginFilter</filter-name> <filter-class>com.hrms.filter.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>LoginFilter</filter-name> <url-pattern>/jsp/emp_list.jsp</url-pattern> <!-- 拦截具体 JSP 页面 --> <url-pattern>/servlet/EmpServlet</url-pattern> <!-- 拦截 Servlet --> </filter-mapping>

LoginFilter.java关键逻辑:

public class LoginFilter implements Filter { @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) req; HttpServletResponse response = (HttpServletResponse) resp; // 1. 检查 session 中是否存在 user 属性 Object user = request.getSession().getAttribute("user"); if (user == null) { // 2. 未登录,重定向到登录页(注意:sendRedirect 用绝对路径) response.sendRedirect(request.getContextPath() + "/jsp/login.jsp"); return; // 阻断后续执行 } // 3. 已登录,放行 chain.doFilter(req, resp); } }

注意:request.getContextPath()返回应用上下文路径(如/hrms),确保重定向地址为http://localhost:8080/hrms/jsp/login.jsp,而非硬编码/jsp/login.jsp(否则部署到 ROOT 上下文会失效)。

3.4 EmpServlet 的 CRUD 实现:URL 路径设计决定功能分支

EmpServlet通常通过?action=add或/emp/delete?id=123区分操作类型:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String action = request.getParameter("action"); switch (action) { case "list": showEmpList(request, response); // 查询全部员工 break; case "toAdd": request.getRequestDispatcher("/jsp/emp_add.jsp").forward(request, response); break; case "delete": deleteEmp(request, response); // 删除 break; default: response.sendError(HttpServletResponse.SC_BAD_REQUEST); } } private void deleteEmp(HttpServletRequest request, HttpServletResponse response) throws IOException { String idStr = request.getParameter("id"); int id = Integer.parseInt(idStr); // 注意:生产环境需 try-catch EmpService.delete(id); // 调用 DAO 执行 DELETE FROM emp WHERE id=? response.sendRedirect(request.getContextPath() + "/servlet/EmpServlet?action=list"); }

边界坑:Integer.parseInt()在id为空或非数字时抛NumberFormatException,必须包裹 try-catch 并返回友好提示,否则 500 错误。


4. 前端 AdminLTE 集成:CSS 文件加载失败的四个真实原因与修复方案

4.1 路径引用必须遵循 WAR 包结构:/static/adminlte.cssvs../static/adminlte.css

index.jsp中引入 CSS 的典型写法:

<!-- 错误:相对路径,依赖当前 JSP 所在目录层级 --> <link rel="stylesheet" href="../static/adminlte.css"> <!-- 正确:绝对路径,从上下文根开始 --> <link rel="stylesheet" href="${pageContext.request.contextPath}/static/adminlte.css">

为什么必须用${pageContext.request.contextPath}?
因为应用可能部署在/hrms或/ROOT下。硬编码/static/在 ROOT 上下文下有效,但在/hrms下会请求http://localhost:8080/static/adminlte.css(404);而${pageContext.request.contextPath}动态输出/hrms或/,保证路径正确。

4.2 AdminLTE 版本兼容性:adminlte.core.css与 jQuery 的版本锁死关系

该 ZIP 包中出现adminlte.core.css和adminlte.core.min.css,表明使用的是 AdminLTE v3+(v2 无 core 文件)。v3 要求 jQuery ≥ 3.4.1,而 Tomcat 默认的jsp-api.jar仅提供 JSP 规范,不包含 jQuery。

检查步骤:

  1. 打开webapp/static/js/,确认存在jquery.min.js(版本号需 ≥ 3.4.1);
  2. 在index.jsp中<head>里,jQuery 必须在 AdminLTE JS 之前加载:
<script src="${pageContext.request.contextPath}/static/js/jquery.min.js"></script> <script src="${pageContext.request.contextPath}/static/js/bootstrap.bundle.min.js"></script> <script src="${pageContext.request.contextPath}/static/js/adminlte.min.js"></script>

翻车现场:若bootstrap.bundle.min.js在jquery.min.js之前加载,浏览器控制台报Uncaught ReferenceError: $ is not defined,AdminLTE 的侧边栏、折叠菜单全部失效。

4.3 中文乱码终极排查:从 MySQL 到 JSP 的四层字符集校验

即使页面<meta charset="UTF-8">正确,仍可能显示??,必须逐层验证:

层级检查项验证命令/方法期望值
MySQL 服务端服务器默认字符集mysql -u root -p -e "SHOW VARIABLES LIKE 'character_set%';"character_set_server = utf8mb4
MySQL 数据库hrms库字符集SHOW CREATE DATABASE hrms;DEFAULT CHARACTER SET = utf8mb4
MySQL 表emp表字符集SHOW CREATE TABLE emp;DEFAULT CHARSET=utf8mb4
JSP 页面页面编码声明查login.jsp第一行:<%@ page contentType="text/html;charset=UTF-8" %>必须存在且为UTF-8

漏掉任何一层,中文都会变问号。尤其注意db.properties中 JDBC URL 必须含?useUnicode=true&characterEncoding=utf8。

4.4 Tomcat 乱码:catalina.sh中 JVM 参数的隐形杀手

Linux 下启动 Tomcat 后,日志中System.out.println("张三")显示为å¼ ä¸‰,根源是 JVM 默认编码非 UTF-8。

修复方法(永久生效):
编辑$TOMCAT_HOME/bin/catalina.sh,在JAVA_OPTS定义处添加:

# 在 catalina.sh 中找到 JAVA_OPTS 行,追加: JAVA_OPTS="$JAVA_OPTS -Dfile.encoding=UTF-8"

Windows 用户:修改catalina.bat,在set JAVA_OPTS=行后添加set JAVA_OPTS=%JAVA_OPTS% -Dfile.encoding=UTF-8。

后悔药:若已部署,可临时在web.xml中添加filter强制请求编码:

<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

5. 避坑指南:五个高频翻车点与对应诊断命令(附真实日志片段)

5.1 现象:启动 Tomcat 后访问http://localhost:8080/hrms/login.jsp返回 404

原因:WAR 包未正确部署,或web.xml中welcome-file-list未包含login.jsp
解决:

  • 检查$TOMCAT_HOME/webapps/下是否存在hrms/目录(而非hrms.war);
  • 查web.xml是否有:
<welcome-file-list> <welcome-file>jsp/login.jsp</welcome-file> <!-- 注意路径:jsp/ 开头 --> </welcome-file-list>

若welcome-file写成login.jsp(无jsp/前缀),Tomcat 会在webapp/根下找,但实际文件在webapp/jsp/下,必然 404。

5.2 现象:登录时控制台报java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver

原因:mysql-connector-java-8.0.33.jar未放入WEB-INF/lib/,或版本与 MySQL 不匹配
解决:

  • 确认src/main/webapp/WEB-INF/lib/下有mysql-connector-java-x.x.jar(x.x ≥ 8.0);
  • 若用 MySQL 5.7,需降级到mysql-connector-java-5.1.49.jar;
  • 验证命令:jar -tf target/hrms/WEB-INF/lib/mysql-connector-java-8.0.33.jar | grep Driver应输出com/mysql/cj/jdbc/Driver.class。

5.3 现象:点击“员工列表”按钮后页面空白,浏览器控制台报Uncaught TypeError: $ is not a function

原因:jQuery 未加载成功,或加载顺序错误
解决:

  • 打开浏览器开发者工具 → Network 标签 → 刷新页面 → 查看jquery.min.js请求状态码是否为 200;
  • 若为 404,检查href路径是否漏写${pageContext.request.contextPath};
  • 若为 200 但控制台仍有报错,查看 Elements 中<script>标签顺序,确保 jQuery 在所有依赖它的 JS 之前。

5.4 现象:新增员工后数据库无记录,但页面跳转到emp_list.jsp

原因:EmpServlet中add方法未 commit 事务,或 DAO 层 SQL 语法错误
解决:

  • 查EmpDao.java中insert方法,确认是否调用conn.commit()(若用 JNDI 数据源,通常已配置自动 commit);
  • 在EmpDao.insert()中添加日志:System.out.println("SQL: " + sql + ", params: " + Arrays.toString(params));;
  • 将打印出的 SQL 粘贴到 MySQL 命令行执行,观察是否报错(如字段名拼写错误、NOT NULL 字段未赋值)。

5.5 现象:Tomcat 启动后立即闪退,catalina.out末尾显示SEVERE: Failed to initialize connector [Connector[HTTP/1.1-8080]]

原因:8080 端口被占用(常见于 Skype、其他 Tomcat 实例)
解决:

  • Linux:netstat -tuln | grep :8080→kill -9 <PID>;
  • Windows:netstat -ano | findstr :8080→taskkill /PID <PID> /F;
  • 或修改$TOMCAT_HOME/conf/server.xml中<Connector port="8080"为8081。

6. 进阶技巧:用 Maven 重构原始项目,实现一键打包与跨环境部署

6.1 为什么必须重构?原始 ZIP 的三大维护痛点

你拿到的 ZIP 是纯手工目录结构,没有pom.xml,这意味着:

  • 无法用mvn clean package一键构建 WAR;
  • 添加新 jar 包(如 Apache Commons Lang)需手动复制到WEB-INF/lib/;
  • 开发环境(localhost)、测试环境(192.168.1.100)、生产环境(prod-db)的数据库配置无法隔离。

重构目标:将src/main/java、src/main/webapp等目录按 Maven 标准布局,用profiles管理不同环境配置。

6.2pom.xml核心配置:定义 Java 版本、Tomcat 插件与依赖范围

<project xmlns="http://maven.apache.org/POM/4.0.0"> <modelVersion>4.0.0</modelVersion> <groupId>com.hrms</groupId> <artifactId>hrms</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- Servlet API:provided 范围,由 Tomcat 提供,不打入 WAR --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <!-- MySQL 驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> </dependencies> <build> <plugins> <!-- Tomcat 插件:mvn tomcat7:run 直接启动 --> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>8080</port> <path>/hrms</path> <uriEncoding>UTF-8</uriEncoding> </configuration> </plugin> </plugins> </build> </project>

关键点:

  • <scope>provided</scope>:告诉 Maven 此依赖由容器提供,打包时不包含,避免与 Tomcat 自带的servlet-api.jar冲突;
  • tomcat7-maven-plugin:虽名 tomcat7,实则支持 Tomcat 8/9/10,mvn tomcat7:run启动内嵌 Tomcat,无需单独安装。

6.3 多环境配置:用profiles实现 dev/test/prod 数据库无缝切换

在pom.xml中添加 profiles:

<profiles> <profile> <id>dev</id> <properties> <jdbc.url>jdbc:mysql://localhost:3306/hrms?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=Asia/Shanghai</jdbc.url> <jdbc.username>root</jdbc.username> <jdbc.password>123456</jdbc.password> </properties> <activation> <activeByDefault>true</activeByDefault> </activation> </profile> <profile> <id>prod</id> <properties> <jdbc.url>jdbc:mysql://prod-db:3306/hrms?...</jdbc.url> <jdbc.username>hrms_prod</jdbc.username> <jdbc.password>${env.PROD_DB_PASSWORD}</jdbc.password> </properties> </profile> </profiles>

配合src/main/resources/db.properties使用:

jdbc.url=${jdbc.url} jdbc.username=${jdbc.username} jdbc.password=${jdbc.password}

打包命令:

  • 开发环境:mvn clean package(默认激活 dev);
  • 生产环境:mvn clean package -Pprod -Denv.PROD_DB_PASSWORD=real_password。

6.4 自动化部署脚本:Linux 下一键重启 Tomcat 并发布新 WAR

编写deploy.sh(需赋予执行权限chmod +x deploy.sh):

#!/bin/bash # 1. 停止 Tomcat $TOMCAT_HOME/bin/shutdown.sh sleep 5 # 2. 删除旧应用 rm -rf $TOMCAT_HOME/webapps/hrms* rm -rf $TOMCAT_HOME/work/Catalina/localhost/hrms* # 3. 复制新 WAR(假设 mvn package 后生成 target/hrms-1.0-SNAPSHOT.war) cp target/hrms-1.0-SNAPSHOT.war $TOMCAT_HOME/webapps/hrms.war # 4. 启动 Tomcat $TOMCAT_HOME/bin/startup.sh # 5. 检查启动日志(tail -f 会持续输出,Ctrl+C 退出) echo "Deploy complete. Checking logs..." tail -n 20 $TOMCAT_HOME/logs/catalina.out

为什么这比手动复制更可靠?

  • 强制删除work/目录:清除 Jasper 编译缓存,避免旧 JSP class 未更新;
  • sleep 5:确保 Tomcat 进程完全退出,防止端口占用;
  • tail -n 20:快速确认最后一屏日志无 ERROR,比打开完整日志高效。

从那以后我每次交付课程设计,都强制走一遍mvn clean package→sh deploy.sh→curl -I http://localhost:8080/hrms/login.jsp三连,哪怕只是本地测试。因为真正的“跑通”,不是浏览器看到登录框,而是curl返回200 OK且Content-Type正确——这背后是数据库连接、Servlet 映射、JSP 编译、静态资源路径、字符集、Session 管理全部链条的咬合。希望帮到你。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 11:57:10

R语言随机森林最小可靠落地路径

简介&#xff1a;本资源是一份面向R语言初学者与数据科学入门者的随机森林算法实践材料&#xff0c;聚焦于分类与回归任务中的集成建模方法&#xff0c;帮助用户快速掌握R环境下随机森林的核心实现与评估流程。压缩包为ZIP格式&#xff0c;仅含1个R源文件&#xff08;.R&#x…

作者头像 李华
网站建设 2026/9/28 11:51:12

Cursor 与 ChatGPT Canvas 配 TaoToken:AI 开发者工具双子星配置对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/28 11:48:35

特斯拉第三代机器人疑似意外曝光

特斯拉尚未正式发布的第三代人形机器人Optimus&#xff0c;疑似先在自家的手机App中露出了轮廓。 9月23日&#xff0c;Tesla North、Drive Tesla等媒体报道&#xff0c;特斯拉安卓App的安装包中出现了一组带有“gen3”标记的机器人图片。图中的机器人采用金色与黑色搭配&#…

作者头像 李华
网站建设 2026/9/28 11:48:05

RustFS站点复制跨集群容灾实战:多站点可写异步同步要踩哪些坑

生产在城市 A&#xff0c;容灾在城市 B&#xff0c;两边各跑一套对象存储集群。平时各写各的&#xff0c;真要切换才发现 B 的数据比 A 旧了半天&#xff0c;还得手工补。站点复制&#xff08;Site Replication&#xff09;要解决的正是这件事&#xff1a;把多套独立部署组成一…

作者头像 李华