spring的@ControllerAdvice注解
@ControllerAdvice注解是Spring3.2中新增的注解,学名是Controller增强器,作用是给Controller控制器添加统一的操作或处理。
对于@ControllerAdvice,我们比较熟知的用法是结合@ExceptionHandler用于全局异常的处理,但其作用不止于此。ControllerAdvice拆开来就是Controller Advice,关于Advice,在Spring的AOP中,是用来封装一个切面所有属性的,包括切入点和需要织入的切面逻辑。这里ControllerAdvice也可以这么理解,其抽象级别应该是用于对Controller进行切面环绕的,而具体的业务织入方式则是通过结合其他的注解来实现的。@ControllerAdvice是在类上声明的注解,其用法主要有三点:
1.结合方法型注解@ExceptionHandler,用于捕获Controller中抛出的指定类型的异常,从而达到不同类型的异常区别处理的目的。
2.结合方法型注解@InitBinder,用于request中自定义参数解析方式进行注册,从而达到自定义指定格式参数的目的。
3.结合方法型注解@ModelAttribute,表示其注解的方法将会在目标Controller方法执行之前执行。
从上面的讲解可以看出,@ControllerAdvice的用法基本是将其声明在某个bean上,然后在该bean的方法上使用其他的注解来指定不同的织入逻辑。不过这里@ControllerAdvice并不是使用AOP的方式来织入业务逻辑的,而是Spring内置对其各个逻辑的织入方式进行了内置支持。
@ControllerAdvice注解的使用
@ControllerAdvice
public class SpringControllerAdvice {
/**
* 应用到所有被@RequestMapping注解的方法,在其执行之前初始化数据绑定器
* @param binder
*/
@InitBinder
public void initBinder(WebDataBinder binder) {} /**
* 把值绑定到Model中,使全局@RequestMapping可以获取到该值
* @param model
*/
@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("words", "hello world");
} /**
* 全局异常捕捉处理
* @param ex
* @return
*/
@ResponseBody
@ExceptionHandler(value = Exception.class)
public Map errorHandler(Exception ex) {
Map map = new HashMap();
map.put("code", 100);
map.put("msg", ex.getMessage());
return map;
} }
在启动应用之后,被@ExceptionHandler、@InitBinder和@ModelAttribute注解的方法都会作用在被@RequestMappping注解的方法上。比如上面的@ModelAttribute注解的方法参数model上设置的值,所有被@RequestMapping注解的方法中都可以通过ModelMap获取。
@RequestMapping("/index")
public String index(ModelMap modelMap) {
System.out.println(modelMap.get("words"));
}
// 也可以通过@ModelAttribute获取
@RequestMapping("/index")
public String index(@ModelAttribute("words") String words) {
System.out.println(words);
}
下面对@ControllerAdvice三种使用方式进行分别讲解。
@ExceptionHandler拦截异常并统一处理
@ExceptionHandler的作用主要在于声明一个或多个类型的异常,当符合条件的Controller抛出这些异常之后将会对这些异常进行捕获,然后按照其标注的方法的逻辑进行处理,从而改变返回的视图信息。
@ExceptionHandler的属性结构
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler {
// 指定需要捕获的异常的Class类型
Class<? extends Throwable>[] value() default {};
}
使用@ExceptionHandler捕获RuntimeException异常的例子
@ControllerAdvice
public class SpringControllerAdvice {
@ExceptionHandler(RuntimeException.class)
public ModelAndView runtimeExceptionHandler(RuntimeException e) {
e.printStackTrace();
return new ModelAndView("error");
}
}
@Controller
public class UserController {
@RequestMapping(value = "/users", method = RequestMethod.GET)
public void users() {
throw new RuntimeException("没有任何用户。");
}
}
这样,当访问/users的时候,因为在该方法中抛出了RuntimeException,那么理论上这里的异常捕获器就会捕获该异常,然后返回我们定义的异常视图(默认的error视图)。
使用@InitBinder绑定一些自定义参数
对于@InitBinder,该注解的主要作用是绑定一些自定义的参数。一般情况下我们使用的参数通过@RequestParam,@RequestBody或者@ModelAttribute等注解就可以进行绑定了,但对于一些特殊类型参数,比如Date,它们的绑定Spring是没有提供直接的支持的,我们只能为其声明一个转换器,将request中字符串类型的参数通过转换器转换为Date类型的参数,从而供给@RequestMapping标注的方法使用。
@InitBinder的属性结构
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface InitBinder {
// 这里value参数用于指定需要绑定的参数名称,如果不指定,则会对所有的参数进行适配,
// 只有是其指定的类型的参数才会被转换
String[] value() default {};
}
使用@InitBinder注册Date类型参数转换器的实现
@ControllerAdvice
public class SpringControllerAdvice {
@InitBinder
public void globalInitBinder(WebDataBinder binder) {
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}
}
@Controller
public class UserController {
@RequestMapping(value = "/users", method = RequestMethod.GET)
public void users(Date date) {
System.out.println(date); // Tue May 02 00:00:00 CST 2019
}
}
这里@InitBinder标注的方法注册的Formatter在每次request请求进行参数转换时都会调用,用于判断指定的参数是否为其可以转换的参数。可以看到当访问/users的时候,对request参数进行了转换,并且在接口方法中成功接收了该参数,并在控制台打印出日期格式的结果。
使用@ModelAttribute在方法执行前进行一些操作
关于@ModelAttribute的用法,除了用于方法参数时可以用于转换对象类型的属性之外,其还可以用来进行方法的声明。如果声明在方法上,并且结合@ControllerAdvice,该方法将会在@ControllerAdvice所指定的范围内的所有接口方法执行之前执行,并且@ModelAttribute标注的方法的返回值还可以供给后续会调用的接口方法使用。
@ModelAttribute的属性结构
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ModelAttribute {
// 该属性与name属性的作用一致,用于指定目标参数的名称
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
// 与name属性一起使用,如果指定了binding为false,那么name属性指定名称的属性将不会被处理
boolean binding() default true;
}
这里@ModelAttribute的各个属性值主要是用于其在接口方法参数上进行标注时使用的,如果是作为方法注解,其name或value属性则指定的是返回值的名称。
使用@ModelAttribute注解进行方法标注的一个例子
@ControllerAdvice
public class SpringControllerAdvice {
@ModelAttribute(value = "message")
public String globalModelAttribute() {
System.out.println("添加了message全局属性。");
return "输出了message全局属性。";
}
}
@Controller
public class UserController {
@RequestMapping(value = "/users", method = RequestMethod.GET)
public void users(@ModelAttribute("message") String message) {
System.out.println(message);
}
}
这里@ModelAttribute注解的方法提供了一个String类型的返回值,而@ModelAttribute注解中指定了该属性的名称是message,这样在Controller层就可以通过@ModelAttribute注解接收名称为message的参数,从而获取到前面绑定的参数了。
添加了message全局属性。
输出了message全局属性。
从输出结果上看,使用@ModelAttribute注解标注的方法确实在目标方法执行之前执行了。需要说明的是,@ModelAttribute标注的方法的执行是在所有的拦截器的preHandle()方法执行之后才会执行。
小结
关于@ControllerAdvice注解的三种使用方式对应的注解,这三种注解如果应用于@ControllerAdvice注解所标注的类中,那么它们表示会对@ControllerAdvice所指定的范围内的方法都有效;如果单纯地将这三种注解应用于某个Controller中,那么它们将只会对该Controller类中的所有接口有效,并且此时是不需要在该Controller上标注@ControllerAdvice注解的。
另外的还有@RestControllerAdvice注解,用法和@ControllerAdvice注解类似,只是当需要返回值到响应头的时候就不用在方法上添加@ResponseBody注解了。
"可能很多事情都在冥冥之中早有安排。"
spring的@ControllerAdvice注解的更多相关文章
- Spring的ControllerAdvice注解
@ControllerAdvice,是spring3.2提供的新注解,其实现如下所示: @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUN ...
- spring之ControllerAdvice注解
@ControllerAdvice是Spring 3.2新增的注解,主要是用来Controller的一些公共的需求的低侵入性增强提供辅助,作用于@RequestMapping标注的方法上. Contr ...
- spring mvc异常统一处理(ControllerAdvice注解)
首先我的项目是一个为移动端提供的json数据的,当后台报错时如果为移动端返回一个错误页面显得非常不友好,于是通过ControllerAdvice注解返回json数据. 首先创建一个异常处理类: pac ...
- Spring boot异常统一处理方法:@ControllerAdvice注解的使用、全局异常捕获、自定义异常捕获
一.全局异常 1.首先创建异常处理包和类 2.使用@ControllerAdvice注解,全局捕获异常类,只要作用在@RequestMapping上,所有的异常都会被捕获 package com.ex ...
- Spring MVC Framework 注解
ControllerAdvice Spring MVC Framework会把 @ControllerAdvice注解内部使用 @ExceptionHandler.@InitBinder.@Model ...
- Spring Boot常用注解总结
Spring Boot常用注解总结 @RestController和@RequestMapping注解 @RestController注解,它继承自@Controller注解.4.0之前的版本,Spr ...
- SpringMVC 中 @ControllerAdvice 注解的三种使用场景!
@ControllerAdvice ,很多初学者可能都没有听说过这个注解,实际上,这是一个非常有用的注解,顾名思义,这是一个增强的 Controller.使用这个 Controller ,可以实现三个 ...
- Spring Boot @ControllerAdvice 处理全局异常,返回固定格式Json
需求 在构建RestFul的今天,我们一般会限定好返回数据的格式比如: { "code": 0, "data": {}, "msg": ...
- spring 、spring boot 常用注解
@Profile 1.用户配置文件注解. 2.使用范围: @Configration 和 @Component 注解的类及其方法, 其中包括继承了 @Component 的注解: @Service. ...
随机推荐
- 关于Maven+Tomcat7下cannot be cast to javax.servlet.Servlet问题的解决办法
今天在开发 JavaWeb 项目的时候,遇到了这么一个问题,这个错误是我在进行表单的异步提交的时候出现的.无法转化为 Servlet 经过我的一番检查之后!没有发现任何问题.... 注解配置无误 继承 ...
- 史上最全的Java命名规范[转]
每个公司都有不同的标准,目的是为了保持统一,减少沟通成本,提升团队研发效能.所以本文中是笔者结合阿里巴巴开发规范,以及工作中的见闻针对Java领域相关命名进行整理和总结,仅供参考. 一.Java中的命 ...
- Spring Boot快速集成kaptcha生成验证码
Kaptcha是一个非常实用的验证码生成工具,可以通过配置生成多样化的验证码,以图片的形式显示,从而无法进行复制粘贴:下面将详细介绍下Spring Boot快速集成kaptcha生成验证码的过程. 本 ...
- Python里三个最高逼格的调试神器
调试是开发过程中不可避免的一个环节,在Python中我们使用print.logging.assert等方法进行调试既简单又实用,但毕竟有其局限性.今天这篇文章为大家带来三个工具,其中有Python的内 ...
- MySQL入门——在Linux下安装和卸载MariaDB
MySQL入门——在Linux下安装和卸载MariaDB 摘要:本文主要学习了如何在Linux系统中安装和卸载MariaDB数据库. 查看有没有安装过MariaDB 使用命令查看有没有安装过: [ro ...
- git设置github的远程仓库的相关操作
git能够把github作为远程仓库,本地可以进行推送有关变更,从而多人可以进行协作开发工作. 1 ssh-keygen -t rsa -C "your-email@163. ...
- Mysql8.0主从复制搭建,shardingsphere+springboot+mybatis读写分离
1.安装mysql8.0 首先需要在192.167.3.171上安装JDK. 下载mysql安装包,https://dev.mysql.com/downloads/,找到以下页面下载. 下载后放到li ...
- Web服务器—IIS
https://blog.csdn.net/qq_33323054/article/details/81628627 https://jingyan.baidu.com/article/67508eb ...
- [Linux] SSH隧道本地端口转发访问远程服务中的数据库
当我的本地没有安装任何数据库服务的时候,可以直接通过我本地的端口访问远程机器上的数据库服务,实现这样的效果就可以使用本地转发功能 实际测试本地端口转发,把本地的9006端口转发给远程服务器的115.1 ...
- __rpm.so: underfined symbol : rpmpkgverifySigs 故障分析
前言: 近期漏洞修复频繁,各种组件需要升级,经多次碰撞,发现 yum update 来升级组件是最有效最安全的方式(绿盟通过版本比对的扫描结果可以忽略). 然而,各家的设备各家管,一到升级就发现一堆问 ...