DispatcherServlet處理器的適配和處理解析
處理大致流程圖
獲取處理器適配器
適配器模式
為什么要處理器適配器,我們前面不是獲取處理器方法了么,直接調(diào)用就好啦。對沒錯,但是那可能只是一種處理器的方式,也就是HandlerMethod
,以前還有另外的方式哦,比如實(shí)現(xiàn)Controller
接口的:
還有實(shí)現(xiàn)HttpRequestHandler
接口的:
他們的接口都不一樣,總得兼容吧,處理接口不一致的辦法不就是適配器模式嘛,你接口不同,我用不同的適配器來適配,對外都是統(tǒng)一接口,如果以后有新的實(shí)現(xiàn),我只要添加適配器即可,這里就是適配器模式的應(yīng)用啦。
DispatcherServlet的getHandlerAdapter
這里就是遍歷所有的處理器適配器,看哪個是適配的就直接返回了。
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í)候初始化的,我就不說了,前面已經(jīng)把方法都演示過了,就是一些自動配置類里,自己可以去找啦,剩下的適配器自己可以也去看看。
處理器適配器處理
其實(shí)前面有攔截器,后面會說,還是說主要的,處理器適配器獲得到之后,要進(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
這個也一樣。
@Override @Nullable public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return ((Controller) handler).handleRequest(request, response); }
AbstractHandlerMethodAdapter的handle
這個是重點(diǎn),我們要詳細(xì)說。
@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),每個都挺復(fù)雜的,沒關(guān)系,我們一個個來看,新不追求太細(xì)節(jié)的東西,知道大致流程,大致的流程就是創(chuàng)建數(shù)據(jù)綁定工廠,這個東西就是做參數(shù)綁定用的,后面會介紹,然后是模型工廠,最終是要創(chuàng)建模型返回的,所以需要這個,而且數(shù)據(jù)綁定工廠也會封裝在里面。
然后初始化模型,會根據(jù)方法的參數(shù)來找解析器解析,找到的話就可以解析出參數(shù),最后封裝到模型里去,最后再調(diào)用處理器的方法處理,然后獲取模型和視圖返回。看起來好像沒多少東西,其實(shí)里面還是表深的。
@Nullable protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { //先封裝一個 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ù)名探測器 //創(chuàng)建ModelAndView容器 ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));//獲取前面重定向來的屬性 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處理器適配的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java泛型在集合使用與自定義及繼承上的體現(xiàn)和通配符的使用
泛型又稱參數(shù)化類型,是Jdk5.0 出現(xiàn)的新特性,解決數(shù)據(jù)類型的安全性問題,在類聲明或?qū)嵗瘯r(shí)只要指定好需要的具體的類型即可。Java泛型可以保證如果程序在編譯時(shí)沒有發(fā)出警告,運(yùn)行時(shí)就不會產(chǎn)生ClassCastException異常。同時(shí),代碼更加簡潔、健壯2021-09-09Nacos設(shè)置為windows自啟動服務(wù)的步驟詳解
這篇文章給大家介紹了Nacos設(shè)置為windows自啟動服務(wù)的操作步驟,文中通過代碼示例和圖文結(jié)合講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2023-12-12Java模擬實(shí)現(xiàn)QQ三方登錄(單點(diǎn)登錄2.0)
這篇文章主要為大家詳細(xì)介紹了Java模擬實(shí)現(xiàn)QQ三方登錄,單點(diǎn)登錄2.0,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06