自定义异常处理 HandlerExceptionResolver

需求:

    需要将项目里自定义的拦截器中抛出的错误信息按照一定的规则返回到不同界面进行展示


分析:

   自定义的拦截器属于HandlerInterceptor组件,用于拦截HandlerAdapter调用Handler(Controller类对象、方法对象)的过程。因为DispatcherServlet会处理此过程中产生的异常,所以可以通过扩展spring的HandlerExceptionResolver来满足需求。


DispatcherServlet.java部分源代码:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
				processedRequest = checkMultipart(request);
				multipartRequestParsed = processedRequest != request;
				mappedHandler = getHandler(processedRequest, false);
				if (mappedHandler == null || mappedHandler.getHandler() == null) {
					noHandlerFound(processedRequest, response);
					return;
				}
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (logger.isDebugEnabled()) {
						String requestUri = urlPathHelper.getRequestUri(request);
						logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				try {
					 // 调用HandlerAdapter实例的handle方法
                                        //如果自定义的HandlerInterceptorAdapter中报错,则此方法也会报错,错误统一在下面的processDispatchResult方法中处理					
                                        mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
				}
				finally {
					if (asyncManager.isConcurrentHandlingStarted()) {
						return;
					}
				}

				applyDefaultViewName(request, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
                        //处理结果
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		....此处省略
	}


处理正常返回的ModelAndView或者将异常被解析到ModelAndView中去

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
        boolean errorView = false;
        if (exception != null) {
            if (exception instanceof ModelAndViewDefiningException) { 
                //处理ModelAndViewDefiningException异常
                logger.debug("ModelAndViewDefiningException encountered", exception);
                mv = ((ModelAndViewDefiningException) exception).getModelAndView();
            }else {
                Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null); 
                //在这里处理程序执行过程中抛出的异常,如拦截器抛出来的异常
                mv = processHandlerException(request, response, handler, exception);
                errorView = (mv != null);
            }
         }
        ....此处省略
    }


processHandlerException方法部分代码:

protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
			Object handler, Exception ex) throws Exception {

		// Check registered HandlerExceptionResolvers...
		ModelAndView exMv = null;
		for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
                         //在这里可通过扩展handlerExceptionResolver来进行自定义异常处理
			exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
			if (exMv != null) {
				break;
			}
		}
		......此处省略
	}


以下为扩展的示例:


public class TestHandlerExceptionResolver implements HandlerExceptionResolver {
    /** 普通日志 */
    private static final Logger LOGGER           = LoggerFactory
                                                     .getLogger(TestHandlerExceptionResolver.class);
    /** 默认错误展示页面 */
    private final String        defaultErrorPage = "error.vm";

  
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
                                         Object handler, Exception ex) {
  
        ModelAndView mv = new ModelAndView(defaultErrorPage);
        if (ex instanceof DuplicateFormSubmitException) {

            ExceptionUtil.caught(ex, "请求处理过程中表单重复提交");
            mv.getModel().put(MVCCommonConstant.VALUE_RETURN_STAT_FAIL, "请求处理过程中表单重复提交");

        } else if (ex instanceof AlipaySecurityException) {

            ExceptionUtil.caught(ex, "您无权访问此数据或功能!");
            mv.getModel().put(MVCCommonConstant.VALUE_RETURN_STAT_FAIL, "您无权访问此数据或功能!");

        } else if (ex instanceof InvalidUploadFileException) {

            ExceptionUtil.caught(ex, "文件上传失败");
            mv.getModel().put(MVCCommonConstant.VALUE_RETURN_STAT_FAIL,
                "请确认您的附件是否是xlsx,xls,txt格式," + "并且大小不能超过3M,否则不允许上传!");
        } else if (ex instanceof IcfmngFileDownloadException) {

            mv.getModel().put(MVCCommonConstant.VALUE_RETURN_STAT_FAIL, ex.getMessage());
        } else if (ex instanceof ReadFileException) {
            LOGGER.error("读取文件异常", ex);
            mv.getModel().put(MVCCommonConstant.VALUE_RETURN_STAT_FAIL, "读取文件异常。");
        } else {
            LOGGER.error("请求处理过程中发生异常!", ex);
            mv.getModel().put(MVCCommonConstant.VALUE_RETURN_STAT_FAIL, "系统发生未知异常,请联系工程师处理。");
        }

        return mv;
    }
}

通过扩展HandlerExceptionResolver的方式返回的页面会优先于web.xml中配置的错误界面。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值