Java Tomcat筛选器不支持异步
比如标题Java Tomcat筛选器不支持异步,java,asynchronous,tomcat,filter,Java,Asynchronous,Tomcat,Filter,比如标题 @WebFilter("/*") @Component @Slf4j public class FilterDemo1 implements Filter { public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException, IOException { new Thre
@WebFilter("/*")
@Component
@Slf4j
public class FilterDemo1 implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException, IOException {
new Thread(() -> {
try {
chain.doFilter(req, resp);
} catch (Exception e) {
log.error("a", e);
}
}).start();
}
}
因此,如果Tomcat筛选器中有耗时的任务(如RPC或HTTP),它们必须等待并且不能是异步的
java.lang.NullPointerException: null
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]```
[error][1]
[1]: https://i.stack.imgur.com/tFYTH.png
ServletRequest
、ServletResponse
和FilterChain
对象仅在调用doFilter
的线程上有效。如果要异步使用它们,则需要启用异步处理(cf.)
ServletRequest.startAsync()
将ServletRequest
和ServletResponse
置于异步模式,但FilterChain
只能在原始线程上使用:
服务
方法需要与应用于servlet的所有过滤器在同一线程中运行
(参见)
因此,您需要按照以下步骤进行操作:
ServletRequest.startAsync()
并启动新线程或使用任何其他执行器进行异步筛选(例如AsyncContext.start(Runnable)
)AsyncContext.dispatch()
:这将从一开始重新启动筛选器链doFilter
时,您可以使用请求的属性执行过滤逻辑并调用FilterChain.doFilter
@WebFilter(asyncSupported=true,urlPatterns={”/*},dispatcherTypes={DispatcherType.ASYNC,DispatcherType.REQUEST})
公共类过滤器1实现过滤器{
@凌驾
public void doFilter(ServletRequest请求、ServletResponse响应、FilterChain链)抛出IOException、ServletException{
开关(request.getDispatcherType()){
案件请求:
//第一步:启动异步处理
final AsyncContext AsyncContext=request.startAsync();
新线程(()->{
试一试{
Thread.currentThread().sleep(5000);
}捕获(例外e){
setAttribute(“过滤器1错误”,e);
}
asyncContext.dispatch();
}).start();
打破
案例异步:
//第二次传球:投还是向前
异常e=(异常)请求.getAttribute(“filter1Error”);
if(IOException的实例){
抛出(IOException)e;
}else if(例如ServletException实例){
抛出(ServletException)e;
}如果(e!=null),则为else{
抛出新的ServletException(e);
}
链式过滤器(请求、响应);
打破
违约:
}
}