在Java Servlet的上下文中,URL重写和转发有什么区别?

作为Java Web应用程序的开发人员,何时需要使用URL重写以及URL重写和转发之间的区别是什么?

我在其他网站上搜索,我得到的是相互矛盾的信息,这取决于你所说的人,SEO人会以不同的方式回答这个问题。

AFAIK在两种情况下都不会通知客户端(浏览器)更改,并且最终用户看到客户端在从服务器返回休止符时最初请求的完全相同的URL。

请问这个问题是在Java Servlet API的上下文中,其中定义了forward方法和sendRedirect方法,其中重定向和转发完全是两个不同的东西。 这个问题是关于forward(由Servlet API中的forward方法定义)和URL重写之间的区别。 问题清楚地表明答案应该在Java servlet的上下文中。 最重要的是,在开发Java Web应用程序的上下文中,我何时需要使用URL重写。

在这个问题中,“转发”一词含糊不清。 在JSP / Servlet世界中,从MVC概念中可以更加了解“转发”,即请求URL(在浏览器地址栏中可见)有效地调用servlet(与web.xml@WebServlet URL模式匹配)充当控制器以准备模型并使用JSP作为视图来呈现模型。 反过来,JSP被称为“转发”。 这是由RequestDispatcher#forward()

 request.getRequestDispatcher("/WEB-INF/foo.jsp").forward(request, response); 

这确实没有反映浏览器地址栏中的JSP的URL。 这完全发生在服务器端。 基本上,servlet“加载”JSP并将请求/响应传递给它,以便它可以完成生成HTML内容的工作。 请注意,上例中的JSP隐藏在/WEB-INF文件夹中,这使得尝试在浏览器地址栏中输入完整路径的最终用户无法访问它。

在一般的web开发世界中,术语“转发” 可从“URL转发”中获知,其与URL重定向基本相同。 这反过来确实导致浏览器地址栏的更改。 这在JSP / Servlet世界中更正式地称为“重定向”(尽管大多数初学者最初将其与“转发”混淆)。 这是由HttpServletResponse#sendRedirect()

 response.sendRedirect("another-servlet-url"); 

基本上,服务器通过具有Location头的HTTP 3nn响应告诉客户端客户端应该在给定Location上发出新的GET请求。 以上实际上与以下内容相同:

 response.setStatus(302); response.setHeader("Location", "another-servlet-url"); 

由于是指示执行该作业的客户端(webbrowser),您会看到此URL更改反映在浏览器地址栏中。


术语“URL重写” 也是不明确的。 在JSP / Servlet世界中,“URL重写”是将会话ID附加到URL的forms,这样无cookie的浏览器仍然可以维护与服务器的会话。 您可能曾经在URL中看到过;jsessionid=somehexvalue属性。 默认情况下,这不是自动完成的,但大多数基于Servlet的MVC框架都会自动完成。 这是由HttpServletResponse#encodeURL() encodeRedirectURL()encodeRedirectURL()

 String encodedURL = response.encodeURL(url); // or response.encodeRedirectURL(url) // Then use this URL in links in JSP or response.sendRedirect(). 

(这反过来是-again-一个模糊的术语。使用“URL编码”你通常会想到百分比编码 。没有为此提供Servlet API的工具,这通常由URLEncoder#encode()或MVC完成。 – 技术上更正确,在JSP中由JSTL的或基于servlet的MVC框架提供的任何UI组件,例如JSF的

在一般的Web开发世界中(特别是使用Apache HTTPD / PHP人员),“URL重写”更为人所知的是Apache HTTPD的mod_rewrite正在做的事情:将传入的URL映射到具体的资源而不反映客户端的URL更改。 在JSP / Servlet世界中,这也是可能的,它通常由使用RequestDispatcher#forward()Filter实现完成。 众所周知的实现是Tuckey的URLRewriteFilter 。


我承认,当我刚刚开始使用JSP / Servlet时,这也让我很困惑,当然我的根源是Apache HTTPD / PHP世界。

重写是一个层(通常在您的servlet之前),通过在提供请求之前修改URL,使URL像处理不同的URL一样处理。 servlet通过单个请求响应,就像请求重写的URL一样,通常从未知道重写发生。

当服务器通过一些3xx错误代码指示时(当客户端允许重定向时) ,浏览器(通常是自动)执行转发(或重定向 )。 在这种情况下,将提供两个请求(不一定都来自您的servlet); 第一个响应错误代码和重定向到的URL,第二个响应客户端重定向后提供正确的请求。