Spring-Web项目中的异常处理

来源:互联网 发布:unity3d加速器 编辑:程序博客网 时间:2024/05/02 02:44

前言

异常体系在任何计算机语言中都有着重要的分量,但是对于普通开发者来说总是存在着多多少少的疑问:什么时候使用异常?什么时候要对异常进行统一处理?该如何对异常进行统一处理?

这里,我将把我们后台系统的异常处理机制的演变过程进行阐释。

分散式处理

大家都知道,在spring-mvc中事务是要切在service层的,也就是当service层抛出异常时,进行数据库操作的回滚。其实也就是说,这一层我们不要去自己捕获异常,异常都由事务机制去拦截和处理,service层有异常只需要抛出即可。

那么捕获异常和处理异常的操作,很自然的就落到了controller层中,所以对于常见的,也就是分散式的处理方式,一般来说异常处理的代码是这个样子的:

//以下仅为示例代码public class UserController{    @RequestMapping("/updateUserInfo")    public @ResponseBody String updateUserInfo(UserInfo ui){        try{            userService.updateUserInfo(ui)        }catch(Exception e){            return "更新失败";        }        return "更新成功";    }}

这样实现的好处就是:很多人写的异常各自维护,不会相互影响,你改你的,我改我的。缺点也比较明显:就是很多的try…catch。

这时候,我们很自然的会想到统一处理,如果能够对异常进行统一处理,那么,在controller层就可以仅仅处理业务逻辑,不用写不必要的try…catch块了。

集中式处理

集中式处理异常有两种方式:一种是使用aop机制,给所有的controller层方面插入处理代码;另一种是使用spring提供的异常处理器机制。这里的第二种,更好一些,因为在实战中经常会遇到参数类型转换错误的异常,这是spring级别的异常,使用方法级别的aop机制不能捕获这些异常。以下说明spring的ExceptionResolver使用方法:

定义ExceptionResolver:

public class ExceptionResolver extends SimpleMappingExceptionResolver {    public ModelAndView resolveException(HttpServletRequest request,            HttpServletResponse response, Object handler, Exception ex) {        try {            Map<String,Object> result = new HashMap<String,Object>();            result.put("code", 1);            //有时候我们不希望直接把后台异常直接展示给用户            result.put("data", "请求处理错误");            JSONObject jo = JSONObject.fromObject(result);            //此行必加,否则返回的json在浏览器中看到是乱码,不易于识别            response.setHeader("Content-Type","text/html;charset=UTF-8");            response.getWriter().write(jo.toString());            response.getWriter().close();        } catch (Exception e) {        }        return null;    }   }

spring的配置文件中添加如下配置项:

    <!-- 异常处理,返回json结果 -->    <bean id="exceptionResolver" class="你的ExceptionResolver类"></bean>

定义好以后,controller层中所有的try…catch就可以去掉了。是不是很好呢?

在实际中遇到复杂的业务逻辑时,也就是service层方法代码逻辑很复杂时,比如:下单、支付、领取优惠券等,根据不同的情况,需要给前端返回不同的错误信息,这个时候一种做法就是返回枚举值,在controller层去识别并返回具体错误信息,另外一种就是直接throw一个异常。

其实,我们只能用第二种方法,因为错误时,我们很可能需要让事务机制起效,想着让已经操作的一部分结果回滚,所以只能选择第二种方式来将错误信息放在异常的Message里面抛出。

这时候,我们就遇到了另外一个问题,spring级别的异常我们不想把message直接抛给前端,我们自己的异常又要把message抛给前端,这时候怎么办呢?

集中-分散式

遇到以上的情况,可以有一种方法处理。就是自定义异常,当controller层遇到自定义异常时,把异常信息返给前端。

也就是对于上述说到的复杂逻辑业务,在controller层仍然保留try…catch块,捕获自定义的异常。

那么,有没有,完全集中式的处理方案呢,其实,再前进一步就可以了。

改进型集中式处理

仍然需要自定义异常,当我们的逻辑要抛出逻辑层面的异常时,创建并抛出自定义的异常,然后在ExceptionResolver里对自定义异常进行差异化处理:

定义ExceptionResolver:

public class ExceptionResolver extends SimpleMappingExceptionResolver {    public ModelAndView resolveException(HttpServletRequest request,            HttpServletResponse response, Object handler, Exception ex) {        try {            Map<String,Object> result = new HashMap<String,Object>();            result.put("code", 1);            if(ex instanceof MyException){                result.put("data", "异常:"+ex.getMessage());            }else{                result.put("data", "请求处理错误");            }            JSONObject jo = JSONObject.fromObject(result);            //此行必加,否则返回的json在浏览器中看到是乱码,不易于识别            response.setHeader("Content-Type","text/html;charset=UTF-8");            response.getWriter().write(jo.toString());            response.getWriter().close();        } catch (Exception e) {            //e.printStackTrace();        }        return null;    }   }
0 0
原创粉丝点击