springMVC 统一异常处理的一种方式

后端发生异常的时候,如果不处理,返回前段的会是printStackTrace()打出来的结果,会泄露我们服务器代码信息,可能会被利用攻击,所以需要一个统一的异常处理机制。

解决方案
@ExceptionHandler 和@ControllerAdvice 注解,在一个文件中处理所有异常类型,并接口返回固定格式。

@ControllerAdvice
 public class WebExceptionHandle {
@ExceptionHandler(DataAccessException.class)
@ResponseBody
ResultDTO handleSqlException(Exception e){
// 处理sql异常
    return  ResultDTO.faileResult(null,"sql failed");
}

@ExceptionHandler()
@ResponseBody
ResultDTO handleException(Exception e){
//默认异常处理
    return  ResultDTO.faileResult(null,"sql failed");
}

}

博文:https://blog.csdn.net/liujia120103/article/details/75126124 给出了这2个注解的解释,但没有说明具体如何能捕获异常并处理的,通过调试观察调用堆栈,发现是通过springMVC 的handlerExceptionResolvers.resolveException后调用的。这个处理过程应该是如下:

  • spring在启动过程通过注解@ExceptionHandler将 方法封装成bean并注入到handlerExceptionResolvers的集合中
  • 当controller执行完成后,执行processDispatchResult对结果进行处理
  • 调用processHandlerException 方法,遍历handlerExceptionResolvers,执行handlerExceptionResolver.resolveException方法。

springMVC过程

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {

    try {
        try {
            ModelAndView mv = null;
            Object dispatchException = null;
            try {
                processedRequest = this.checkMultipart(request);
                multipartRequestParsed = processedRequest != request;
                mappedHandler = this.getHandler(processedRequest);
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    this.noHandlerFound(processedRequest, response);
                    return;
                }
                HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                 ......
                  
             //  web的前置处理器
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }
            // 执行controller的对应方法
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }

                this.applyDefaultViewName(processedRequest, mv);
                // web的后置处理器
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            } catch (Exception var20) {
                dispatchException = var20;
            } catch (Throwable var21) {
                dispatchException = new NestedServletException("Handler dispatch failed", var21);
            }
          //处理controller的执行结果
            this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
        } catch (Exception var22) {
            this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
        } catch (Throwable var23) {
            this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
        }

    } finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            }
        } else if (multipartRequestParsed) {
            this.cleanupMultipart(processedRequest);
        }

    }
}

processDispatchResult 中执行processHandlerException方法

protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    ModelAndView exMv = null;
    Iterator var6 = this.handlerExceptionResolvers.iterator();
    while(var6.hasNext()) {
        HandlerExceptionResolver handlerExceptionResolver = (HandlerExceptionResolver)var6.next();
        exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
        if (exMv != null) {
            break;
        }
    }   
 if (exMv != null) {
        if (exMv.isEmpty()) {
            request.setAttribute(EXCEPTION_ATTRIBUTE, ex);
            return null;
        } else {
            if (!exMv.hasView()) {
                exMv.setViewName(this.getDefaultViewName(request));
            }

            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex);
            }

            WebUtils.exposeErrorRequestAttributes(request, ex, this.getServletName());
            return exMv;
        }
    } else {
        throw ex;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值