Spring MVC 转发与重定向

1. 前言

WEB 应用程序的交互模式通过请求包与响应包来完成,请求包一般由浏览器构建,并发送给服务器端。服务器端解析请求包,并根据具体的业务逻辑处理请求包中的数据,并构建响应包回应请求方。

响应包的实体部分中的内容可以由控制器的方法决定,或者说由需求来决定。根据响应包中的内容不同,可以分两者响应方式:

  • 转发:响应包直接包含响应给浏览器的数据;
  • 重定向:响应包仅包含数据视图的地址。

本节课程将向大家讲解 Spring MVC 中如何实现转发和重定向。本章节的重点是了解转发和重定向的本质。

2. 响应的本质

Spring MVC 项目中的用户控制器用来处理用户的请求,无论处理的结果如何,都需要给用户一个响应,HTTP 响应包可以说是这个响应结果的载体。

理论上讲,用户控制器处理完请求,得到的结果数据可以直接写入到响应包中。

@Controller
public class ResponseAction {
@RequestMapping("/response01")
public void response01(HttpServletResponse response) throws IOException {
	//发送给客户端的响应数据
	String hello="hello";
	PrintWriter out =response.getWriter();
	out.write(hello);
	out.close();
}
}

把需要响应给客户端的数据写入响应包中便是响应的本质。

如果仅仅只是把数据发送给客户端,数据在浏览器中显示时,出来的样式会过于简单、甚至丑陋。要解决这个问题,也好办,发送数据时,也附带发送数据格式。

Tips:如果客户端只需要纯数据,如 JSON 格式,则可以直接使用上面的方法。

修改上面的响应数据:

String hello="<font color=\"red\">hello</font>";

这时,在浏览器中不仅能看到数据,还能用设计好的样式显示出来。初期 WEB 开发,便采用了这种 “数据 + 样式” 的方式。因初期页面中数据并不是很多,人为对于页面无素显示也没有多大需求。

但是,随着项目功能越来越大,数据量成倍增加,比如说商城首页,需要显示当前登录者信息、商品信息、推荐的商品信息、用户浏览信息…… 并且用户对最终显示结果也提出了更多要求,如美观、大方、整洁……

如果还是如前面一样,把数据和 HTML 一起编织在一起,然后响应给客户端,代码将变得丑陋不堪。

新的解决方案是采用组件化开发思想:控制器处理数据,视图组件提供模板样式用来显示最终数据。

所以在构建响应包时,控制器需要 2 方面信息:

  • 数据:由控制器返回;
  • 视图:由视图解析器组件维护。

Spring MVC 提供数据模型组件充当数据和视图之间的桥梁。

  • 控制器先把处理后的数据保存到数据模型中;
  • 找到视图,由视图从数据模型中取得数据,并显示在视图中。

重定向和转发的区别在于寻找视图的方式。

2.1 转发

如下面的实例:

@RequestMapping("/response02")
public String response02(ModelMap model) throws IOException {
	//发送给客户端的响应数据
	String hello="Hello";
	model.addAttribute("data", hello);
	return "hello";
}

上面代码是一个典型的 Spring MVC 控制器代码:

  • 变量 hello 中保存的就是要发送给浏览器的数据。
  • ModelMap 类型的数据模型可以说是一个中间载体,用来临时保存 hello 中的数据;
  • return 后面的 “hello” 是视图的逻辑名,由视图解析器解析并找到真正的页面。

下面是一个标准的视图模板,页面中已经提供了样式,只等数据的到来。

  <html>
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>Insert title here</title>
  </head>
  <body>
  <div style="color:red"> ${data} </div> 
  </body>
  </html>

有了这些信息后,视图解析器把数据和视图合二为一后进行渲染,得到纯 HTML 后写入响应包,发送给浏览器。

图片描述

这便于转发或者叫派发。默认情况下,控制器的响应方式使用的是转发。

转发是在一次请求中一气呵成完成的。如上代码,在浏览器输入请求:http://localhost:8888/sm-demo/response02。

服务端响应包中的数据这就是响应给客户端的最终数据。

Tips: Spring MVC 的整个请求和响应过程是由多个组件协作完成的,这里不深究细节。

2.2 重定向

Spring MVC 中使用重定向很简单,只需要在返回值中添加 redirect 关键字。

@RequestMapping("/response03")
public String response03(ModelMap model) throws IOException {
	//发送给客户端的响应数据
	String hello="Hello";
	model.addAttribute("data", hello);
	return "redirect:/hello";
}

重定向和转发的本质区别在于如何找到视图。转发是控制器自己找的,也就是在服务器端找的。

重定向则是先把视图地址写入响应包,然后发送浏览器,意思是说,浏览器,麻烦你自己找一下。浏览器获取到响应包中的地址后再发送一次请求,找到视图,然后,把数据模型中的数据读出来显示在页面中。

相比较转发,重定向会多一次请求,也意味着数据模型中的数据需要在跨请求间被解析到。另外,视图文件必须放置在浏览器能访问到的位置。如果视图文件放在 WEB-INF 目录下,则重定向是不能访问到的。

图片描述

3. 小结

本章节和大家一起讲解 Spring MVC 框架如何实现转发和重定向,从实现角度来讲,没有太多难度。默认情况下就是转发,加上 redirect 关键字后就能实现重定向。需要注意的是,redirect 后面需要指定视图文件的完整路径。

转发和重定向都是一种响应方式,其内在区别就在于一个是寻找视图的方式是不同的。一个是控制器帮着找,一个是浏览器通过再次发起请求寻找,所以,重定向和转发对数据模型的作用域要求是不同的。