文档章节

精通Spring Boot —— 第十五篇:自定义异常处理

liululee
 liululee
发布于 2018/10/25 09:46
字数 973
阅读 339
收藏 8

在Spring 3.2中,新增了@ControllerAdvice、@RestControllerAdvice 注解,可以用于定义@ExceptionHandler、@InitBinder、@ModelAttribute,并应用到所有@RequestMapping、@PostMapping, @GetMapping注解中。 接下来我将通过代码展示如何使用这些注解,以及处理异常。

1.注解的介绍

先定义一个ControllerAdvice。代码如下

/**
 * @author Lensen
 * @desc
 * @since 2018/10/5 11:01
 */
@ControllerAdvice
public class MyExceptionHandler {

    /**
     * 应用到所有@RequestMapping注解方法,在其执行之前初始化数据绑定器
     * @param binder
     */
    @InitBinder
    public void initWebBinder(WebDataBinder binder){
        //对日期的统一处理
        binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
        //添加对数据的校验
        //binder.setValidator();
    }

    /**
     * 把值绑定到Model中,使全局@RequestMapping可以获取到该值
     * @param model
     */
    @ModelAttribute
    public void addAttribute(Model model) {
        model.addAttribute("attribute",  "The Attribute");
    }

    /**
     * 捕获CustomException
     * @param e
     * @return json格式类型
     */
    @ResponseBody
    @ExceptionHandler({CustomException.class}) //指定拦截异常的类型
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) //自定义浏览器返回状态码
    public Map<String, Object> customExceptionHandler(CustomException e) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", e.getCode());
        map.put("msg", e.getMsg());
        return map;
    }

    /**
     * 捕获CustomException
     * @param e
     * @return 视图
     */
//    @ExceptionHandler({CustomException.class})
//    public ModelAndView customModelAndViewExceptionHandler(CustomException e) {
//        Map<String, Object> map = new HashMap<>();
//        map.put("code", e.getCode());
//        map.put("msg", e.getMsg());
//        ModelAndView modelAndView = new ModelAndView();
//        modelAndView.setViewName("error");
//        modelAndView.addObject(map);
//        return modelAndView;
//    }
}

需要注意的是使用@ExceptionHandler注解传入的参数可以一个数组,且使用该注解时,传入的参数不能相同,也就是不能使用两个@ExceptionHandler去处理同一个异常。如果传入参数相同,则初始化ExceptionHandler时会失败。 对于@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 {};
}

我们可以传递basePackage,声明的类(是一个数组)指定的Annotation参数,具体参考:spring framework doc

2.异常的处理

###编写自定义异常类

package com.developlee.errorhandle.exception;

/**
 * @author Lensen
 * @desc 自定义异常类
 * @since 2018/10/5 11:04
 */
public class CustomException extends RuntimeException {

    private long code;
    private String msg;

    public CustomException(Long code, String msg){
        this.code = code;
        this.msg = msg;
    }

    public long getCode() {
        return code;
    }

    public void setCode(long code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }
}

Spring 对于 RuntimeException类的异常才会进行事务回滚,所以我们一般自定义异常都继承该异常类。

编写全局异常处理类

/**
 * @author Lensen
 * @desc
 * @since 2018/10/5 11:01
 */
@ControllerAdvice("com.developlee.errorhandle")
public class MyExceptionHandler {

    /**
     * 应用到所有@RequestMapping注解方法,在其执行之前初始化数据绑定器
     * @param binder
     */
    @InitBinder
    public void initWebBinder(WebDataBinder binder){

    }

    /**
     * 把值绑定到Model中,使全局@RequestMapping可以获取到该值
     * @param model
     */
    @ModelAttribute
    public void addAttribute(Model model) {
        model.addAttribute("attribute",  "The Attribute");
    }

    /**
     * 捕获CustomException
     * @param e
     * @return json格式类型
     */
    @ResponseBody
    @ExceptionHandler({CustomException.class}) //指定拦截异常的类型
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) //自定义浏览器返回状态码
    public Map<String, Object> customExceptionHandler(CustomException e) {
        Map<String, Object> map = new HashMap<>();
        map.put("code", e.getCode());
        map.put("msg", e.getMsg());
        return map;
    }

    /**
     * 捕获CustomException
     * @param e
     * @return 视图
     */
//    @ExceptionHandler({CustomException.class})
//    public ModelAndView customModelAndViewExceptionHandler(CustomException e) {
//        Map<String, Object> map = new HashMap<>();
//        map.put("code", e.getCode());
//        map.put("msg", e.getMsg());
//        ModelAndView modelAndView = new ModelAndView();
//        modelAndView.setViewName("error");
//        modelAndView.addObject(map);
//        return modelAndView;
//    }
}

测试

在controller中抛出自定义异常

/**
 * @author Lensen
 * @desc
 * @since 2018/10/5 11:00
 */
@Controller
public class DemoController {
  
    /**
   * 关于@ModelAttribute,
   * 可以使用ModelMap以及@ModelAttribute()来获取参数值。
   */    
    @GetMapping("/one")
    public String testError(ModelMap modelMap ) {
        throw new CustomException(500L, "系统发生500异常!" + modelMap.get("attribute"));
    }

    @GetMapping("/two")
    public String testTwo(@ModelAttribute("attribute") String attribute) {
        throw new CustomException(500L, "系统发生500异常!" + attribute);
    }
}

启动应用,范围localhost:8080/one.返回报文为:

{"msg":"系统发生500异常!The Attribute","code":500}

可见我们的@InitBinder和@ModelAttribute注解生效。且自定义异常被成功拦截。如果全部异常处理都返回json,那么可以使用 @RestControllerAdvice 代替 @ControllerAdvice ,这样在方法上就可以不需要添加 @ResponseBody。@RestControllerAdvice在注解上已经添加了@ResponseBody。

最后,以上示例代码可在我的github.com中找到。 我的个人公众号:developlee的潇洒人生。 关注了也不一定更新,更新就不得了了。 qrcode_for_gh_2bd3f44efa21_258

© 著作权归作者所有

liululee
粉丝 127
博文 66
码字总数 90743
作品 0
杭州
程序员
私信 提问
springboot微服务系列教程

微服务系列教程 Spring Boot 2是微服务的基础,在2018年3月初,Spring Boot 正式宣布进入2.0时代。下面一起来步入Spring Boot 2时代,领略Spring Boot 2带来的开发乐趣吧! 本系统源代码地址...

鱼煎
01/13
316
0
Spring Boot /error 接口异常处理简介

为什么会有这篇博客 故事的开始是这个样子的。在一个慵懒的午后,闲的蛋疼的一天里我在测试着接口,然后我就看到了如下画面 ,它们是这样的还有这样的: 很显然这是当应用发生错误时候的提示...

OSC首席骠妓大将军
08/28
27
0
Spring Boot 2 Webflux的全局异常处理

本文首先将会回顾Spring 5之前的SpringMVC异常处理机制,然后主要讲解Spring Boot 2 Webflux的全局异常处理机制。 SpringMVC的异常处理 Spring 统一异常处理有 3 种方式,分别为: 使用 注解...

aoho
2018/12/20
0
0
苞米豆 — 谷歌验证码快速启动器 1.1.0 发布

https://gitee.com/baomidou/kaptcha-spring-boot-starter 修复了一个重复校验引起的Np bug 支持了jdk 1.7 简介 kaptcha-spring-boot-starter 基于 springBoot 和 Google Kaptcha 验证码组件......

小锅盖
2018/07/20
2.5K
10
扼住高并发、高性能的咽喉---Spring Boot并发进阶

原文链接:https://www.e4developer.com/2018/03/30/introduction-to-concurrency-in-spring-boot/ 作者: Bartosz Jedrzejewski 译者: helloworldtang 概览 在使用Spring Boot构建服务时,......

生活点亮技术
2018/09/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

反编译9.png图片还原

本文链接:https://blog.csdn.net/a1140778530/article/details/10528507 经常反编译apk文件找资源,9.png的文件处理起来很麻烦。 最近使用Ant自动编译打包app时,从别处搜罗来的9.png文件导...

shzwork
6分钟前
1
0
Shell脚本应用 – for、while循环语句

一、for循环语句 在实际工作中,经常会遇到某项任务需要多次执行的情况,而每次执行时仅仅是处理的对象不一样,其他命令相同。例如:根据通讯录中的姓名列表创建系统账号等情况。 当面对各种...

linux-tao
6分钟前
2
0
RPA风潮下企业财务工作模式的变革

RPA(机器人流程自动化)在财务领域的应用,正给企业财务带来前所未有的改变。 前RPA时代,财务领域面临的痛点 在RPA机器人应用之前,企业财务工作进程的推进,主要通过财务人员人工操作或信...

UiBot
11分钟前
2
0
Hive之命令行修改表注释

最近遇到一个需求,在不重建表的情况下,修改表的注释,hive有没有类似关系型数据库的SQL命令来修改呢,找了下,亲测有效,如下List-1 List-1 hive>use your_schemahvie>ALTER TABLE tabl...

克虏伯
12分钟前
2
0
是什么,它的作用是什么

在HTML文档的首部往往会有这么一句话<!DOCTYPE html>,许多时候我们忽视了它的存在,它实际上是一个声明,告诉浏览器用哪种HTML版本的规范来解读HTML文档。 尽管我们不给出这句声明浏览器照样...

前端老手
17分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部