前言

前段时间部门搭建新系统,需要出异常后统一接口的返回格式,于是用到了Spring的注解@RestControllerAdvice。现在把此注解的用法总结一下。

用法

首先定义返回对象ResponseDto

  1. package com.staff.points.common;
  2.  
  3. import lombok.Data;
  4.  
  5. import java.io.Serializable;
  6.  
  7. @Data
  8. public class ResponseDto<T> implements Serializable {
  9. private static final long serialVersionUID = -284719732991678911L;
  10.  
  11. private String code;
  12.  
  13. private String message;
  14.  
  15. private T data;
  16.  
  17. public static <T> ResponseDto<T> assemblingSuccessResponse(T data) {
  18. ResponseDto<T> responseDto = new ResponseDto<>();
  19. responseDto.setCode(ResponseCodeEnum.SUCCESS.getCode());
  20. responseDto.setMessage(ResponseCodeEnum.SUCCESS.getMessage());
  21. responseDto.setData(data);
  22. return responseDto;
  23. }
  24.  
  25. public static <T> ResponseDto<T> assemblingSuccessResponse() {
  26. ResponseDto<T> responseDto = new ResponseDto<>();
  27. responseDto.setCode(ResponseCodeEnum.SUCCESS.getCode());
  28. responseDto.setMessage(ResponseCodeEnum.SUCCESS.getMessage());
  29. responseDto.setData(null);
  30. return responseDto;
  31. }
  32.  
  33. public static <T> ResponseDto<T> assemblingFailureResponse(ResponseCodeEnum data) {
  34. ResponseDto<T> responseDto = new ResponseDto<>();
  35. responseDto.setCode(data.FAILURE.getCode());
  36. responseDto.setMessage(data.FAILURE.getMessage());
  37. return responseDto;
  38. }
  39.  
  40. public static <T> ResponseDto<T> assemblingFailureResponse() {
  41. ResponseDto<T> responseDto = new ResponseDto<>();
  42. responseDto.setCode(ResponseCodeEnum.FAILURE.getCode());
  43. responseDto.setMessage(ResponseCodeEnum.FAILURE.getMessage());
  44. return responseDto;
  45. }
  46. }

然后定义返回码的枚举类,此处只定义了两种,有需要可以往下添加很多。

  1. package com.staff.points.common;
  2.  
  3. import lombok.AllArgsConstructor;
  4. import lombok.Getter;
  5.  
  6. @AllArgsConstructor
  7. @Getter
  8. public enum ResponseCodeEnum {
  9. SUCCESS("00", "成功"),
  10. FAILURE("01", "系统异常");
  11.  
  12. private String code;
  13. private String message;
  14. }

下面是自定义的异常类

  1. package com.staff.points.common;
  2.  
  3. import lombok.Data;
  4.  
  5. @Data
  6. public class StaffPointsException extends RuntimeException{
  7. private String code;
  8. private String message;
  9. public StaffPointsException () {}
  10.  
  11. public StaffPointsException (Exception e) {
  12. super(e);
  13. }
  14.  
  15. public StaffPointsException (String code, String message) {
  16. super(message);
  17. this.code = code;
  18. this.message = message;
  19. }
  20.  
  21. public StaffPointsException (ResponseCodeEnum codeEnum) {
  22. super(codeEnum.getMessage());
  23. this.code = codeEnum.getCode();
  24. this.message = codeEnum.getMessage();
  25. }
  26. }

然后是关键的@RestControllerAdvice修饰的类

  1. package com.staff.points.exception;
  2.  
  3. import com.staff.points.common.ResponseCodeEnum;
  4. import com.staff.points.common.ResponseDto;
  5. import com.staff.points.common.StaffPointsException;
  6. import org.slf4j.Logger;
  7. import org.slf4j.LoggerFactory;
  8. import org.springframework.stereotype.Component;
  9. import org.springframework.web.bind.annotation.ExceptionHandler;
  10. import org.springframework.web.bind.annotation.RestControllerAdvice;
  11.  
  12. @RestControllerAdvice
  13. @Component
  14. public class UnifyExceptionHandler {
  15. private Logger logger = LoggerFactory.getLogger(UnifyExceptionHandler.class);
  16.  
  17. @ExceptionHandler(Exception.class)
  18. public ResponseDto handlerCommonException (Exception e) {
  19. ResponseDto responseDto = new ResponseDto<>();
  20. responseDto.setCode(ResponseCodeEnum.FAILURE.getCode());
  21. responseDto.setMessage(ResponseCodeEnum.FAILURE.getMessage());
  22. logger.info("UnifyExceptionHandler.handlerCommonException exception:" + e);
  23. return responseDto;
  24. }
  25. // 报StaffPointException时,对其进行拦截并处理的方法
  26. @ExceptionHandler(StaffPointsException.class)
  27. public ResponseDto handlerCustomizeException (StaffPointsException e) {
  28. ResponseDto responseDto = new ResponseDto<>();
  29. responseDto.setCode(e.getCode());
  30. responseDto.setMessage(e.getMessage());
  31. logger.info("UnifyExceptionHandler.handlerCustomizeException StaffPointsException:" + e);
  32. return responseDto;
  33. }
  34. }

运行代码时,如果出现了StaffPointException,那么就会被拦截进入第27行的方法(就是说可以自由的在业务代码里往外throw自定义异常了);如果出现了其他的异常,则进入18行的方法,统一返回。

验证一下,在代码里造一个NPE异常时,返回结果:

  1. {
  2. "code": "01",
  3. "message": "系统异常",
  4. "data": null
  5. }

造一个StaffPointsException异常时,返回结果:

  1. {
  2. "code": "99",
  3. "message": "自定义业务异常",
  4. "data": null
  5. }

它的作用原理,大体是先在spring初始化时将类扫描进容器,出异常后,在DispatcherServlet类的doDispatch方法中调用了对异常的拦截处理。

小结

看@RestControllerAdvice源码可以知道,它就是@ControllerAdvice和@ResponseBody的合并。此注解通过对异常的拦截实现的统一异常返回处理,如果大家在项目中有类似的需求,不妨试一下,好用又方便。

Spring注解之@RestControllerAdvice的更多相关文章

  1. spring注解式参数校验

    很痛苦遇到大量的参数进行校验,在业务中还要抛出异常或者返回异常时的校验信息,在代码中相当冗长,今天我们就来学习spring注解式参数校验. 其实就是:hibernate的validator. 开始啦. ...

  2. spring注解预览

    从Java5.0开始,Java开始支持注解.Spring做为Java生态中的领军框架,从2.5版本后也开始支持注解.相比起之前使用xml来配置Spring框架,使用注解提供了更多的控制Spring框架 ...

  3. Spring注解概览(数漫江湖)

    从Java5.0开始,Java开始支持注解.Spring做为Java生态中的领军框架,从2.5版本后也开始支持注解.相比起之前使用xml来配置Spring框架,使用注解提供了更多的控制Spring框架 ...

  4. Spring 注解概览

    从Java5.0开始,Java开始支持注解.Spring做为Java生态中的领军框架,从2.5版本后也开始支持注解.相比起之前使用xml来配置Spring框架,使用注解提供了更多的控制Spring框架 ...

  5. spring注解源码分析--how does autowired works?

    1. 背景 注解可以减少代码的开发量,spring提供了丰富的注解功能.我们可能会被问到,spring的注解到底是什么触发的呢?今天以spring最常使用的一个注解autowired来跟踪代码,进行d ...

  6. Spring注解

    AccountController .java Java代码   1.        /** 2.         * 2010-1-23 3.         */ 4.        packag ...

  7. spring 注解的优点缺点

    注解与XML配置的区别 注解:是一种分散式的元数据,与源代码耦合. xml :是一种集中式的元数据,与源代码解耦. 因此注解和XML的选择上可以从两个角度来看:分散还是集中,源代码耦合/解耦. 注解的 ...

  8. spring注解说明之Spring2.5 注解介绍(3.0通用)

    spring注解说明之Spring2.5 注解介绍(3.0通用) 注册注解处理器 方式一:bean <bean class="org.springframework.beans.fac ...

  9. 使用Spring注解来简化ssh框架的代码编写

     目的:主要是通过使用Spring注解的方式来简化ssh框架的代码编写. 首先:我们浏览一下原始的applicationContext.xml文件中的部分配置. <bean id="m ...

随机推荐

  1. 像智能手机一样管理云端应用:阿里云联合微软全球首发开放应用模型(OAM)

    2019 年 10 月 17 日上午 9 点 15 分,阿里巴巴合伙人.阿里云智能基础产品事业部总经理蒋江伟在 QCon 上海<基于云架构的研发模式演进>主题演讲中,正式宣布: " ...

  2. cobalt strike笔记-CS与MSF,Armitage,Empire互转shell

    0x01 Metasploit派生shell给Cobaltstrike 生成木马: msfvenom -p windows/meterpreter/reverse_tcp -e x86/shikata ...

  3. MySQL 插入记录时自动更新时间戳

    将字段设置成timestamp类型,同时默认值设置成 CURRENT_TIMESTAMP.

  4. 01--Java语言概述与开发环境 最适合入门的Java教程

    Java 程序运行机制 编译型语言: 使用专门的编译器,针对特定平台(操作系统)将某种高级语言源代码一次性"翻 译"成可被该平台硬件执行的机器码(包括机器指令和操作数),并包装成该 ...

  5. javascript学习 first-day

    1.javascript是一种客户端语言,设计它的目的是在用户的机器上而不是服务器上执行任务. 1.1 javascript不允许写服务器机器上的语言:   1.2 Javascript不能关闭不是由 ...

  6. 在.net core3.0中使用SignalR实现实时通信

    最近用.net core3.0重构网站,老大想做个站内信功能,就是有些耗时的后台任务的结果需要推送给用户.一开始我想简单点,客户端每隔1分钟调用一下我的接口,看看是不是有新消息,有的话就告诉用户有新推 ...

  7. 拒绝黑盒应用-Spring Boot 应用可视化监控

    图文简介 逻辑关系 效果演示 快速开始 1.Spring Boot 应用暴露监控指标[版本 1.5.7.RELEASE] 首先,添加依赖如下依赖: <dependency> <gro ...

  8. kafka里的一些管理脚本

    kafka-server-start脚本 ------启动kafka server kafka-server-stop脚本 ------关闭kafka server kafka-topics脚本 -- ...

  9. Java基础(39)Arrays.binarySearch方法

    1.源码中可以看到,binarySearch方法调用了binarySearch0方法,binarySearch0方法才是标准的二分查找实现. 2.对于binarySearch0方法来说,注意最后的re ...

  10. vue-cli安装方法

    vue-cli:vue文件,css文件,less文件,图片--->htmles6代码--->es5代码 template标签里面,只能有1个跟元素 script标签里面导入组件import ...