使用Spring中的ExceptionHandlerExceptionResolver进行统一的异常

1。 编写相关AnnotationHandlerMethodExceptionResolver异常处理类

package com.pss.res.base.exceptionresolver;  
  
import com.pss.res.client.base.constants.BusiStatusCons;  
import com.pss.res.client.base.domain.ServiceResponse;  
import com.pss.res.common.util.DateHelper;  
import org.springframework.core.annotation.AnnotationUtils;  
import org.springframework.http.HttpInputMessage;  
import org.springframework.http.HttpOutputMessage;  
import org.springframework.http.HttpStatus;  
import org.springframework.http.MediaType;  
import org.springframework.http.converter.HttpMessageConverter;  
import org.springframework.http.server.ServletServerHttpRequest;  
import org.springframework.http.server.ServletServerHttpResponse;  
import org.springframework.util.StringUtils;  
import org.springframework.web.bind.annotation.ResponseBody;  
import org.springframework.web.bind.annotation.ResponseStatus;  
import org.springframework.web.method.HandlerMethod;  
import org.springframework.web.servlet.ModelAndView;  
import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver;  
  
import javax.servlet.ServletException;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import java.io.IOException;  
import java.lang.reflect.Method;  
import java.util.Collections;  
import java.util.List;  
import java.util.Map;  
  
/** 
 * 不必在Controller中对异常进行处理,抛出即可,由此异常解析器统一控制。<br> 
 * ajax请求(有@ResponseBody的Controller)发生错误,输出JSON。<br> 
 * 页面请求(无@ResponseBody的Controller)发生错误,输出错误页面。<br> 
 * 需要与AnnotationMethodHandlerAdapter使用同一个messageConverters<br> 
 * Controller中需要有专门处理异常的方法。 
 * 
 * 
 * */  
public class AnnotationHandlerMethodExceptionResolver extends ExceptionHandlerExceptionResolver {  
  
    private String defaultErrorView;  
  
    public String getDefaultErrorView() {  
        return defaultErrorView;  
    }  
  
    public void setDefaultErrorView(String defaultErrorView) {  
        this.defaultErrorView = defaultErrorView;  
    }  
  
    protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod, Exception exception) {  
  
        if (handlerMethod == null) {  
            return null;  
        }  
  
        Method method = handlerMethod.getMethod();  
  
        if (method == null) {  
            return null;  
        }  
        //如果定义了ExceptionHandler则返回相应的Map中的数据  
        ModelAndView returnValue = super.doResolveHandlerMethodException(request, response, handlerMethod, exception);  
        ResponseBody responseBodyAnn = AnnotationUtils.findAnnotation(method, ResponseBody.class);  
        if (responseBodyAnn != null) {  
            try {  
                ResponseStatus responseStatusAnn = AnnotationUtils.findAnnotation(method, ResponseStatus.class);  
                if (responseStatusAnn != null) {  
                    HttpStatus responseStatus = responseStatusAnn.value();  
                    String reason = responseStatusAnn.reason();  
                    if (!StringUtils.hasText(reason)) {  
                        response.setStatus(responseStatus.value());  
                    } else {  
                        try {  
                            response.sendError(responseStatus.value(), reason);  
                        } catch (IOException e) { }  
                    }  
                }  
                // 如果没有ExceptionHandler注解那么returnValue就为空  
                if (returnValue == null) {  
                    ServiceResponse res = new ServiceResponse();  
                    res.setResultCode(BusiStatusCons.STATUS_FAILURE);  
                    res.setResultDesc("系统异常:" + exception.getLocalizedMessage());  
                    res.setTimestamp(DateHelper.getCurrentTimeStamp(null));  
                    handleResponseError(res, request, response);  
                    return new ModelAndView();  
                }  
                return handleResponseBody(returnValue, request, response);  
            } catch (Exception e) {  
                return null;  
            }  
        }  
  
        if( null == returnValue) {  
            returnValue = new ModelAndView();  
            if (null == returnValue.getViewName()) {  
                returnValue.setViewName(defaultErrorView);  
            }  
        }  
        return returnValue;  
    }  
  
  
    @SuppressWarnings({ "unchecked", "rawtypes" })  
    private ModelAndView handleResponseBody(ModelAndView returnValue, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
        Map value = returnValue.getModelMap();  
        HttpInputMessage inputMessage = new ServletServerHttpRequest(request);  
        List<MediaType> acceptedMediaTypes = inputMessage.getHeaders().getAccept();  
        if (acceptedMediaTypes.isEmpty()) {  
            acceptedMediaTypes = Collections.singletonList(MediaType.ALL);  
        }  
        MediaType.sortByQualityValue(acceptedMediaTypes);  
        HttpOutputMessage outputMessage = new ServletServerHttpResponse(response);  
        Class<?> returnValueType = value.getClass();  
        List<HttpMessageConverter<?>> messageConverters = super.getMessageConverters();  
        if (messageConverters != null) {  
            for (MediaType acceptedMediaType : acceptedMediaTypes) {  
                for (HttpMessageConverter messageConverter : messageConverters) {  
                    if (messageConverter.canWrite(returnValueType, acceptedMediaType)) {  
                        messageConverter.write(value, acceptedMediaType, outputMessage);  
                        return new ModelAndView();  
                    }  
                }  
            }  
        }  
        if (logger.isWarnEnabled()) {  
            logger.warn("Could not find HttpMessageConverter that supports return type [" + returnValueType + "] and " + acceptedMediaTypes);  
        }  
        return null;  
    }  
    @SuppressWarnings({ "unchecked", "rawtypes" })  
    private ModelAndView handleResponseError(ServiceResponse returnValue, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
        HttpInputMessage inputMessage = new ServletServerHttpRequest(request);  
        List<MediaType> acceptedMediaTypes = inputMessage.getHeaders().getAccept();  
        if (acceptedMediaTypes.isEmpty()) {  
            acceptedMediaTypes = Collections.singletonList(MediaType.ALL);  
        }  
        MediaType.sortByQualityValue(acceptedMediaTypes);  
        HttpOutputMessage outputMessage = new ServletServerHttpResponse(response);  
        Class<?> returnValueType = returnValue.getClass();  
        List<HttpMessageConverter<?>> messageConverters = super.getMessageConverters();  
        if (messageConverters != null) {  
            for (MediaType acceptedMediaType : acceptedMediaTypes) {  
                for (HttpMessageConverter messageConverter : messageConverters) {  
                    if (messageConverter.canWrite(returnValueType, acceptedMediaType)) {  
                        messageConverter.write(returnValue, acceptedMediaType, outputMessage);  
                        return new ModelAndView();  
                    }  
                }  
            }  
        }  
        if (logger.isWarnEnabled()) {  
            logger.warn("Could not find HttpMessageConverter that supports return type [" + returnValueType + "] and " + acceptedMediaTypes);  
        }  
        return null;  
    }  
  
}

其中以下的代码,需要根据具体情况进行改变。

// 如果没有ExceptionHandler注解那么returnValue就为空  
if (returnValue == null) {  
    ServiceResponse res = new ServiceResponse();  
    res.setResultCode(BusiStatusCons.STATUS_FAILURE);  
    res.setResultDesc("系统异常:" + exception.getLocalizedMessage());  
    res.setTimestamp(DateHelper.getCurrentTimeStamp(null));  
    handleResponseError(res, request, response);  
    return new ModelAndView();  
}

2。 xml配置文件中,需要进行的相关配置操作,如下:

<bean id="handlerExceptionResolver" class="com.pss.res.base.exceptionresolver.AnnotationHandlerMethodExceptionResolver">  
    <property name="defaultErrorView" value="error/500"/> <!--错误页面-->  
    <property name="messageConverters">  
        <list>  
            <bean    class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />  
            <!-- JSON转换器无需设置mediaType,由外部客户端调用时,手动设置相关mediaType -->  
            <bean    class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />  
        </list>  
    </property>  
</bean>

3。 测试类中,只要controller中有异常抛出,即会被捕获,并显示在浏览器中。

@Controller  
@RequestMapping("/exeHandler")  
public class ExeHandlerController {  
  
      
    @RequestMapping(value="/test")  
    public @ResponseBody Object getAllIndusType(IndusTypeReqVO indusTypeReqVO) throws Exception{  
          
        System.err.println("cccccc");  
        throw new Exception("这边出错了。");  
//      return null;  
    }  
      
}



你可能感兴趣的:(使用Spring中的ExceptionHandlerExceptionResolver进行统一的异常)