哈喽,各位代码战士们,我是Jensen,一个梦想着和大家一起在代码的海洋里遨游,顺便捡起那些散落的知识点的程序员小伙伴。
今天,我要给大家带来一个超级无敌霹雳的编码新招式,只要看完,保证你的代码像用了某某洗发水一样,不仅去屑还更柔顺。
咱们要聊的是那些让人又爱又恨的技术点:自定义异常、全局异常捕获、断言。
首先,让我们来聊聊自定义异常。
你知道的,在Java的世界里,我们通常用if-else语句来检查那些让人头疼的条件。
比如用户登录:
// 伪代码if (验证码 != 8888) { return "验证码错误";}// 处理其他业务逻辑return "登录成功";
但是,你有没有想过,如果不用if-else,而是用异常来控制流程,会怎样呢?
比如,你的登录方法里,验证码不正确,不是返回一个错误信息,而是“砰”地一声抛出个异常。
// 伪代码if (验证码 != 8888) { throw new ServiceException("验证码错误");}// 处理其他业务逻辑return "登录成功";
听起来是不是有点疯狂?但这就是自定义异常的魅力所在,它能让你的代码看起来像是在演电影,每个异常都是一个剧情转折。
这里封装了一个业务类异常类ServiceException,该异常类继承了运行时异常RuntimeException:
/** * 服务异常,可用于控制业务异常流程,抛出后由统一异常增强类捕获,返回友好提示 * * @author Jensen * @公众号 架构师修行录 */@Datapublic class ServiceException extends RuntimeException { protected Integer code; public ServiceException(Integer code, String message) { super(message); this.code = code; } public ServiceException() { this(500, "请求成功但是服务异常"); } public ServiceException(String message) { this(500, message); } public ServiceException(Throwable e) { this(e.getMessage()); }}
使用自定义异常来代替传统的if-else语句进行错误处理和流程控制,有其优缺点:
优点:
缺点:
总的来说,自定义异常在处理错误和异常情况时提供了一种强大而灵活的机制,我觉得可以使用,但不能滥用,常规的还是要使用if-else控制,涉及API的中断流程可以快速跳出内部,并且R对象可无须传递进Service层。
想象一下,你的业务代码里抛出了一大堆异常,你总不能把这些异常原封不动地扔给API的使用者吧。
这时候,@RestControllerAdvice就像是那个超级英雄,跳出来拯救世界,把所有的异常都捕获起来,然后优雅地包装成一个个友好的响应。
@RestControllerAdvice 是 Spring MVC 中的一个注解,用于定义一个全局的异常处理类,该类可以捕获和处理 Spring 应用中发生的特定类型的异常。这个注解通常与 @ExceptionHandler 注解一起使用,来定义处理特定异常的方法。
@RestControllerAdvice 的主要作用和特点包括:
捕获业务异常ServiceException后,封装R对象返回给接口调用方:
@RestControllerAdvicepublic class GlobalRestExceptionAdvice { @ExceptionHandler({ServiceException.class}) public R<Map<String, String>> serviceException(HttpServletRequest request, ServiceException e) { return R.fail(e.getCode(), e.getMessage(), null); }}
到这里,我们就可以通过抛出ServiceException来实现异常流程的控制了,并且方法上注解了@Transactional实现的事务控制,在抛出异常后也是能正常回滚的。
在Java中,断言就像是那个总是在后台默默支持你的好朋友,它在开发和测试阶段帮你检查那些逻辑错误。
但是,别忘了,它也是有脾气的,一旦到了生产环境,它就罢工了。所以,记得在需要的时候启用它,不需要的时候,就让它好好休息。
assert condition : "This is an error message.";
断言的特点:
使用断言的注意事项:
断言是Java语言的一个特性,它的使用应该谨慎,主要限于开发和测试阶段,以确保生产环境中的程序性能和稳定性。
我们借鉴断言这种设计思想,针对业务异常进一步封装,形成 “业务断言”,主要目标只有一个:
管理我们对代码的期望。
先定义一个业务断言工具类BizAssert:
/** * 业务断言类,断言不通过将抛出ServiceException */@UtilityClasspublic class BizAssert { public <T> T notNull(T dontNull) { if (dontNull == null) { throw new ServiceException("this object must not be null"); } return dontNull; } public void notBlank(String dontBlank) { if (dontBlank == null || dontBlank.length() == 0) { throw new ServiceException("this string must not be null or blank"); } } public <E, T extends Iterable<E>> T notEmpty(T dontEmpty) { if (dontEmpty == null || !dontEmpty.iterator().hasNext()) { throw new ServiceException("this collection must not be null or empty"); } return dontEmpty; } public <T> T isOk(IR r) { if (r == null || !r.isOk()) { throw new ServiceException(r == null ? "this result must not be null" : r.getMsg()); } return r.getData(); } public <T> T notNull(IR r) { if (r == null || !r.isOk() || r.getData() == null) { throw new ServiceException(r == null ? "this result must not be null" : r.getMsg()); } return r.getData(); }}
使用业务断言:
// 从数据库中查询出用户User user = UserQuery.builder().id(userId).build().getOne();// 业务断言,我希望查出来的用户不能为null,否则后续业务会报错BizAssert.notNull(user);// 其他针对user的业务处理逻辑Map<String, String> data = new HashMap<>();data.put("girl-friend", user.getName());
Gitee源码地址:
https://gitee.com/jensvn/d3boot(例行赊Star)
D3boot基础框架具体的使用方式见源码的README.md文件,这里不再赘述。
能写一行代码的事,绝不写3行5行,适度封装,让代码更优雅!
本文链接:http://www.28at.com/showinfo-26-85874-0.html一种避免大量If-else代码的新思路
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com