Spring MVC 整體介紹
Spring MVC 整體介紹
大學(xué)時(shí)寫的的文章,當(dāng)時(shí)文章水平略差,大家見諒。 Spring MVC 是以servlet 為核心進(jìn)行實(shí)現(xiàn)的,統(tǒng)一入口進(jìn)入拿到請(qǐng)求后,做一次路由,找到對(duì)應(yīng)的controller及對(duì)應(yīng)的RequestMapping,完成邏輯的后,返回對(duì)應(yīng)的視圖或者數(shù)據(jù)元,如果是順道完成視圖的解析,返回對(duì)應(yīng)html,完成響應(yīng)。
開發(fā)步驟: 1、建立Spring 工程,引入對(duì)應(yīng)Spring MVC 所需要的Jar。
2、創(chuàng)建web.xml 文件,指定dispacherServlet,然后指定攔截的請(qǐng)求規(guī)則,比如說 *.do,再配置對(duì)應(yīng)的listener,還有spring 依賴的bean的配置文件 3、創(chuàng)建springMVC-servlet.xml 類似于這樣的一個(gè)配置文件,設(shè)置啟用注解,設(shè)置對(duì)應(yīng)掃描的包,然后指定頁(yè)面存在的位置,指定前綴后綴什么 4、在對(duì)應(yīng)目錄下創(chuàng)建一個(gè)controller 類,并指定對(duì)應(yīng)注解,創(chuàng)建對(duì)應(yīng)RequestMapping 注解的函數(shù),設(shè)置URI。 5、編寫對(duì)應(yīng)邏輯。 6、部署&運(yùn)行 內(nèi)部處理流程: 1、dispacher Servlet 攔截到外部所有的請(qǐng)求 2、根據(jù)HandlerMapping找到對(duì)應(yīng)的Handler,并將一堆***和Handler封裝至HandlerExecutionChain 3、帶著Handler 找到對(duì)應(yīng)的HandlerAdapter,完成對(duì)應(yīng)的邏輯處理。 4、帶著具體的Model&View返回 5、首先通過ViewResolver對(duì)于視圖進(jìn)行解析,并完成 對(duì)應(yīng)的視圖渲染,反饋給Dispacher Servlet。
6、**dispacher Servlet 完成響應(yīng) 這就是Spring MVC 中的一個(gè)簡(jiǎn)要流程。 這里的Handler 是需要我們手動(dòng)實(shí)現(xiàn)邏輯的,也就具體的controller、然后ModleAndView 也是我們開發(fā)中所接觸的ModelAndView,具體的渲染和解析的過程其實(shí)就是將對(duì)應(yīng)視圖變?yōu)榍岸丝勺R(shí)別HTML 文檔的形式,過程中將對(duì)應(yīng)的對(duì)象信息解析進(jìn)去就OK了。 具體的看后續(xù)操作~ 這里介紹的主要是核心的分發(fā)器dispacherServlet,在說之前先來看一看常規(guī)的servlet。
public interface Servlet { } sevlet 是Java 在Java web開發(fā)中定義的一個(gè)規(guī)范,任何一個(gè)可以處理外部用戶請(qǐng)求的應(yīng)用組件都需要實(shí)現(xiàn)這個(gè)接口(即作為一種servlet 存在)。 public abstract class GenericServlet implements Servlet, ServletConfig, Serializable { 這是GenericServlet,一種servlet的通用實(shí)現(xiàn),提供了servlet應(yīng)該有的基礎(chǔ)功能。 我們常用的是HTTP servlet,一種基于HTTP協(xié)議對(duì)于GenericServlet實(shí)現(xiàn)的Servlet,能夠?qū)τ谕獠縃TTP請(qǐng)求進(jìn)行對(duì)應(yīng)的處理并且完成對(duì)應(yīng)的響應(yīng)。
并且針對(duì)各種HTTP 請(qǐng)求原語(yǔ)實(shí)現(xiàn)了對(duì)應(yīng)的處理方法(具體來說是要求使用者自己必須實(shí)現(xiàn)) DispacherServlet 就是一種HTTP servlet ,它實(shí)現(xiàn)了對(duì)于所有符合規(guī)則的的HTTP請(qǐng)求進(jìn)行攔截,并對(duì)具有handler的請(qǐng)求完成具體的邏輯。
個(gè)人對(duì)于spring mvc框架的理解
以下我的個(gè)人理解加上**上的所查閱資料,對(duì)于spring mvc框架的一些總結(jié),不足之處還望指出 在web模型中,MVC是一種很流行的框架,通過把Model,View,Controller分離,把較為復(fù)雜的web應(yīng)用分成邏輯清晰的幾部分,是為了簡(jiǎn)化開發(fā),減少出錯(cuò),同時(shí)也為了組內(nèi)開發(fā)人員之間的配合??傊褪且环N分層工作的辦法。
(1) 用戶通過瀏覽器向服務(wù)器發(fā)送請(qǐng)求,請(qǐng)求被springmvc的前端控制器DispatcherServlet攔截; (2) DispatcherServlet攔截到請(qǐng)求后,會(huì)調(diào)用HandlerMapping處理映射器; (3) 處理器映射器根據(jù)請(qǐng)求URL找到具體的處理器,生成處理器對(duì)象及處理器***(如果有則生成)一并返回給調(diào)用處理器DispatcherServlet; (4)DispatcherServlet會(huì)通過返回信息選擇合適的HanderAdapter(處理器適配器); (5)HanderAdapter會(huì)調(diào)用并執(zhí)行Handler(處理器),這里的處理器值的就是程序中編寫的Controller類,也被稱之為后端控制器; (6)Controller執(zhí)行完成后,會(huì)返回一個(gè)ModelAndView對(duì)象,該對(duì)象中包含視圖名或包含模型和視圖名 (7)HandlerAdapter將ModelAndView對(duì)象返回給DispatcherServlet; (8)DispatcherServlet會(huì)根據(jù)ModelAndView對(duì)象選擇一個(gè)合適的ViewReslover(視圖解析器) (9)ViewReslover解析后,會(huì)向DispatcherServlet中返回具體的View (10)DispatcherServlet對(duì)view進(jìn)行渲染(即將模型數(shù)據(jù)填充至視圖中) (11)視圖渲染結(jié)果會(huì)返回給客戶端瀏覽器顯示 (1)DispatcherServlet接口:Spring提供的前端控制器,所有的請(qǐng)求都有經(jīng)過它來統(tǒng)一分發(fā)。
在DispatcherServlet將請(qǐng)求分發(fā)給Spring Controller之前,需要借助于Spring提供的HandlerMapping定位到具體的Controller。 (2)HandlerMapping接口:能夠完成客戶請(qǐng)求到Controller映射。 (3)Controller接口:需要為并發(fā)用戶處理上述請(qǐng)求,因此實(shí)現(xiàn)Controller接口時(shí),必須保證線程安全并且可重用。Controller將處理用戶請(qǐng)求,這和Struts Action扮演的角色是一致的。
一旦Controller處理完用戶請(qǐng)求,則返回ModelAndView對(duì)象給DispatcherServlet前端控制器,ModelAndView中包含了模型(Model)和視圖(View)。 從宏觀角度考慮,DispatcherServlet是整個(gè)Web應(yīng)用的控制器;從微觀考慮,Controller是單個(gè)Http請(qǐng)求處理過程中的控制器,而ModelAndView是Http請(qǐng)求過程中返回的模型(Model)和視圖(View)。 (4)ViewResolver接口:Spring提供的視圖解析器(ViewResolver)在Web應(yīng)用中查找View對(duì)象,從而將相應(yīng)結(jié)果渲染給客戶。
是整個(gè)Spring MVC的核心。它負(fù)責(zé)接收HTTP請(qǐng)求組織協(xié)調(diào)Spring MVC的各個(gè)組成部分。其主要工作有以下三項(xiàng): (1)截獲符合特定格式的URL請(qǐng)求。
(2)初始化DispatcherServlet上下文對(duì)應(yīng)WebApplicationContext,并將其與業(yè)務(wù)層、持久化層的WebApplicationContext建立關(guān)聯(lián)。 (3)初始化Spring MVC的各個(gè)組成組件,并裝配到DispatcherServlet中。
spring mvc的優(yōu)點(diǎn)是什么
1、spring3開發(fā)效率高于struts;2、spring3 mvc可以認(rèn)為已經(jīng)****零配置;3、struts2是類級(jí)別的攔截, 一個(gè)類對(duì)應(yīng)一個(gè)request上下文,springmvc是方法級(jí)別的攔截,一個(gè)方法對(duì)應(yīng)一個(gè)request上下文,而方法同時(shí)又跟一個(gè)url對(duì)應(yīng)。所以說從架構(gòu)本身上 spring3 mvc就容易實(shí)現(xiàn)restful url,而struts2的架構(gòu)實(shí)現(xiàn)起來要費(fèi)勁。
Spring MVC 面試總結(jié)
SpringMVC的核心就是DispatcherServlet,DispatcherServlet實(shí)質(zhì)也是一個(gè)HttpServlet,繼承 了FrameworkServlet,實(shí)現(xiàn) ApplicationContextAware 接口,繼承 HttpServletBean 抽象類 , 負(fù)責(zé)初始化 Spring Servlet WebApplicationContext 容器,同時(shí)該類覆寫了 doGet、doPost 等方法,并將所有類型的請(qǐng)求委托給 doService 方法去處理,doService 是一個(gè)抽象方法,需要子類實(shí)現(xiàn),DispatcherServlet負(fù)責(zé)初始化 Spring MVC 的各個(gè)組件,以及處理客戶端的請(qǐng)求,協(xié)調(diào)各個(gè)組件工作WebApplicationContext 是實(shí)現(xiàn) ApplicationContext 接口的子類,專門為 WEB 應(yīng)用準(zhǔn)備的 它允許從相對(duì)于 Web 根目錄的路徑中加載配置文件,完成初始化 Spring MVC 組件的工作。 從 WebApplicationContext 中,可以獲取 ServletContext 引用,整個(gè) Web 應(yīng)用上下文對(duì)象將作為屬性放置在 ServletContext 中,以便 Web 應(yīng)用環(huán)境可以訪問 Spring 上下文。
ContextLoaderListener 繼承 ContextLoader 類,實(shí)現(xiàn) Servlet 容器啟動(dòng)和關(guān)閉時(shí),分別初始化和銷毀 WebApplicationContext 容器,WebApplicationContext 有兩處 Servlet 3.0 新增的一個(gè)接口ServletContainerInitializer?,配合@HandlesTypes 注解來指定希望被處理的類,容器在啟動(dòng)時(shí)使用 JAR 服務(wù) 的時(shí)候會(huì)通過SPI機(jī)制發(fā)現(xiàn)?ServletContainerInitializer?的實(shí)現(xiàn)類,并且容器將 WEB-INF/lib 目錄下 JAR 包中的類都交給該類的 onStartup() 方法處理,實(shí)現(xiàn)的 onStartup 方法中可以向 ServletContext 對(duì)象(Servlet 上下文)添加之前在 web.xml 中配置的 Filter和 Servlet,這樣一來就可以去除 web.xml 文件了?SpringMVC的實(shí)現(xiàn)類?SpringServletContainerInitializer?就是實(shí)現(xiàn)了ServletContainerInitializer接口,負(fù)責(zé)初始化web環(huán)境,SpringServletContainerInitializer把所有的初始化任務(wù)委托給WebApplicationInitializer這個(gè)接口的實(shí)現(xiàn)類,其中AbstractDispatcherServletInitializer便是創(chuàng)建DispatcherServlet 的關(guān)鍵類SpringBoot 是通過?org.springframework.boot.web.embedded.tomcat.TomcatStarter?這個(gè)類進(jìn)行初始化流程的,TomcatStarter同樣也是實(shí)現(xiàn)了ServletContainerInitializer接口,通過構(gòu)造方法傳入的ServletContextInitializer去初始化Web環(huán)境,其中ServletWebServerApplicationContext?負(fù)責(zé)?加載Filter、Servlet、Listener ServletWebServerApplicationContext 的 onRefresh() 方法觸發(fā)配置了一個(gè)匿名的 ServletContextInitializer 這個(gè)匿名的 ServletContextInitializer 的 onStartup 方**去容器中搜索到了所有的 RegisterBean 并按照順序加載到 ServletContext 中 這個(gè)匿名的 ServletContextInitializer 最終傳遞給 TomcatStarter,由 TomcatStarter 的 onStartup 方法去觸發(fā) ServletContextInitializer 的 onStartup 方法,最終完成裝配 注冊(cè)方式一: Servlet3.0 注解(@WebServlet,@WebFilter,@WebListener) +@ServletComponentScan , 在啟動(dòng)類上面添加?@ServletComponentScan?注解去掃描到這些注解 注冊(cè)方式二: RegistrationBean,比如?ServletRegistrationBean 和 FilterRegistrationBean 都繼成 RegistrationBean,它是 SpringBoot 中廣泛應(yīng)用的一個(gè)注冊(cè)類,負(fù)責(zé)把 Servlet,F(xiàn)ilter,Listener 給容器化,使它們被 Spring 托管,并且完成自身對(duì) Web 容器的注冊(cè)用戶的瀏覽器發(fā)送一個(gè)請(qǐng)求,這個(gè)請(qǐng)求經(jīng)過互聯(lián)網(wǎng)到達(dá)了我們的服務(wù)器。
Servlet 容器首先接待了這個(gè)請(qǐng)求,并將該請(qǐng)求委托給?DispatcherServlet?進(jìn)行處理。 1.?DispatcherServlet 主要通過 dispatch 這個(gè)方法去處理整個(gè)流程,這個(gè)流程他會(huì)先去通過 HandlerMapping 的getHandler方法得到一個(gè)HandlerExecutionChain對(duì)象 HandlerMapping 就是一個(gè)接口,里面就只有一個(gè)方法就叫g(shù)etHandler,他有很多實(shí)現(xiàn)類,但是大體主要通過兩種方式獲得Handler 一種是 AbstracHandlerMethodMapping?和 AbstractUrlHandlerMapping ,一個(gè)是基于 Method 進(jìn)行匹配的,比如@RequestMapping注解,一個(gè)是基于 URL 進(jìn)行匹配,我們平常用的最多的還是RequestMappingHandlerMapping,這個(gè)就是 AbstracHandlerMethodMapping?的子類 HandlerExecutionChain 這個(gè)對(duì)象就是包含了***和處理器對(duì)象,這個(gè)處理器對(duì)象是object類型的,對(duì)象比如說,我們平常通過在方法上標(biāo)記@RequestMapping注解,然后呢他這個(gè)對(duì)象就是HandlerMethod 類型, 這個(gè)?HandlerMethod封裝了很多屬性,在訪問請(qǐng)求方法的時(shí)候可以方便的訪問到方法、方法參數(shù)、方法上的注解、所屬類等并且對(duì)方法參數(shù)封裝處理,也可以方便的訪問到方法參數(shù)的注解等信息。***呢,就是實(shí)現(xiàn)了HandlerInterceptor接口的類,就是在執(zhí)行方法之前和執(zhí)行方法之后進(jìn)行一些處理 2.?拿到這個(gè) HandlerExecutionChain 對(duì)象之后呢,還要找一個(gè)HandlerAdapter 適配器,他通過遍歷 HandlerAdapter 組件,判斷是否支持處理該?handler?處理器,支持則返回該 HandlerAdapter 組件,這個(gè)HandlerAdapter組件負(fù)責(zé)處理執(zhí)行整個(gè)流程,參數(shù)的解析,方法的執(zhí)行,返回值的處理,都是在他里面完成的, 像我們平時(shí)用的最多的還是RequestMappingHandlerAdapter類,他就是執(zhí)行 HandlerMethod 類型的處理器,也就是通過?@RequestMapping?等注解標(biāo)注的方法 3. 然后呢通過執(zhí)行HandlerAdapter的handle方法,會(huì)給我們返回一個(gè)ModelAndView 對(duì)象,這個(gè)呢就是數(shù)據(jù)和視圖地址,然后呢就會(huì)調(diào)用processDispatchResult這個(gè)方法去解析視圖,這里面他會(huì)通過render這個(gè)方法進(jìn)行頁(yè)面渲染邏輯,這里面就會(huì)交給viewResolvers去處理,但是我們平常開發(fā)都是標(biāo)注了ResponseBody注解,所以在HandlerAdapter這里面會(huì)將我們返回的結(jié)果直接將數(shù)據(jù)通過HttpServletResponse.write寫進(jìn)去,**直接返回?Spring MVC的***的實(shí)現(xiàn)了HandlerInterceptor接口 , 里面主要有三個(gè)方法?preHandle,postHandle,afterCompletion,分別是前置處理,后置處理和已完成處理 這個(gè)HandlerInterceptor呢,他會(huì)在在HanderMapping的子類 AbstractHandlerMapping 中的?getHandler 方法中去獲取,一般是在獲取完handler處理器后然后會(huì)去和HandlerInterceptor去組裝成 HandlerExecutionChain 對(duì)象, HandlerInterceptor***呢會(huì)在AbstractHandlerMapping?initApplicationContext ()方法中初始化完成的,因?yàn)檫@個(gè)方法是重寫了父類 ApplicationObjectSupport 的initApplicationContext()ApplicationObjectSupport最上層的接口ApplicationContextAware中的 setApplicationContext ,所以他會(huì)在初始化該ben的時(shí)候調(diào)用setApplicationContext這個(gè)方法,然后這個(gè)方法將 interceptors 初始化成 HandlerInterceptor 類型,添加到?adaptedInterceptors 中 HandlerMapping 組件,請(qǐng)求的 處理器匹配器 ,負(fù)責(zé)為請(qǐng)求找到合適的?HandlerExecutionChain?處理器執(zhí)行鏈,包含處理器(handler)和***們(interceptors),下面先說 AbstractHandlerMapping AbstractHandlerMapping 抽象類,一個(gè)基類,實(shí)現(xiàn)了“為請(qǐng)求找到合適的?HandlerExecutionChain?處理器執(zhí)行鏈”對(duì)應(yīng)的的骨架邏輯,而暴露?getHandlerInternal()?抽象方法,交由子類實(shí)現(xiàn)。 AbstractUrlHandlerMappingAbstractHandlerMethodMapping 因?yàn)槠渲刑幚砥鞯膶?shí)現(xiàn)有多種,例如通過實(shí)現(xiàn) Controller 接口、HttpRequestHandler 接口,或者使用?@RequestMapping?注解將方法作為一個(gè)處理器等。
Spring MVC 就無法直接執(zhí)行這個(gè)處理器,所以這里需要一個(gè)處理器適配器,由它去執(zhí)行處理器, HandlerAdapter 接口也就三個(gè)方法,一個(gè)是判斷是否支持該處理器的,一個(gè)是執(zhí)行處理器返回ModelAndView的,還有一個(gè)是返回請(qǐng)求的**更新時(shí)間的 HttpRequestHandlerAdapter :執(zhí)行實(shí)現(xiàn)了 HttpRequestHandler 接口的處理器 SimpleControllerHandlerAdapter :執(zhí)行實(shí)現(xiàn)了 Controller 接口的處理器 SimpleServletHandlerAdapter :執(zhí)行實(shí)現(xiàn)了 Servlet 接口的處理器 RequestMappingHandlerAdapter : 執(zhí)行 HandlerMethod 類型的處理器,也就是通過?@RequestMapping?等注解標(biāo)注的方法,主要說說RequestMappingHandlerAdapter的執(zhí)行流程: 1. 會(huì)先創(chuàng)建ServletInvocableHandlerMethod并且設(shè)置一些屬性,這個(gè)是對(duì)HandlerMethod?處理器的封裝,然后通過這個(gè)對(duì)象的invokeAndHandle方法去執(zhí)行 2?然后需要通過?HandlerMethodArgumentResolver?對(duì)象進(jìn)行參數(shù)解析 3?在通過反射執(zhí)行對(duì)應(yīng)的 Method 方法對(duì)象 4?**通過?HandlerMethodReturnValueHandler?對(duì)象對(duì)執(zhí)行結(jié)果進(jìn)行處理,設(shè)置到?response?響應(yīng)中,生成對(duì)應(yīng)的 ModelAndView 對(duì)象 ServletInvocableHandlerMethod 封裝?HandlerMethod?處理器對(duì)象,它還包含?HandlerMethodArgumentResolver?參數(shù)解析器和?HandlerMethodReturnValueHandler?返回值處理器等組件 參數(shù)解析器,先說說他是怎么處理的吧, 在ServletInvocableHandlerMethod解析參數(shù)會(huì)先用到一個(gè)HandlerMethodArgumentResolverComposite對(duì)象,這也是一個(gè)實(shí)現(xiàn)HandlerMethodArgumentResolver接口的對(duì)象,他呢是一個(gè)組合對(duì)象,里面就包含了很多的參數(shù)解析器,他會(huì)遍歷所有的參數(shù)解析器去調(diào)用supportsParameter這個(gè)方法去看是否支持解析該參數(shù),如果支持呢他就會(huì)返回這個(gè)參數(shù)解析器,不支持就會(huì)給返回一個(gè)IllegalStateException的異常,然后呢就會(huì)調(diào)用resolveArgument去解析這個(gè)參數(shù),像解析參數(shù)處理器的就非常多了,常見的有: RequestParamMethodArgumentResolver: 基于?@RequestParam?注解的 也可以不帶 PathVariableMethodArgumentResolver : 基于?@PathVariable?注解的 ServletModelAttributeMethodProcessor :基于ModelAttribute注解的,處理實(shí)體類,也可以不帶 RequestResponseBodyMethodProcessor: 基于@RequestBody注解的 在轉(zhuǎn)換的過程中呢還有個(gè)參數(shù)轉(zhuǎn)換器,比如啊我們從瀏覽器發(fā)過來的請(qǐng)求都是text類型的,所以必須要把這這些類型轉(zhuǎn)換成我們的目標(biāo)類型,比如Date,Number啊這些類型,都需要通過轉(zhuǎn)換器去完成,WebDataBinder 利用它里面的 Converters 將請(qǐng)求數(shù)據(jù)轉(zhuǎn)成指定的數(shù)據(jù)類型。再次封裝到JavaBean中,拿到這些處理好的值,直接通過反射調(diào)用我們寫好的方法獲得拿到需要返回的值就好了 HandlerMethodReturnValueHandler?返回值處理器將返回結(jié)果設(shè)置到響應(yīng)中,或者設(shè)置相應(yīng)的 Model 和 View 用于后續(xù)的視圖渲染。這個(gè)接口也就兩個(gè)方法,一個(gè)是判斷是否支持該返回類型的,還有一個(gè)就是處理返回值的 RequestResponseBodyMethodProcessor :?負(fù)責(zé)處理@ResponseBody注解的返回值,現(xiàn)在前后端分離,后端基本是提供 Restful API,最常用的就是他,RequestResponseBodyMethodProcessor中還有個(gè)最重要的就是MessageConverters內(nèi)容協(xié)商,利用 MessageConverters將返回的數(shù)據(jù) 寫為json,他 =會(huì)根據(jù)請(qǐng)求頭Accept去看瀏覽器接收什么樣的數(shù)據(jù)類型,在根據(jù)MessageConverters實(shí)現(xiàn)類的MediaType這個(gè)類去和你匹配看自己能支持那些內(nèi)容類型的數(shù)據(jù),那你瀏覽器需要json就會(huì)得到MappingJackson2HttpMessageConverter這個(gè)對(duì)象,然后把對(duì)象轉(zhuǎn)成json寫到response中 ViewNameMethodReturnValueHandler :?適用于前后端未分離,Controller 返回視圖名的場(chǎng)景,例如 JSP、thymeleaf模板引擎就用這個(gè)處理器異常解析器,將處理器執(zhí)行請(qǐng)求時(shí)發(fā)生的異常,解析成對(duì)應(yīng)的 ModelAndView 結(jié)果,大致就是通過@ControllerAdvice+@ExceptionHandler注解處理全局異常,底層就是HandlerExceptionResolver 接口支持的,其中一個(gè)實(shí)現(xiàn)類 ExceptionHandlerExceptionResolver 會(huì)在初始化的時(shí)候去掃描 掃描 @ControllerAdvice 注解的 Bean 們?nèi)缓笳业接?@ExceptionHandler 注解的方法,則添加到 exceptionHandlerAdviceCache 中,執(zhí)行的時(shí)候他里面也有參數(shù)解析器和返回值處理器,處理完了之后也會(huì)返回ModelAndView對(duì)象視圖解析器,根據(jù)視圖名和國(guó)際化,獲得最終的視圖 View 對(duì)象。
Spring MVC 執(zhí)行完處理器后生成一個(gè) ModelAndView 對(duì)象,如果該對(duì)象不為?null?并且有對(duì)應(yīng)的?viewName,那么就需要通過?ViewResolver?根據(jù)?viewName?解析出對(duì)應(yīng)的 View 對(duì)象MultipartResolver?組件,內(nèi)容類型(?Content-Type?)為?multipart/*?的請(qǐng)求的解析器,主要解析文件上傳的請(qǐng)求。例如,MultipartResolver?會(huì)將 HttpServletRequest 封裝成?MultipartHttpServletRequest?對(duì)象, DispatcherServlet?Spring MVC 的核心組件,是請(qǐng)求的入口,負(fù)責(zé)協(xié)調(diào)各個(gè)組件工作 MultipartResolver 內(nèi)容類型(?Content-Type?)為?multipart/*?的請(qǐng)求的解析器,例如解析處理文件上傳的請(qǐng)求,便于獲取參數(shù)信息以及上傳的文件 HandlerMapping 請(qǐng)求的處理器匹配器,負(fù)責(zé)為請(qǐng)求找到合適的?HandlerExecutionChain?處理器執(zhí)行鏈,包含處理器(handler)和***們(interceptors) HandlerAdapter 處理器的適配器。因?yàn)樘幚砥?handler?的類型是 Object 類型,需要有一個(gè)調(diào)用者來實(shí)現(xiàn)?handler?是怎么被執(zhí)行。
Spring 中的處理器的百科實(shí)現(xiàn)多變,比如用戶處理器可以實(shí)現(xiàn) Controller 接口、HttpRequestHandler 接口,也可以用?@RequestMapping?注解將方法作為一個(gè)處理器等,這就導(dǎo)致 Spring MVC 無法直接執(zhí)行這個(gè)處理器。所以這里需要一個(gè)處理器適配器,由它去執(zhí)行處理器 HandlerExceptionResolver 處理器異常解析器,將處理器(?handler?)執(zhí)行時(shí)發(fā)生的異常,解析( 轉(zhuǎn)換 )成對(duì)應(yīng)的 ModelAndView 結(jié)果 RequestToViewNameTranslator 視圖名稱轉(zhuǎn)換器,用于解析出請(qǐng)求的默認(rèn)視圖名 LocaleResolver 本地化(國(guó)際化)解析器,提供國(guó)際化支持 ThemeResolver 主題解析器,提供可設(shè)置應(yīng)用整體樣式風(fēng)格的支持 ViewResolver 視圖解析器,根據(jù)視圖名和國(guó)際化,獲得最終的視圖 View 對(duì)象 FlashMapManager FlashMap 管理器,負(fù)責(zé)重定向時(shí),保存參數(shù)至臨時(shí)存儲(chǔ)(默認(rèn) Session)@Controller 注解有什么用? @Controller?注解標(biāo)記一個(gè)類為 Spring Web MVC 控制器 Controller。Spring MVC 會(huì)將掃描到該注解的類,然后掃描這個(gè)類下面帶有?@RequestMapping?注解的方法,根據(jù)注解信息,為這個(gè)方法生成一個(gè)對(duì)應(yīng)的 處理器 對(duì)象,在上面的 HandlerMapping 和 HandlerAdapter組件中講到過。
當(dāng)然,除了添加?@Controller?注解這種方式以外,你還可以實(shí)現(xiàn) Spring MVC 提供的?Controller?或者?HttpRequestHandler?接口,對(duì)應(yīng)的實(shí)現(xiàn)類也會(huì)被作為一個(gè) 處理器 對(duì)象 @RequestMapping 注解有什么用? @RequestMapping?注解,在上面已經(jīng)講過了,配置 處理器 的 HTTP 請(qǐng)求方法,URI等信息,這樣才能將請(qǐng)求和方法進(jìn)行映射。這個(gè)注解可以作用于類上面,也可以作用于方法上面,在類上面一般是配置這個(gè) 控制器 的 URI 前綴 @RestController 和 @Controller 有什么區(qū)別? @RestController?注解,在?@Controller?基礎(chǔ)上,增加了?@ResponseBody?注解,更加適合目前前后端分離的架構(gòu)下,提供 Restful API ,返回例如 JSON 數(shù)據(jù)格式。當(dāng)然,返回什么樣的數(shù)據(jù)格式,根據(jù)客戶端的?ACCEPT?請(qǐng)求頭來決定。 @RequestMapping 和 @GetMapping 注解的不同之處在哪里? @RequestMapping:可注解在類和方法上;@GetMapping?僅可注冊(cè)在方法上 @RequestMapping:可進(jìn)行 GET、POST、PUT、DELETE 等請(qǐng)求方法;@GetMapping?是?@RequestMapping?的 GET 請(qǐng)求方法的特例,目的是為了提高清晰度。
@RequestParam 和 @PathVariable 兩個(gè)注解的區(qū)別 兩個(gè)注解都用于方法參數(shù),獲取參數(shù)值的方式不同,@RequestParam?注解的參數(shù)從請(qǐng)求攜帶的參數(shù)中獲取,而?@PathVariable?注解從請(qǐng)求的 URI 中獲取 返回 JSON 格式使用什么注解? 可以使用 @ResponseBody 注解,或者使用包含?@ResponseBody?注解的 @RestController 注解。 當(dāng)然,還是需要配合相應(yīng)的支持 JSON 格式化的 HttpMessageConverter 實(shí)現(xiàn)類。