1 前言
- 轉發(forward):RequestDispatcher.forward() 方法在服務器端內部將請求轉發給另外一個資源,瀏覽器只知道發出了請求並得到了響應結果,並不知道在服務器程序內部發生了轉發行爲。
- 重定向(redirect):HttpServletResponse.sendRedirect() 方法對瀏覽器的請求直接作出響應,響應的結果就是告訴瀏覽器去重新發出對另外一個URL的 訪問請求。
RequestDispatcher.forward() 方法的調用者與被調用者之間共享相同的 request 對象和 response 對象,它們屬於同一個訪問請求和響應過程;HttpServletResponse.sendRedirect() 方法調用者與被調用者使用各自的 request 對象和 response 對象,它們屬於兩個獨立的訪問請求和響應過程。
轉發(forward)和重定向(redirect)示意圖如下:
主要區別有:
轉發(forward) | 重定向(redirect) |
瀏覽器發出1次請求,獲取1次響應 | 瀏覽器發出2次請求,獲取2次響應 |
轉發前後,瀏覽器地址欄不發生變化 | 重定向前後,瀏覽器地址欄發生變化 |
資源2中可以獲取到用戶提交請求中的數據 | 資源2中不可以獲取到用戶提交請求中的數據,但可以獲取到第2次由瀏覽器自動發出的請求中攜帶的數據 |
可以將請求轉發到 WEB-INF 目錄下的資源 | 不可以將請求重定向到 WEB-INF 目錄下的資源 |
只能將請求轉發到 Web 應用的內部資源 | 可以重定向到 Web 應用以外的資源 |
另外,轉發(forward)比重定向(redirect)較快 ,因爲重定向需要請求2次,而轉發只需請求1次。
2 案例分析
首先介紹下公共文件,主要有 index.jsp、User.java、show.jsp,不同的是 Test.java,將在2.1和2.2節分別介紹。
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>首頁</title>
</head>
<body>
<form method="post" action="resource1">
用戶號:<input type="text" name="id"/><br/>
用戶名:<input type="text" name="name"/><br/>
<input type="submit" value="提交">
</form>
</body>
</html>
User.java
package com.test;
public class User {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
show.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>顯示</title>
</head>
<body>
賬戶:${user.id}<br/>
姓名:${user.name}<br/>
</body>
</html>
2.1 轉發(forward)
Test.java
package com.test;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class Test {
@RequestMapping("resource1")
public String resource1(Map<String,Object> map,User user) {
map.put("user", user);
return "forward:/resource2";
}
@RequestMapping("resource2")
public String resource2() {
return "show";
}
}
注意: 由於 forward 可以將請求轉發到 WEB-INF目錄下的資源,因此 resource1 中的返回值可以爲如下:
return "forward:/WEB-INF/view/show.jsp";
測試一:在地址欄中輸入 http://localhost:8080/SpringMVC/resource1,跳轉到 show.jsp 頁面,但地址不變,如下。由此說明:轉發(forward)不改變請求地址。
測試二:若將 resource1 中返回值設置如下:
return "forward:https://www.baidu.com";
並在地址欄中輸入 http://localhost:8080/SpringMVC/resource1,網頁會報錯如下:
由此說明: 轉發(forward)不能訪問 Web 應用外部資源。
測試三: 在地址欄中輸入 http://localhost:8080/SpringMVC/,填寫表單如下:
點擊提交後,跳轉到 show.jsp 頁面,參數能夠顯示出來,如下。由此說明:在轉發時,resource1 和 resource2 共用同一個請求域。
刷新上述頁面時,會提示重複提交表單,如下。因此,在增刪改操作時,不建議使用轉發(forward)
2.2 重定向(redirect)
Test.java
package com.test;
import java.util.Map;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class Test {
@RequestMapping("resource1")
public String resource1(Map<String,Object> map,User user) {
map.put("user", user);
return "redirect:/resource2";
}
@RequestMapping("resource2")
public String resource2() {
return "show";
}
}
注意: 由於 redirect 不能將請求重定向到 WEB-INF目錄下的資源,因此 resource1 中的返回值不可以爲如下:
return "redirect:/WEB-INF/view/show.jsp";
測試一:在地址欄中輸入 http://localhost:8080/SpringMVC/resource1,跳轉到 show.jsp 頁面,但地址發生變化,如下。由此說明:重定向(redirect)改變了請求地址。
測試二:若將 resource1 中返回值設置如下:
return "redirect:https://www.baidu.com";
並在地址欄中輸入 http://localhost:8080/SpringMVC/resource1,會跳到百度網頁,如下:
由此說明: 重定向(redirect)可以訪問 Web 應用外部資源。
注意:在上述返回值中的 redirect 之後,不要加“/”,否則會報錯如下,加“/”後表示在當前訪問路徑下尋找資源。
測試三: 在地址欄中輸入 http://localhost:8080/SpringMVC/,填寫表單如下:
點擊提交後,跳轉到 show.jsp 頁面,參數不能夠顯示出來,如下。由此說明:在重定向時,resource1 和 resource2 用的是不同的請求域。
刷新上述頁面時,沒有提示重複提交表單。因此,在增刪改操作時,建議使用轉發(redirect )
配置文件
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<!-- 首頁網頁 -->
<welcome-file-list>
<welcome-file>/WEB-INF/view/index.jsp</welcome-file>
</welcome-file-list>
<!-- 配置核心(前端)控制器 DispatcherServlet -->
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!-- 加載IOC容器配置文件 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 配置CharacterEncodingFilter,用於解決後臺中文亂碼 -->
<filter>
<filter-name>characterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>characterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 掃描組件,將加@Controller註解的類作爲SpringMVC的控制層 -->
<context:component-scan base-package="com.test"></context:component-scan>
<!-- 配置視圖解析器 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"></property>
<property name="suffix" value=".jsp"></property>
</bean>
</beans>