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
实现示例。
【讨论】:
以上是关于ServletResponse 和 HttpServletResponseWrapper 的区别?的主要内容,如果未能解决你的问题,请参考以下文章
http协议,ServletRequest和ServletResponse
获取用于日志记录的 ServletResponse 内容字符串 [重复]
HttpServletResponse ServletResponse 返回响应 设置响应头设置响应正文体 重定向 常用方法 如何重定向 响应编码 响应乱码
HttpServletResponse ServletResponse 返回响应 设置响应头设置响应正文体 重定向 常用方法 如何重定向 响应编码 响应乱码