@ControllerAdvice,是Spring3.2提供的新注解,从名字上可以看出大体意思是控制器增强。让我们先看看@ControllerAdvice的实现:

package org.springframework.web.bind.annotation;@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 {};
}

没什么特别之处,该注解使用@Component注解,这样的话当我们使用<context:component-scan>扫描时也能扫描到。

再一起看看官方提供的comment。

大致意思是:

  • @ControllerAdvice是一个@Component,用于定义@ExceptionHandler@InitBinder@ModelAttribute方法,适用于所有使用@RequestMapping方法。

  • Spring4之前,@ControllerAdvice在同一调度的Servlet中协助所有控制器。Spring4已经改变:@ControllerAdvice支持配置控制器的子集,而默认的行为仍然可以利用。

  • 在Spring4中, @ControllerAdvice通过annotations()basePackageClasses()basePackages()方法定制用于选择控制器子集。

不过据经验之谈,只有配合@ExceptionHandler最有用,其它两个不常用。

在SpringMVC重要注解(一)@ExceptionHandler@ResponseStatus我们提到,如果单使用@ExceptionHandler,只能在当前Controller中处理异常。但当配合@ControllerAdvice一起使用的时候,就可以摆脱那个限制了。

package com.somnus.advice;import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;@ControllerAdvice
public class ExceptionAdvice {@ExceptionHandler({ ArrayIndexOutOfBoundsException.class })
@ResponseBody
public String handleArrayIndexOutOfBoundsException(Exception e) {
e.printStackTrace();
return "testArrayIndexOutOfBoundsException";
@Controller
@RequestMapping(value = "exception")
public class ExceptionHandlerController {@RequestMapping(value = "e2/{id}", method = { RequestMethod.GET })
@ResponseBody
public String testExceptionHandle2(@PathVariable(value = "id") Integer id) {
List<String> list = Arrays.asList(new String[]{"a","b","c","d"});
return list.get(id-1);
}}

当我们访问http://localhost:8080/SpringMVC/exception/e2/5的时候会抛出ArrayIndexOutOfBoundsException异常,这时候定义在@ControllerAdvice中的@ExceptionHandler就开始发挥作用了。

如果我们想定义一个处理全局的异常

package com.somnus.advice;import javax.servlet.http.HttpServletRequest;import org.springframework.core.annotation.AnnotationUtils;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.ResponseStatus;@ControllerAdvicepublic class ExceptionAdvice {@ExceptionHandler({ Exception.class })@ResponseBodypublic String handException(HttpServletRequest request ,Exception e) throws Exception {e.printStackTrace();return e.getMessage();}
}

乍一眼看上去毫无问题,但这里有一个纰漏,由于Exception是异常的父类,如果你的项目中出现过在自定义异常中使用@ResponseStatus的情况,你的初衷是碰到那个自定义异常响应对应的状态码,而这个控制器增强处理类,会首先进入,并直接返回,不会再有@ResponseStatus的事情了,这里为了解决这种纰漏,我提供了一种解决方式。

    package com.somnus.advice;import javax.servlet.http.HttpServletRequest;import org.springframework.core.annotation.AnnotationUtils;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.ResponseStatus;@ControllerAdvicepublic class ExceptionAdvice {@ExceptionHandler({ Exception.class })@ResponseBodypublic String handException(HttpServletRequest request ,Exception e) throws Exception {e.printStackTrace();//If the exception is annotated with @ResponseStatus rethrow it and let// the framework handle it - like the OrderNotFoundException example// at the start of this post.// AnnotationUtils is a Spring Framework utility class.if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null){throw e;}// Otherwise setup and send the user to a default error-view./*ModelAndView mav = new ModelAndView();mav.addObject("exception", e);mav.addObject("url", request.getRequestURL());mav.setViewName(DEFAULT_ERROR_VIEW);return mav;*/return e.getMessage();}}

如果碰到了某个自定义异常加上了@ResponseStatus,就继续抛出,这样就不会让自定义异常失去加上@ResponseStatus的初衷。

SpringMVC重要注解(二)@ControllerAdvice相关推荐

  1. SpringMVC学习(二)——快速搭建SpringMVC开发环境(注解方式)

    文章目录 说明 1.工程搭建 2.注解配置 2.1.context:annotation-config说明 2.2.context:component-scan配置说明 2.3.mvc:annotat ...

  2. springmvc常用注解

    转载自   springmvc常用注解 第一部分 一.@Controller 在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请 ...

  3. springmvc常用注解与类型转换

    springmvc常用注解与类型转换 一:前置 spring -servlet.xml 注入 <!-- 启用spring mvc 注解 --><context:annotation- ...

  4. JAVAWEB开发之SpringMVC详解(二)——高级开发、数据回显、参数绑定集合、图片上传、json交互、validation校验、异常处理、RESTful支持、拦截器

    知识回顾 springmvc框架 用户请求url到DispatcherServlet前端控制器,相当于中央调度器,降低系统各组件之间的耦合度. DispatcherServlet前端控制器通过Hand ...

  5. SpringMVC全注解环境搭建

    源代码: 链接:https://pan.baidu.com/s/1Lxb-riH–YQNIy3c0i8pFA 提取码:y3aq 文档地址:https://shphuang_aliyun.gitee.i ...

  6. SpringMVC入门(二)—— 参数的传递、Controller方法返回值、json数据交互、异常处理、图片上传、拦截器

    SpringMVC入门(二)-- 参数的传递.Controller方法返回值.json数据交互.异常处理.图片上传.拦截器 参考文章: (1)SpringMVC入门(二)-- 参数的传递.Contro ...

  7. SpringMVC-学习笔记03【SpringMVC常用注解】

    Java后端 学习路线 笔记汇总表[黑马程序员] SpringMVC-学习笔记01[SpringMVC概述及入门案例][day01] SpringMVC-学习笔记02[参数绑定及自定义类型转换] Sp ...

  8. 04springMVC结构,mvc模式,spring-mvc流程,spring-mvc的第一个例子,三种handlerMapping,几种控制器,springmvc基于注解的开发,文件上传,拦截器,s

     1. Spring-mvc介绍 1.1市面上流行的框架 Struts2(比较多) Springmvc(比较多而且属于上升的趋势) Struts1(即将被淘汰) 其他 1.2  spring-mv ...

  9. springmvc php,SpringMVC 常用注解

    SpringMVC 常用注解 1.@Controller 在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理 ...

最新文章

  1. 微信支付回调重复通知,正确的响应
  2. uva5984(简单计算几何)
  3. 从工程文化和运维理念理解Netflix
  4. CSE lab7 RPC 攻略
  5. java ee ssh三大框架知识点_详解JAVAEE——SSH三大框架整合(spring+struts2+hibernate)...
  6. DICOM开发工具总结
  7. 2019-11-25 编写cmake 脚本注意事项
  8. ENVI数据类型和MATLAB数据类型对比
  9. [机缘参悟-61]:《兵者,诡道也》-2-三十六计解读-胜战计
  10. 电机与拖动基础--第一章
  11. Python验证哥德巴赫猜想,并返回数组
  12. 信息检索关键词的进阶使用
  13. 1405:三元一次方程
  14. 优秀!95后程序员月薪2万背电脑送外卖,送单途中修bug!
  15. 一把王者的时间带你拿捏计算机中整形提升的问题
  16. 开发、测试、测试开发
  17. MySQL——基础知识总结超详细版本(一)
  18. Java是剑客,.NET是刀客
  19. phpcms 点赞_php+js实现点赞功能的示例详解
  20. 平凡前端之路_05.CSS与CSS3

热门文章

  1. BTC交易费激增,LTC活跃地址数飙升! BRC-20爆火背后,区块链网络经历了什么?
  2. android系统中定义的按键码(包含键盘,游戏手柄,TV遥控器)
  3. 字节跳动薪酬体系曝光,我承认我酸了
  4. xerces-c++内存管理策略为何耗费大量内存
  5. 语音播报 android,Android 语音播报 文字转语音
  6. 穷人版生产力工具,好用得飞起 「GitHub 热点速览」
  7. 发adb强制打开关闭webview应用,关闭后打开web显示白屏,默认关闭快霸。移除快霸。工模测试,蓝牙测试,前后摄像头测试没有成功失败按钮。
  8. Revit二次开发——不启动Revit,做rvt文件数据导出
  9. 有源rc电压放大器实验报告_常见的有源器件和无源器件
  10. runat=”server”