来自 jsp:include 的 response.sendRedirect() 被忽略?

Posted

技术标签:

【中文标题】来自 jsp:include 的 response.sendRedirect() 被忽略?【英文标题】:response.sendRedirect() from jsp:include being ignored? 【发布时间】:2011-07-09 22:49:52 【问题描述】:

我有一个 jsp 文件,其中包含另一个 jsp 文件来检查一些值等:

<jsp:include page="setup.jsp" />

在 setup.jsp 中,我有一些条件代码,用于确定是否在会话中设置了一些需要的值,如果没有,则将它们重定向到不同的页面。或者至少应该如此,但重定向似乎被忽略了。

System.err.println("Redirecting!");
response.sendRedirect("http://www.google.com");
return;

我看到“重定向!”登录到控制台,但页面继续并正常呈现。我让 curl 为我转储了标头,发现响应是 HTTP/1.1 200 OK,所以它肯定没有发送 302 重定向。

知道问题出在哪里以及如何解决这个问题吗?

编辑:我已确认我的回复尚未提交。 response.isCommitted() 返回false 表示状态码和标头尚未发送。

编辑 2:我尝试在许多其他地方调用 response.sendRedirect() 并发现我可以在 . JSP 内部的重定向似乎被忽略了,如果我尝试在 jsp 之后立即重定向,那么我会得到一个非法状态异常,因为响应已经提交。

【问题讨论】:

有可能部分响应已经发送到客户端并且重定向被忽略。重定向应该(几乎)首先被解析。 我必须把它放在一个更大的网络应用程序结构中,所以当涉及到何时何地可以放置代码以进行重定向时,我的双手被束缚了。当我尝试进行重定向时,有没有一种方法可以测试响应是否已经将内容传递回浏览器?当我沉浸在 jsp:includes 中时,您对如何启动某种重定向有什么建议吗? 我在调用重定向的位置添加了一个简单的 out.println() 消息,并且该输出出现在响应的任何其他输出之前。那我不应该被允许重定向吗? 好的,我发现 response.isCommitted() 是一种确定标头是否已写入的方法。响应尚未提交,因此它仍应对重定向开放。 【参考方案1】:

<jsp:include> 在幕后使用RequestDispatcher#include()。单击链接以查看 javadoc。这是相关性的摘录(强调我的):

...

ServletResponse 对象的路径元素和参数与调用者的保持不变。 包含的servlet不能改变响应状态码或设置headers;任何进行更改的尝试都会被忽略。

...

HttpServletResponse#sendRedirect() 基本上将 HTTP 响应状态设置为 302,并将 HTTP Location 标头设置为目标 URL。因此它被完全忽略了。

更深层次的问题是您滥用 JSP 作为页面控制器/过滤器。您实际上应该为此使用普通的 servlet 或 filter 类,它远在 JSP 之前运行。

【讨论】:

我完全同意这种滥用,不幸的是,我需要适应一些非常严格的界限。谢谢上面的sn-p文档,我不知道。【参考方案2】:

重定向标题(我相信)需要位于页面顶部。查看 html 规范以供参考。

您是否尝试将其放在页面的最顶部?一个代码示例将帮助我们调试...

【讨论】:

不幸的是,由于我的客户的隐私问题,我无法提供太多的代码 sn-ps 方式。这是一个相当复杂的站点,包含多个级别的 jsp:includes 等。 我已验证在我尝试重定向时未发送任何状态代码或其他标头,因此它实际上位于“页面顶部”。

以上是关于来自 jsp:include 的 response.sendRedirect() 被忽略?的主要内容,如果未能解决你的问题,请参考以下文章

ajax 和 jsp

如何修复 Typescript 编译错误 ts2345“类型 'Response' 丢失......来自'Response'类型:重定向、预告片、formData!”

来自 WebApi2 response.data 的 Angular ng-repeat 刷新

来自网络管理员 ejabberd docker 的 ERR_EMPTY_RESPONSE

URL总结

NameError - 未初始化的常量 Twilio::TwiML::Response(可能来自旧 API 代码?)