抛弃丑陋的try-catch,优雅处理异常

这篇具有很好参考价值的文章主要介绍了抛弃丑陋的try-catch,优雅处理异常。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

随着业务逻辑变得越来越复杂,我们在编写代码时会遇到各种异常情况,这时就需要使用try-catch语句来捕获异常并进行处理。但是,大量的try-catch语句会让代码变得臃肿,不易维护,因此,我们需要一种优雅的方式来统一处理异常,减少代码中的try-catch语句。

比较下面两张图,看看您现在编写的代码属于哪一种风格?然后哪种编码风格您更喜欢?

丑陋的 try catch 代码块:

抛弃丑陋的try-catch,优雅处理异常

 

优雅的Controller:

抛弃丑陋的try-catch,优雅处理异常

 

那么问题来了,我们改如何实现第二种异常处理方式,如何优雅的处理各种异常?

异常处理的基本原则

在讲解如何减少try-catch语句之前,我们先来了解一下异常处理的基本原则。

首先,异常应该被及时捕获并进行处理。如果异常未被捕获,程序将崩溃并抛出未处理的异常,影响系统的稳定性。因此,我们需要在代码中合理地使用try-catch语句来捕获异常,并在catch块中进行处理。

异常应该被分类处理。不同类型的异常需要采取不同的处理方式,比如,对于业务逻辑异常,我们需要将异常信息返回给客户端,而对于系统异常,我们需要记录日志并通知管理员。

最后,异常处理应该是统一的。在一个应用程序中,我们可能会遇到很多不同的异常类型,如果每个异常都需要单独处理,会使代码变得很冗长。因此,我们需要将异常处理的逻辑抽象出来,实现统一的异常处理。

Spring Boot中的异常处理

Spring Boot提供了很多种方式来处理异常,比如使用@ControllerAdvice注解来定义一个全局的异常处理类,使用@ExceptionHandler注解来处理特定的异常类型等。下面,我们将介绍如何使用@ControllerAdvice注解来实现统一的异常处理。

定义异常处理类

我们可以使用@ControllerAdvice注解来定义一个全局的异常处理类,该类中的方法会被自动调用来处理异常。下面是一个示例:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(BusinessException.class)
    @ResponseBody
    public ResponseData handleBusinessException(BusinessException e) {
        // 处理业务逻辑异常
        return new ResponseData(e.getCode(), e.getMessage(), null);
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ResponseData handleException(Exception e) {
        // 处理系统异常
        return new ResponseData(500, "系统异常", null);
    }
}

在上面的代码中,我们定义了一个全局的异常处理类GlobalExceptionHandler,该类中定义了两个方法:handleBusinessException和handleException。其中,handleBusinessException方法用来处理业务逻辑异常,handleException方法用来处理系统异常。@ExceptionHandler注解指定了处理的异常类型,@ResponseBody注解将返回结果序列化成JSON格式,方便客户端进行处理。

自定义异常类

在上面的代码中,我们使用了BusinessException和Exception两个异常类来区分业务逻辑异常和系统异常。因此,我们需要定义这两个异常类。下面是一个示例:

public class BusinessException extends RuntimeException {

    private int code;

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

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }
}

在上面的代码中,我们定义了一个BusinessException类,继承自RuntimeException。该类中包含了一个code字段,用来标识业务逻辑异常的类型。

抛出异常

在我们的业务逻辑中,如果遇到了异常情况,我们需要抛出对应的异常。下面是一个示例:

javaCopy codepublic User getUserById(Long id) {
    User user = userRepository.findById(id).orElse(null);
    if (user == null) {
        throw new BusinessException(1001, "用户不存在");
    }
    return user;
}

在上面的代码中,如果根据id未找到对应的用户,我们就会抛出BusinessException异常,该异常包含了错误码1001和错误信息"用户不存在"。

优雅的异常处理方式

通过上面的示例,我们已经实现了一个基本的统一异常处理,但是在实际开发中,我们还可以优化异常处理的方式,使代码更加优雅。

使用枚举类定义错误码

在上面的示例中,我们在BusinessException中定义了错误码,但是错误码的值可能会有重复,而且不太容易管理。因此,我们可以使用枚举类来定义错误码。下面是一个示例:

public enum ErrorCode {

    USER_NOT_FOUND(1001, "用户不存在"),
    PASSWORD_ERROR(1002, "密码错误"),
    ;

    private int code;
    private String message;

    ErrorCode(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }
}

在上面的代码中,我们定义了一个ErrorCode枚举类,包含了多个错误码及其对应的错误信息。

使用自定义注解来简化代码

在上面的示例中,我们需要在每个抛出异常的方法中手动创建BusinessException对象,并指定错误码和错误信息。这样做的代码量比较大,而且不太优雅。因此,我们可以使用自定义注解来简化代码。下面是一个示例:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface CheckUser {

    long id() default 0;

}

在上面的代码中,我们定义了一个CheckUser注解,用来标注需要检查用户的方法。该注解包含了一个id属性,用来指定用户的id。

下面是一个使用该注解的示例:

@GetMapping("/{id}")
@CheckUser(id = 1)
public User getUserById(@PathVariable("id") Long id) {
    User user = userService.getUserById(id);
    return user;
}

在上面的代码中,我们使用了@CheckUser注解,指定了id为1,表示需要检查id为1的用户是否存在。在CheckUserAspect切面中,我们会根据该注解的值来进行业务逻辑的处理。

使用AOP实现统一异常处理

在上面的示例中,我们使用了@ExceptionHandler注解来实现异常的处理。但是,如果我们有很多的Controller方法,每个方法都需要加上该注解,这样就会使代码量变得很大,而且不太优雅。因此,我们可以使用AOP来实现统一异常处理。下面是一个示例:

javaCopy code@Aspect
@Component
public class ExceptionAspect {

    private static final Logger logger = LoggerFactory.getLogger(ExceptionAspect.class);

    @Pointcut("execution(public * com.example.springbootdemo.controller..*.*(..))")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        Object result;
        try {
            result = pjp.proceed();
        } catch (BusinessException e) {
            result = new Response<>(e.getCode(), e.getMessage());
        } catch (Exception e) {
            logger.error("系统异常", e);
            result = new Response<>(ErrorCode.SYSTEM_ERROR.getCode(), ErrorCode.SYSTEM_ERROR.getMessage());
        }
        return result;
    }

}

在上面的代码中,我们定义了一个ExceptionAspect切面,用来处理所有Controller方法抛出的异常。@Pointcut注解用来定义切入点,表示所有public方法。@Around注解用来定义环绕通知,表示在目标方法执行前后都要执行该通知。在该通知中,我们可以处理抛出的异常,然后返回处理结果。

总结

通过上面的示例,我们实现了一个简单的统一异常处理。在实际开发中,我们可以根据需求进行一些优化,使代码更加简洁、优雅。异常处理是一个很重要的功能,需要我们在开发过程中认真对待,避免出现漏洞,保证系统的稳定性和安全性。文章来源地址https://www.toymoban.com/news/detail-419668.html

到了这里,关于抛弃丑陋的try-catch,优雅处理异常的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • try-catch以及使用技巧

    try-catch 是 JavaScript 处理错误的一种重要机制。try 块用来包含可能会出错的代码,catch 块用来处理 try 块中的错误。使用 try-catch 的主要目的是在代码出错时不会导致整个程序崩溃,可以让错误被妥善处理。 如果你想捕获代码中所有可能的异常,可以使用一个不带参数的 catch 代码

    2024年02月22日
    浏览(45)
  • 使用try...catch语句优雅地处理JavaScript错误

    🧑‍🎓 个人主页: 《爱蹦跶的大A阿》 🔥 当前正在更新专栏: 《VUE》 、《JavaScript保姆级教程》、《krpano》、《krpano中文文档》 ​  目录 ✨ 前言 ✨ 正文 简介 语法 示例 错误对象 抛出错误 finally 语句 总结 ✨ 结语   ​         JavaScript作为一门脚本语言,代码运行时

    2024年01月22日
    浏览(55)
  • C++ try-catch语法分析与应用

    通过前面的学习,我们了解了try-catch语法的基本使用。但是,C++提供的异常处理机制很全面,下面再具体分析。 发生异常的时候,我们可以主动抛出一个异常,所以,使用throw抛出一个异常。异常可以是一个数值,字符,或者表达式。 抛出的异常可以有try-catch语句捕获。tr

    2024年02月16日
    浏览(44)
  • kotlin协程异常处理之-try catch

    kotlin协程小记 协程的async使用 kotlin协程异常处理之-try catch kotlin协程异常处理之-CoroutineExceptionHandler try catch是否一定有效呢?未必,来看一下: withContext是一个挂起函数,它会暂停当前协程的执行,等待传递进来的协程上下文切换后继续执行。当在withContext内部发生异常时,

    2024年02月12日
    浏览(35)
  • java中的异常,以及出现异常后的处理【try,catch,finally】

    异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。 注意: 在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的方式是中断处理。 异常机制其实是帮助我们找到程序中的问题

    2024年02月08日
    浏览(42)
  • JavaScript的try-catch-finally异常处理机制--详解

    JavaScript 提供了异常处理机制,通过 try-catch-finally 语句块来捕获和处理异常。以下是对该机制的详细解释和示例: 1. try 块: try 块用于包裹可能会产生异常的代码块。在 try 块内,您可以放置任何可能引发异常的代码。 2. catch 块: catch 块用于捕获和处理 try 块中抛出的异常。

    2024年02月11日
    浏览(57)
  • 面试官:try-catch 到底写在循环里面好,还是外面好?大部分人都会答错!

    面试官: try-catch 到底写在循环里面好,还是外面好? 这个问题,我相信大部分人都会答错! 很多人会说当然写在循环外面好,也有一部分人说写在循环里面好,其实这两种回答都不完全对,我们来分析下两者的弊端。 try-catch 写在循环外面的弊端: 如果 try-catch 写在循环外

    2024年02月16日
    浏览(43)
  • 如何优雅的写个try catch的方式!

    丑陋的 try catch 代码块 优雅的 Controller 上面的示例,还只是在 Controller 层,如果是在 Service 层,可能会有更多的 try catch 代码块。这将会严重影响代码的可读性、“美观性”。 所以如果是我的话,我肯定偏向于第二种,我可以把更多的精力放在业务代码的开发,同时代码也会

    2024年02月01日
    浏览(40)
  • 【Java练习题汇总】《第一行代码JAVA》异常处理篇,汇总Java练习题——异常的概念及处理标准格式(try、catch、finally、throws、throw)、断言机制 Assertion ~

    一、填空题 Throwable 下的两个子类是______________ 、______________ 。 ArthmeticException 类表示______________ 异常, ArraysIndexOutOfBoundsException 表示______________ 异常。 一个 try 代码后面必须跟着若干个_______ 代码段或者一个_______ 代码段。 如果一个方法使用了_______ , 则编译器会强制在使用此

    2024年02月16日
    浏览(41)
  • try catch捕获异常并打印报错行号等信息

    在我们系统中,如果某一行代码报错了,我们打印日志的时候却不知道具体报错行号,报错信息等等。 如何才能打印报错行号呢? 我们拿到Exception对象后,首先要拿到错误的堆栈信息,可以通过下面方法拿到: 拿到堆栈信息后,那么我们就可以获取具体的报错信息了. 通过

    2024年02月12日
    浏览(94)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包