java实现统一异常处理的示例

网友投稿 167 2023-01-05

java实现统一异常处理的示例

对于Dao层 和Service产生的异常要一直网上抛,直至Controller层,但是对于controller层不能处理的异常也不能直接抛给前端。

为什么不能在service处理异常?

答:Service 层往往涉及数据库事务,出现异常同样不适合捕获,否则事务无法自动回滚。此外 Service 层涉及业务逻辑,有些业务逻辑执行中遇到业务异常,可能需要在异常后转入分支业务流程。如果业务异常都被框架捕获了,业务功能就会不正常。【引用:极客时间的java业务开发常见错误100例】

实现统一异常处理:

在spring框架下实现一个异常处理的类,用 @RestControllerAdvice + @ExceptionHandler

进行修饰:

即@RestControllerAdvice默认会拦截 controller类上抛出的不能处理的异常

一个全局异常处理类需要处理三类异常: 1.业务类异常,2.运行时异常 ,3.Error

1.运行时异常

/**

* @创建人: liup

* @创建时间: 2021/6/18

* @描述 全局异常捕获处理类

*/

@RestControllerAdvice

@Slf4j

public class GlobalExceptionHandler {

/**

* @Author: liup

* @date: 2021/6/18 14:34

方法实现说明: 拦截运行时异常

*/

@ExceptionHandler(value = RuntimeException.class)

public R runtimeExceptionHandle(RuntimeException e){

log.error("捕捉到运行时异常",e);

return R.failed("未知错误");

}

}

目前仅是拦截运行时异常

R 是返回的消息体:

那如果不使用GlobalExceptionHandler,会报出什么错误呢?

这个错误是在service层抛出的,当从redis 通过key获取一个已删除的value时,redis返回的是null,但是我没有判断这个value是否为null,就将其打印出来:

log.info(authInfoVo.toString());

注意:这是要返回给前端的,msg的内容,是对用户十分不友好的。

2.Error

RuntimeException只是异常中的一个类,不能包含所有的异常体系,还有一大类是叫Error(系统级异常),所以需要有一个兜底的异常捕获:

/**

* @Author: liup

* @date: 2021/6/18 15:01

方法实现说明: 捕获系统级异常

*/

@ExceptionHandler(value = Throwable.class)

public R throwableHandle(Throwable th){

log.error("捕捉到Throwable异常",th);

return R.failed("系统异常");

}

和上面那个运行时异常同时存在 。

3.业务类异常

【自己定义的异常】

首先创建业务异常类

/**

* @创建人: liup

* @创建时间: 2021/6/18

* @描述 业务类异常

*/

public class BusinessException extends RuntimeException{

@Getter

private final String code;

/**

* @Author: liup

* @date: 2021/6/18 15:10

方法实现说明: 根据消息码【可用枚举类】 构造业务类异常

*/

public BusinessExceptionuaOELyoWY(String code) {

this.code = code;

}

/**

* @Author: liup

* @date: 2021/6/18 15:08

方法实现说明: 自定义消息体构造业务类异常

*/

public BusinessException(String code,String message) {

super(message);

this.code = code;

}

/**

* @Author: liup

* @date: 2021/6/18 15:09

方法实现说明: 根据异常 构造业务类异常

*/

public BusinessException(String code,Throwable cause) {

super(cause);

this.code = code;

}

}

三种异常拦截同时存在;

/**

* @创建人: liup

* @创建时间: 2021/6/18

* @描述 全局异常捕获处理类

*/

@RestControllerAdvice

@Slf4j

public class GlobalExceptionHandler {

/**

* @Author: liup

* @date: 2021/6/18 15:14

方法实现说明: 拦截业务类异常

*/

@ExceptionHandler(value = BusinessException.class)

public R businessExceptionHandle(BusinessException e){

log.error("捕获业务类异常:",e);

return R.failed("业务类异常:"+e.getMessage());

}

/**

* @Author: liup

* @date: 2021/6/18 14:34

方法实现说明: 拦截运行时异常

// */

@ExceptionHandler(value = RuntimeException.class)

public R runtimeExceptionHandle(RuntimeException e){

log.error("捕捉到运行时异常",e);

return R.failed("未知错误:");

}

/**

* @Author: liup

* @date: 2021/6/18 15:01

方法实现说明: 捕获系统级异常

*/

@ExceptionHandler(value = Throwable.class)

public R throwableHandle(Throwable th){

log.error("捕捉到Throwable异常",th);

return R.failed("系统异常");

}

}

4.对服务器友好:

以上是对前端友好,但是在服务器上,不是容易定位错误,

但是若是在参数上添加上HttpServletRequest req, HandlerMethod method,就很容易定位到错误

private static int GENERIC_SERVER_ERROR_CODE = 2000;

private static String GENERIC_SERVER_ERROR_MESSAGE = "服务器忙,请稍后再试";

@ExceptionHandler

public R handle(HttpServletRequest req, HandlerMethod method, Exception ex) {

if (ex instanceof BusinessException) {

BusinessException exception = (BusinessException) ex;

log.warn(String.format("访问 %s -> %s 出现业务异常!", req.getRequestURI(), method.toString()), ex);

return R.failed(GENERIC_SERVER_ERROR_MESSAGE);

} else if (ex instanceof RuntimeException){

log.error(String.format("访问 %s -> %s 出现运行时异常!", req.getRequaOELyoWYuestURI(), method.toString()), ex);

return R.failed(GENERIC_SERVER_ERROR_MESSAGE);

}

else {

log.error(String.format("访问 %s -> %s 出现系统异常!", req.getRequestURI(), method.toString()), ex);

return R.failed(GENERIC_SERVER_ERROR_MESSAGE);

}

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:浅谈System.getenv()和System.getProperty()的区别
下一篇:各种api接口网站源码(开发api接口教程)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~