tomcat筛选器不支持异步

jhkqcmku  于 2021-10-10  发布在  Java
关注(0)|答案(1)|浏览(436)

比如标题

  1. @WebFilter("/*")
  2. @Component
  3. @Slf4j
  4. public class FilterDemo1 implements Filter {
  5. public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException, IOException {
  6. new Thread(() -> {
  7. try {
  8. chain.doFilter(req, resp);
  9. } catch (Exception e) {
  10. log.error("a", e);
  11. }
  12. }).start();
  13. }
  14. }

因此,如果tomcat筛选器中有耗时的任务(如rpc或http),它们必须等待并且不能是异步的

  1. java.lang.NullPointerException: null
  2. at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
  3. at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]```
  4. [error][1]
  5. [1]: https://i.stack.imgur.com/tFYTH.png
kzipqqlq

kzipqqlq1#

这个 ServletRequest , ServletResponseFilterChain 对象仅在以下线程上有效: doFilter 被称为。如果希望异步使用它们,则需要启用异步处理(参见jakarta ee教程)。 ServletRequest.startAsync()ServletRequestServletResponse 进入异步模式,但 FilterChain 只能在原始螺纹上使用:
这个 service 方法必须与应用于servlet的所有筛选器在同一线程中运行。
(参见servlet规范)
因此,您需要按照以下步骤进行操作:
当一个新请求通过过滤器时,您调用 ServletRequest.startAsync() 并启动新线程或使用任何其他执行器进行异步筛选(例如。 AsyncContext.start(Runnable) ),
异步任务完成后,将结果写入请求属性并调用 AsyncContext.dispatch() :这将从一开始重新启动过滤器链,
什么时候 doFilter 再次调用时,使用请求的属性执行过滤逻辑并调用 FilterChain.doFilter 例如,您可以使用如下内容:

  1. @WebFilter(asyncSupported = true, urlPatterns = {"/*"}, dispatcherTypes = {DispatcherType.ASYNC, DispatcherType.REQUEST})
  2. public class Filter1 implements Filter {
  3. @Override
  4. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  5. switch (request.getDispatcherType()) {
  6. case REQUEST :
  7. // First pass: start asynchronous processing
  8. final AsyncContext asyncContext = request.startAsync();
  9. new Thread(() -> {
  10. try {
  11. Thread.currentThread().sleep(5000);
  12. } catch (Exception e) {
  13. request.setAttribute("filter1Error", e);
  14. }
  15. asyncContext.dispatch();
  16. }).start();
  17. break;
  18. case ASYNC :
  19. // Second pass: throw or forward
  20. Exception e = (Exception) request.getAttribute("filter1Error");
  21. if (e instanceof IOException) {
  22. throw (IOException) e;
  23. } else if (e instanceof ServletException) {
  24. throw (ServletException) e;
  25. } else if (e != null) {
  26. throw new ServletException(e);
  27. }
  28. chain.doFilter(request, response);
  29. break;
  30. default :
  31. }
  32. }
展开查看全部

相关问题