浅谈Spring Boot 异常处理篇

网友投稿 266 2023-04-13


浅谈Spring Boot 异常处理篇

前言

先谈谈“异常处理”这件事。下面有 2 份伪代码,对比下:

// ① 基于 if/else 判断

if(deletePage(page) == E_OK){

if(registry.deleteReference(page.name) == E_OK){

if(configKeys.deleteKey(page.name.makeKey()) == E_OK){

logger.log("page deleted");

}else{

logger.log("configKey not deleted");

}

}else{

logger.log("deleteReference from registry failed");

}

}else{

logger.log("delete failed");

return E_RROR;

}

// ② 基于异常处理

try{

deletePage(page);

registry.deleteReference(page.name);

configKeys.deleteKey(page.name.makeKey());

}catch(Exception e){

logError(e);

}

可以看出,如果使用异常替代返回错误码,错误处理代码就能从主路径逻辑中分离出来,得到简化!

②中,基于异常处理的代码真的好吗?其实是丑陋不堪的,它搞乱了代码结构,把错误处理与正常流程混为一谈。最好把 try 和 catch 代码块的主体部分抽离出来,形成另外的函数。

// ③ 优雅的异常处理逻辑

public void delete(Page page){

try{

deletePageAndAllReferences(page);

}catch(Exception e){

logError(e);

}

}

private void deletePageAndAllReferences(Page page) throw Exception{

deletePage(page);

registry.deleteReference(page.name);

configKeys.deleteKey(page.name.makeKey());

}

private void logError(Exception e){

logger.log(e.getMessage());

}

③中,函数各司其职,更易于理解和修改了。

总结:使用异常而不是错误码,优雅地使用异常!函数应该只做一件事,处理错误就是一件事。因此,处理错误的函数不该做其他事!

在 Spring Boot 中处理异常

1、默认的异常处理

例如 http://401,404,500,5XX 等异常,Spring Boot 默认会跳转到预配置的页面,此处以 thymeleaf 模板引擎为例:

+ resources

+ templates

+ error

- 401.html

- 404.html

- 500.html

只需在 resources/templates/error/ 路径下添加对应的html文件即可。

2、局部异常处理

局部异常一般处理业务逻辑出现的异常情况,在 Controller 下使用 @ExceptionHandler 注解来处理异常。举个小例子:

先定义 ResponseBean 和 ExceptionEnhttp://um 两个对象,辅助完成优雅的代码。

/**

* 统一响应

* @author anoy

*/

public class ResponseBean {

private int code;

private String message;

private T data;

public ResponseBean(){}

public ResponseBean(ExceptionEnum exceptionEnum){

this.code = exceptionEnum.getCode();

this.message = exceptionEnum.getMessage();

}

// 省略 setter/getter

}

/**

* 异常类型枚举

* @author anoy

*/

public enum ExceptionEnum {

GIRL_FRIEND_NOT_FOUND(100000, "girl friend not found");

private int code;

private String message;

ExceptionEnum(int code, String message){

this.code = code;

this.message = message;

}

public int getCode() {

return code;

}

public String getMessage() {

return message;

}

}

今天七夕,写个 GirlFriendNotFoundException(很有同感,是不是?)

@Controller

public class UserController {

@RequestMapping("/friend/{id}")

public String friend(@PathVariable("id") Long id) throws GirlFriendNotFoundException {

if (id == 1L){

throw new GirlFriendNotFoundException();

}

return "friend";

}

@ExceptionHandler(GirlFriendNotFoundException.class)

@ResponseBody

public ResponseBean handleGirlFriendNotFound(GirlFriendNotFoundException exception){

loggerError(exception);

return new ResponseBean(ExceptionEnum.GIRL_FRIEND_NOT_FOUND);

}

private void logError(Exception e){

logger.error(e.getMessage());

}

}

3、全局异常处理

个人观点:全局异常应该处理系统故障级别的问题,像参数校验这种类型的异常,应该作为局部异常来处理,例如 Redis 连接断开,无法请求数据,这种异常就应该当做全局异常来处理,在异常处理的逻辑中,还应该添加通知到开发人员的功能,方便开发人员及时处理错误!

全局异常处理,使用 @ControllerAdvice 和 @ExceptionHandler 来配合。

@ControllerAdvice

public class GlobalExceptionHandler {

@ExceptionHandler(RedisConnectionFailureException.class)

public void handlerRedisConnectionFailureException(RedisConnectionFailureException exception){

logError(exception);

noticeToDev();

}

private void logError(Exception e){

logger.error(e.getMessage());

}

private void noticeToDev(){

// 通知具体开发人员

}

}


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

上一篇:接口自动化测试(IPS,保护您的网络安全)
下一篇:接口自动化(点燃你的生活,尽享精彩)
相关文章

 发表评论

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