SpringBoot异常处理的简单理解 - Go语言中文社区

SpringBoot异常处理的简单理解


Springboot异常处理:

1、局部异常处理:

直接对Controller类进行操作

 

2、全局统一异常处理

Springboot两种全局异常统一处理的方式:

A使用继承BasicErrorController 来实现

B通过@ControllerAdvice 注解来处理统一错误(Advice 异常处理)

 

(1)Java 异常的 Root 是 Throwable, 其下有 Error 和 Exception. Error 是 JVM 级的致命错误, 应用系统内部一般不用关心这类错误. Exception 是异常的父类, 其下分为两类, 一类是 Runtime Exception, 一类是 Checked Exception. Checked Exception 是那些编译器能检查到的异常, 如果一个函数中抛出了这类异常, 我们要么 catch 它, 要么在函数签名上继续抛出去, 否则程序将不能编译通过。

Runtime Exception 有, 包括 RuntimeException 和它的子类. 比如 ArrayIndexOutOfBoundsException/ClassCastException/被 0 除等. 
Checked Exception 有: Exception 类和所有非 RuntimeException 类的异常都属于 checked exception, 比如 IoException 等.

(2)dao、service、controller出现的未知异常都通过throws Exception向上抛出,最后由springmvc前端控制器交由异常处理器进行异常处理,springmvc提供全局异常处理器进行统一的异常处理,一个系统只有一个异常处理器。Springboot也有统一的异常处理器ControllerAdvice。

一般思路:系统有自定义异常时,在程序中手动抛出throw MyException,对于未知异常通过在函数上声明throws Exception向上抛出,dao抛给service,service再抛给Controller,最后Controller抛给前端控制器,前端控制器调用全局异常处理器进行处理。

(3)异常处理的一般实践步骤。

===================================
自定义类的最佳实践:
===================================
1. 先定义一个基类 BusinessException, 继承自 RuntimeException. 
2. 定义一套BusinessErrorCode 枚举类型, 包含 BusinessErrorCode/HttpStatus/BusinessErrorMessage, 这里的 BusinessErrorCode 不同于 HttpStatus, 它是业务上的错误代码 (int 型). 
2. 在 BusinessException 基类上, 加上绑定 BusinessErrorCode 枚举类型的机制. 
3. 基于 BusinessException 定义一组子类, 比如 UserNotLoginException/PermissionForbiddenException/DataNotFoundException 等等, 并将这些子类加入到一个 BusinessExceptionEnum 枚举中, 方便使用.

 

===================================
Spring 项目数据验证最佳实践
===================================
1. 针对 UI 输入检查, 如果 js 前端检查有困难, 可以在 Controller 层使用 Pojo validation 手段做检查, 然后前端使用 ajax 拿到校验结果. 检查过程没有触发 UI 完整渲染, 用户体验会很好. 
2. Controller 层使用 validation 进行检查, 可以在视图函数的形参上检查, 或者在视图函数内部检查. 
3. Service 层, 使用 org.springframework.util.Assert 进行数据验证, 比如 Assert.notNull(user, "user is not null.");
4. DAO 层, 不做任何数据验证, 因为所有数据问题应该在Service层或Controller层做个验证.


===================================
Spring 各层封装的手法
===================================
1. DAO 层, 函数的形参最好以 DO 类做参数, 而不是传入很多个字段参数. 这样的好处是, 避免Table增删字段, DAO层函数定义也要跟着修改, 上层的调用代码也要修改. 
2. DAO 层, insert 和 update 要独立为两个函数. 到底是新增还是更新, 应由 Service 层进行逻辑控制. 
3. Service 层函数的形参, 到底是使用 DO 类, 还是简单的属性清单, 看具体情况吧.


===================================
Spring 日志和异常处理的最佳实践
===================================
异常处理的基本思路是: 早抛出, 晚捕获. 日志输出的基本思路是, 详尽但不冗余. 
落实到具体的项目中, 在不同分层中, 应采用不同的规则, 一般的分层有: DAO -> Service -> Controller -> 统一异常 Controller 层.

1. DAO 层: 
   (1) 尽量不 catch 任何异常, 该向上抛就抛. 
   (2) 不用记录 log 日志, 或者仅使用 logger.debug() 记录

2. Service 层的做法: 
    (1) @Transactional 注解应该加在 Service 层上. 
    (2) 对于一些关键问题, 比如 Checked Exception 或者数据的问题, 应该及时 throw new BusinessException 异常, 以确保事务完整. 
    (3) throw new BusinessException 时的日志, 为了避免日志重复, 不需要 log 日志输出. 
    (4) Service 层一般的日志级别, 应该用 logger.debug() 记日志. 
    (5) Service 层函数的返回值应该是 Optional 类型, 方便 Controller 做 null 判断.


3. Controller 层: 
   (1) Controller 层负责组装 Service, 在关键步骤上应该加日志输出 (info 级别) 
   (2) Controller 层不应再主动 throw 异常. 
4. 统一异常 Controller 层: 
   (1) 通过 json 或 UI 返回详细的报错信息, 包括 HttpStatus 和详尽的 BusinessErrorCode/BusinessErrorMessage 以及 DetailErrorMessage(来源于 exception.getMessage()), 甚至包括 exception 的 stack trace. 
   (2) 对于 Exception 类的异常, 说明这是我们预料之外的报错, 应该使用 logger.error() 级别记录; 
   (3) 对于 BusinessException 和子类的异常, 则说明我们的程序已经预料到了, 事物该回滚也已经回滚了, 所以应该以 logger.warn() 或 logger.info() 记录日志. 
   (4) 对于 Spring Boot 缺省的 /error 进行定制, 增加一些"系统主页"和"返回"的链接, 改善用户体验.

(4)一些重要的注意事项:

Adao层一般不需要抛出异常,有事务的情况下,会将service的异常抛出到控制层做处理的,不然可能会影响事务的回滚,如果不存在事务,则可以直接在service层进行处理。

B针对预期可能发生的异常(检查类型(checked)),在代码手动处理异常可以try/catch捕获,可以向上抛出,可以声明。

try-catch 是在当前位置处理异常,尝试能不能正常的走完整个作用域,如果不能则抛出一个异常。
throws是向上抛出异常,用来声明一个方法可能产生的所有异常,不做任何处理而是将异常往上传,谁调用我我就抛给谁,throws在方法后边声明异常,其实就是自己不想对异常做出任何的处理,告诉别人自己可能出现的异常,交给别人处理

throw 就是抛出一个具体的异常,并获取这个异常的引用,这个异常会被抛到外部的环境,由外部环境进行处理。

 

C 在service中如果声明了@Transactional,但是又在方法里面自己捕获了异常,也就是try catch掉了,那就不会回滚了,因为切入点根本没捕获到,也谈不上调用增强处理中的方法了。解决:1.抛出RuntimeException 2.抛出Exception,同时在事务声明中加上@Transactional(rollbackFor = Exception.class)

 

 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_34562093/article/details/98315172
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-02-25 01:01:22
  • 阅读 ( 906 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢