zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【springMVC】转发与重定向

2023-09-11 14:20:52 时间

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>