资料来源于:http://blog.csdn.net/m13321169565/article/details/7641978
在使用web开发和API 开发都使用到异常的处理,web 异常后跳到指定的错误页面,那么API或AJAX调用需要返回JSON的错误信息,所以我们需要一个统一的异常处理机制来管理这些异常!
1.定义自己的异常处理类
import java.io.IOException; import java.lang.reflect.Method; import java.util.Collections; import java.util.List; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; 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; /** * 不必在Controller中对异常进行处理,抛出即可,由此异常解析器统一控制。<br> * ajax请求(有@ResponseBody的Controller)发生错误,输出JSON。<br> * 页面请求(无@ResponseBody的Controller)发生错误,输出错误页面。<br> * 需要与AnnotationMethodHandlerAdapter使用同一个messageConverters<br> * Controller中需要有专门处理异常的方法。 * * @author dongjian * * */ 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; } 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) { } } } return handleResponseBody(returnValue, request, response); } catch (Exception e) { return null; } } if(returnValue.getViewName() == null){ returnValue.setViewName(defaultErrorView); } return returnValue; } /** * 异常后 返回json * @param returnValue * @param request * @param response * @return * @throws ServletException * @throws IOException */ @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; } }
2.在spring MVC 配置中添加如下配置
<!-- ResponseBody 的类型 --> <bean id="messageConverters" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>application/json;charset=UTF-8</value> </list> </property> </bean> <bean id="handlerAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="cacheSeconds" value="0" /> <property name="messageConverters" ref="messageConverters" /> </bean> <!-- 设置自定义异常处理 --> <bean id="handlerExceptionResolver" class="com.chengkun.base.exception.AnnotationHandlerMethodExceptionResolver"> <property name="defaultErrorView" value="error.jsp"/><!-- 错误页面 --> <property name="messageConverters" ref="messageConverters"/> <!--JSON 处理的messageConverters-> </bean>
3.修改web.xml 禁止自动注册,让其使用我们自定义的类
<servlet> <servlet-name>spring-mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-mvc.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>
4.在BaseController 中加入异常控制,所有controller必须继承BaseController
/** * 异常控制,可以根据不同的异常类型 在此定义不同的错误消息和操作 * */ @ExceptionHandler(Exception.class) @ResponseStatus(value=HttpStatus.INTERNAL_SERVER_ERROR) public ModelAndView handleException(Exception ex, HttpServletRequest request) { return new ModelAndView().addObject(new ResultPojo(500)); }
扫描二维码关注公众号,回复:
498536 查看本文章