Java Web开发:在传递请求对象时将控制从一个servlet转移到另一个[重复]

Posted

技术标签:

【中文标题】Java Web开发:在传递请求对象时将控制从一个servlet转移到另一个[重复]【英文标题】:Java web development: transfer control from one servlet to another while passing the request object [duplicate] 【发布时间】:2017-05-14 20:26:15 【问题描述】:

编辑:我在这里发布了一个简短且经过修改的问题:Java web development: transfer control from one servlet to another while passing the request object (Version 2)

作为 Java Web 开发的初学者,我不确定在提交表单 (POST) 时应该如何构建 servlet/页面之间的流程。这是一个基本问题,我怀疑这对于专家来说可能是一个容易回答的问题。 (不过,我的书和一些谷歌搜索并没有给出明确的答案。)我的问题有点长,那是因为我想弄清楚我来自哪里。感谢您的耐心等待。

假设我们有两个 servlet A 和 B,每个都有自己的 .jsp 页面;我们分别称这些页面为 a.jsp 和 b.jsp。现在只要任何一个页面上都没有表单(即没有使用 POST 方法),事情应该如何发展就很清楚了。也就是说,在显示任何 .jsp 页面之前,相应的 servlet 被激活,通过设置 .jsp 页面的相关数据元素(最明显的是,作为请求对象的属性)为 .jsp 页面做一些准备需要,然后将请求对象(等)转发到 .jsp 页面,然后实际显示带有数据的页面。例如,页面 a.jsp 上的链接可能链接到 servlet B,单击该链接会触发 servlet B 的 GET 请求,然后在转发到它之前做一些准备(设置一些请求属性)自己的 .jsp 页面 (iebjsp)。

但是现在让我们假设页面 a.jsp 显示一个带有提交按钮、method=”POST” 和 action=”B” 的表单。那么是的,servlet B 被激活,这个 servlet 要判断用户输入的数据是否有效。如果数据确实有效,我们可以简单地转发到 b.jsp,那里没有问题。但是,如果数据无效怎么办?

在这种情况下,我们显然希望再次显示 a.jsp(表单页面),而用户第一次输入的数据仍然存在。实现此目的的一种方法是简单地将 servlet B 转发到 a.jsp(从而绕过 servlet A)。但是,这样做有一个大问题:在地址栏中显示给用户的 URL 仍然会显示“……/B”。因此,用户将看到正确的页面(即 a.jsp,包含表单),但 URL (/B) 错误。例如,如果我们使用“Register”和“ThanksForRegistering”而不是“A”和“B”,用户将看到 register.jsp——但 URL 为“……/ThanksForRegistering”!不好。

在 request-dispatcher 上调用“include()”而不是“forward()”似乎也不起作用。如果我们这样做,不仅会导致 GET 请求(与我们想要的 POST 请求相反),而且我们实际上会丢失整个(原始)请求对象及其属性(毕竟,我们需要,重新填充表单)。至少,我自己的实验似乎表明了这一点。所以使用“include()”似乎根本不是一个可行的选择。

另一个明显的想法是提交时使用“action=A”(而不是“action=B”)。然后servlet A自己就可以处理验证了,如果验证失败可以简单的再次转发到a.jsp,没问题。但是,如果验证成功怎么办?然后我们要显示后续页面b.jsp,但是该页面很可能再次需要来自原始请求对象(来自表单提交)的属性;例如,让用户检查他输入的数据实际上是否正确。所以基本上我们遇到了和以前一样的问题,但是 A 和 B(以及它们各自的 .jsp 页面)的角色颠倒了。所以这似乎也不是一个真正的解决方案。

而且我没有看到任何其他选择。

所以基本上,我只是希望能够让一个 servlet 将控制权交还给另一个 servlet,但请求对象从前者传递给后者。或者,如果这不可行,我希望能够直接从 servlet B 转发到 a.jsp,但向用户显示 正确 URL。或任何其他方式来完成我想要的。

非常感谢。

【问题讨论】:

确实有点长,很难解决问题。也许发布代码会对我们有所帮助。 另外,你不使用任何网络框架吗?他们提出了重定向、流程、...的解决方案。 我认为您需要阅读重定向。您可以做的是,在您的原始场景中,如果 servlet B 中的验证失败。您将重定向发送到 A。参考:***.com/questions/6175722/redirect-from-servlet @Pascal 谢谢。我只是在使用 NetBeans……这是课程作业(学校)。但我想应该可以在没有框架的情况下做我想做的事。此外,我将编辑以添加我的问题的口头版本(尽管可能需要几个小时)。 你应该让 JSP A 中的表单提交给 Servlet A,它的 doPost() 应该反过来决定是在验证错误的情况下转发回 JSP A,还是发送重定向到 Servlet/JSP B. 此方法在此处进行了概述:***.com/q/3541077,我认为这几乎是您正在寻找的规范问答。因此,您的具体错误是您提交了错误的 URL。您基本上应该提交到您希望在浏览器地址栏中看到的完全相同的(相同的)URL,以防验证失败(正确的术语是“回发”)。 【参考方案1】:

我认为每个 servlet 必须有一个页面的假设导致了这里的问题....有一个基于输入重定向、转发或包含特定页面的 servlet....你真的不需要总是为页面调用不同的 servlet .....您可以有一个带有视图解析器的前端控制器,其组合将重定向或转发到页面。

【讨论】:

+1 建议使用单个 servlet 作为路由器。这有点像实现自己的路由器。但我认为,如果您的目标是为此目的实现单个 servlet,那么它应该始终转发并充当幕后路由器,而不进行任何处理。 谢谢@phrasant,是的,我想你可能正在做点什么。但是,假设如果验证成功,我想返回主页,并在主页上显示一些输入的数据(即,我仍然需要请求对象的属性)。在地址栏中显示带有注册页面(即表单页面)的 URL 的主页(.jsp)肯定会很奇怪。但是,如果我只是从 Register servlet 转发到 homepage.jsp,就会发生这种情况。 @MukulGoel 正确的mukul ...所有业务逻辑都应该由从servlet调用的服务实现...并根据服务响应...然后servlet将决定使用视图解析器来决定要显示哪个视图... @Holland....如果验证成功,在您重定向到主页之前,您的路由 servlet 将在请求对象中设置输入的数据........总结基于您的 servlet 数据中的逻辑将通过您的路由 servlet 从一个页面传递到另一个页面..... @phrasant 是的,这里的关键问题是我如何从 servlet 重定向到主页,这样不仅可以传递请求对象,还可以传递正确的 URL(在这种情况下,“主页”)出现在地址栏中?我确实尝试过使用重定向(忘了在问题中提到它),但它似乎没有达到我想要的效果。【参考方案2】:

您可以使用过滤器来实现相同的目的,或者如果验证成功,可以考虑在 HttpSession 中设置属性,并在需要时检索所有页面中的数据。 session.setAttribute("object", object);

我希望这是您正在寻找的。

【讨论】:

以上是关于Java Web开发:在传递请求对象时将控制从一个servlet转移到另一个[重复]的主要内容,如果未能解决你的问题,请参考以下文章

将上下文从 Web 请求的控制器传递到数据库层

如何在WebAPI的控制器的GET请求中传递参数

csharp 创建一个从AJAX POST请求调用的Web API,它在对象中传递多个值

关闭时将值传递给视图控制器时出错 |斯威夫特 5

如何在使用桥接头时将数据(字典)从 Objective-C 控制器传递到 Swift `viewcontroller` 中?还有其他方法吗?

初学 Java Web 开发,请远离各种框架,从 Servlet 开发