Spring MVC 统一异常处理

关闭系统级别的 detectAllHandlerExceptionResolvers = false 不加载默认的那三个异常处理器

org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.DefaultHandlerExceptionResolver

<servlet>
    <servlet-name>sample</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/conf/spring-sample.xml</param-value>
    </init-param>
    <init-param>
        <param-name>detectAllHandlerExceptionResolvers</param-name>
        <param-value>false</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

添加异常处理BEAN bean handlerExceptionResolver 在Spring的配置文件中添加下面的Bean

<bean id="handlerExceptionResolver" class="....UnifyExceptionHandlerExceptionResolver"/>

创建自己的全局异常处理BEAN 继承自ExceptionHandlerExceptionResolver

支持默认的 @ExceptionHandler @ControlAdvise

import java.lang.reflect.Field;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

/**
 * 异常的统一处理  返回错误页面或者JSON
 * @author zln
 *
 */
public class UnifyExceptionHandlerExceptionResolver extends ExceptionHandlerExceptionResolver{
    @SuppressWarnings("unused")
    private Logger logger = LoggerFactory.getLogger( this.getClass() );
    
    @Resource RequestMappingHandlerAdapter requestMappingHandlerAdapter;
    
    @Override
    public void afterPropertiesSet() {
        //设置消息转换器 以及内容协商管理器
        Field cnm = ReflectionUtils.findField(RequestMappingHandlerAdapter.class, "contentNegotiationManager");
        cnm.setAccessible(true);
        setContentNegotiationManager( (ContentNegotiationManager) ReflectionUtils.getField(cnm, requestMappingHandlerAdapter) );
        setMessageConverters( requestMappingHandlerAdapter.getMessageConverters() );
        
        super.afterPropertiesSet();
    }
    
    /**
     * 重写 {@code doResolveHandlerMethodException} 以便支持 @ExceptionHandler
     */
    @Override
    protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, HttpServletResponse response, 
            HandlerMethod handlerMethod,
            Exception exception) {
        ModelAndView mv = null;
        
        mv =  super.doResolveHandlerMethodException(request, response, handlerMethod, exception);
        if( null != mv ){
            return mv;
        }
        
        if( null != handlerMethod.getMethodAnnotation(ResponseBody.class) ){
            mv = doResolveResponseBodyHandlerMehtod(request, response, handlerMethod, exception);
            
            if( null != mv ){
                return mv;
            }
        }
        
        return doFallbackResolveHandlerMethodException( request, response, handlerMethod, exception );
    }
    
    protected ModelAndView doFallbackResolveHandlerMethodException( HttpServletRequest request, HttpServletResponse response,
            HandlerMethod handlerMethod,
            Exception exception ){
        
        ModelAndView oops = new ModelAndView();
        oops.setViewName("oops");
        
        return oops;
    }
    
    protected ModelAndView doResolveResponseBodyHandlerMehtod(HttpServletRequest request, HttpServletResponse response, 
            HandlerMethod handlerMethod,
            Exception exception) {
        try {
            ModelAndViewContainer mavContainer = new ModelAndViewContainer();
            ServletWebRequest webRequest = new ServletWebRequest(request, response);
            
            String wsResult = null;

            this.getReturnValueHandlers().handleReturnValue(wsResult, handlerMethod.getReturnValueType(wsResult), 
                    mavContainer,
                    webRequest);

            if (mavContainer.isRequestHandled()) {
                return new ModelAndView();
            } else {
/*              ModelAndView mav = new ModelAndView().addAllObjects(mavContainer.getModel());
                mav.setViewName(mavContainer.getViewName());
                if (!mavContainer.isViewReference()) {
                    mav.setView((View) mavContainer.getView());
                }
                return mav;*/
                return null;
            }
        } catch (Exception e) {
            return null;
        }
    }
    
posted @ 2017-07-19 17:17  -风筝-  阅读(1492)  评论(0编辑  收藏  举报