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 后面需要指定视图文件的完整路径。
转发和重定向都是一种响应方式,其内在区别就在于一个是寻找视图的方式是不同的。一个是控制器帮着找,一个是浏览器通过再次发起请求寻找,所以,重定向和转发对数据模型的作用域要求是不同的。