用了@ResponseBody後,用攔截器設置cookies或header失效

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable ModelAndView modelAndView) throws Exception {
	response.setHeader("Content-Type", "text/json;charset=UTF-8");
	CMessage cmsg = CMessage.getInstance(request, response);
	cmsg.setTimes(getTimes());
	response.setHeader("CMessage", cmsg.toString());
}

原本是想經過 攔截器 統一處理,給reponse設置一個自定義的Header。 後來發現一直沒有生效。瀏覽器里老是看不到自定義的header信息。 後來發現 沒有用到spring @ResponseBody這個註解的方法就有。java

跟了一下源碼 web

@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType,
            ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
            throws IOException, HttpMediaTypeNotAcceptableException,HttpMessageNotWritableException{

        mavContainer.setRequestHandled(true);
        ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
        ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);

        // Try even with null return value. ResponseBodyAdvice could get involved.
        writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}

在用到@ResponseBody這個玩意的時候,它把 response 和 request都作了一下處理。並在這裏調用write方法 。 spring

public void write(Object t, Type type, MediaType contentType, HttpOutputMessage outputMessage 
    ) throws IOException, HttpMessageNotWritableException {

        HttpHeaders headers = outputMessage.getHeaders();
        if (headers.getContentType() == null) {
            if (contentType == null || contentType.isWildcardType() || contentType.isWildcardSubtype()) {
                contentType = getDefaultContentType(t);
            }
            if (contentType != null) {
                headers.setContentType(contentType);
            }
        }
        if (headers.getContentLength() == -1) {
            Long contentLength = getContentLength(t, headers.getContentType());
            if (contentLength != null) {
                headers.setContentLength(contentLength);
            }
        }
        writeInternal(t, outputMessage);
        outputMessage.getBody().flush();
    }

在這裏 它已經給你寫出去了。並flush了。 因此致使了在postHandler裏的攔截無效了json

個人作法是 寫個類實現 ResponseBodyAdvice。 這個裏面有個 beforeBodyWrite方法 。 它先於write執行。  在這個裏面 不少人都是用它來處理 body。由於這個方法的參數 只有它本身的ServerHttpRequest request, ServerHttpResponse response。 沒有提供設置 cookies 或者 header的方法。瀏覽器

ServerHttpResponse 裏面沒有。 但它的實現類ServletServerHttpResponse 這個裏面有HttpServletResponse 。因而就有了下面這個代碼:cookie

public SMessage beforeBodyWrite(SMessage body, MethodParameter returnType, MediaType selectedContentType,Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request,ServerHttpResponse response) {
		
		HttpServletRequest req = ((ServletServerHttpRequest) request).getServletRequest();
		
		HttpServletResponse res = ((ServletServerHttpResponse) response).getServletResponse();
		
		res.setHeader("Content-Type", "text/json;charset=UTF-8");
		try {
			
			CMessage cmsg = (CMessage)req.getAttribute("CMessage");
			cmsg.setTimes(getTimes());
			res.setHeader("CMessage", cmsg.toString());
		}catch (Exception e) {
			e.printStackTrace();
		}
		
		return body;
	}

這樣就解決了 上面說的問題了。ide

相關文章
相關標籤/搜索