DispatcherServlet處理器的適配和處理解析
處理大致流程圖

獲取處理器適配器
適配器模式
為什么要處理器適配器,我們前面不是獲取處理器方法了么,直接調(diào)用就好啦。對(duì)沒(méi)錯(cuò),但是那可能只是一種處理器的方式,也就是HandlerMethod,以前還有另外的方式哦,比如實(shí)現(xiàn)Controller接口的:

還有實(shí)現(xiàn)HttpRequestHandler接口的:

他們的接口都不一樣,總得兼容吧,處理接口不一致的辦法不就是適配器模式嘛,你接口不同,我用不同的適配器來(lái)適配,對(duì)外都是統(tǒng)一接口,如果以后有新的實(shí)現(xiàn),我只要添加適配器即可,這里就是適配器模式的應(yīng)用啦。
DispatcherServlet的getHandlerAdapter
這里就是遍歷所有的處理器適配器,看哪個(gè)是適配的就直接返回了。
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter;
}
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
如何適配
RequestMappingHandlerAdapter的supports
判斷是否是HandlerMethod類型的。
@Override
public final boolean supports(Object handler) {
return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
}
@Override
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return true;
}
HttpRequestHandlerAdapter的supports
是不是實(shí)現(xiàn)了HttpRequestHandler接口。
@Override
public boolean supports(Object handler) {
return (handler instanceof HttpRequestHandler);
}
SimpleControllerHandlerAdapter的supports
是不是實(shí)現(xiàn)了Controller接口。
@Override
public boolean supports(Object handler) {
return (handler instanceof Controller);
}
至于這些是什么時(shí)候初始化的,我就不說(shuō)了,前面已經(jīng)把方法都演示過(guò)了,就是一些自動(dòng)配置類里,自己可以去找啦,剩下的適配器自己可以也去看看。
處理器適配器處理
其實(shí)前面有攔截器,后面會(huì)說(shuō),還是說(shuō)主要的,處理器適配器獲得到之后,要進(jìn)行適配器調(diào)用啦,不同的適配器調(diào)用方式不一樣,但是核心還是調(diào)用處理器的方法啦:
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
HttpRequestHandlerAdapter的handle
轉(zhuǎn)換成接口類型,調(diào)用接口。
@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
((HttpRequestHandler) handler).handleRequest(request, response);
return null;
}
SimpleControllerHandlerAdapter的handle
這個(gè)也一樣。
@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return ((Controller) handler).handleRequest(request, response);
}
AbstractHandlerMethodAdapter的handle
這個(gè)是重點(diǎn),我們要詳細(xì)說(shuō)。
@Override
@Nullable
public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return handleInternal(request, response, (HandlerMethod) handler);
}
RequestMappingHandlerAdapter的handleInternal
留出核心代碼,就是處理器處理,然后準(zhǔn)備response。
@Override
protected ModelAndView handleInternal(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
ModelAndView mav;
...
mav = invokeHandlerMethod(request, response, handlerMethod);//
...
prepareResponse(response);
...
return mav;
}invokeHandlerMethod
這里面的才是重點(diǎn),每個(gè)都挺復(fù)雜的,沒(méi)關(guān)系,我們一個(gè)個(gè)來(lái)看,新不追求太細(xì)節(jié)的東西,知道大致流程,大致的流程就是創(chuàng)建數(shù)據(jù)綁定工廠,這個(gè)東西就是做參數(shù)綁定用的,后面會(huì)介紹,然后是模型工廠,最終是要?jiǎng)?chuàng)建模型返回的,所以需要這個(gè),而且數(shù)據(jù)綁定工廠也會(huì)封裝在里面。
然后初始化模型,會(huì)根據(jù)方法的參數(shù)來(lái)找解析器解析,找到的話就可以解析出參數(shù),最后封裝到模型里去,最后再調(diào)用處理器的方法處理,然后獲取模型和視圖返回。看起來(lái)好像沒(méi)多少東西,其實(shí)里面還是表深的。
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
//先封裝一個(gè)
ServletWebRequest webRequest = new ServletWebRequest(request, response);
try {
WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);//數(shù)據(jù)綁定工廠
ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);//模型工廠
//進(jìn)行handlerMethod封裝
ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
if (this.argumentResolvers != null) {//設(shè)置參數(shù)解析器
invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {//設(shè)置返回類型解析器
invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
invocableMethod.setDataBinderFactory(binderFactory);//綁定工廠
invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);//參數(shù)名探測(cè)器
//創(chuàng)建ModelAndView容器
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));//獲取前面重定向來(lái)的屬性
modelFactory.initModel(webRequest, mavContainer, invocableMethod);//初始化模型
mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
...
//調(diào)用處理方法
invocableMethod.invokeAndHandle(webRequest, mavContainer);
...
return getModelAndView(mavContainer, modelFactory, webRequest);
}
finally {
webRequest.requestCompleted();
}以上就是DispatcherServlet的處理器的適配和處理解析的詳細(xì)內(nèi)容,更多關(guān)于DispatcherServlet處理器適配的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java泛型在集合使用與自定義及繼承上的體現(xiàn)和通配符的使用
泛型又稱參數(shù)化類型,是Jdk5.0 出現(xiàn)的新特性,解決數(shù)據(jù)類型的安全性問(wèn)題,在類聲明或?qū)嵗瘯r(shí)只要指定好需要的具體的類型即可。Java泛型可以保證如果程序在編譯時(shí)沒(méi)有發(fā)出警告,運(yùn)行時(shí)就不會(huì)產(chǎn)生ClassCastException異常。同時(shí),代碼更加簡(jiǎn)潔、健壯2021-09-09
Springboot自動(dòng)掃描包路徑來(lái)龍去脈示例詳解
這篇文章主要介紹了Springboot自動(dòng)掃描包路徑來(lái)龍去脈示例詳解,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-12-12
SpringBoot整合EasyExcel的完整過(guò)程記錄
easyexcel是阿里巴巴旗下開源項(xiàng)目,主要用于Excel文件的導(dǎo)入和導(dǎo)出處理,下面這篇文章主要給大家介紹了關(guān)于SpringBoot整合EasyExcel的完整過(guò)程,需要的朋友可以參考下2021-12-12
Nacos設(shè)置為windows自啟動(dòng)服務(wù)的步驟詳解
這篇文章給大家介紹了Nacos設(shè)置為windows自啟動(dòng)服務(wù)的操作步驟,文中通過(guò)代碼示例和圖文結(jié)合講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-12-12
Java模擬實(shí)現(xiàn)QQ三方登錄(單點(diǎn)登錄2.0)
這篇文章主要為大家詳細(xì)介紹了Java模擬實(shí)現(xiàn)QQ三方登錄,單點(diǎn)登錄2.0,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06

