download:迈向高级的 Java 面试解围课内附材料文档
SpringBoot- 全局异样处理
背景
在 Web 开发中, 咱们常常会需要处理各种异样, 这是一件辣手的事件, 需要考虑以下几个问题 :
什么时候需要捕捉 (try-catch) 异样, 什么时候需要抛出 (throws) 异样到下层 ?
在 dao 层捕捉还是在 service 捕捉, 还是在 controller 层捕捉 ?
抛出异样后要怎么处理. 怎么返回给页面错误信息 ?
全局异样处理
推荐做法
不要在业务代码中进行捕捉异样, 即 dao, service, controller 层的所有异样都全副抛出到下层. 这样不会导致业务代码中的一堆 try-catch 导致业务代码错乱.
哪一层都不捕捉.
返回对立的后果集 (错误码 + 谬误描述).
通常会将事务配置在 Service 层, 当数据库操作失败时, 让 Service 层抛出运行时异样, 而不进行 try-catch 处理, Spring 事物管理器就会进行回滚. 为了事务回滚
但 Service 层抛出后. 在 Controller 层就需要 try-catch 去捕捉异样, 否则会返回原生错误信息到客户端. 然而, 如果在 Controller 层的每个方法体外面都写一些模板化的 try-catch 的代码, 代码岂但不美观, 也减少了保护的难度, 特地是还需要对 Service 层的不同异样进行不同处理的时候.
@ControllerAdvice 注解是 Spring 3.2 中新增的. 用于拦挡全局的 Controller 的异样. 注意:该注解只能拦挡 Controller 不能拦挡 Interceptor 的异样.
全局异样处理的步骤
在 SpringMVC / SpringBoot 我的项目中, 只需要使用 AOP 编写一个全局的异样处理切面类, 用它来对立处理所有的异样即可.
定义一个类, 在类上增加 @ControllerAdvice+@ExceptionHandler 注解, 同时需要使用 @ResponseBody 注解示意返回值为 JSON 字符串.
全局异样处理 - 实例
在 Github 上的代码地址:
github.com/SanJingYe88…
① 使用对立的返回值
在 Controller 层的返回值只有两种, 一种是 Result 作为非分页请求的返回值, 一种是 PageResult 作为分页请求的返回值.
Result 非分页请求, 返回后果实体类.
PageResult 分页请求, 返回后果实体类.
② 全局异样谬误
编写一个 CodeMsg 全局异样错误码实体类. 将错误码集中管理, 而后通过 Result.error(CodeMsg codeMsg) 这种形式调用, 将业务错误码间接传回前端. 并且错误码可能随便扩大.
③ 自定义异样类
ServiceException 自定义业务异样类. 通过组合, 外部维持一个 CodeMsg 的引用, 在业务层对异样进行实例化并抛出, 让切面 GlobalExceptionHandler 捕捉处理. ServiceException
CheckException 自定义参数校验异样类.
④ 校验工具类
可能创建校验工具类来对罕用的校验做对立抽取, 还可能进行 i18n 国际化浮现消息. 这里是咱们自己手动编写了校验工具类, 还可能使用 Guava 提供的 Preconditions 类.
⑤ 全局异样处理类
编写 GlobalExceptionHandler 全局异样处理类. 对业务层传输来的异样做判断, 通过 Result.error(ex.getCodeMsg()) 对不同类型的异样对立返回.
@ControllerAdvice 注解, 在类上使用, 示意该类为全局异样处理类, 当 Controller 层抛出异样时调用.
@ExceptionHandler 注解, 在方法上使用, 示意该方法在发生何种类型异样时会被调用. 由该注解的 value 属性决定.
全局异样处理不失效的可能原因
被 Swagger 自带的注解影响到了,RequestMapping 注解,肯定要放在 Swagger 相干注解的后面。
多模块工程,全局异样处理器没有被 Sping 扫描到,所以无奈处理。