這期內(nèi)容當(dāng)中小編將會給大家?guī)碛嘘P(guān)spring webmvc請求處理流程中返回值處理是什么,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價值的長期合作伙伴,公司提供的服務(wù)項目有:域名與空間、網(wǎng)絡(luò)空間、營銷軟件、網(wǎng)站建設(shè)、白堿灘網(wǎng)站維護(hù)、網(wǎng)站推廣。
講解3.2.x版本之后使用的RequestMappingHandlerAdapter,該類替換了AnnotationMethodHandlerAdapter。
自3.2之后的版本,引入了RequestMappingHandlerAdapter來替換了AnnotationMethodHandlerAdapter的處理。這里也來分析一下這個玩意兒。
因為也是一個HandlerAdapter,所以,前面的處理流程都是一樣的,servlet的getHandlerAdapter這個時候就返回了RequestMappingHandlerAdapter,而不是AnnotationMethodHandlerAdapter了。
拿到HandlerAdapter之后,我們就直接沖ha.handle()方法開始分析吧。
// RequestMAppingHandlerAdapter.java
protected final ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
//...做一些檢查
return invokeHandleMethod(request, response, handlerMethod);
}
private ModelAndView invokeHandleMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ServletWebRequest webRequest = new ServletWebRequest(request, response);
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
//拿取我們需要執(zhí)行的controller的方法
ServletInvocableHandlerMethod requestMappingMethod = createRequestMappingMethod(handlerMethod, binderFactory);
// 用于后面構(gòu)造mv的Container
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
modelFactory.initModel(webRequest, mavContainer, requestMappingMethod);
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
//...這一段是對異步請求的處理
//調(diào)用controller的方法,并處理mavContainer
requestMappingMethod.invokeAndHandle(webRequest, mavContainer);
if (asyncManager.isConcurrentHandlingStarted()) {
return null;
}
return getModelAndView(mavContainer, modelFactory, webRequest);
}
private ModelAndView getModelAndView(ModelAndViewContainer mavContainer,
ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception {
modelFactory.updateModel(webRequest, mavContainer);
//判斷,如果當(dāng)前請求已經(jīng)處理完成,則不進(jìn)行后續(xù)的處理沒直接返回null
if (mavContainer.isRequestHandled()) {
return null;
}
//如果請求還未處理完成,那說明可能有頁面需要返回,開始查找,處理并返回mav
ModelMap model = mavContainer.getModel();
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model);
if (!mavContainer.isViewReference()) {
mav.setView((View) mavContainer.getView());
}
if (model instanceof RedirectAttributes) {
Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes();
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
}
return mav;
}直接跟進(jìn)去。來到RequestMappingHAndlerAdapter的handleInternal()方法,不要驚慌,按照spring的一貫風(fēng)格,這TM當(dāng)然不是核心方法,他只是做了一些檢查。方法最后調(diào)用了invokeHandleMethod()。在該方法中,做了一些所需參數(shù)的獲取,比如請求的controller層方法,參數(shù)。然后調(diào)用ServletInvocableHandlerMethod對象invokeAndHandle方法。
//ServletInvocableHandlerMethod.java
public final void invokeAndHandle(ServletWebRequest webRequest,
ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
// 真正調(diào)用controller方法,獲得結(jié)果
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
//設(shè)置響應(yīng)狀態(tài)
setResponseStatus(webRequest);
//如果返回值為null,則說明該請求不返回任何結(jié)果,直接設(shè)置mavContainer.setRequestHandled(true)
//設(shè)置為true之后,表示該請求已經(jīng)處理完,后續(xù)不再處理,后續(xù)會提到這個
if (returnValue == null) {
if (isRequestNotModified(webRequest) || hasResponseStatus() || mavContainer.isRequestHandled()) {
mavContainer.setRequestHandled(true);
return;
}
}
else if (StringUtils.hasText(this.responseReason)) {
mavContainer.setRequestHandled(true);
return;
}
//設(shè)置為false,表示當(dāng)前請求還未處理完成
mavContainer.setRequestHandled(false);
try {
//調(diào)用默認(rèn)的和自定義的所有返回值解析器處理返回結(jié)果
this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
catch (Exception ex) {//...}
throw ex;
}
}從注釋中可于了解到,首先調(diào)用業(yè)務(wù)邏輯獲得返回結(jié)果,然后對返回值做一定的判斷并簡單處理。通過returnValueHandlers對象來進(jìn)一步處理返回結(jié)果。這是個HandlerMethodReturnValueHandlerComposite類型的對象,繼續(xù)跟進(jìn)。
public void handleReturnValue(
Object returnValue, MethodParameter returnType,
ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
throws Exception {
// 獲得可以處理返回值的handler,當(dāng)然也是通過遍歷,可以看方法
HandlerMethodReturnValueHandler handler = getReturnValueHandler(returnType);
//如果沒有合適的返回值處理器,就會報錯
Assert.notNull(handler, "Unknown return value type [" + returnType.getParameterType().getName() + "]");
//使用返回值處理器處理返回結(jié)果
handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}
private HandlerMethodReturnValueHandler getReturnValueHandler(MethodParameter returnType) {
//遍歷所有handler,包括自定義的
for (HandlerMethodReturnValueHandler returnValueHandler : returnValueHandlers) {
//...
if (returnValueHandler.supportsReturnType(returnType)) {
//如果該handler能夠處理當(dāng)前返回值,就返回該handler
return returnValueHandler;
}
}
return null;
}來,看一下所有的默認(rèn)注冊的處理器。看到了RequestResponseBodyMethodProcessor是不是很親切呢,對咯,他就是處理@ResponseBody注解的。喜歡的朋友可以去看哈這個類的supportsReturnType()方法就明白了。

到這里就不繼續(xù)跟了,我們熟悉的RequestResponseBodyMethodProcessor處理器處理結(jié)果的時候會設(shè)置mavContainer.setRequestHandled(true);表示處理已經(jīng)完畢。
處理完之后,回到RequestMappingHandlerAdapter的invokeHandleMethod()方法。這個方法最終返回了getModelAndView();
從該方法中,我們可以看到,如果當(dāng)前請求已經(jīng)處理完成(mavContainer.isRequestHandled()值為true),則不進(jìn)行后續(xù)的處理沒直接返回null,否則spring會繼續(xù)處理當(dāng)前請求,并試圖返回一個ModelAndView。
既然上面提到了自定義的返回值處理器,那這個自定義是在哪里的呢?這個返回值處理器就是在哪里注冊的呢?精彩馬上回來!
返回值處理器需要實現(xiàn)HandlerMethodReturnValueHandler
public class MyCustomReturnValueHandler implements HandlerMethodReturnValueHandler {
@Override
public boolean supportsReturnType(MethodParameter returnType) {
//判斷方法是否包含自定義注解MyResonse或者返回結(jié)果是指定的某種類型
return returnType.getMethodAnnotation(MyResponse.class) != null || ResponseResult.class.isAssignableFrom(returnType.getParameterType());
}
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
// 表明該請求已經(jīng)處理,后面spring不會再處理
mavContainer.setRequestHandled(true);
HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(JSON.toJSONString(returnValue));
}
}controller,我這里注解和返回值類型都符合上面處理器的要求,事實上只要一種就好了。
@RequestMapping("/testValueHandler")
@MyResponse
public ResponseResult testValueHandler() {
return new ResponseResult(0,"success");
}springmvc.xml
<mvc:annotation-driven> <mvc:return-value-handlers> <bean class="com.wt.test.webmvc.config.MyCustomReturnValueHandler"/> </mvc:return-value-handlers> </mvc:annotation-driven>
從xml中可以看到是自定義標(biāo)簽mvc:return-value-handlers,跟蹤MvcNamespaceHandler。
// MvcNamespaceHandler.java
public void init() {
//解析自定義標(biāo)簽的parser
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
}進(jìn)入AnnotationDrivenBeanDefinitionParser的parse方法,自定義的就是在這里處理的,我們來看一下。
// AnnotationDrivenBeanDefinitionParser
public BeanDefinition parse(Element element, ParserContext parserContext) {
//...
//獲取自定義的返回值處理器
ManagedList<?> returnValueHandlers = getReturnValueHandlers(element, parserContext);
//...
// 定義RequestMappingAdapterHandler
RootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);
//...
if (returnValueHandlers != null) {
//設(shè)置自定義返回值處理器的屬性customReturnValueHandlers
handlerAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);
}
//...
// 將定義的RequestMappingAdapterHandler注冊為spring的bean
parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, handlerAdapterName));
//...
}
// 解析自定義標(biāo)簽return-value-handlers
private ManagedList<?> getReturnValueHandlers(Element element, ParserContext parserContext) {
Element handlersElement = DomUtils.getChildElementByTagName(element, "return-value-handlers");
if (handlersElement != null) {
return extractBeanSubElements(handlersElement, parserContext);
}
return null;
}直接看注釋了,不解釋了。到這里自定義的返回值處理器就已經(jīng)注冊完了,已經(jīng)是spring的一個bean了。現(xiàn)在我們來看看RequestMappingHandlerAdapter。
這個家伙實現(xiàn)了InitializingBean,我們來看afterPropertiesSet方法。
public void afterPropertiesSet() {
//...
}
if (this.returnValueHandlers == null) {
//獲取所有的返回值處理器,不要看方法名是getDefaultReturnVanlueHandler,實際上在里面也包含了自定義的處理器
List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers();
this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers);
}
initControllerAdviceCache();
}
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() {
List<HandlerMethodReturnValueHandler> handlers = new ArrayList<HandlerMethodReturnValueHandler>();
// 默認(rèn)的返回值處理器
// Single-purpose return value types
handlers.add(new ModelAndViewMethodReturnValueHandler());
handlers.add(new ModelMethodProcessor());
handlers.add(new ViewMethodReturnValueHandler());
handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
handlers.add(new CallableMethodReturnValueHandler());
handlers.add(new DeferredResultMethodReturnValueHandler());
handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory));
// Annotation-based return value types
handlers.add(new ModelAttributeMethodProcessor(false));
handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager));
// Multi-purpose return value types
handlers.add(new ViewNameMethodReturnValueHandler());
handlers.add(new MapMethodProcessor());
// 自定義的返回值處理器,就是在之前parse處理的那些
if (getCustomReturnValueHandlers() != null) {
handlers.addAll(getCustomReturnValueHandlers());
}
// 添加其他的默認(rèn)返回值處理器
// Catch-all
if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) {
handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers()));
}
else {
handlers.add(new ModelAttributeMethodProcessor(true));
}
return handlers;
}從上可以看出,我們雖然我們的自定義返回值處理器放進(jìn)去了,但是一定會用到嘛?那不一定哦。可以看到對所有的返回值處理器,并沒有進(jìn)行排序,因此我們不能控制這個順序。先給一個調(diào)試的圖:

從圖中我們可看到,我們自定義的handler確實是加載進(jìn)去了,但是由于spring在處理這個handlers的時候并沒有進(jìn)行排序,所以我們自定義被放在了后面,我們不能夠控制這個順序(其他騷方法可以實現(xiàn),這里不考慮這種情況)。所以存在一種情況,我們的返回值能夠被前面的11個處理器中的某一個處理,那么就輪不到我們自定義的返回值處理器了。舉個簡單的例子,比如你返回值類型是String,那么就會別ViewNameMethodReturnValueHandler處理;如果返回的類型是Map,那么就會被MapMethodProcessor處理,可以自行測試。因此我們的返回值其實也很重要。所以要使用到我們自定義的處理器,那么首先我們就得讓前面的處理器無法處理我們的返回結(jié)果。
通常可以實現(xiàn)一個通用的返回結(jié)果實體,或者某個標(biāo)記接口(空接口),這樣其他的返回值處理器無法處理返回的值類型,這樣就輪到我們自己的返回值處理器了。也可以返回喜歡的實體類型,像示例中一樣使用注解也可以。但是因為通常一個項目來講返回值都是有定義的,返回的類型都是有同一種格式的,所以這類比較偏向使用通用相同的返回實體,或者使用某個接口標(biāo)記。
over ...
上述就是小編為大家分享的spring webmvc請求處理流程中返回值處理是什么了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)站欄目:springwebmvc請求處理流程中返回值處理是什么
網(wǎng)頁地址:http://chinadenli.net/article4/ppcpie.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗、服務(wù)器托管、建站公司、做網(wǎng)站、網(wǎng)站排名、網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)