Java学习笔记-Day72 SpringMVC 框架(四)
一、转发和重定向
加入forward和redirect关键字,视图解析器的前缀和后缀会失效。
1、转发
(1)return “fc1”;(页面会转发到 /WEB-INF/jsp/fc1.jsp)
@Controller
public class ForwardController {
@GetMapping("fc1")
public String fc1() {
return "fc1";// /WEB-INF/jsp/fc1.jsp
}
}
(2)return “forward:fc2”;(页面会转发到 fc1,即/fc1)
@Controller
public class ForwardController {
@GetMapping("fc2")
public String fc2() {
return "forward:fc1";// /fc1
}
}
(3)return “froward:fc3.jsp”;(相对路径,会转发到相对路径下的fc3.jsp)
@Controller
public class ForwardController {
@GetMapping("fc3")
public String fc3() {
return "forward:fc3.jsp";//相对路径,转发到 /fc3.jsp
}
}
@Controller
@RequestMapping("api")
public class ForwardController {
@GetMapping("fc3")
public String fc3() {
return "forward:fc3.jsp"; //相对路径,转发到 /api/fc3.jsp
}
}
(4)return “forward:/fc3.jsp”;(绝对路径,会转发到WebContent目录下的fc3.jsp,即/fc3.jsp)
@Controller
public class ForwardController {
@GetMapping("fc3")
public String fc3() {
return "forward:/fc3.jsp"; //绝对路径,转发到 /fc3.jsp
}
}
@Controller
@RequestMapping("api")
public class ForwardController {
@GetMapping("fc3")
public String fc3() {
return "forward:/fc3.jsp"; //绝对路径,转发到 /fc3.jsp
}
}
2、重定向
(1)return “redirect:/WEB-INF/jsp/hello.jsp”;(无法重定向到该文件,会出现404错误)
@Controller
public class RedirectController {
@GetMapping("rc1")
public String rc1() {
return "redirect:/WEB-INF/jsp/rc1.jsp"; // 无法访问/WEB-INF/jsp/rc1.jsp,
}
}
不能使用redirect重定向到WEB-INF目录下的文件中,这个是web项目的一种安全级别,即WEB-INF目录是受保护的,不能直接通过url访问WEB-INF目录下的数据。可以将后台文件放入WEB-INF目录中。
(2)return “redirect:rc1”;(页面会重定向到 rc1,即/rc1)
@Controller
public class RedirectController {
@GetMapping("rc2")
public String rc2() {
return "redirect:rc1";// /rc1
}
}
(2)return "redirect:rc2.jsp";(相对路径,会重定向到相对路径下的fc3.jsp)
```java
@Controller
public class RedirectController {
@GetMapping("rc2")
public String rc2() {
return "redirect:rc2.jsp";//相对路径,重定向到 /rc2.jsp
}
}
@Controller
@RequestMapping("api")
public class RedirectController {
@GetMapping("rc2")
public String rc2() {
return "redirect:rc2.jsp"; //相对路径,重定向到 /api/rc2.jsp
}
}
(3)return “/redirect:rc2.jsp”;(绝对路径,会重定向到WebContent目录下的rc2.jsp,即/rc2.jsp)
@Controller
public class RedirectController {
@GetMapping("rc2")
public String rc2() {
return "redirect:/rc2.jsp"; //绝对路径,重定向到 /rc2.jsp
}
}
@Controller
@RequestMapping("api")
public class RedirectController {
@GetMapping("rc2")
public String rc2() {
return "redirect:/rc2.jsp"; //绝对路径,重定向到 /rc2.jsp
}
}
二、从控制器传回数据到视图(非ajax请求)
(1)request.setAttribute(键, 值);
@Controller// 转发请求
public class DataTransController {
@GetMapping("dc")
public String dc1(HttpServletRequest request) {
request.setAttribute("msg1", "dc1");
return "dc";
}
}
(2)ModelAndView类(写在方法内部,作为返回值)
@Controller // 转发请求
public class DataTransController {
@RequestMapping("test1")
public ModelAndView sayHello() {
ModelAndView mv = new ModelAndView("test1");
mv.addObject("msg2", "Hello");
return mv; // 转发到/WEB-INF/jsp/test1,jsp
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>test1.jsp</title>
</head>
<body>
<h1>${msg2}</h1>
</body>
</html>
(3)Model、Map或ModelMap。Spring Web MVC 提供Model、Map或ModelMap,能暴露渲染视图需要的模型数据。
ModelMap对象主要用于传递控制方法处理数据到结果页面,也就是说把结果页面上需要的数据放到ModelMap对象中即可,作用类似于request对象的setAttribute方法,用来在一个请求过程中传递处理的数据。
在控制器中通过以下方法向页面传递参数: addAttribute(String key,Object value);
在页面上通过 el变量方式$key 或者 其他的数据展示标签 获取并展示modelmap中的数据。
ModelMap对象本身不能设置页面跳转的url地址别名或者物理跳转地址,那么我们可以通过控制器方法的返回值来设置跳转url地址别名或者物理跳转地址。
@Controller
public class ModelTestController {
@GetMapping("tmc2")
public String tmc2(Model model,Map map,ModelMap modelmap) {
// Model、Map、ModelMap使用的都是同一个BindingAwareModelMap实现类的对象
model.addAttribute("msg1", "model");
map.put("msg2", "map");
modelmap.addAttribute("msg3", "modelmap");
return "tmc1";
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>tmc1.jsp</title>
</head>
<body>
${msg1}<br/>
${msg2}<br/>
${msg3}<br/>
</body>
</html>
(4)@ModelAttribute
1、@ModelAttribute具有如下三个作用:
① 绑定请求参数到命令对象:放在功能处理方法的入参(某个控制器的方法参数)上时,用于将多个请求参数绑定到一个命令对象,从而简化绑定流程,而且自动暴露为模型数据用于视图页面展示时使用。此时,和(Model model) 写法的功能相同。
② 暴露表单引用对象为模型数据:放在处理器的一般方法(非功能处理方法)上时,是为表单准备要展示的表单引用对象,如注册时需要选择的所在城市等,而且在执行功能处理方法(@RequestMapping注解的方法)之前,自动添加到模型对象中,用于视图页面展示时使用。
③暴露@RequestMapping方法返回值为模型数据:放在功能处理方法的返回值上时,是暴露功能处理方法的返回值为模型数据,用于视图页面展示时使用。
2、在 SpringMVC 的 Controller 中使用 @ModelAttribute 时,应用位置包括下面几种:
① 应用在方法前:在访问GetMapping、PostMapping等映射注解的方法时,会先执行这个方法,会将返回的对象存放在request范围中,从而实现将数据传递到jsp页面。
@Controller
public class ModelAttributeTestController {
// c->v
@GetMapping("matc1")
@ModelAttribute("user")
public User matc1() {
User user = new User(1,"小明",10,12);
return user; //跳转到 /WEB-INF/jsp/matc1.jsp
}
}
当方法的返回值不是一个字符串,同时是非ajax请求时,则会跳转到一个和映射名相同的视图资源中。
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>matc1.jsp</title>
</head>
<body>
${user}<br/>
</body>
</html>
注意:当调用该控制器类中带有@GetMapping等映射注解的方法时,都会先调用这个方法。
@Controller
public class ModelAttributeTestController {
@GetMapping("matc1")
public String matc1() {
return "matc1";
}
@GetMapping("matc2")
public String matc2() {
return "matc1";
}
//当调用以上带有@GetMapping等映射注解的方法时,都会先调用这个方法
@ModelAttribute("u")
public User matc4() {
User u = new User(4,"小白",10,12);
return u;
}
}
② 放在参数前,主要是接收从视图传递过来的数据。如果有传递参数,则会将这个对象放在request范围内,如果没有传递参数,则不会将这个对象存放在request范围内。
@Controller
public class ModelAttributeTestController {
// view -> controller -> view
@GetMapping("matc2")
public String matc3(@ModelAttribute("user") User user) {
System.out.println("user="+user);
return "matc2";//跳转到 /WEB-INF/jsp/matc2.jsp
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>matc3.jsp</title>
</head>
<body>
${user}<br/>
</body>
</html>
三、@SessionAttributes
有时候我们需要在多次请求之间保持数据,一般情况需要我们明确的调用HttpSession的API来存取会话数据。
方式一:request.getSession().setAttribute方法
@Controller
public class SessionTestController {
@RequestMapping("hello_session")
public String sessionTest(HttpServletRequest request) {
Users u = new Users(1,"小明");
request.getSession().setAttribute("u", u);
return "hello_session";
}
}
在hello_session.jsp就可以直接访问: ${sessionScope.u.userId}
或者${u.userId}
。
方式二:session.setAttribute方法
@Controller
public class SessionTestController {
@RequestMapping("/hello_session2")
public String sessionTest2(HttpSession session, SessionStatus sta) {
// 如果session还在
if (!sta.isComplete()) {
sta.setComplete(); // 让旧的session过期
}
Users u = new Users(1,"小明");
session.setAttribute("u", u);
return "hello_session2";
}
}
在hello_session2.jsp就可以直接访问: ${sessionScope.u.userId}
或者${u.userId}
。
方式三:Spring Web MVC提供了@SessionAttributes进行请求间透明的存取会话数据。@SessionAttributes绑定命令对象(@ModelAtrribute)到session,注解的位置在类前面,不能出现在方法前面.。通常与@ModelAttribute组合使用。
@Controller
@SessionAttributes(value= {
"nickname","name"})
public class SessionTestController {
@GetMapping("stc1")
public String stc1() {
return "stc1";
}
@ModelAttribute("nickname")
public String getModelValue1() {
return "小红";
}
@GetMapping("stc2")
@ModelAttribute("name")
public String getModelValue2() {
return "小安";
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>stc1.jsp</h1>
request:${requestScope.nickname}<br/>
session:${sessionScope.nickname}<br/>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>stc2.jsp</h1>
request:${requestScope.name}<br/>
session:${sessionScope.name}<br/>
</body>
</html>
@SessionAttributes基本原理:
首先根据@SessionAttributes注解信息查找会话内的对象放入到模型数据中。执行@ModelAttribute注解的方法:如果模型数据中包含同名的数据,则不执行@ModelAttribute注解方法进行准备表单引用数据,而是使用方式一中的会话数据。如果模型数据中不包含同名的数据,执行@ModelAttribute注解的方法并将返回值添加到模型数据中。