编码技巧(二)多分支结构

在实际编程中,常常会遇到这样的情况,多个if语句嵌套使用,我曾见过最深的嵌套达4个,简直让人抓狂,通常代码可读性随着嵌套的层数增多而几何级数的降低。似我这等凡夫俗子,到4层几乎很难凭借肉眼看出代码的含义了。那么如何避免多if语句嵌套呢?看下面的例子。
在Spring MVC中,我们通常会定义我们的统一异常处理类,由它来捕获系统的异常。像下面这样

public class ExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {}
}

我们将在resolveException中写我们的异常处理逻辑

    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        if(ex instanceof NullPointerException){
            //do something
        }else if(ex instanceof IllegalArgumentException){
            //do something
        }else if(ex instanceof IllegalAccessException){
            //do something
        }
 }

上面这段代码看起来还好,判断下异常的类型,然后做出不同的处理。那么再复杂一些的情况呢?如果抛出IllegalArgumentException,那么我们判断是哪个请求抛出的,并记录用户信息,根据用户的行为(正常用户,恶意攻击)告诉他是参数的完整格式还是直接拒绝。通常情况下,我们是会抽象出一个方法来做这件事。那么有没有别的方法呢?看下面的代码

    private static Map<Class, ExceptionHandler> exceptionHandlerMap = Maps.newHashMap();
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        ExceptionHandler exceptionHandler = exceptionHandlerMap.get(ex.getClass());

        if (exceptionHandler == null) {
            exceptionHandler = exceptionHandlerMap.get(DEFAULT_HANDLER);
        }

        LogUtil.ERROR_LOGGER.error("request {} parameter is {} error", request.getRequestURL(), JsonUtil.writeAsString(request.getParameterMap()));
        exceptionHandler.handle(request, response, handler, ex);
        return null;
    }

    interface ExceptionHandler {
        void handle(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex);
    }

上面的代码抽象出一个ExceptionHandler接口,用于处理异常。而exceptionHandlerMap则持有ExceptionHandler的引用。当异常发生时,根据异常类型,从exceptionHandlerMap中取出对应的处理方法。exceptionHandlerMap的初始化如下

    private static final Class DEFAULT_HANDLER = null;
    static {
        //非法参数
        exceptionHandlerMap.put(IllegalArgumentException.class, new ExceptionHandler() {
            @Override
            public void handle(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //do something
            }
        });
        //非法访问
        exceptionHandlerMap.put(IllegalAccessException.class, new ExceptionHandler() {
            @Override
            public void handle(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //do something
            }
        });
        //null point exception
        exceptionHandlerMap.put(NullPointerException.class, new ExceptionHandler() {
            @Override
            public void handle(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //do something
            }
        });
        //exception
        exceptionHandlerMap.put(Exception.class, new ExceptionHandler() {
            @Override
            public void handle(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //do something
            }
        });
        //默认handler
        exceptionHandlerMap.put(DEFAULT_HANDLER, new ExceptionHandler() {
            @Override
            public void handle(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        //do something
            }
        });
    }

故事到这里就结束了。当然,上面的case其实还有优化的空间,作为一个懒人,你让我写这么多的初始化语句干啥?最好是我实现一个ExceptionHandle你就给我自动注册到Map里就好了。那么怎么实现呢?我想到两种方式,1.spring自动注入; 2.enum。具体方法就不说了,推荐使用enum,不需要与spring集成,且java语言保证了单例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值