ServletResponse 和 HttpServletResponseWrapper 的区别?

Posted

技术标签:

【中文标题】ServletResponse 和 HttpServletResponseWrapper 的区别?【英文标题】:Differences between ServletResponse and HttpServletResponseWrapper? 【发布时间】:2011-10-24 19:13:35 【问题描述】:

我是 servlet 的新手,正在阅读一些关于过滤器和包装器的文本。我可以理解过滤器,但对包装器感到困惑。在书中,作者举了一个例子:

如果没有包装器:

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

        String name = request.getParameter("name").trim();

        try 
            chain.doFilter(request, response);
            PrintWriter out = response.getWriter();
            if (name.length() == 0) 
                out.println("Some message");
                out.println("</body>");
                out.println("</html>");
                out.close();
            
         catch (Throwable t) 
        
    

如果是包装器:

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

        String name = request.getParameter("name").trim();

        HttpServletResponse httpRes = (HttpServletResponse) response;
        HttpServletResponseWrapper resWrapper = new HttpServletResponseWrapper(httpRes);
        try 
            chain.doFilter(request, response);

            PrintWriter out = resWrapper.getWriter(); // why dont we just use response.getWriter();
            if (name.length() == 0) 
                out.println("<h3>Some message");
                out.println("</body>");
                out.println("</html>");
                out.close();
            
         catch (Throwable t) 
        
    

为什么我们需要HttpServletResponseWrapper 而我们可以在案例1 中使用ServletResponse 做同样的事情?谁能给我一个明确的例子,我们必须使用HttpServletResponseWrapper 而不是ServletResponse?我试过谷歌,但没有找到运气。

【问题讨论】:

这段代码看起来很奇怪。包装 servlet 响应的目的是进一步传递它 (chain.doFilter(request, resWrapper);) 并拦截包装器中的选定调用。例如,通过这种方式,您可以返回不同的响应编写器,它们会即时更改或压缩内容并将其发送到目标response。这个例子没有多大意义......你能提供这个(页面,书籍?)的来源吗? 我也觉得自己很奇怪。这段代码是我从大学讲师的幻灯片中截取的。如果我们这样做更有意义 chain.doFilter(request, resWrapper);作为你的建议 【参考方案1】:

BalusC 的回答很好,但如果你刚刚开始,可能会有点不知所措。

简单地说:SerlvetResponse 及其扩展HttpServletResponse 是接口,告诉您可以调用哪些方法来完成您需要的事情。在使用过滤器、Servlet 等的正常过程中,您会经常使用 HttpServletResponse 来告诉您的应用如何响应请求。

HttpServletResponseWrapper 是 HttpServletResponse 的一种特殊实现,它为您提供了一种方便的方法,可以用您自己的一些逻辑包装现有响应,而无需编写接口的全新实现。它有很多 很多 方法,所以这真的很好。举个简单的例子,假设您想禁止对response.flushBuffer() 的调用。这段代码,使用 HttpServletResponseWrapper,将做到这一点:

class DisallowFlushResponseWrapper extends HttpServletResponseWrapper 
    public DisallowFlushResponseWrapper(HttpServletResponse response) 
        super(response);
    

    @Override
    public void flushBuffer() 
        throw new UnsupportedOperationException("Don't call this!");
    

使用这种包装器的典型方法是创建一个像这样的过滤器:

class DisallowFlushFilter implements Filter 
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) 
        if (response instanceof HttpServletResponse) 
            HttpServletResponse newResponse =
                new DisallowFlushResponseWrapper((HttpServletResponse) response);
            chain.doFilter(request, newResponse);
        
        ...
    
    ...

请注意,我们使用我们自己的包装器实例包装进入过滤器的响应。然后我们将包装器交给过滤器链中的下一个项目。因此,如果它调用 flushBuffer(),这个过滤器之后的任何东西都会得到一个异常,因为它将在我们的包装器上调用它。由于其默认行为,包装器会将任何其他调用委托给包装响应,这是真正的响应,因此除了对该方法的调用之外的所有操作都将正常工作。

【讨论】:

但是最初的问题仍然没有答案,即为什么我们不能用原始的 HttpServletResponse 对象本身来做这一切?【参考方案2】:

这真是一个愚蠢的例子,它没有显示请求/响应包装器的好处。实际上,整个过滤器示例很差。发出 HTML 应该由 JSP 或至多由 servlet 完成(但这仍然很差)。浏览我们的filters wiki page,了解过滤器的用途。

如果您想修改响应的行为或只想收集有关响应同时在请求-响应链中使用的信息,则响应包装器非常有用。每当某个 servlet 或 JSP 在响应上调用某个方法时,就会发生修改后的行为。如果你在你的包装类中重写了它,那么这个会被调用。您可以在那里改变行为或收集信息。

您可以在 *** 上找到 some concrete 有用的 HttpServletResponseWrapper 实现示例。

How to insert JSF page rendering time and response size into the page itself, at least partially? MD5 Signing a HttpServletResponse How to configure Tomcat to not encode the session id into the URL when HttpServletResponse.encodeURL() is invoked How to add response headers based on Content-type; getting Content-type before the response is committed How is annotations support in jsp implemented in sitebricks? Capture and log the response body Log only http servlet response headers How to include a JSP page in a Facelets page? Capture generated dynamic content at server side

【讨论】:

以上是关于ServletResponse 和 HttpServletResponseWrapper 的区别?的主要内容,如果未能解决你的问题,请参考以下文章

ServletResponse下载文件乱码

http协议,ServletRequest和ServletResponse

获取用于日志记录的 ServletResponse 内容字符串 [重复]

ServletResponse接口提供的两种输出流

HttpServletResponse ServletResponse 返回响应 设置响应头设置响应正文体 重定向 常用方法 如何重定向 响应编码 响应乱码

HttpServletResponse ServletResponse 返回响应 设置响应头设置响应正文体 重定向 常用方法 如何重定向 响应编码 响应乱码