Servlet过滤器行为模棱两可?

Posted

技术标签:

【中文标题】Servlet过滤器行为模棱两可?【英文标题】:Servlet Filter acts ambiguously? 【发布时间】:2012-08-14 03:20:18 【问题描述】:

在servlet过滤器中,filterChain.doFilter(request, response);应该将请求传递给链中的下一个。 但请考虑以下两个代码: 代码 1:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException 

filterChain.doFilter(request, response);
try

Thread.sleep(20000);

catch(Exception e)

            

代码 2:

public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException 

try

Thread.sleep(20000);

catch(Exception e)

      
filterChain.doFilter(request, response);      

两个过滤器的执行方式相同。即在服务请求之前两者都需要 20 秒。 但实际上应该发生的是Code1 应该立即发球,Code2 应该在 20 秒后发球。 为什么过滤器会出现这种歧义?

【问题讨论】:

【参考方案1】:

在 servlet 或过滤器中休眠总是一个坏主意,因为 HTTP 工作线程是稀缺资源,因此您不应该阻止它们。但在你的具体例子中是有希望的。

基本上,您在 servlet 中打印或过滤到输出的任何内容都会被隐式缓冲以提高性能。如果您在 servlet/filter 中打印足够的数据,则 servlet 容器将刷新缓冲区,并且您的部分响应将到达客户端。但你也可以手动冲洗!

public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException 
    filterChain.doFilter(request, response);
    response.flushBuffer();
    Thread.sleep(20000);

flushBuffer() 指令强制容器刷新输出缓冲区。所有响应标头以及您从 servlet 发送的任何内容都将发送到客户端。但这里有一个问题:客户端将接收数据,但 HTTP 连接在接下来的 20 秒内保持打开状态。我用curl 对此进行了测试,它按预期工作。但是当在浏览器中使用相同的 URL 时(在 Opera、Firefox 和 Google Chrome 上测试),浏览器会等待 20 秒再显示任何内容(这可能取决于您实际发送的内容)。

【讨论】:

您可以通过显式关闭与响应关联的输出流(或写入器)来释放客户端,但我认为这不能保证。

以上是关于Servlet过滤器行为模棱两可?的主要内容,如果未能解决你的问题,请参考以下文章

不同线程上的 Appengine 过滤器和 Servlet

用于防止滥用的 Servlet 过滤器? (DoS、垃圾邮件等)

行为型设计模式之责任链模式

尝试初始化 CoreML 模型会导致模棱两可的错误消息

Servlet过滤器-日志记录

过滤器