记录一个Tomcat启动参数修改,导致不识别<async-supported>的问题

本文记录了在Tomcat中遇到的一个问题,即由于在启动参数中设置了`JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCE=true"`,导致Tomcat无法识别web.xml中的`<async-supported>`标签,从而使得war包启动失败。解决方法是移除或调整这个启动参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

web3.0之后新增一个<async-supported>的属性,支持web.xml中filter添加 <async-supported>标签。

标准情况下只要Tomcat7.0+  JDK1.6+就可以支持该功能,然后这次遇到Tomcat启动报无法识别该属性的问题,花费了很长时间定位,这里记录一下原因。


tomcat启动参数中添加的一个参数 : JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.STRICT_SERVLET_COMPLIANCE=true"

就是该参数最终导致了Tomcat无法识别<async-supported>标签,war包启动失败。


在Tomcat官方文档中查询了一下(https://tomcat.apache.org/tomcat-8.5-doc/config/context.html),该参数的解释如下:

The default value of this system property is false.
If this is true the default values will be changed for:
org.apache.catalina.core.
ApplicationContext.GET_RESOURCE_REQUIRE_SLASH
org.apache.catalina.core.
ApplicationDispatcher.WRAP_SAME_OBJECT
org.apache.catalina.core.
StandardHostValve.ACCESS_SESSION
org.apache.catalina.session.
StandardSession.ACTIVITY_CHECK
org.apache.catalina.session.
StandardSession.LAST_ACCESS_AT_START
org.apache.tomcat.util.http.
ServerCookie.STRICT_NAMING
The URIEncoding attribute of any HTTP connector or AJP connector element.
The resourceOnlyServlets attribute of any Context element.
The tldValidation attribute of any Context element.
The useRelativeRedirects attribute of any Context element.
The xmlNamespaceAware attribute of any Context element.
The xmlValidation attribute of any Context element.

在查看具体的解释分析,应该是 resourceOnlyServlets 属性造成了这个问题:
Comma separated list of Servlet names (as used in /WEB-INF/web.xml) that expect a resource to be present. Ensures that welcome files associated with Servlets that expect a resource to be present (such as the JSP Servlet) are not used when there is no resource present. This prevents issues caused by the clarification of welcome file mapping in section 10.10 of the Servlet 3.0 specification. 

先粗略记录一下,有时间再研究

### 启用Servlet和过滤器中的异步支持 #### 通过`web.xml`配置方式 为了在传统的基于XML的部署描述符中启用异步支持,可以在`<servlet>`或`<filter>`标签下添加子元素`<async-supported>true</async-supported>`。此设置告知容器该Servlet或Filter可以参与异步操作[^1]。 ```xml <servlet> <servlet-name>AsyncExampleServlet</servlet-name> <servlet-class>com.example.AsyncExampleServlet</servlet-class> <async-supported>true</async-supported> </servlet> <filter> <filter-name>AsyncExampleFilter</filter-name> <filter-class>com.example.AsyncExampleFilter</filter-class> <async-supported>true</async-supported> </filter> ``` 上述配置表明`AsyncExampleServlet`和`AsyncExampleFilter`都启用了异步支持。 --- #### 使用Java代码实现异步支持 除了通过`web.xml`声明外,还可以利用Servlet API动态启用异步功能。这通常涉及调用`HttpServletRequest.startAsync()`方法来启动异步上下文,并确保Servlet类实现了`javax.servlet.annotation.WebServlet`注解并设置了属性`asyncSupported=true`。 以下是具体的代码示例: ```java 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; @WebServlet(urlPatterns = "/async", asyncSupported = true) public class AsyncExampleServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 开始异步处理 final var asyncContext = req.startAsync(); new Thread(() -> { try { // 模拟耗时任务 Thread.sleep(5000); // 设置响应内容 resp.setContentType("text/plain"); resp.getWriter().write("Asynchronous processing completed!"); } catch (Exception e) { throw new RuntimeException(e); } finally { // 完成异步请求 asyncContext.complete(); } }).start(); } } ``` 在此示例中,`@WebServlet`注解的`asyncSupported`参数被显式设为`true`,表示允许异步执行。此外,在`doGet`方法内部调用了`req.startAsync()`以创建一个新的异步上下文。 对于过滤器而言,同样可以通过实现`javax.servlet.Filter`接口并在其初始化阶段指定`async-supported`特性来完成相同的功能。 --- #### 注意事项 当使用异步模式时,需要注意以下几点: - 如果未正确结束异步操作(即未调用`asyncContext.complete()`),可能会导致连接保持打开状态直到超时。 - 需要确保所有参与异步流程的对象线程安全,因为它们可能由同的线程访问。 - 异步支持仅适用于运行于Servlet 3.0及以上版本规范的容器环境中。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值