这样搞——保证你的代码没有try-catch
来源:互联网 发布:淘宝双11营销策略分析 编辑:程序博客网 时间:2024/06/07 05:30
常常听到有技术圈的朋友抱怨,尤其是从其他语言转到Java语言的同行,说Java的try-catch语言让代码显得很凌乱。的确,作为一个Java Follower,笔者也觉得Java中的try-catch会导致代码很不整齐,易读性变差。那么有什么好办法让Java工程中尽量不出现try-catch语法块呢?办法还真有,请听我娓娓道来!
首先,笔者带领大家回顾一下Java的异常处理机制。如下图,Java中有个类叫做Throwable。该Throwable类有两个子类,一个是Error,一个是Exception。Error代表JVM系统级别的错误,通常是程序员不可控的,因此不需要程序员过多的关注。因此,在Java中提起异常时,通常指的是Exception类及其子类。
从上图中也可以看出,Exception类的子类分为RuntimeException类和其他子类。这是需要我们重点关注的。其中RuntimeException类是unchecked异常类(是指那些不需要try-catch捕获或者显式抛出的异常类),而Exception类的其他子类是checked异常类(指代那些需要try-catch捕获或者显示抛出的类)。因此,我们的程序中之所以有太多try-catch代码块的原因,就在于我们抛出了太多的checked异常类。
因此,笔者觉得有一种方案可以考虑,我们是否可以将一个软件系统中的所有自定义异常类都定义为RuntimeException类的子类,比如可以叫做SystemException和LogicException。SystemException的子类代表是真的系统运行时错误引起的异常,而LogicException的子类代表那些并非是系统运行时错误引起的异常,比如“用户不存在”这种逻辑异常。
这样在我们的软件系统中,所有的异常都是RuntimeException。即便有些方法会抛出checked异常,我们可以在他的try-catch中二次抛出一个自定义的SystemException或者LogicException。通过这样的方式,我们的系统中就基本上不需要感知异常的处理模块了。
但毕竟异常处理是一个系统健壮性必不可少的一部分。那么我们怎么来处理我们自定义的SystemException和LogicException呢?相比熟练使用Spring框架的童鞋一定知道SpringMVC中有这样一个类:HandlerExceptionResolver。这个类的作用是捕获Spring在运行过程中的所有异常。网上关于这个类的介绍有很多,在此不再赘述。
本来我们写一个HandlerExceptionResolver的实现类,然后在Spring的配置文件中声明该bean即可。但是为了实现可插拔的设计,使用同博客玩转Spring——从拒绝filter开始相同的方式。我们来看代码:
public class DefaultExceptionHandler implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { if (e instanceof BusinessException) { System.out.println("this is a businessException"); BusinessException businessException = (BusinessException) e; putErrorEnumToResponse(businessException.getErrorEnum(), httpServletResponse); } else if (e instanceof SystemException) { System.out.println("this is a businessException"); SystemException systemException = (SystemException) e; putErrorEnumToResponse(systemException.getErrorEnum(), httpServletResponse); } else { System.out.println("this is a unknownException"); putErrorEnumToResponse(ErrorEnum.UNKNOWN_EXCEPTION, httpServletResponse); } return null; } private static void putErrorEnumToResponse(ErrorEnum errorEnum, HttpServletResponse response) { response.setContentType("application/json;charset=utf-8"); response.addHeader("Content-Length", String.valueOf(errorEnum.toString().length())); String result= JSON.toJSONString(HttpResult.failedResult(errorEnum)); try { ServletOutputStream servletOutputStream = response.getOutputStream(); servletOutputStream.print(result); servletOutputStream.flush(); } catch (IOException e) { System.out.println("put error msg to response exception"); e.printStackTrace(); } }}其中的ErrorEnum是一个枚举,它定义了系统中所有出现的异常信息。
瞧,仅仅上面 一个类,就解决了整个Web系统中的异常处理。业务Developer仅仅需要在异常发生的地方判断该异常是属于SystemException还是BusinessException,然后定义一个说明该Exception的ErrorEnum作为SystemException或者BusinessException的参数,然后直接使用throw语句抛出即可。由于SystemException和BusinessException都是RuntimeException的子类,因此他们不再需要使用try-catch捕获或者显示在方法定义中声明,十分方便。而且HandlerExceptionResolver为我们提供了统一的异常处理入口,可以让我们方便快捷,轻松愉快的完成整个异常系统的处理任务。下面是一个业务代码使用异常的例子:
@Service("userService")public class UserServiceImpl implements IUserService { @Resource(name = "userDao") private UserDao userDao; @Override public HttpResult<UserDTO> getUserByAccount(String account) { UserDO userDO = userDao.getUserByAccount(account); if (userDO == null) { throw new BusinessException(ErrorEnum.USER_NOT_EXIST); } UserDTO userDTO = UserConvent.conventToUserDTO(userDO); return HttpResult.successResult(userDTO); }}
上面是UserController对应的逻辑层的Service类,当用户不存在时,Service层直接抛出逻辑异常,这个异常会被DefaultExceptionHandler捕获,而UserController完全不需要感知该异常的存在。在来看一个Controller层抛出异常的例子:@Controller@RequestMapping(value = CommonUrl.UrlConstant.TEST_PREFIX)public class TestExceptionController { @RequestMapping(value = CommonUrl.UrlConstant.TEST_CONTROLLER_EXCEPTION, produces = CommonUtils.CONTENT_TYPE) @ResponseBody public String getUserByAccount(HttpServletRequest request, HttpServletResponse response) { return CommonExecutor.execute(request, response, BaseParam.class, new CommonExecute() { @Override public HttpResult execute(BaseParam param) { throw new SystemException(ErrorEnum.UNKNOWN_EXCEPTION); } }); }}可见,通过这样的方式解决系统中的异常处理还是很好的。
觉得本文好的话,别忘了关注我哦。
代码参见本人的github。点击打开链接
1 0
- 这样搞——保证你的代码没有try-catch
- try catch finally 中有多个return时,代码是这样执行的
- 如何编写没有Try/Catch的程序
- try finally没有catch的用法
- try——catch
- java try没有catch
- 【恶搞】如何在Unity正确的使用try-catch
- try—catch—finally的使用
- java—try、catch、finally的使用
- 在try—catch的点点滴滴
- 几分钟让你彻底搞懂 c#之using和try-catch-finaly的区别和联系
- 我是那么的喜欢你 try catch
- Try-Catch你真的很懂吗?
- try catch测试代码
- java中try—catch
- 记录一个try catch没有生效的原因,以便备忘
- 保证都是你没有体验过的
- Java的容错机制——try—catch机制
- git
- 关于hibernate如何把原生sql查出的结果转化为对象
- 第15周OJ实践2 字符串分段
- 安卓CVB模式
- android:windowSoftInputMode属性
- 这样搞——保证你的代码没有try-catch
- 容器
- 一个经典例子让你彻彻底底理解java回调机制(转)
- Eclipse自动编译问题
- 《Thinking in Java》笔记
- 51Nod 1354 选数字
- 哈尔滨理工大学第六届程序设计团队赛—C
- SIP SDP Profile-level-id解析
- UnityC#注册C++Dll事件回调