注解说明

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

/**
* Specialization of {@link Component @Component} for classes that declare
* {@link ExceptionHandler @ExceptionHandler}, {@link InitBinder @InitBinder}, or
* {@link ModelAttribute @ModelAttribute} methods to be shared across
* multiple {@code @Controller} classes.
*
* <p>Classes with {@code @ControllerAdvice} can be declared explicitly as Spring
* beans or auto-detected via classpath scanning. All such beans are sorted via
* {@link org.springframework.core.annotation.AnnotationAwareOrderComparator
* AnnotationAwareOrderComparator}, i.e. based on
* {@link org.springframework.core.annotation.Order @Order} and
* {@link org.springframework.core.Ordered Ordered}, and applied in that order
* at runtime. For handling exceptions, an {@code @ExceptionHandler} will be
* picked on the first advice with a matching exception handler method. For
* model attributes and {@code InitBinder} initialization, {@code @ModelAttribute}
* and {@code @InitBinder} methods will also follow {@code @ControllerAdvice} order.
*
* <p>Note: For {@code @ExceptionHandler} methods, a root exception match will be
* preferred to just matching a cause of the current exception, among the handler
* methods of a particular advice bean. However, a cause match on a higher-priority
* advice will still be preferred to a any match (whether root or cause level)
* on a lower-priority advice bean. As a consequence, please declare your primary
* root exception mappings on a prioritized advice bean with a corresponding order!
*
* <p>By default the methods in an {@code @ControllerAdvice} apply globally to
* all Controllers. Use selectors {@link #annotations()},
* {@link #basePackageClasses()}, and {@link #basePackages()} (or its alias
* {@link #value()}) to define a more narrow subset of targeted Controllers.
* If multiple selectors are declared, OR logic is applied, meaning selected
* Controllers should match at least one selector. Note that selector checks
* are performed at runtime and so adding many selectors may negatively impact
* performance and add complexity.
*
* @author Rossen Stoyanchev
* @author Brian Clozel
* @author Sam Brannen
* @since 3.2
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice { /**
* Alias for the {@link #basePackages} attribute.
* <p>Allows for more concise annotation declarations e.g.:
* {@code @ControllerAdvice("org.my.pkg")} is equivalent to
* {@code @ControllerAdvice(basePackages="org.my.pkg")}.
* @since 4.0
* @see #basePackages()
*/
@AliasFor("basePackages")
String[] value() default {}; /**
* Array of base packages.
* <p>Controllers that belong to those base packages or sub-packages thereof
* will be included, e.g.: {@code @ControllerAdvice(basePackages="org.my.pkg")}
* or {@code @ControllerAdvice(basePackages={"org.my.pkg", "org.my.other.pkg"})}.
* <p>{@link #value} is an alias for this attribute, simply allowing for
* more concise use of the annotation.
* <p>Also consider using {@link #basePackageClasses()} as a type-safe
* alternative to String-based package names.
* @since 4.0
*/
@AliasFor("value")
String[] basePackages() default {}; /**
* Type-safe alternative to {@link #value()} for specifying the packages
* to select Controllers to be assisted by the {@code @ControllerAdvice}
* annotated class.
* <p>Consider creating a special no-op marker class or interface in each package
* that serves no purpose other than being referenced by this attribute.
* @since 4.0
*/
Class<?>[] basePackageClasses() default {}; /**
* Array of classes.
* <p>Controllers that are assignable to at least one of the given types
* will be assisted by the {@code @ControllerAdvice} annotated class.
* @since 4.0
*/
Class<?>[] assignableTypes() default {}; /**
* Array of annotations.
* <p>Controllers that are annotated with this/one of those annotation(s)
* will be assisted by the {@code @ControllerAdvice} annotated class.
* <p>Consider creating a special annotation or use a predefined one,
* like {@link RestController @RestController}.
* @since 4.0
*/
Class<? extends Annotation>[] annotations() default {}; }

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

通过类型的描述,可以得知几点:

  1. @ControllerAdvice是一个@Component,用于定义@ExceptionHandler,@InitBinder和@ModelAttribute方法,适用于所有使用@RequestMapping方法。
  2. Spring4之前,@ControllerAdvice在同一调度的Servlet中协助所有控制器。Spring4已经改变:@ControllerAdvice支持配置控制器的子集,而默认的行为仍然可以利用。
  3. 在Spring4中, @ControllerAdvice通过annotations(), basePackageClasses(), basePackages()方法定制用于选择控制器子集

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

如果单使用@ExceptionHandler,只能在当前Controller中处理异常。但当配合@ControllerAdvice一起使用的时候,就可以摆脱那个限制了。

实现方式

一、统一异常处理中心(Handler)

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; import com.alibaba.fastjson.JSONObject; /**
* 统一异常处理
* @ClassName: GlobalExceptionHandler
* @Description: TODO
* @author OnlyMate
* @Date 2018年8月29日 下午2:19:42
*
*/
@ControllerAdvice
public class GlobalExceptionHandler {
private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); /**
* 处理所有不可知的异常
* @Title: handleException
* @Description: TODO
* @Date 2018年8月29日 下午2:21:10
* @author OnlyMate
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
@ResponseBody
public JSONObject handleException(HttpServletRequest req, Exception e){
JSONObject jsonObject = new JSONObject();
Throwable throwable = e.getCause();
        logger.error(throwable.getMessage(), e);
        if (throwable instanceof DuplicateSubmitException) {
         jsonObject.put("resultCode", ((DuplicateSubmitException) throwable).getCode());
jsonObject.put("resultMsg", ((DuplicateSubmitException) throwable).getMsg());
        } else {
            jsonObject.put("resultCode", "9999");
jsonObject.put("resultMsg", "系统异常");
        }
return jsonObject;
} /**
* 处理自定义异常(这里处理的异常是继承RunTimeException的自定义的异常)
* @Title: handleBusinessException
* @Description: TODO
* @Date 2018年8月29日 下午2:24:55
* @author OnlyMate
* @param e
* @return
*/
@ResponseBody
@ExceptionHandler(CustomBizRuntimeException.class)
public JSONObject handleBusinessException(CustomBizRuntimeException e){
logger.error("handleBusinessException ==> "+ e.getErrorMessage(), e);
JSONObject jsonObject = new JSONObject();
jsonObject.put("resultCode", "9999");
jsonObject.put("resultMsg", "CustomBizRuntimeException 自定义业务异常类 ==> 系统异常");
return jsonObject;
} /**
* 处理自定义异常(这里处理的异常是继承Exception的自定义的异常)
* @Title: handleCommonException
* @Description: TODO
* @Date 2018年8月29日 下午2:24:55
* @author OnlyMate
* @param e
* @return
*/
@ResponseBody
@ExceptionHandler(CustomCommonException.class)
public JSONObject handleCommonException(CustomCommonException e){
logger.error("handleCommonException ==> "+ e.getErrorMessage(), e);
JSONObject jsonObject = new JSONObject();
jsonObject.put("resultCode", "9999");
jsonObject.put("resultMsg", "CustomCommonException 自定义普通异常类 ==> 系统异常");
return jsonObject;
}
}

二、自定义异常

CustomBizRuntimeException,继承RuntimeException,可用于涉及事务操作时抛该异常回滚事务

/**
* 自定义业务异常类
* @ClassName: CustomBizRuntimeException
* @Description: TODO
* @author OnlyMate
* @Date 2018年9月1日 下午4:17:49
*
*/
public class CustomBizRuntimeException extends RuntimeException {
private static final long serialVersionUID = -8021190492897458166L;
private String errorMessage = "CustomBizRuntimeException 自定义业务异常类 "; public String getErrorMessage() {
return this.errorMessage;
}
}

CustomCommonException,普通自定义异常

/**
* 自定义普通异常类
* @ClassName: CustomCommonException
* @Description: TODO
* @author OnlyMate
* @Date 2018年9月1日 下午4:17:49
*
*/
public class CustomCommonException extends Exception {
private static final long serialVersionUID = -8021190492897458166L;
private String errorMessage = "CustomCommonException 自定义普通异常类"; public String getErrorMessage() {
return this.errorMessage;
}
}

三、编写抛出对应异常的Controller

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; import com.onlymate.springboot.exception.CustomBizRuntimeException;
import com.onlymate.springboot.exception.CustomCommonException; @Controller
@RequestMapping(value="/exception")
public class ExceptionController {
private Logger logger = LoggerFactory.getLogger(HelloWorldController.class); /**
* 抛出CustomCommonException异常,然后处理该异常
* @Title: index1
* @Description: TODO
* @Date 2018年9月1日 下午4:42:58
* @author OnlyMate
* @return
* @throws CustomCommonException
*/
@ResponseBody
@RequestMapping("/index1")
public String index1() throws CustomCommonException {
try {
String str = null;
logger.info(str.toString());
} catch (Exception e) {
throw new CustomCommonException();
}
return "Success";
} /**
* 抛出CustomBizRuntimeException异常,然后处理该异常
* @Title: index2
* @Description: TODO
* @Date 2018年9月1日 下午4:43:25
* @author OnlyMate
* @return
*/
@ResponseBody
@RequestMapping("/index2")
public String index2() {
try {
String str = null;
logger.info(str.toString());
} catch (Exception e) {
throw new CustomBizRuntimeException();
}
return "Success";
} /**
* 抛出Exception异常,然后处理该异常
* @Title: index3
* @Description: TODO
* @Date 2018年9月1日 下午4:43:49
* @author OnlyMate
* @return
*/
@ResponseBody
@RequestMapping("/index3")
public String index3() {
String str = null;
logger.info(str.toString());
return "Success";
}
}

效果图

一、抛出CustomCommonException异常效果图

页面访问:http://localhost:8088/springboot/exception/index1

二、抛出CustomBizRuntimeException异常效果图

页面访问:http://localhost:8088/springboot/exception/index2

三、抛出Exception异常效果图

页面访问:http://localhost:8088/springboot/exception/index3

Spring Boot实践——统一异常处理的更多相关文章

  1. 基于Spring Boot的统一异常处理设计

    基于Spring Boot的统一异常处理设计 作者: Grey 原文地址:https://www.cnblogs.com/greyzeng/p/11733327.html Spring Boot中,支 ...

  2. spring boot配置统一异常处理

    基于@ControllerAdvice的统一异常处理 >.这里ServerException是我自定义的异常,和普通Exception分开处理 >.这里的RequestResult是我自定 ...

  3. spring boot 中统一异常处理

    基于 spring boot 对异常处理的不友好,现在通过其他的方式来统一处理异常 步骤一:自定义异常类 public class UserNotExistException extends Runt ...

  4. 基于spring boot的统一异常处理

    一.springboot的默认异常处理 Spring Boot提供了一个默认的映射:/error,当处理中抛出异常之后,会转到该请求中处理,并且该请求有一个全局的错误页面用来展示异常内容. 例如这里我 ...

  5. Spring Boot学习——统一异常处理

    本随笔记录使用Spring Boot统一处理异常. 本文实例是从数据库中根据ID查询学生信息,要求学生的年龄在14——20岁之间.小于14岁,提示“你可能在上初中”:大于20岁,提示“呢可能在上大学” ...

  6. 【Spring Boot】Spring Boot之统一异常处理

    一.统一异常处理的作用 在web应用中,请求处理时,出现异常是非常常见的.所以当应用出现各类异常时,进行异常的统一捕获或者二次处理(比如空指针异常或sql异常正常是不能外抛)是非常必要的,然后右统一异 ...

  7. spring boot 2 统一异常处理

    spring mvc 针对controller层异常统一处理非常简单,使用 @RestControllerAdvice 或 @RestControllerAdvice 注解就可以轻@RestContr ...

  8. Spring Boot实践——AOP实现

    借鉴:http://www.cnblogs.com/xrq730/p/4919025.html     https://blog.csdn.net/zhaokejin521/article/detai ...

  9. Spring Boot API 统一返回格式封装

    今天给大家带来的是Spring Boot API 统一返回格式封装,我们在做项目的时候API 接口返回是需要统一格式的,只有这样前端的同学才可对接口返回的数据做统一处理,也可以使前后端分离 模式的开发 ...

随机推荐

  1. axis2 webservice jar包使用情况(转)

    原文地址:axis2 webservice jar包使用情况 今天使用axis2webservice,整理了下jar包,方便以后时候. axis2 webservice 服务端jar包: --> ...

  2. 124. Binary Tree Maximum Path Sum *HARD* -- 二叉树中节点和最大的路径的节点和

    Given a binary tree, find the maximum path sum. For this problem, a path is defined as any sequence ...

  3. 前端构建工具 Grunt 入门

    之前也介绍过前端构建工具 Ant 和 Yeoman,其中 Yeoman 工具就包含了 Grunt 所以就不多说.那么与 Ant 相比 Grunt 有这么几个优点: Javascript 语法,相比 A ...

  4. HALCON之喷码OCR识别案例

    一个喷码识别的案例 1 read_image (Image, 'D:/用户目录/Desktop/2.png') 2 3 rgb1_to_gray(Image, Image) 4 5 get_image ...

  5. Android 4.3发布 新增4大改变25日推送升级[附Android 4.3 工厂镜像]

    北京时间7月25日,谷歌举行发布会,正式发布了全新的Nexus 7平板电脑以及Android 4.3系统. 其中Android 4.3系统隶属于4.X果冻豆(Jelly Bean)系列,是目前最新的操 ...

  6. IE、Chrome、Firefox 三大浏览器对比

    1. 代理 IE 浏览器设置代理位置在: [Internet 选项]⇒ [连接]选项卡 ⇒ [局域网设置],如下: Chrome 的代理配置界面完全同 IE,只是你设置路径在: [设置]⇒ [高级]⇒ ...

  7. redis安装全过程

    1. 从官网上下载redis. 2.安装gcc 3.进入./redis/src目录下make MALLOC =libc 4.遇到的问题 Redis简介: Redis是一个开源的使用ANSI C语言编写 ...

  8. Python itertools.combinations 和 itertools.permutations 等价代码实现

    最近编程时经常要用到排序组合的代码,想当年还抱着一些情况买了一本<组合数学>,不过现在这货也不知道被自己放哪里了,估计不会是垫桌子腿了吧. 由于去年去东北大学考博面试的时候遇到过可能涉及排 ...

  9. I.MX6 Android mmm convenient to use

    # # 主要是记录mmm的简便自动化执行方式,为了减少键盘输入 # ]; then echo echo " Usage: ./remmm.sh <source dirctory> ...

  10. js字符串的裁剪

    一.JavaScript字符串的处理方法 1.split()  功能:使用一个指定的分隔符把一个字符串分割存储到数组 例子:   str=”jpg|bmp|gif|ico|png”; arr=str. ...