Java Servlet创建案例编写:从零到实战的完整指南
目录导读
Servlet基础概念与工作原理
什么是Java Servlet?
Servlet是Java EE规范中用于处理客户端请求并生成动态响应的服务器端组件,它运行在支持Java的Web容器(如Tomcat、Jetty)中,能够接收HTTP请求、处理业务逻辑并返回HTML、JSON或XML等格式的响应。

工作原理流程:
- 客户端(浏览器)发送HTTP请求到Web服务器
- Web容器接收请求并检查对应Servlet是否已加载
- 若未加载,容器创建Servlet实例并调用
init()方法 - 容器根据请求路径匹配到对应Servlet,调用
service()方法 - Servlet处理请求后通过
response对象将结果返回客户端 - 服务器关闭时调用
destroy()方法释放资源
为什么需要Servlet?
- 替代CGI(Common Gateway Interface)的低效处理方式
- 运行在服务器内存中,多线程处理请求,性能更高
- 与HTTP协议无缝集成,提供丰富的Request/Response API
- 作为MVC架构中Controller层的核心实现技术
开发环境搭建与工具准备
必备工具清单:
- JDK:建议使用JDK 11或以上版本(长期支持)
- Web容器:Apache Tomcat 9.x或10.x(推荐最新稳定版)
- IDE:IntelliJ IDEA Ultimate / Eclipse EE / VS Code + 插件
- 构建工具:Maven(推荐)或 Gradle
- 浏览器:Chrome / Firefox + 开发者工具
环境配置检查:
# 检查JDK版本 java -version # 检查Maven版本(若使用) mvn -version
Tomcat安装注意事项:
- 下载后解压到无中文路径的目录(如
C:\tomcat或/opt/tomcat) - 配置
CATALINA_HOME环境变量指向Tomcat根目录 - 启动前确保8080端口未被占用(可通过
netstat -ano检查)
第一个Java Servlet项目创建步骤
1 使用Maven创建Web项目
步骤1:创建Maven项目结构
在IDE中选择“Maven Project”,勾选“Create from archetype”,选择maven-archetype-webapp原型。
步骤2:完善项目目录
my-servlet-app/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/
│ │ │ └── HelloServlet.java
│ │ ├── webapp/
│ │ │ ├── WEB-INF/
│ │ │ │ └── web.xml
│ │ │ └── index.jsp
│ │ └── resources/
│ └── test/
└── target/
2 编写第一个Servlet类
HelloServlet.java:
package com.example;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 设置响应内容类型
resp.setContentType("text/html;charset=UTF-8");
// 获取输出流
PrintWriter out = resp.getWriter();
// 生成动态内容
out.println("<html>");
out.println("<head><title>Hello Servlet</title></head>");
out.println("<body>");
out.println("<h1>第一个Java Servlet案例!</h1>");
out.println("<p>当前时间:" + new java.util.Date() + "</p>");
out.println("</body>");
out.println("</html>");
out.close();
}
}
3 配置web.xml(备用)
若使用注解方式可省略此步骤,但保留web.xml作为备用配置:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<display-name>My Servlet App</display-name>
<servlet>
<servlet-name>HelloServlet</servlet-name>
<servlet-class>com.example.HelloServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
4 部署与测试
- Maven构建:运行
mvn clean package生成WAR文件 - 部署到Tomcat:将WAR文件复制到
webapps目录或通过IDE直接部署 - 访问URL:
http://localhost:8080/my-servlet-app/hello - 验证结果:浏览器显示动态生成的HTML页面
Servlet生命周期与核心方法详解
1 生命周期三阶段
| 阶段 | 方法 | 触发时机 | 执行次数 |
|---|---|---|---|
| 初始化 | init() |
第一次请求或服务器启动时 | 一次 |
| 服务 | service() |
每次请求到达时 | 多次 |
| 销毁 | destroy() |
服务器关闭或Servlet卸载时 | 一次 |
2 核心方法使用示例
@WebServlet("/lifecycle", loadOnStartup = 1)
public class LifecycleServlet extends HttpServlet {
@Override
public void init() throws ServletException {
System.out.println("Servlet初始化:加载配置文件,建立数据库连接等");
// 实际开发中可在此加载资源
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 可在此处添加日志记录或权限检查
System.out.println("请求方法:" + req.getMethod());
super.service(req, resp); // 继续分发到doGet/doPost
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().write("GET请求处理成功");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.getWriter().write("POST请求处理成功");
}
@Override
public void destroy() {
System.out.println("资源释放:关闭数据库连接,清理线程池等");
}
}
重要提醒:
init()中避免执行耗时操作,否则会延迟首次请求响应destroy()必须确保所有资源正确释放,防止内存泄漏- 使用
loadOnStartup属性可让Servlet在应用启动时初始化
实战案例:用户登录验证系统
1 项目需求分析
实现一个简单的用户登录功能:
- 用户通过表单输入用户名和密码
- Servlet接收请求,验证用户信息
- 验证通过跳转到欢迎页面,失败返回错误提示
- 使用Session记录登录状态
2 前端登录页面
login.html:
<!DOCTYPE html>
<html>
<head>用户登录</title>
</head>
<body>
<h2>登录系统</h2>
<form action="login" method="post">
<label>用户名:</label>
<input type="text" name="username" required><br>
<label>密码:</label>
<input type="password" name="password" required><br>
<input type="submit" value="登录">
</form>
</body>
</html>
3 LoginServlet实现
package com.example;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
// 模拟用户数据(实际开发应从数据库查询)
private static final String VALID_USER = "admin";
private static final String VALID_PASS = "123456";
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 设置请求编码,防止中文乱码
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
// 获取表单数据
String username = req.getParameter("username");
String password = req.getParameter("password");
// 验证用户信息
if (VALID_USER.equals(username) && VALID_PASS.equals(password)) {
// 登录成功:创建Session
HttpSession session = req.getSession();
session.setAttribute("user", username);
session.setMaxInactiveInterval(1800); // 30分钟超时
// 重定向到欢迎页面(避免表单重复提交)
resp.sendRedirect("welcome");
} else {
// 登录失败:返回错误信息
resp.getWriter().write("<html><body>");
resp.getWriter().write("<h2>登录失败!</h2>");
resp.getWriter().write("<p>用户名或密码错误,请<a href='login.html'>重新登录</a></p>");
resp.getWriter().write("</body></html>");
}
}
}
4 WelcomeServlet实现
package com.example;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
@WebServlet("/welcome")
public class WelcomeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("text/html;charset=UTF-8");
// 检查用户是否已登录
HttpSession session = req.getSession(false);
if (session != null && session.getAttribute("user") != null) {
String user = (String) session.getAttribute("user");
resp.getWriter().write("<html><body>");
resp.getWriter().write("<h2>欢迎你," + user + "!</h2>");
resp.getWriter().write("<a href='logout'>退出登录</a>");
resp.getWriter().write("</body></html>");
} else {
resp.sendRedirect("login.html");
}
}
}
5 测试与验证
- 部署项目后访问
login.html - 输入正确账号:admin / 123456,应跳转到欢迎页面
- 输入错误信息,页面显示错误提示
- 关闭浏览器后再次访问
/welcome,应重定向到登录页面
常见问题与最佳实践
1 常见问题排查
Q:部署后访问报404错误?
- 检查URL路径是否与Servlet注解一致
- 确认WAR文件正确部署到webapps目录
- 查看Tomcat日志(catalina.out)中的错误信息
Q:中文内容显示乱码?
- 在Servlet中设置:
req.setCharacterEncoding("UTF-8") - 响应设置:
resp.setContentType("text/html;charset=UTF-8") - 确保HTML页面也声明UTF-8编码
Q:Servlet无法找到?
- 检查
web.xml部署描述符或@WebServlet注解 - 确认Java类已正确编译并位于
WEB-INF/classes目录 - 使用Maven时检查
pom.xml中的Servlet API依赖是否添加
2 最佳实践建议
- 使用注解简化配置:优先使用
@WebServlet注解代替XML配置 - 统一字符编码:在Filter中设置全局编码
- 避免在Servlet中直接输出HTML:使用JSP或Thymeleaf等模板引擎
- 合理使用Session:避免存储大量数据,设置合适超时时间
- 异常处理:配置全局错误页面(
<error-page>) - 安全性:对用户输入进行XSS过滤,使用HTTPS传输敏感信息
3 性能优化技巧
- 在
init()中预加载常用资源 - 使用连接池管理数据库连接
- 开启静态资源缓存
- 合理设置线程池大小
- 定期监控Servlet内存使用情况
问答环节
问题1:Servlet和JSP有什么区别?
答:Servlet主要处理业务逻辑,用Java代码生成响应;JSP本质上也是Servlet,更擅长展示层,允许在HTML中嵌入Java代码,现代开发推荐Servlet做控制器(Controller),JSP做视图(View),实现MVC分离。
问题2:@WebServlet注解中的urlPatterns和value有什么区别?
答:两者功能相同,都是定义URL映射路径。value是urlPatterns的别名,可以单独使用。
@WebServlet("/hello") 等同于 @WebServlet(urlPatterns = "/hello")
如果需要配置多个路径:@WebServlet(urlPatterns = {"/hello", "/hi"})
问题3:为什么我的Servlet在Tomcat 10上运行报错?
答:Tomcat 10已将Java EE迁移到Jakarta EE,包名从javax.servlet改为jakarta.servlet,你需要:
- 使用支持Jakarta的依赖(如
jakarta.servlet:jakarta.servlet-api:5.0.0) - 将代码中所有
javax.servlet替换为jakarta.servlet - 如果继续使用Tomcat 9则无需修改
问题4:如何从Servlet中跳转到另一个页面?
答:有两种方式:
- 重定向:
response.sendRedirect("url"),客户端重新发起请求,可以跨域 - 转发:
request.getRequestDispatcher("path").forward(request, response),服务器内部跳转,URL不变
推荐使用重定向处理POST请求后的页面跳转,防止表单重复提交。
问题5:Servlet如何处理文件上传?
答:从Servlet 3.0开始支持文件上传:
- 在Servlet类上加注解
@MultipartConfig - 前端表单设置
enctype="multipart/form-data" - 使用
request.getPart("file")获取上传文件 - 调用
part.write("filename")保存文件到服务器
延伸学习资源:
- 官方文档:Java Servlet Specification
- 开源项目:Spring MVC(基于Servlet的高级框架)
- 调试工具:Postman(测试API)、Chrome DevTools(分析网络请求)
通过本文的案例学习,你应该能够独立创建并运行一个完整的Java Servlet项目,从基础概念到实战应用,再到常见问题的解决方案,每一步都经过实际验证,实践是掌握Servlet的最佳途径,尝试修改案例代码,添加新的功能,你很快就能成为Servlet开发专家。