微服务框架(十四)Spring Boot @ControllerAdvice异常处理

简介: 此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。  本文为Spring Boot使用@ControllerAdvice进行自定义异常捕捉

  此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。
  本文为Spring Boot使用@ControllerAdvice进行自定义异常捕捉及处理

本系列文章中所使用的框架版本为Spring Boot 2.0.3-RELEASE,Spring 5.0.7-RELEASE,Dubbo 2.6.2。

注解

@ControllerAdvice

控制器增强,所有在Controller中被抛出的异常将会被使用@ControllerAdvice注解的类捕捉。默认情况下, @ControllerAdvice全局应用于所有控制器的方法。

若所有异常处理类返回的数据格式为json,则可以使用 @RestControllerAdvice 代替 @ControllerAdvice
@RestControllerAdvice = @ControllerAdvice + @ResponseBody

@ExceptionHandler

异常处理器,在特定异常处理程序的类或方法中以处理异常的注解。

业务异常

常规的Controller层,会抛出业务异常、校检异常等

@RestController
@RequestMapping(value = "/")
public class TestController {
   

    @Autowired
    private BussinessService bussinessService ;

    @RequestMapping(value = "/basic", method = RequestMethod.POST)
    public Resp<RespVO> getBasic(@RequestBody @Valid ReqVO reqVO) {
   

        RespVO respVO = bussinessService.getResult(reqVO);
        if(respVO  == null)
            throws BussinessExceptionMapper.build("调用失败");

        return Resp.createSuccess(respVO);
    }

}

业务异常定义

@Setter
@Getter
public class BussinessException extends RuntimeException {
   

    public static final String UNKNOWN_EXCEPTION = "unknown.exception";
    public static final String SERVICE_FAIL = "service.fail";
    public static final String NETWORK_EXCEPTION = "network.exception";
    public static final String TIMEOUT_EXCEPTION = "timeout.exception";

    private String code;

    public BussinessException() {
   
        super();
    }

    public BussinessException(String message, Throwable cause) {
   
        super(message, cause);
    }

    public BussinessException(String message) {
   
        super(message);
    }

    public BussinessException(Throwable cause) {
   
        super(cause);
    }

    public BussinessException(String code, String message, Throwable cause) {
   
        super(message, cause);
        this.code = code;
    }

    public BussinessException(String code, String message) {
   
        super(message);
        this.code = code;
    }
}

业务异常构造类

public class BussinessExceptionMapper {
   

    public static BussinessException build(String message) {
   
        return build(BussinessException.SERVICE_FAIL, message);
    }

    public static BussinessException build(String code, String message) {
   
        return new BussinessException(code, message);
    }

    public static BussinessException build(String message, Throwable cause) {
   
        return build(BussinessException.SERVICE_FAIL, message, cause);
    }

    public static BussinessException build(String code, String message, Throwable cause) {
   
        return new BussinessException(code, message, cause);
    }

}

异常处理

@Controller@RestController中的异常捕捉及处理

参数校检异常

使用hibernate validator校检参数,@Valid注解抛出的校检异常为MethodArgumentNotValidException,在@ExceptionHandler注释的方法中捕捉第一个错误信息

    @ResponseBody
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Resp validHandler(MethodArgumentNotValidException ex) {
   

        logger.error("ValidException:", ex);

        List<ObjectError> list = ex
                .getBindingResult().getAllErrors();

        String errorMsg = StringUtils.defaultString(list.get(0).getDefaultMessage(), "参数错误");

        return Resp.createError(RespCode.PARAM_ERR, "input.param.error", errorMsg);
    }

业务异常

    @ResponseBody
    @ExceptionHandler(value = BussinessException.class)
    public Resp bussinessHandler(BussinessException ex) {
   

        logger.error("BussinessException:", ex);

        return Resp.createError(RespCode.BUSINESS_INVALID, ex.getCode(), ex.getMessage());
    }

Dubbo Rpc异常及运行时异常

@ControllerAdvice
public class GlobalControllerAdvice {
   

    private Logger logger = LoggerFactory.getLogger(GlobalControllerAdvice.class);

    @ResponseBody
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public Resp validHandler(MethodArgumentNotValidException ex) {
   

        logger.error("ValidException:", ex);

        List<ObjectError> list = ex
                .getBindingResult().getAllErrors();

        String errorMsg = StringUtils.defaultString(list.get(0).getDefaultMessage(), "参数错误");

        return Resp.createError(RespCode.PARAM_ERR, "input.param.error", errorMsg);
    }

    @ResponseBody
    @ExceptionHandler(value = BussinessException.class)
    public Resp bussinessHandler(BussinessException ex) {
   

        logger.error("BussinessException:", ex);

        return Resp.createError(RespCode.BUSINESS_INVALID, ex.getCode(), ex.getMessage());
    }

    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Resp errorHandler(Exception e) {
   

        logger.error("uncaught Exception:", e);

        Resp resp;
        if (e instanceof RpcException) {
   
            resp = Resp.createError(RespCode.ERROR, "rpc.exception",
                    e.getMessage());
        } else if (e instanceof RuntimeException) {
   
            resp = Resp.createError(RespCode.ERROR, "runtime.exception",
                    "运行时异常,详见堆栈日志");
        } else {
   
            resp = Resp.createError(RespCode.BUSINESS_INVALID,
                    "service.fail", "服务失败");
        }

        return resp;
    }


}

参考资料:
1.ControllerAdvice
2.RestControllerAdvice

相关文章
|
5天前
|
安全 Java API
第7章 Spring Security 的 REST API 与微服务安全(2024 最新版)(上)
第7章 Spring Security 的 REST API 与微服务安全(2024 最新版)
24 0
第7章 Spring Security 的 REST API 与微服务安全(2024 最新版)(上)
|
5天前
|
Java API 微服务
【Spring Boot系列】通过OpenAPI规范构建微服务服务接口
【4月更文挑战第5天】通过OpenAPI接口构建Spring Boot服务RestAPI接口
|
1月前
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(二)Rest微服务工程搭建
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(二)Rest微服务工程搭建
52 0
|
2天前
|
存储 Java 时序数据库
【SpringBoot系列】微服务监测(常用指标及自定义指标)
【4月更文挑战第6天】SpringBoot微服务的监测指标及自定义指标讲解
|
1月前
|
SpringCloudAlibaba Java 持续交付
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
146 0
|
1月前
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
98 0
|
1天前
|
Java 关系型数据库 数据库
【SpringBoot系列】微服务集成Flyway
【4月更文挑战第7天】SpringBoot微服务集成Flyway
【SpringBoot系列】微服务集成Flyway
|
8天前
|
负载均衡 Java 开发者
细解微服务架构实践:如何使用Spring Cloud进行Java微服务治理
【4月更文挑战第17天】Spring Cloud是Java微服务治理的首选框架,整合了Eureka(服务发现)、Ribbon(客户端负载均衡)、Hystrix(熔断器)、Zuul(API网关)和Config Server(配置中心)。通过Eureka实现服务注册与发现,Ribbon提供负载均衡,Hystrix实现熔断保护,Zuul作为API网关,Config Server集中管理配置。理解并运用Spring Cloud进行微服务治理是现代Java开发者的关键技能。
|
23天前
|
负载均衡 网络协议 Java
构建高效可扩展的微服务架构:利用Spring Cloud实现服务发现与负载均衡
本文将探讨如何利用Spring Cloud技术实现微服务架构中的服务发现与负载均衡,通过注册中心来管理服务的注册与发现,并通过负载均衡策略实现请求的分发,从而构建高效可扩展的微服务系统。
|
28天前
|
Java 编译器 API
Spring Boot 异常处理
Java异常分为 Throwable 类的两个子类:Error 和 Exception。Error 是不可捕获的,由JVM处理并可能导致程序终止,如 OutOfMemoryError。Exception 是可捕获的,包括运行时异常如 ArrayIndexOutOfBoundsException 和编译时异常如 IOException。
13 1