版权声明:From Lay https://blog.csdn.net/Sadlay/article/details/84109065
SpringMVC(九)控制器通知
在spring AOP中,可以通过通知来增强Bean的功能。同样地,spring MVC也可以给控制器增加通知,于是在控制器方法的前后和异常发生时去执行不同的处理
这里涉及4个注解,分别是@ControllerAdvice
、@InitBinder
、ExceptionHandler
和@ModelAttribute
。
- @ControllerAdvice:定义一个控制器的通知类,允许定义一些关于增强控制器的各类通知和限定增强哪些控制器功能等。
- @InitBinder:定义控制器参数绑定规则,如转换规则,格式化等,它会在参数转换之前执行。
- @ExceptionHandler:定义控制器发生异常后的操作。一般来说,发生异常后,可以挑战到指定的友好页面,以避免用户使用的不友好。
- @ModelAtrribute:可以在控制器的方法执行之前,对数据模型进行操作。
下面通过代码来看这些注解的使用方法
package com.lay.mvc.controller.advice;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Description: 定义控制器通知
* @Author: lay
* @Date: Created in 17:07 2018/11/15
* @Modified By:IntelliJ IDEA
*/
@ControllerAdvice(
//指定拦截的包
basePackages = {"com.lay.mvc.controller.advice.test.*"},
//限定被标注@Controller的类才被拦截
annotations = Controller.class)
public class MyControllerAdvice {
//绑定格式化参、参数转换规则和增加验证器
@InitBinder
public void initDataBinder(WebDataBinder binder){
//自定义日期编辑器,限定格式为yyyy-Mm-dd,且参数不允许为空
CustomDateEditor dateEditor=new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),false);
//注册自定义日期编辑其
binder.registerCustomEditor(Date.class,dateEditor);
}
//在控制器之前线执行,可以初始化数据模型
@ModelAttribute
public void projectModel(Model model){
model.addAttribute("projectName","spring_mvc");
}
// 异常处理,使得被拦截的控制器发生异常时,都能用相同的视图响应
@ExceptionHandler(value = Exception.class)
public String exception(Model model ,Exception ex){
//给数据模型增加异常消息
model.addAttribute("exception_message",ex.getMessage());
//返回异常视图
return "exception";
}
}
- @ControllerAdvice:标明一个控制器的通知类,这个注解也标注了
@Controller
,所以它会在Spring Ioc容器中自动扫描和装配。它的配置项basePackages
配置的是包名限制,也就是符合该配置的包控制器才会被这个控制器通知所拦截,而annotaions
得配置项则是在原有包名限定的基础上再添加被标注为@Controller
的类才会被拦截。 - @InitBinder:是一个控制器参数转换前被执行的代码。这里的
WebDataBinder
参数对象是spring mvc会自动生成的参数,这里定义了日期(Date)类型的参数,采用了限定格式"yyyy-MM-dd",则不再需要加入@DateTimeFormat
对格式再进行指定,直接采用”yyyy-MM-dd“格式传输日期参数即可。 - @ModelAtrribute:是一个数据模型的注解。它在执行控制器方法前被执行,代码中增加了一个字符串,因此在控制器方法中可以获取它。
- @ExceptionHandler:配置项为Exception,它可以拦截所有控制器发生的异常。这里的Exception参数是Spring MVC执行控制器发生异常时传递的,而在方法中,给数据模型添加了异常信息,然后返回一个字符串exception,这个字符指向了对应的视图。
为了测试控制器通知,我们写一个测试的控制器
TestController
package com.lay.mvc.controller.advice.test;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.thymeleaf.util.DateUtils;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* @Description:
* @Author: lay
* @Date: Created in 17:09 2018/11/15
* @Modified By:IntelliJ IDEA
*/
@Controller
@RequestMapping("/advice")
public class TestController {
@GetMapping("/test")
public String test(Date date, ModelMap modelMap){
//从数据模型中获取数据
String projectName = (String) modelMap.get("projectName");
System.out.println(projectName);
//打印日期参数
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(date));
//抛出异常,这样转到控制器异常通知
throw new RuntimeException("异常,跳转到控制器通知的异常信息里");
}
}
展示异常页面
exception.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>异常页面</title>
</head>
<body>
<h1 th:text="${exception_message}"></h1>
</body>
</html>