springmvc系列之 ------------- 統一異常處理和響應處理

首先是異常的分類

 

1、統一的控制器異常處理器

首先,在web項目中的異常處理的原則是:

@ControllerAdvice
public class ControllerExceptionHandler<T> {

	@ExceptionHandler(Exception.class)
	@ResponseBody
	@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
	public Response<? extends Object> handleControllerException(Exception e) {
		Response<Object> response = new Response<>();
		response.setCode("500");
		response.setMessage(e.getMessage());
		return response;
	}
}

這是統一處理controller拋出的異常的地方,但是,當該類存在的時候,異常是不會傳遞到interceptor中的afterCompletion()方法中的,也就是afterCompletion()方法中的ex會爲空。

因爲異常處理類的執行是在interceptor類中的afterCompletion()方法之前的。

2、統一的響應處理

統一的響應處理是通過filter來實現的,我試過通過interceptor和advice這樣的方式來實現,但是都沒有達成目的。以下是實現,實現是通過spring提供的ContentCachingRequestWrapper和ContentCachingResponseWrapper來完成的。

在次過程中踩過兩個坑:

1、設置處理以後的響應數據不能成功

2、返回的數據沒有content-type設置

第一個問題:

是通過respWrapper.reset()和respWrapper.copyBodyToResponse()來實現將response清空和刷新寫入的數據,在使用ContentCachingXXXXXWrapper的時候,一定要使用copyBodyToResponse()來刷新response,否則返回的body中會是空的。

第二個問題:

需要設置response的content-type爲application/json;charset=UTF-8,但是該設置一定要是在copyBodyToResponse()之前。

所以,總結以上兩個問題,copyBodyToResponse()方法一定是在所有操作的最後。

@Configuration
public class ControllerResponseHandler implements Filter {

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper((HttpServletRequest) request);
		ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(
				(HttpServletResponse) response);

		chain.doFilter(requestWrapper, responseWrapper);

        // 通過判斷URL中是否有v1來判斷該訪問是否是到達controller的,因爲我在controller的地址上都加了一個v1
		if (reqWrapper.getRequestURI().contains("v1/")) {
			wrapResponse(respWrapper);
			respWrapper.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
		}
		respWrapper.copyBodyToResponse();
	}

	private void wrapResponse(ContentCachingResponseWrapper response) throws IOException {
		// 判斷響應的類型是否是json或是否是正常的,如果是錯誤響應,那麼不需要通過該類進行響應處理,而是通過統一的異常處理類來處理
		if (MediaType.APPLICATION_JSON_UTF8_VALUE.equals(response.getContentType()) && response.getStatus() < 300) {
			byte[] b = response.getContentAsByteArray();
			// 重置response中的body
			response.reset();
			Response<Object> result = new Response<>();
			if (b.length == 0) {
				result.setCode(ResponseStatus.NO_RESOURCE.getCode());
				result.setMessage(ResponseStatus.NO_RESOURCE.getMessage());
			} else {
				result.setCode(ResponseStatus.SUCESS.getCode());
				result.setMessage(ResponseStatus.SUCESS.getMessage());
			}
			result.setData(JSON.parse(b));
			// 通過response的outputStream寫入新的數據
			ServletOutputStream outputStream = response.getOutputStream();
			outputStream.write(JSON.toJSONBytes(result));
		}
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章