微服务框架(十四)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

相关文章
|
7月前
|
数据可视化 Java BI
将 Spring 微服务与 BI 工具集成:最佳实践
本文探讨了 Spring 微服务与商业智能(BI)工具集成的潜力与实践。随着微服务架构和数据分析需求的增长,Spring Boot 和 Spring Cloud 提供了构建可扩展、弹性服务的框架,而 BI 工具则增强了数据可视化与实时分析能力。文章介绍了 Spring 微服务的核心概念、BI 工具在企业中的作用,并深入分析了两者集成带来的优势,如实时数据处理、个性化报告、数据聚合与安全保障。同时,文中还总结了集成过程中的最佳实践,包括事件驱动架构、集中配置管理、数据安全控制、模块化设计与持续优化策略,旨在帮助企业构建高效、智能的数据驱动系统。
391 1
将 Spring 微服务与 BI 工具集成:最佳实践
|
7月前
|
安全 Java Ruby
我尝试了所有后端框架 — — 这就是为什么只有 Spring Boot 幸存下来
作者回顾后端开发历程,指出多数框架在生产环境中难堪重负。相比之下,Spring Boot凭借内置安全、稳定扩展、完善生态和企业级支持,成为构建高可用系统的首选,真正经受住了时间与规模的考验。
598 2
|
7月前
|
Java 数据库 数据安全/隐私保护
Spring 微服务和多租户:处理多个客户端
本文介绍了如何在 Spring Boot 微服务架构中实现多租户。多租户允许单个应用实例为多个客户提供独立服务,尤其适用于 SaaS 应用。文章探讨了多租户的类型、优势与挑战,并详细说明了如何通过 Spring Boot 的灵活配置实现租户隔离、动态租户管理及数据源路由,同时确保数据安全与系统可扩展性。结合微服务的优势,开发者可以构建高效、可维护的多租户系统。
684 127
|
7月前
|
存储 安全 Java
管理 Spring 微服务中的分布式会话
在微服务架构中,管理分布式会话是确保用户体验一致性和系统可扩展性的关键挑战。本文探讨了在 Spring 框架下实现分布式会话管理的多种方法,包括集中式会话存储和客户端会话存储(如 Cookie),并分析了它们的优缺点。同时,文章还涵盖了与分布式会话相关的安全考虑,如数据加密、令牌验证、安全 Cookie 政策以及服务间身份验证。此外,文中强调了分布式会话在提升系统可扩展性、增强可用性、实现数据一致性及优化资源利用方面的显著优势。通过合理选择会话管理策略,结合 Spring 提供的强大工具,开发人员可以在保证系统鲁棒性的同时,提供无缝的用户体验。
170 0
|
7月前
|
消息中间件 Java 数据库
Spring 微服务中的数据一致性:最终一致性与强一致性
本文探讨了在Spring微服务中实现数据一致性的策略,重点分析了最终一致性和强一致性的定义、优缺点及适用场景。结合Spring Boot与Spring Cloud框架,介绍了如何根据业务需求选择合适的一致性模型,并提供了实现建议,帮助开发者在分布式系统中确保数据的可靠性与同步性。
507 0
|
6月前
|
安全 前端开发 Java
《深入理解Spring》:现代Java开发的核心框架
Spring自2003年诞生以来,已成为Java企业级开发的基石,凭借IoC、AOP、声明式编程等核心特性,极大简化了开发复杂度。本系列将深入解析Spring框架核心原理及Spring Boot、Cloud、Security等生态组件,助力开发者构建高效、可扩展的应用体系。(238字)
|
6月前
|
监控 Cloud Native Java
Spring Boot 3.x 微服务架构实战指南
🌟蒋星熠Jaxonic,技术宇宙中的星际旅人。深耕Spring Boot 3.x与微服务架构,探索云原生、性能优化与高可用系统设计。以代码为笔,在二进制星河中谱写极客诗篇。关注我,共赴技术星辰大海!(238字)
1206 2
Spring Boot 3.x 微服务架构实战指南
|
6月前
|
负载均衡 Java API
《深入理解Spring》Spring Cloud 构建分布式系统的微服务全家桶
Spring Cloud为微服务架构提供一站式解决方案,涵盖服务注册、配置管理、负载均衡、熔断限流等核心功能,助力开发者构建高可用、易扩展的分布式系统,并持续向云原生演进。
|
6月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
497 8
|
7月前
|
消息中间件 Java Kafka
消息队列比较:Spring 微服务中的 Kafka 与 RabbitMQ
本文深入解析了 Kafka 和 RabbitMQ 两大主流消息队列在 Spring 微服务中的应用与对比。内容涵盖消息队列的基本原理、Kafka 与 RabbitMQ 的核心概念、各自优势及典型用例,并结合 Spring 生态的集成方式,帮助开发者根据实际需求选择合适的消息中间件,提升系统解耦、可扩展性与可靠性。
518 1
消息队列比较:Spring 微服务中的 Kafka 与 RabbitMQ