Java异常实践

简介: 对于Java理论在《Java异常处理》[1]中已经阐述了,看看理论如何指导落地现流行的文章SpringBoot如何优雅处理异常,落地的确方便,使用AOP统一处理异常,但只是处理了api层次的异常

对于Java理论在《Java异常处理》[1]中已经阐述了,看看理论如何指导落地

现流行的文章SpringBoot如何优雅处理异常,落地的确方便,使用AOP统一处理异常,但只是处理了api层次的异常

应用中抛出异常有两种方式:

1.带有ErrorCode的异常2.明确类型的异常

对于controller层,也是面向用户的,需要error code,所以采用第一种方式

前端通过映射关系给出更好用户体验的提示语,也有很多项目都是controller层直接拼接出提示语,前端直接展示

所以一般会定义一个接口ErrorCode

interface ErrorCode
{ String getErrorCode();
String getMessage();
}

具体的实现可以通过enum

@Getter
enum ApiErrorCode implements ErrorCode {
    USER_NOT_FOUND("10000","用户不存在");
    private String errorCode;
    private String message;
}

再定义一个统一异常

public class ApiException extends RuntimeException {
    public ApiException(ErrorCode errorCode) {
    }
}

在aop拦截时,直接拦截此异常就行

api层次的异常可以这么处理,那业务层呢?很多时候都是缺失设计的,这也在上篇说过exception从语法层面看很简单,但要设计一个好的异常是很难的

大多项目直接把api exception拿来当做business exception使用

对于一个良好的业务接口,应该采用第二种方法:细致的异常


User login(String username, String password) throws UserNotFoundException, PasswordNotMatchException;

已检查异常要比错误返回码(许多老式的语言中使用)好很多。迟早(或许不久),人们将不能检查一个错误返回值;使用编译程序来实施正确的错误处理是一件好事。同参数与返回值一样,这样的已检查异常对一个对象的API来说是整体的一个不可分割部分

这样的接口更丰富,也更面向对象,可也给客户端带来的麻烦,缺点在上篇已经阐述

对可恢复的情况使用已检查异常,对程序错误使用运行时异常

在大多项目中,其实业务层抛出异常后,通常会“可恢复”吗?大多数情况也需要用户手工干预,系统无法自行恢复,比如UserNotFoundException, PasswordNotMatchException系统能怎么处理,无非还是得给用户重新输入用户名和密码

在controller层去调用service方法,也只能如此处理

Response login(String username,String password) {
    try {
        userService.login(username,password);
    }catch(UserNotFoundException ue) {
        throw new ApiException(ApiErrorCode.USER_NOT_FOUND);
    }catch(PasswordNotMatchException pe){
        throw new ApiException(ApiErrorCode.Password_Not_Match);
    }
}

这样处理也就理论化了,带来了多少优点呢?这些缺点不正是checked exception被嘟囔的地方吗

那我们把业务异常也定义为runtime exception,这样减少客户端压力,想处理就处理,不想处理,我们也可在拦截器中兜底

不过抛出运行期异常,减少客户端的压力,但也带来了接口不明确的困惑

非检查型异常的最大风险之一就是它并没有按照检查型异常采用的方式那样自我文档化。除非 API 的创建者明确地文档化将要抛出的异常,否则调用者没有办法知道在他们的代码中将要捕获的异常是什么

总结起来,还是那句话,异常语法很简单,但设计好异常不易;现在技术快速发展,通过技术手段可以达到更大的便捷性,但不能只有技术手段而忽略设计,没有设计的代码称不上好代码,可以取舍,但不能全舍

References



目录
相关文章
|
8天前
|
Java
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
|
15天前
|
设计模式 安全 Java
Java编程中的单例模式:理解与实践
【10月更文挑战第31天】在Java的世界里,单例模式是一种优雅的解决方案,它确保一个类只有一个实例,并提供一个全局访问点。本文将深入探讨单例模式的实现方式、使用场景及其优缺点,同时提供代码示例以加深理解。无论你是Java新手还是有经验的开发者,掌握单例模式都将是你技能库中的宝贵财富。
22 2
|
8天前
|
Java
在 Java 中,如何自定义`NumberFormatException`异常
在Java中,自定义`NumberFormatException`异常可以通过继承`IllegalArgumentException`类并重写其构造方法来实现。自定义异常类可以添加额外的错误信息或行为,以便更精确地处理特定的数字格式转换错误。
|
9天前
|
IDE 前端开发 Java
怎样避免 Java 中的 NoSuchFieldError 异常
在Java中避免NoSuchFieldError异常的关键在于确保类路径下没有不同版本的类文件冲突,避免反射时使用不存在的字段,以及确保所有依赖库版本兼容。编译和运行时使用的类版本应保持一致。
|
11天前
|
Java 编译器
如何避免在 Java 中出现 NoSuchElementException 异常
在Java中,`NoSuchElementException`通常发生在使用迭代器、枚举或流等遍历集合时,尝试访问不存在的元素。为了避免该异常,可以在访问前检查是否有下一个元素(如使用`hasNext()`方法),或者使用`Optional`类处理可能为空的情况。正确管理集合边界和条件判断是关键。
|
12天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####
|
9天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
13天前
|
SQL Java 数据库连接
从理论到实践:Hibernate与JPA在Java项目中的实际应用
本文介绍了Java持久层框架Hibernate和JPA的基本概念及其在具体项目中的应用。通过一个在线书店系统的实例,展示了如何使用@Entity注解定义实体类、通过Spring Data JPA定义仓库接口、在服务层调用方法进行数据库操作,以及使用JPQL编写自定义查询和管理事务。这些技术不仅简化了数据库操作,还显著提升了开发效率。
27 3
|
12天前
|
Java UED
Java中的多线程编程基础与实践
【10月更文挑战第35天】在Java的世界中,多线程是提升应用性能和响应性的利器。本文将深入浅出地介绍如何在Java中创建和管理线程,以及如何利用同步机制确保数据一致性。我们将从简单的“Hello, World!”线程示例出发,逐步探索线程池的高效使用,并讨论常见的多线程问题。无论你是Java新手还是希望深化理解,这篇文章都将为你打开多线程的大门。
|
13天前
|
Java
Java异常捕捉处理和错误处理
Java异常捕捉处理和错误处理
14 1
下一篇
无影云桌面