1. 概述
Java EE注解通过让开发者声明组件在容器中的行为方式,极大简化了开发工作。这些注解是XML描述符的现代替代方案,能显著减少样板代码。
本文将聚焦Java EE 7中Servlet API 3.1引入的注解,深入探讨它们的作用和实际用法。
2. Web注解一览
Servlet API 3.1引入了一套可在Servlet类中使用的新注解类型:
-
@WebServlet
-
@WebInitParam
-
@WebFilter
-
@WebListener
-
@ServletSecurity
-
@HttpConstraint
-
@HttpMethodConstraint
-
@MultipartConfig
接下来我们将逐一详解这些注解。
3. @WebServlet
简单来说,这个注解能将Java类声明为Servlet:
@WebServlet("/account")
public class AccountServlet extends javax.servlet.http.HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// ...
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// ...
}
}
3.1. @WebServlet
属性详解
@WebServlet
提供多个属性用于定制Servlet:
-
name
-
description
-
urlPatterns
-
initParams
使用示例:
@WebServlet(
name = "BankAccountServlet",
description = "Represents a Bank Account and it's transactions",
urlPatterns = {"/account", "/bankAccount" },
initParams = { @WebInitParam(name = "type", value = "savings")})
public class AccountServlet extends javax.servlet.http.HttpServlet {
String accountType = null;
public void init(ServletConfig config) throws ServletException {
// ...
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// ...
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// ...
}
}
name
属性会覆盖默认的Servlet名称(默认为全限定类名)。description
属性用于描述Servlet功能。urlPatterns
指定Servlet可访问的URL(支持多值配置)。
4. @WebInitParam
该注解配合@WebServlet
的initParams
属性使用,用于设置Servlet初始化参数。
示例中设置初始化参数type
值为savings
:
@WebServlet(
name = "BankAccountServlet",
description = "Represents a Bank Account and it's transactions",
urlPatterns = {"/account", "/bankAccount" },
initParams = { @WebInitParam(name = "type", value = "savings")})
public class AccountServlet extends javax.servlet.http.HttpServlet {
String accountType = null;
public void init(ServletConfig config) throws ServletException {
accountType = config.getInitParameter("type");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// ...
}
}
5. @WebFilter
当需要在不修改Servlet内部逻辑的情况下拦截请求和响应时,@WebFilter
就是最佳选择。通过URL模式可将过滤器关联到特定Servlet或静态资源组。
示例使用@WebFilter
将未授权访问重定向到登录页:
@WebFilter(
urlPatterns = "/account/*",
filterName = "LoggingFilter",
description = "Filter all account transaction URLs")
public class LogInFilter implements javax.servlet.Filter {
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(
ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
res.sendRedirect(req.getContextPath() + "/login.jsp");
chain.doFilter(request, response);
}
public void destroy() {
}
}
6. @WebListener
若需监控Servlet及其请求的初始化和变更过程,@WebListener
注解就能派上用场。
编写Web监听器需实现以下接口之一:
-
ServletContextListener
– 监听ServletContext生命周期 -
ServletContextAttributeListener
– 监听ServletContext属性变更 -
ServletRequestListener
– 监听资源请求 -
ServletRequestAttributeListener
– 监听ServletRequest属性变更 -
HttpSessionListener
– 监听会话创建和销毁 -
HttpSessionAttributeListener
– 监听会话属性变更
示例展示如何使用ServletContextListener
配置Web应用:
@WebListener
public class BankAppServletContextListener
implements ServletContextListener {
public void contextInitialized(ServletContextEvent sce) {
sce.getServletContext().setAttribute("ATTR_DEFAULT_LANGUAGE", "english");
}
public void contextDestroyed(ServletContextEvent sce) {
// ...
}
}
7. @ServletSecurity
需要为Servlet指定安全模型(包括角色、访问控制和认证要求)时,使用@ServletSecurity
注解。
示例限制AccountServlet
的访问权限:
@WebServlet(
name = "BankAccountServlet",
description = "Represents a Bank Account and it's transactions",
urlPatterns = {"/account", "/bankAccount" },
initParams = { @WebInitParam(name = "type", value = "savings")})
@ServletSecurity(
value = @HttpConstraint(rolesAllowed = {"Member"}),
httpMethodConstraints = {@HttpMethodConstraint(value = "POST", rolesAllowed = {"Admin"})})
public class AccountServlet extends javax.servlet.http.HttpServlet {
String accountType = null;
public void init(ServletConfig config) throws ServletException {
// ...
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException {
// ...
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException {
double accountBalance = 1000d;
String paramDepositAmt = request.getParameter("dep");
double depositAmt = Double.parseDouble(paramDepositAmt);
accountBalance = accountBalance + depositAmt;
PrintWriter writer = response.getWriter();
writer.println("<html> Balance of " + accountType + " account is: " + accountBalance
+ "</html>");
writer.flush();
}
}
调用AccountServlet
时,浏览器会弹出登录界面要求输入有效凭据。
@HttpConstraint
和@HttpMethodConstraint
用于指定@ServletSecurity
的value
和httpMethodConstraints
属性值:
✅ @HttpConstraint
:适用于所有HTTP方法,指定默认安全约束
value
rolesAllowed
transportGuarantee
- 最常用的是
rolesAllowed
(示例中允许Member
角色访问所有方法)
✅ @HttpMethodConstraint
:指定特定HTTP方法的安全约束
value
emptyRoleSemantic
rolesAllowed
transportGuarantee
- 示例中限制
doPost
方法仅Admin
角色可访问(存款功能仅管理员可用)
8. @MultipartConfig
处理multipart/form-data
请求(通常用于文件上传)时,使用此注解标注Servlet。
该注解会暴露HttpServletRequest
的getParts()
和getPart(name)
方法,用于访问所有或单个文件部分。通过调用Part
对象的write(fileName)
可将上传文件写入磁盘。
示例UploadCustomerDocumentsServlet
展示其用法:
@WebServlet(urlPatterns = { "/uploadCustDocs" })
@MultipartConfig(
fileSizeThreshold = 1024 * 1024 * 20,
maxFileSize = 1024 * 1024 * 20,
maxRequestSize = 1024 * 1024 * 25,
location = "./custDocs")
public class UploadCustomerDocumentsServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
for (Part part : request.getParts()) {
part.write("myFile");
}
}
}
@MultipartConfig
包含四个属性:
-
fileSizeThreshold
– 文件大小阈值(字节),超过则存磁盘,否则存内存 -
maxFileSize
– 单个文件最大大小(字节) -
maxRequestSize
– 整个请求最大大小(字节,含文件和表单数据) -
location
– 文件存储目录
9. 总结
本文深入探讨了Servlet API 3.1引入的Java EE注解及其作用与用法。这些注解能显著简化Web开发,减少配置负担。
⚠️ 实际开发中需注意:
- 注解虽简化配置,但复杂场景仍需XML配合
- 安全相关注解需与容器安全策略协同工作
- 文件上传参数需根据实际需求合理设置
相关源码可在GitHub获取。