1. 概述
在本教程中,我们将使用 Servlet 3.0+ 构建一个 Java Web 应用。
重点介绍三个核心注解:@WebServlet
、@WebFilter
和 @WebListener
,它们可以完全替代传统的 web.xml
配置文件。
2. Maven 依赖
要使用这些新特性,我们需要引入以下依赖:
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0-M1</version>
</dependency>
3. 基于 XML 的配置(传统方式)
在 Servlet 3.0 之前,Java Web 应用的配置是通过 web.xml
文件完成的:
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<listener>
<listener-class>com.baeldung.servlets3.web.listeners.RequestListener</listener-class>
</listener>
<servlet>
<servlet-name>uppercaseServlet</servlet-name>
<servlet-class>com.baeldung.servlets3.web.servlets.UppercaseServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>uppercaseServlet</servlet-name>
<url-pattern>/uppercase</url-pattern>
</servlet-mapping>
<filter>
<filter-name>emptyParamFilter</filter-name>
<filter-class>com.baeldung.servlets3.web.filters.EmptyParamFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>emptyParamFilter</filter-name>
<url-pattern>/uppercase</url-pattern>
</filter-mapping>
</web-app>
接下来,我们将用 Servlet 3.0 引入的注解逐步替代这些配置项。
4. Servlet 配置
从 JEE 6 开始,Servlet 3.0 支持使用注解定义 Servlet,从而减少对 web.xml
的依赖。
✅ 使用 @WebServlet
注解可以定义一个 Servlet 并绑定 URL 模式。
例如,我们定义一个用于 /uppercase
路径的 Servlet,它将请求参数 input
转为大写:
@WebServlet(urlPatterns = "/uppercase", name = "uppercaseServlet")
public class UppercaseServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
String inputString = request.getParameter("input").toUpperCase();
PrintWriter out = response.getWriter();
out.println(inputString);
}
}
⚠️ 注意我们给 Servlet 指定了名称 uppercaseServlet
,这个名称可以在其他地方引用(如 Filter 映射)。
使用 @WebServlet
注解,我们替代了 web.xml
中的 <servlet>
和 <servlet-mapping>
部分。
5. Filter 配置
Filter 是用来拦截请求或响应的对象,常用于预处理或后处理逻辑。
✅ 使用 @WebFilter
注解可以定义一个 Filter。
下面是一个用于检查 input
参数是否存在的 Filter:
@WebFilter(urlPatterns = "/uppercase")
public class EmptyParamFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
String inputString = servletRequest.getParameter("input");
if (inputString != null && inputString.matches("[A-Za-z0-9]+")) {
filterChain.doFilter(servletRequest, servletResponse);
} else {
servletResponse.getWriter().println("Missing input parameter");
}
}
// 其他方法实现
}
通过 @WebFilter
注解,我们替代了 web.xml
中的 <filter>
和 <filter-mapping>
部分。
6. Listener 配置
Listener 用于监听特定事件(如请求创建/销毁),并执行我们自定义的逻辑。
✅ 使用 @WebListener
注解可以定义一个 Listener。
下面是一个监听请求销毁事件的 Listener,用于统计请求次数:
@WebListener
public class RequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent event) {
HttpServletRequest request = (HttpServletRequest)event.getServletRequest();
if (!request.getServletPath().equals("/counter")) {
ServletContext context = event.getServletContext();
context.setAttribute("counter", (int) context.getAttribute("counter") + 1);
}
}
// 其他方法实现
}
⚠️ 注意我们排除了 /counter
路径的请求,避免计数干扰。
通过 @WebListener
注解,我们替代了 web.xml
中的 <listener>
部分。
7. 构建与运行
测试时我们还添加了一个 /counter
接口,用于返回当前请求计数。
我们使用 Tomcat 作为应用服务器。
如果你使用的是 maven-war-plugin
3.1.0 之前的版本,需要设置:
<failOnMissingWebXml>false</failOnMissingWebXml>
然后将 .war
文件部署到 Tomcat,测试接口:
测试 /uppercase
接口
curl http://localhost:8080/spring-mvc-java/uppercase?input=texttouppercase
TEXTTOUPPERCASE
测试错误处理
curl http://localhost:8080/spring-mvc-java/uppercase
Missing input parameter
测试 Listener 统计
curl http://localhost:8080/spring-mvc-java/counter
Request counter: 2
8. 仍需使用 web.xml 的场景
虽然 Servlet 3.0 大幅减少了对 web.xml
的依赖,但在以下场景中仍然需要它:
❌ 无法通过注解定义 Filter 执行顺序
✅ 如果有多个 Filter 需要按顺序执行,仍需使用 <filter-mapping>
配置
❌ 定义 Session 超时时间 需要使用 <session-config>
❌ 容器级安全角色配置仍需 <security-role>
❌ 指定欢迎页面仍需 <welcome-file-list>
✅ Servlet 3.0 还提供了 **编程式配置接口 ServletContainerInitializer
**,可用于弥补部分 XML 配置的缺失。
9. 总结
本教程展示了如何使用 Servlet 3.0+ 的注解替代 web.xml
来配置 Java Web 应用。
✅ 优点:
- 配置更简洁
- 更易维护
- 代码即配置,减少配置文件冗余
❌ 局限:
- 无法完全替代 XML(如 Filter 顺序)
- 对于复杂项目,混合使用 XML 和注解更合理
源码地址:
如果你使用的是 Spring 框架,可以参考这篇教程:web.xml vs. Initializer with Spring