1. 程式人生 > >spring mvc 輸出 json 異常處理

spring mvc 輸出 json 異常處理

/**
 * 不必在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;
		
	}
	
	
	@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;
	}

}