【问题标题】:JSP - Servlet not forwarding to JSP correctlyJSP - Servlet 未正确转发到 JSP
【发布时间】:2014-12-18 11:00:23
【问题描述】:

我有一个必须将请求转发到特定 JSP 的控制器 Servlet。但是,每当我转发请求时,它都会加载 JSP,但浏览器中的 URL 会做一些很奇怪的事情。

例如:

通过index.jsp我点击:<a href="/login" />

在控制器中我有一个方法

if(request.getPathInfo().equals("/login"){
  dispatcher = this.getServletContext().getRequestDispatcher("/login.jsp");
  dispatcher.forward(request, response);
}

浏览器中的网址会显示:

http://mywebsite.com/my_work/do/login

而不是:

http://mywebsite.com/my_work/login.jsp

login.jsp 页面将显示,只是 URL 错误。这会导致问题,因为我必须在每个 JSP 中包含 2 x 对 Javascript 和 CSS 文件的引用,因为相对 URL 会发生变化,具体取决于我是通过在浏览器中键入 http://mywebsite.com/my_work/login.jsp 来手动访问该页面,还是通过转发访问该页面来自 Controller servlet。

我的 web.xml:

    <?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <servlet>
        <servlet-name>Controller</servlet-name>
        <servlet-class>controller.Controller</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Controller</servlet-name>
        <url-pattern>/do/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <resource-ref>
        <res-ref-name>jdbc/LessonDatabase</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
        <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref>
</web-app>

任何帮助都会很棒。我已经做好了一切工作,但我猜这是不正确的!

应该注意,任何转发都会发生这种情况。

【问题讨论】:

  • 你正在寻找的是重定向。

标签: java jsp servlets


【解决方案1】:

这是因为您将请求转发到您的JSP

if(request.getPathInfo().equals("/login"){
  dispatcher = this.getServletContext().getRequestDispatcher("/login.jsp");
  dispatcher.forward(request, response);
}

当您从forward a request 到下一个JSP or Servlet 时,它会继续在浏览器的地址栏中显示您转发的地址栏中的URL pattern

如果你想更改URL,你应该redirect它。

response.sendRedirect("YOUR_JSP");

因此,您的代码应该是,

if(request.getPathInfo().equals("/login"){
  response.sendRedirect("/login.jsp");
}

注意

Forwarding 请求(即使用 RequestDispatcher)和 redirecting 请求(即使用 sendRedirect)之间的区别在于,如果您将请求转发到下一个资源,那么您的相同 request 对象将传递给下一个资源,因此它的所有attributes &amp; parameters 都被发送到下一个JSP or Servlet

相反,如果您重定向您的请求,则会要求客户端(浏览器)将new request 发送到next resource。因此,您之前在请求中的所有 parameters and attributes 在下一个资源的新请求中都无法访问。

但是(parameters &amp; attributes) 存储在sessioncontext 中的信息不受重定向请求的影响。

【讨论】:

  • 很好的答案。重定向和请求转发的基本区别链接:javapractices.com/topic/TopicAction.do?Id=181
  • @Sid 感谢您的链接。我有点懒得在答案中找到链接。
  • 感谢您的深入回复,真的为我扫清了!但是,假设我在浏览器中键入:www.mywebsite.com/myView.jsp,在这种情况下,我收到 HTTP 状态 500 错误 - javax.ServletException。我假设这与 JSP 从会话中的数据创建表单这一事实有关,如果不存在会话,则会引发此错误。这是 JSP 文件的正常行为吗?如果正常,在使用 PHP 时可以说(伪代码)if(session.is_null()) { redirect; },JSP 中是否有类似的选项?再次感谢!
  • 正如我在回答中指出的那样,您只是通过实现重定向来解决静态资源的路径问题,从而使自己面临各种问题。您接受的答案是解决问题的错误方法。除非您完全理解其中的含义,否则不要这样做。
  • @AlanHay 感谢您的回复。但是,我没有实现任何一个答案,因为我的讲师改变了主意,并认为dispatcher.forward 很好,即使它没有更改 URL。她没有意识到 URL 并不是要使用 forward 方法更改。再次感谢。
【解决方案2】:

执行重定向而不是转发(并处理其影响)是解决静态资源引用方式问题的完全错误的方法。

除非您了解执行重定向的含义,否则最好(也是最简单)的解决方案是修复引用静态资源的方式。

您可以通过计算和设置基本路径以与框架无关的方式执行此操作,如下所示(尽管您的框架可能提供其他方式)。

http://www.w3schools.com/tags/tag_base.asp

在下文中,无论当前资源的路径如何,JS 和 CSS 文件都将始终相对于 webapp 的根目录进行引用。

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<!--
  To avoid scriptlets and use JSTL see: 
  http://stackoverflow.com/questions/6271075/how-to-get-the-base-url-from-jsp-request-object
-->
<%
    String path = request.getContextPath();
    String basePath = request.getScheme()
            + "://"
            + request.getServerName()
            + ":"
            + (request.getServerPort() != 80
                    ? request.getServerPort()
                    : "") + path + "/";
%>


<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>ABC</title>

<base href="<%=basePath%>" />

<link href="css/styles.css" rel="stylesheet"
    media="screen" />

<script src="js/jquery-1.8.3.js"></script>

</head>

【讨论】:

  • 嗨艾伦,感谢您的回答。但是,我不允许在这项工作中使用&lt;% %&gt;。但是你说的很好,很有道理,我一定会在以后的工作中实现它。
  • 是的,尽可能避免使用 scriptlet。你也可以在 JSTL 中做。查看更新。
【解决方案3】:

只需确保 URL 模式的地址与该模式完全匹配即可。 **这些模式区分大小写。我花了几个小时才弄清楚类似的问题。 **

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-25
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    • 2019-11-03
    • 2014-02-25
    • 1970-01-01
    相关资源
    最近更新 更多