时间:2021-05-19
前言
先谈谈“异常处理”这件事。下面有 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、默认的异常处理
例如 401,404,500,5XX 等异常,Spring Boot 默认会跳转到预配置的页面,此处以 thymeleaf 模板引擎为例:
+ resources + templates + error - 401.html - 404.html - 500.html只需在 resources/templates/error/ 路径下添加对应的html文件即可。
2、局部异常处理
局部异常一般处理业务逻辑出现的异常情况,在 Controller 下使用 @ExceptionHandler 注解来处理异常。举个小例子:
先定义 ResponseBean 和 ExceptionEnum 两个对象,辅助完成优雅的代码。
/** * 统一响应 * @author anoy */public class ResponseBean<T> { 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(很有同感,是不是?)
@Controllerpublic 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 来配合。
@ControllerAdvicepublic 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(){ // 通知具体开发人员 }}以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
前言之前一篇文章介绍了基本的统一异常处理思路:SpringMVC/Boot统一异常处理最佳实践.上篇文章也有许多人提出了一些问题:如何区分Ajax请求和普通页面
一)spring-boot-starter命名规则自动配置模块命名规则:xxx-spring-boot,如:aspectlog-spring-boot启动器命名
一、spring-boot-starter-validation依赖概述上一篇《SpringBootWeb开发注解篇》,就可以快速地进行Web开发。那么在表单提
1.什么是spring-boot-devtoolsspring-boot-devtools是spring-boot项目开发时的一个热部署工具,安装了spring
1.加入mybatis-spring-boot-stater的Maven依赖org.mybatis.spring.bootmybatis-spring-boot