springboot的@RestControllerAdvice作用和捕获自定义异常返回自定义结果案例
创始人
2025-05-29 08:40:08

一、@RestControllerAdvice是什么?

@RestContrllerAdvice是一种组合注解,由@ControllerAdvice,@ResponseBody组成

@ControllerAdvice继承了@Component,反过来,可以理解为@RestContrllerAdvice本质上就是@Component

1.1 @Component是什么?

本质上是一个类,泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller,@Service等的时候),我们就可以使用@Component

作用就是实现bean注入,利用这个注解可以取代spring的xml配置文件

1.2 @Component案例

1.2.1 准备的jar

         com.alibabafastjson1.2.75

1.2.2 controller

@RestController
public class TestController {@Autowiredprivate TestService testService;@GetMapping("/test3")public String test3() {return testService.test();}
}

1.2.3 接口

public interface TestService {String test();
}

1.2.4组件

@Component
public class TestServiceImpl implements TestService {@Autowiredprivate ObjectMapper objectMapper;@Overridepublic String test() {String b = null;try {b =  objectMapper.writeValueAsString("a");System.out.println(b);} catch (Exception e) {}return b;}
}

二、@RestControllerAdvice有什么作用?

  1. 自定义客户端返回格式

  1. 捕获客户端返回异常

三、@RestControllerAdvice案例和使用场景

捕获客户端返回异常案例(自定义返回异常)

3.1 未自定义捕获异常之前

3.2 自定义捕获异常以后

3.3代码实现自定义捕获异常

3.3.1 自定义异常枚举

public interface BaseCodeMsg {String getCode();String getMsg();
}
public enum PlatformExceptionMsgEnum implements BaseCodeMsg {/*** base平台返回的异常信息*/SELECT_NULL("000000001", "查询数据为空"),INVOKE_IS_REJECT("00000002", "请求被拒绝"),ILLEGAL_ARGUMENT_FORMAT("000000003", "非法参数格式"),ILLEGAL_ARGUMENT("000000004","数据非法"),SYSTEM_EXCEPTION("000000005", "系统异常");/*** 错误码*/private final String code;/*** 错误信息*/private final String msg;PlatformExceptionMsgEnum(String code, String msg) {this.code = code;this.msg = msg;}@Overridepublic String getCode() {return code;}@Overridepublic String getMsg() {return msg;}}

3.3.2 自定义平台异常

public abstract class AbstractApiException extends RuntimeException{public AbstractApiException() {}public abstract String getCode();public abstract String getMsg();
}
public class PlatformException extends AbstractApiException {private String code;private String msg;public PlatformException(BaseCodeMsg baseCodeMsg) {code = baseCodeMsg.getCode();msg = baseCodeMsg.getMsg();}public static void throwException(BaseCodeMsg baseCodeMsg) {throw new PlatformException(baseCodeMsg.getCode(), baseCodeMsg.getMsg());}public static void throwException(BaseCodeMsg baseCodeMsg, String msg) {throw new PlatformException(baseCodeMsg.getCode(), StringUtils.isEmpty(baseCodeMsg.getMsg()) ? msg : baseCodeMsg.getMsg());}public static void throwException(String code, String msg) {throw new PlatformException(code, msg);}public static void throwException(String msg) {throw new PlatformException(PlatformExceptionMsgEnum.SYSTEM_EXCEPTION.getCode(), msg);}public PlatformException(String code, String msg) {this.code = code;this.msg = msg;}@Overridepublic String getCode() {return code;}@Overridepublic String getMsg() {return msg;}
}

3.3.3 自定义返回类

@Data
public class BaseResult implements Serializable {private static final long serialVersionUID = 1L;private String code;private String msg;private String traceId;private T data;public boolean isSuccess() {return PlatformExceptionMsgEnum.SUCCESS.getCode().equals(this.code);}public static BaseResult ok() {return restBaseResult((Object)null, PlatformExceptionMsgEnum.SUCCESS);}public static  BaseResult ok(T data) {return restBaseResult(data, PlatformExceptionMsgEnum.SUCCESS);}public static BaseResult fail() {return restBaseResult((Object)null, PlatformExceptionMsgEnum.SYSTEM_ERROR);}public static BaseResult fail(BaseCodeMsg baseCodeMsg) {return restBaseResult((Object)null, baseCodeMsg);}public static BaseResult fail(String code, String msg) {return restBaseResult((Object)null, code, msg);}private static  BaseResult restBaseResult(T data, BaseCodeMsg baseCodeMsg) {return restBaseResult(data, baseCodeMsg.getCode(), baseCodeMsg.getMsg());}private static  BaseResult restBaseResult(T data, String code, String msg) {BaseResult apiBaseResult = new BaseResult();apiBaseResult.setCode(code);apiBaseResult.setData(data);apiBaseResult.setMsg(msg);apiBaseResult.setTraceId(MDC.get("traceId"));return apiBaseResult;}public BaseResult() {}
}

3.3.4 controller层

@RestController
public class TestController {@GetMapping("/test")public void test() {PlatformException.throwException(PlatformExceptionMsgEnum.SYSTEM_EXCEPTION);}}

3.3.5 @RestControllerAdvice

@RestControllerAdvice
@Configuration
public class GlobalExceptionHandler {private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);private MessageSource messageSource;/*** 捕获全局异常类** @param e* @return*/@ExceptionHandler({MethodArgumentNotValidException.class})public BaseResult handle(MethodArgumentNotValidException e) {if (e.getBindingResult().hasErrors()) {String msg = ((ObjectError) e.getBindingResult().getAllErrors().get(0)).getDefaultMessage();return BaseResult.fail(PlatformExceptionMsgEnum.ILLEGAL_ARGUMENT.getCode(), this.getI18nMsg(msg));} else {log.info(e.getMessage(), e);return BaseResult.fail(PlatformExceptionMsgEnum.ILLEGAL_ARGUMENT.getCode(), this.getI18nMsg(PlatformExceptionMsgEnum.ILLEGAL_ARGUMENT.getMsg()));}}/*** 捕获API调用接口的异常类** @param e* @return*/@ExceptionHandler(AbstractApiException.class)public BaseResult abstractApiException(AbstractApiException e) {return BaseResult.fail(e.getCode(), e.getMsg());}/*** 前端传入的参数和后端传入的参数接收不匹配** @param e* @return*/@ExceptionHandler({HttpMessageNotReadableException.class})public BaseResult handle(HttpMessageNotReadableException e) {log.warn(e.getMessage(), e);return BaseResult.fail(PlatformExceptionMsgEnum.ILLEGAL_ARGUMENT_FORMAT.getCode(), this.getI18nMsg(PlatformExceptionMsgEnum.ILLEGAL_ARGUMENT_FORMAT.getMsg()));}/*** 子类异常(相当于子类不能抛出比父类更广泛异常)** @param e* @return*/@ExceptionHandler({UndeclaredThrowableException.class})public BaseResult handle(UndeclaredThrowableException e) {log.warn(e.getMessage(), e);return BaseResult.fail(PlatformExceptionMsgEnum.INVOKE_IS_REJECT.getCode(), this.getI18nMsg(PlatformExceptionMsgEnum.INVOKE_IS_REJECT.getMsg()));}/*** 异常捕获** @param e 捕获的异常,封装返回的对象* @return*/@ExceptionHandler(Exception.class)public BaseResult handleException(Exception e) {log.warn(e.getMessage(), e);StringJoiner joiner = new StringJoiner(":");joiner.add(this.getI18nMsg(PlatformExceptionMsgEnum.INVOKE_IS_REJECT.getMsg())).add(e.getMessage());return BaseResult.fail(PlatformExceptionMsgEnum.SYSTEM_EXCEPTION.getCode(), joiner.toString());}private String getI18nMsg(String msg) {try {return this.messageSource.getMessage(msg, (Object[]) null, LocaleContextHolder.getLocale());} catch (NoSuchMessageException var3) {return msg;}}public GlobalExceptionHandler(MessageSource messageSource) {this.messageSource = messageSource;}
}

3.4 代码实现自定义返回结果

没有自定义返回结果之前

自定义返回结果以后

3.4.1 controller

@RestController
public class TestController {@GetMapping("/test2")public String test2() {return "test2";}}

3.4.2 返回结果来

BaseResult返回结果类在上面,对应需要导入json的jar也在上面

3.4.3 @RestControllerAdvice

@RestControllerAdvice(annotations = {RestController.class}
)
@Configuration
public class BaseResultResponseAdvice implements ResponseBodyAdvice {@Autowiredprivate ObjectMapper objectMapper;/*** @param methodParameter 利用这个参数判断注解信息* @param aClass* @return*/@Overridepublic boolean supports(MethodParameter methodParameter, Class> aClass) {return true;}/*** @param body               原controller需要返回的内容* @param methodParameter    利用这个参数判断注解信息* @param mediaType* @param aClass* @param serverHttpRequest* @param serverHttpResponse* @return*/@Overridepublic Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {try {if (methodParameter.getParameterType() == ResponseEntity.class) {return body;} else if (methodParameter.getParameterType() == BaseResult.class) {return body;} else if (methodParameter.getParameterType() == String.class) {serverHttpResponse.getHeaders().setContentType(MediaType.APPLICATION_JSON);return this.objectMapper.writeValueAsString(BaseResult.ok(body));} else {return BaseResult.ok(body);}} catch (Throwable t) {return BaseResult.fail();}}
}

四、拓展

@RestControllerAdvice的使用还可以指定对应的注解、包,类。比如你需要返回自定义结果格式,可以指定@RestController层使用,如果你要指定类和包也可以

4.1 指定注解

@RestControllerAdvice(annotations = {RestController.class}
)

4.2 指定类

@RestControllerAdvice(basePackageClasses = TestController.class
)

4.3 指定包

@RestControllerAdvice(basePackages = "com.common.base.controller"
)

相关内容

热门资讯

湖北高考作文【通用3篇】 湖北高考作文 篇一:挑战中成长高考是每个湖北考生都无法绕过的一座大山,它既是对我们学习成果的检验,也...
高中生文学常识(优质3篇) 高中生文学常识 篇一文学是一门精深的学科,它涵盖了各种文学体裁和文学作品,对于高中生来说,了解一些文...
2022年湖南卷高考作文(通... 2022年湖南卷高考作文 篇一:科技与人类的未来科技的快速发展已经深刻地改变了我们的生活方式和社会结...
拒绝平庸850字作文【推荐3... 拒绝平庸850字作文 篇一拒绝平庸时光荏苒,岁月如梭。在这个飞速发展的时代,人们追求着更好的生活,追...
四川卷高考作文解析及(优质3... 四川卷高考作文解析及 篇一四川卷高考作文解析及应对策略四川卷高考作文一直以其独特的题材和考查角度而备...