springboot的@RestControllerAdvice作用和捕获自定义异常返回自定义结果案例

这篇具有很好参考价值的文章主要介绍了springboot的@RestControllerAdvice作用和捕获自定义异常返回自定义结果案例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、@RestControllerAdvice是什么?

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

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

1.1 @Component是什么?

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

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

1.2 @Component案例

1.2.1 准备的jar

         <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>

1.2.2 controller

@RestController
public class TestController {

    @Autowired
    private 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 {

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public 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 未自定义捕获异常之前

restcontrolleradvice,spring boot,spring,java,Powered by 金山文档

3.2 自定义捕获异常以后

restcontrolleradvice,spring boot,spring,java,Powered by 金山文档

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;
    }

    @Override
    public String getCode() {
        return code;
    }

    @Override
    public 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;
    }

    @Override
    public String getCode() {
        return code;
    }

    @Override
    public String getMsg() {
        return msg;
    }
}

3.3.3 自定义返回类

@Data
public class BaseResult<T> 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 <T> BaseResult<T> 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 <T> BaseResult<T> restBaseResult(T data, BaseCodeMsg baseCodeMsg) {
        return restBaseResult(data, baseCodeMsg.getCode(), baseCodeMsg.getMsg());
    }

    private static <T> BaseResult<T> restBaseResult(T data, String code, String msg) {
        BaseResult<T> 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 代码实现自定义返回结果

没有自定义返回结果之前

restcontrolleradvice,spring boot,spring,java,Powered by 金山文档

自定义返回结果以后

restcontrolleradvice,spring boot,spring,java,Powered by 金山文档

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<Object> {

    @Autowired
    private ObjectMapper objectMapper;

    /**
     * @param methodParameter 利用这个参数判断注解信息
     * @param aClass
     * @return
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    /**
     * @param body               原controller需要返回的内容
     * @param methodParameter    利用这个参数判断注解信息
     * @param mediaType
     * @param aClass
     * @param serverHttpRequest
     * @param serverHttpResponse
     * @return
     */

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> 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层使用,如果你要指定类和包也可以文章来源地址https://www.toymoban.com/news/detail-778237.html

4.1 指定注解

@RestControllerAdvice(
        annotations = {RestController.class}
)

4.2 指定类

@RestControllerAdvice(
        basePackageClasses = TestController.class
)

4.3 指定包

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

到了这里,关于springboot的@RestControllerAdvice作用和捕获自定义异常返回自定义结果案例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringBoot中@ControllerAdvice/@RestControlAdvice+@ExceptionHandler实现全局异常捕获与处理

    在编写Controller接口时,为避免接口因为未知的异常导致返回不友好的结果和提示。 如果不进行全局异常捕获则需要对每个接口进行try-catch或其他操作。   可以对Controller进行全局的异常捕获和处理,一旦发生异常,则返回通用的500响应码与通用错误提示。 并将异常发生的具

    2024年02月05日
    浏览(34)
  • 【深入解析spring cloud gateway】07 自定义异常返回报文

    Servlet的HttpResponse对象,返回响应报文,一般是这么写的,通过输出流直接就可以将返回报文输出。 在filter中如果发生异常(例如请求参数不合法),抛出异常信息的时候,调用方收到的返回码和body都是Spring Cloud Gateway框架处理来处理的。这一节我们分析一下,gateway的异常返

    2024年02月10日
    浏览(24)
  • springboot优雅的统一返回格式 + 全局异常处理(包括404等异常)

    目录 1.自定义枚举类 2.自定义统一返回格式类 3.统一返回格式的高级实现 4.全局异常处理 5.更优雅的全局异常处理 6.处理404错误 该枚举类为我们和前端约定好的返回状态码和描述信息,可根据自己的需求修改状态码和描述 @Data 注解为Lombok工具类库中的注解,提供类的get、s

    2024年02月11日
    浏览(29)
  • SpringBoot统一异常处理和统一返回格式

    上篇博客我们讲解了使用AOP来进行统一的用户登录判断,其实像这种功能统一且使用较多的地方,都可以用AOP来处理,除了统⼀的⽤户登录判断之外,AOP 还可以实现: 统⼀⽇志记录 统⼀⽅法执⾏时间统计 (在性能优化阶段,监控流量,接口的响应时间等甚至每个方法的响应

    2024年02月15日
    浏览(25)
  • SpringBoot统一收集异常信息并返回给前端

    目录 适用场景 实现方法 结合Servlet对象 @RestControllerAdvice 通常前后端交互时,后端对前端参数进行校验后,对于校验不通过的信息会自定义一个异常抛出,但是后端一旦抛出异常,后台接口服务就会报500的错误 对于有些逻辑错误而言,我们只是想将此信息提示给用户,这时候

    2023年04月08日
    浏览(31)
  • 【python基础】—函数def()的定义与调用、参数、return返回值及变量作用域

    语法: 举例: 上面我们定义一个名字为hello的函数,括号内部是函数接收的参数name,紧接着就是函数的功能代码。 多次调用 位置参数 这里的\\\"手拍黄瓜\\\"和\\\"大米饭\\\"是对应参数appetizer和course的位置顺序传递的,所以被叫作位置参数,这也是最常见的参数类型。 默认参数 注意

    2024年02月02日
    浏览(33)
  • 【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅

    博友的需求就是我最大的动力 博友一说话,本狗笑哈哈。 博友要我写啥,我就写啥 。 特来一篇关于 SpringBoot接口返回结果及异常统一处理 ,虽说封不封装都能用,但咱后端也得给前端小姐姐留个好印象不是。项目前后端分离, 规范的数据传输格式,让REST风格的API具有简单

    2024年02月08日
    浏览(33)
  • 05-python之函数-函数的定义/函数的参数/函数返回值/函数说明文档/函数的嵌套使用/函数变量的作用域

    对应输出如上,没有使用len()函数,对应的子算出字符的长度,但是代码整体写的就很别扭。代码过于重复,代码中唯一不一样的地方就是被统计的字符串不同。同时对应的,代码整体也就会比较低效。可以使用函数,优化过程,先定义函数。 同样的输出,效果一样,两者

    2024年01月19日
    浏览(46)
  • springboot全局异常处理和自定义异常处理

    在spring项目中,优雅处理异常,好处是可以将系统产生的全部异常统一捕获处理,自定义的异常也由全局异常来捕获,如果涉及到validator参数校验器使用全局异常捕获也是较为方便。 GlobalExceptionHandler类: 自定义异常CustomException类: 通用返回类:AjaxResult 枚举类ResultCodeEnum:

    2024年02月04日
    浏览(32)
  • 【微服务】Feign 整合 Sentinel,深入探索 Sentinel 的隔离和熔断降级规则,以及授权规则和自定义异常返回结果

    在前文中,介绍了 Sentinel 的流控模式和流控效果,然而限流只是一种预防措施,虽然可以尽量避免因为并发问题而引起的服务故障,但服务仍然可能因其他因素而发生故障。为了将这些故障控制在一定范围内,以避免雪崩效应的发生,我们需要依赖线程隔离(舱壁模式)和熔

    2024年02月08日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包