在Spring 3.2中,新增了@ControllerAdvice、@RestControllerAdvice 注解,都是对Controller进行增强。
1.@ControllerAdvice和@RestControllerAdvice
ControllerAdviceh和RestControllerAdvice一样,本质上是一个Component,因此也会被当成组件注册到IOC容器中。
以@ControllerAdvice为例,我们来看下它的源码定义:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<?>[] assignableTypes() default {};
Class<? extends Annotation>[] annotations() default {};
}
初定义拦截规则:
@ControllerAdvice或者@RestControllerAdvice 提供了多种指定Advice规则的定义方式,默认什么都不写,则是对所有的Controller起作用,当然你也可以通过下列的方式指定规则 比如: 写成@ControllerAdvice("org.my.pkg") 或者 @ControllerAdvice(basePackages="org.my.pkg"), 则匹配org.my.pkg包及其子包下的所有Controller,当然也可以用数组的形式指定,如:@ControllerAdvice(basePackages={"org.my.pkg", "org.my.other.pkg"}), 也可以通过指定注解来匹配,比如我自定了一个 @CustomAnnotation 注解,我想匹配所有被这个注解修饰的 Controller, 可以这么写:@ControllerAdvice(annotations={CustomAnnotation.class})
@RestControllerAdvice作用与@ControllerAdvice类似,可以理解为@RestControllerAdvice = @ControllerAdvice + @ResponseBody。
2.实例
处理全局异常。
例如:有以下登录接口。
@RestController
@RequestMapping("users")
public class UsersController {
@GetMapping("/auth")
public R login(@RequestParam("username") String username, @RequestParam("password") String password){
try{
if("admin".equals(username)&&"123456".equals(password)){
return R.success("登录成功!");
}
return R.fail("登录失败!");
}catch(Exception ex){
ex.printStackTrace();
return R.error("出现异常!");
}
}
}
如果调用这个接口,参数不完整,则抛出以下异常。但是这样的界面显然不友好。

我们可以通过@RestControllerAdvice实现全局异常处理。
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MissingServletRequestParameterException.class)
public R handleException(MissingServletRequestParameterException e){
return R.error("参数不符合规范!");
}
}
如果再次调用该接口,出现参数不完整的情况,将会显示更友好的报错信息。
{"data":null,"msg":"参数不符合规范!","code":500,"token":null}