Servlet include在Tomcat中会吞噬HTTP头信息

3
我有一个servlet,它通过请求分派器包含了另一个servlet。
被包含的servlet设置了一些头信息,我希望在“包含”servlet中读取这些信息。因此,我在include()方法中传递了一个自定义的HTTPResponse对象,以捕获来自servlet的所有反馈活动。
问题是这些头信息没有被设置到我的自定义响应对象中。我运行了调试并检查了类似于Tomcat包装我的自定义响应对象的东西。setHeader调用会传递到这个包装类,而不是传递到我的自定义响应对象。
我想象Tomcat这样做是为了保护客户端免受头信息在错误位置被设置的影响。有趣的是,在Jetty中使用相同的方法可以按照我期望的方式工作。
已经有一段时间我没有认真地做Servlets了,所以我有点困难。我正在努力找出如何从通过dispatcher.include()调用的servlet中读取响应头信息。
1个回答

4

来自Servlet规范部分SRV.8.3:

RequestDispatcher接口的include方法可以在任何时候调用。include方法的目标servlet可以访问请求对象的所有方面,但是它对响应对象的使用更加有限。

它只能将信息写入ServletResponse接口的ServletOutputStream或Writer,并通过在响应缓冲区末尾写入内容或显式调用ServletResponse接口的flushBuffer方法来提交响应。

它无法设置标头或调用任何影响响应标头的方法。任何尝试这样做的都必须被忽略

那么,您如何使用request.setAttribute(...)在请求范围内设置调用servlet的值,然后在返回后从那里读取呢?这种方式可行吗?


谢谢你为我解释这个行为。你知道我考虑使用request.setAttribute()方法,这种方式可以工作,但是我把它保留为备选方案,因为从“不重复自己”的角度来看并不是最优选择。我需要访问内容类型和内容长度以传播到包含的servlet中。使用请求属性会强制产生冗余。尽管如此,包含的servlet仍然需要重构。再次感谢! - Cliff
如果我将我的“包括”servlet转换为过滤器,那样行得通吗?我的意思是,在由过滤器调用的servlet中编写头部是否违反规范? - Cliff
+1 正确。我已在_WildFly Full 9.0.1.Final_,_Apache Tomcat/6.0.29_,_Apache Tomcat/7.0.47_和_Jetty-9.3.3.v20150827_上进行了测试,并且在包含的响应中更改标头在任何一个服务器上都不可能(正如预期的那样)。这个问题发布已经有很长时间了,所以这里没有什么意外。我只是想再次确认一下。 - Alberto
顺便说一下,"_在请求范围内设置呼叫servlet的值如何?[...]",我还测试过了,包括一个空的JSP,这也可以工作。 - Alberto
但是为了记录,我也测试过一个更大的JSP,显然只有在响应尚未提交时才能更改响应。这可以解释它:https://dev59.com/SHI-5IYBdhLWcg3wEEBV#2030908 - Alberto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接