Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Tomcat筛选器不支持异步_Java_Asynchronous_Tomcat_Filter - Fatal编程技术网

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);
    }
    链式过滤器(请求、响应);
    打破
    违约:
    }
    }