1.@ControllerAdvice

1.场景一

在构建RestFul的今天,我们一般会限定好返回数据的格式比如:

{

  "code": 0,
"data": {},
"msg": "操作成功" }

  但有时却往往会产生一些bug。这时候就破坏了返回数据的一致性,导致调用者无法解析。所以我们常常会定义一个全局的异常拦截器。

2.场景二

  对于与数据库相关的 Spring MVC 项目,我们通常会把 事务 配置在 Service层,当数据库操作失败时让 Service 层抛出运行时异常,Spring 事物管理器就会进行回滚。

如此一来,我们的 Controller 层就不得不进行 try-catch Service 层的异常,否则会返回一些不友好的错误信息到客户端。但是,Controller 层每个方法体都写一些模板化的 try-catch 的代码,很难看也难维护,特别是还需要对 Service 层的不同异常进行不同处理的时候。

  @ControllerAdvice + @ExceptionHandler 进行全局的 Controller 层异常处理,只要设计得当,就再也不用在 Controller 层进行 try-catch 了!而且,@Validated 校验器注解的异常,也可以一起处理,无需手动判断绑定校验结果 BindingResult/Errors 了

3.@ControllerAdvice的使用

1.注意

  • 优点:将 Controller 层的异常和数据校验的异常进行统一处理,减少模板代码,减少编码量,提升扩展性和可维护性。
  • 缺点:只能处理 Controller 层未捕获(往外抛)的异常,对于 Interceptor(拦截器)层的异常,Spring 框架层的异常,就无能为力了。

2.@ControllerAdvice

  该注解是springMVC的注解

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

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

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

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

3.使用

  @ControllerAdvice 注解定义全局异常处理类

@ControllerAdvice
public class GlobalExceptionHandler {
}

  @ExceptionHandler 注解声明异常处理方法

@ControllerAdvice
public class GlobalExceptionHandler { @ExceptionHandler(Exception.class)
@ResponseBody
String handleException(){
return "Exception Deal!";
}
}

  方法 handleException() 就会处理所有 Controller 层抛出的 Exception 及其子类的异常,这是最基本的用法了。

被 @ExceptionHandler 注解的方法的参数列表里,还可以声明很多种类型的参数,详见文档。其原型如下:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ExceptionHandler { /**
* Exceptions handled by the annotated method. If empty, will default to any
* exceptions listed in the method argument list.
*/
Class<? extends Throwable>[] value() default {}; }

如果 @ExceptionHandler 注解中未声明要处理的异常类型,则默认为参数列表中的异常类型。所以上面的写法,还可以写成这样:

@ControllerAdvice
public class GlobalExceptionHandler { @ExceptionHandler()
@ResponseBody
String handleException(Exception e){
return "Exception Deal! " + e.getMessage();
}
}

参数对象就是 Controller 层抛出的异常对象!

示例

package com.cmc.schedule.handler;  

import com.gionee.base.entity.JsonResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; import java.io.IOException; /**
* 异常拦截处理器
*
* @author chenmc
*/
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler { private static final String logExceptionFormat = "Capture Exception By GlobalExceptionHandler: Code: %s Detail: %s";
private static Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); //运行时异常
@ExceptionHandler(RuntimeException.class)
public String runtimeExceptionHandler(RuntimeException ex) {
return resultFormat(1, ex);
} //空指针异常
@ExceptionHandler(NullPointerException.class)
public String nullPointerExceptionHandler(NullPointerException ex) {
return resultFormat(2, ex);
} //类型转换异常
@ExceptionHandler(ClassCastException.class)
public String classCastExceptionHandler(ClassCastException ex) {
return resultFormat(3, ex);
} //IO异常
@ExceptionHandler(IOException.class)
public String iOExceptionHandler(IOException ex) {
return resultFormat(4, ex);
} //未知方法异常
@ExceptionHandler(NoSuchMethodException.class)
public String noSuchMethodExceptionHandler(NoSuchMethodException ex) {
return resultFormat(5, ex);
} //数组越界异常
@ExceptionHandler(IndexOutOfBoundsException.class)
public String indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) {
return resultFormat(6, ex);
} //400错误
@ExceptionHandler({HttpMessageNotReadableException.class})
public String requestNotReadable(HttpMessageNotReadableException ex) {
System.out.println("400..requestNotReadable");
return resultFormat(7, ex);
} //400错误
@ExceptionHandler({TypeMismatchException.class})
public String requestTypeMismatch(TypeMismatchException ex) {
System.out.println("400..TypeMismatchException");
return resultFormat(8, ex);
} //400错误
@ExceptionHandler({MissingServletRequestParameterException.class})
public String requestMissingServletRequest(MissingServletRequestParameterException ex) {
System.out.println("400..MissingServletRequest");
return resultFormat(9, ex);
} //405错误
@ExceptionHandler({HttpRequestMethodNotSupportedException.class})
public String request405(HttpRequestMethodNotSupportedException ex) {
return resultFormat(10, ex);
} //406错误
@ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
public String request406(HttpMediaTypeNotAcceptableException ex) {
System.out.println("406...");
return resultFormat(11, ex);
} //500错误
@ExceptionHandler({ConversionNotSupportedException.class, HttpMessageNotWritableException.class})
public String server500(RuntimeException ex) {
System.out.println("500...");
return resultFormat(12, ex);
} //栈溢出
@ExceptionHandler({StackOverflowError.class})
public String requestStackOverflow(StackOverflowError ex) {
return resultFormat(13, ex);
} //其他错误
@ExceptionHandler({Exception.class})
public String exception(Exception ex) {
return resultFormat(14, ex);
} private <T extends Throwable> String resultFormat(Integer code, T ex) {
ex.printStackTrace();
log.error(String.format(logExceptionFormat, code, ex.getMessage()));
return JsonResult.failed(code, ex.getMessage());
} }

注:  

  springboot中这样就可以了!!!

  如果是springMVC配置文件中增加下面的配置

<!-- 处理异常 -->
<context:component-scan base-package="com.gionee.xo" use-default-filters="false">
<!-- base-package 如果多个,用“,”分隔 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
<!--控制器增强,使一个Contoller成为全局的异常处理类,类中用@ExceptionHandler方法注解的方法可以处理所有Controller发生的异常-->
<context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" />
</context:component-scan>

参考:

  https://blog.csdn.net/kinginblue/article/details/70186586

  https://blog.csdn.net/u014044812/article/details/78219692

  https://blog.csdn.net/w372426096/article/details/78429141

    

十四、springboot全局处理异常(@ControllerAdvice + @ExceptionHandler)的更多相关文章

  1. “全栈2019”Java异常第十四章:将异常输出到文本文件中

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java异 ...

  2. (转)springboot全局处理异常(@ControllerAdvice + @ExceptionHandler)

    1.@ControllerAdvice 1.场景一 在构建RestFul的今天,我们一般会限定好返回数据的格式比如: { "code": 0, "data": ...

  3. spring boot 学习(十四)SpringBoot+Redis+SpringSession缓存之实战

    SpringBoot + Redis +SpringSession 缓存之实战 前言 前几天,从师兄那儿了解到EhCache是进程内的缓存框架,虽然它已经提供了集群环境下的缓存同步策略,这种同步仍然需 ...

  4. 十四.spring-boot使用mybatis

    在springMVC+spring中使用mybatis已经非常非常的灵活,但是需要配置很多的信息 一.创建maven web project 二.创建数据库表 三.在application.prope ...

  5. [十四]SpringBoot 之 Spring拦截器(HandlerInterceptor)

    过滤器属于Servlet范畴的API,与spring 没什么关系. Web开发中,我们除了使用 Filter 来过滤请web求外,还可以使用Spring提供的HandlerInterceptor(拦截 ...

  6. @ControllerAdvice + @ExceptionHandler 全局处理 Controller 层异常==》记录

    对于与数据库相关的 Spring MVC 项目,我们通常会把 事务 配置在 Service层,当数据库操作失败时让 Service 层抛出运行时异常,Spring 事物管理器就会进行回滚. 如此一来, ...

  7. @ControllerAdvice + @ExceptionHandler 全局处理 Controller 层异常

    @ControllerAdvice 和 @ExceptionHandler 的区别 ExceptionHandler, 方法注解, 作用于 Controller 级别. ExceptionHandle ...

  8. 转:@ControllerAdvice + @ExceptionHandler 全局处理 Controller 层异常

    继承 ResponseEntityExceptionHandler 类来实现针对 Rest 接口 的全局异常捕获,并且可以返回自定义格式: 复制代码 1 @Slf4j 2 @ControllerAdv ...

  9. Spring @ControllerAdvice @ExceptionHandler 全局处理异常

    对于与数据库相关的 Spring MVC 项目,我们通常会把 事务 配置在 Service层,当数据库操作失败时让 Service 层抛出运行时异常,Spring 事物管理器就会进行回滚. 如此一来, ...

随机推荐

  1. WP8.1学习系列(第十章)——中心控件Hub设计指南

    Windows Phone 应用商店应用中的中心控件指南   在本文中 说明 示例 用法指南 设计指南 相关主题 重要的 API Hub (XAML) HubSection (XAML) 说明 中心控 ...

  2. java基础---->使用Itext生成数据库文档

    这里简单的介绍一下使用Itext生成数据库表的文档.于是我们领教了世界是何等凶顽,同时又得知世界也可以变得温存和美好. 生成数据库的文档 一.maven项目需要引入的jar依赖 <depende ...

  3. jstorm开发指南-写个简单的jstorm应用

    jstorm开发指南-写个简单的jstorm应用 发表于 2015-07-18   |   分类于 大数据   |   暂无评论 jstorm 是阿里巴巴开源的基于storm采用Java重写的一套分布 ...

  4. $.format,jquery.format 使用说明

    为jquery添加 format  功能 $.format = function (source, params) { if (arguments.length == 1) return functi ...

  5. 外网电脑配置8G运行内存,运行Android Studio,速度很轻松

    Win 7系统 之前RAM是 4 G,运行Android studio ,再运行浏览器或办公软件时卡的一比.再插入一个 4G内存条,总共8G时,速度嗖的一下就上来了.

  6. Kafka+Storm+HDFS 整合示例

    消息通过各种方式进入到Kafka消息中间件,比如可以通过使用Flume来收集日志数据,然后在Kafka中路由暂存,然后再由实时计算程序Storm做实时分析,最后将结果保存在HDFS中,这时我们就需要将 ...

  7. explain 和 desc 详解

    MySQL性能分析 1.使用explain语句去查看分析结果 如explain select * from test1 where id=1;会出现:id  selecttype  table  ty ...

  8. cadence allegro 封装产考原点修改

    打开 dra文件后 在菜单栏 setup - change drawing origin 在命令栏输入 新的参考点位置 如想更改新坐标位置为 1,2 .输入  x 1 2 上面两步操作后即可修改!

  9. Android 浅谈 设计与屏幕适配 【1.6235449734285716】

    extends: http://www.ui.cn/detail/45435.html http://www.2cto.com/kf/201501/372699.html http://www.cnb ...

  10. myeclipse乱码/GBK只支持中文

    Windows>>Pereferences>>General>Editors>>Spelling>>Encoding选项下选择other,然后输入 ...