(1)? Spring??DispatcherServlet
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è)組件工作
(2)? ?Spring MVC 中的 WebApplicationContext ?
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 上下文万细。
(3)? ?WebApplicationContext? 加載過程
ContextLoaderListener 繼承 ContextLoader 類扑眉,實(shí)現(xiàn) Servlet 容器啟動(dòng)和關(guān)閉時(shí),分別初始化和銷毀 WebApplicationContext 容器赖钞,WebApplicationContext 有兩處
(4)??說一下Spring MVC為何沒有web.xml文件了
public interface ServletContainerInitializer {
? ? ?void onStartup(Set<Class<?>> var1, ServletContext var2) throws ServletException;
}
?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)鍵類
(5)??SpringBoot中 加載 Servlet 的流程
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 方法會(huì)去容器中搜索到了所有的 RegisterBean 并按照順序加載到 ServletContext 中
這個(gè)匿名的 ServletContextInitializer 最終傳遞給 TomcatStarter,由 TomcatStarter 的 onStartup 方法去觸發(fā) ServletContextInitializer 的 onStartup 方法,最終完成裝配
擴(kuò)展一下 關(guān)于SpringBoot 如何配置 Servlet
? ? ?注冊(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è)
(6)? ?Spring MVC 工作流程
用戶的瀏覽器發(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)去帖旨,最后直接返回
(7)??介紹下 Spring MVC 攔截器箕昭?
? 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中
?preHandle
? ? 在會(huì)在HandlerAdapter執(zhí)行handle之前調(diào)用HandlerExecutionChain的applyPreHandle方法,會(huì)執(zhí)行請(qǐng)求匹配的攔截器的前置處理 琼梆,在執(zhí)行的過程中會(huì)記錄通過interceptorIndex?記錄執(zhí)行的當(dāng)前執(zhí)行的下標(biāo)
?postHandle
? ? 會(huì)在HandlerAdapter執(zhí)行handle之后調(diào)用HandlerExecutionChain.applyPostHandle?執(zhí)行請(qǐng)求匹配的攔截器的后置處理?會(huì)根據(jù)interceptorIndex?下標(biāo)倒序執(zhí)行
?afterCompletion
? ? 會(huì)在所有請(qǐng)求處理完成之后調(diào)用性誉,?不管有沒有異常,都會(huì)執(zhí)行茎杂,調(diào)用HandlerExecutionChain的triggerAfterCompletion方法 也是根據(jù)interceptorIndex?下標(biāo)倒序執(zhí)行
(8)?說說什么是HandlerMapping 错览?
HandlerMapping 組件,請(qǐng)求的處理器匹配器煌往,負(fù)責(zé)為請(qǐng)求找到合適的?HandlerExecutionChain?處理器執(zhí)行鏈倾哺,包含處理器(handler)和攔截器們(interceptors)轧邪,下面先說AbstractHandlerMapping
AbstractHandlerMapping?
AbstractHandlerMapping 抽象類,一個(gè)基類羞海,實(shí)現(xiàn)了“為請(qǐng)求找到合適的?HandlerExecutionChain?處理器執(zhí)行鏈”對(duì)應(yīng)的的骨架邏輯忌愚,而暴露?getHandlerInternal()?抽象方法,交由子類實(shí)現(xiàn)却邓。
HandlerMapping 處理器組件的實(shí)現(xiàn)類分為兩種:
AbstractUrlHandlerMapping
基于 URL 進(jìn)行匹配 硕糊,當(dāng)然,目前這種方式已經(jīng)基本不用了腊徙,被?@RequestMapping?等注解的方式所取代简十。不過,Spring MVC 內(nèi)置的一些路徑匹配撬腾,還是使用這種方式
AbstractHandlerMethodMapping
基于 Method 進(jìn)行匹配螟蝙。例如,我們所熟知的?@RequestMapping?等注解的方式
AbstractHandlerMethodMapping初始化時(shí)會(huì)掃描@Controller或者@RequestMapping注解標(biāo)注的 Bean 對(duì)象时鸵,會(huì)將帶有@RequestMapping注解(包括其子注解)解析成RequestMappingInfo對(duì)象胶逢。接下來厅瞎,會(huì)將RequestMappingInfo饰潜、該方法對(duì)象、該方法所在類對(duì)象往MappingRegistry注冊(cè)表進(jìn)行注冊(cè)和簸,其中會(huì)生成HandlerMethod處理器(方法的所有信息)對(duì)象保存起來彭雾。當(dāng)處理某個(gè)請(qǐng)求時(shí),HandlerMapping 找到該請(qǐng)求對(duì)應(yīng)的HandlerMethod處理器對(duì)象后锁保,就可以通過反射調(diào)用相應(yīng)的方法了
(9)?說一說HandlerAdapter 適配器薯酝?
? ? ? ? ? ? 因?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?
ServletInvocableHandlerMethod?封裝?HandlerMethod?處理器對(duì)象,它還包含?HandlerMethodArgumentResolver?參數(shù)解析器和?HandlerMethodReturnValueHandler?返回值處理器等組件
說一說HandlerMethodArgumentResolver?
參數(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
? 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è)
(10)說一說HandlerExceptionResolver 蛹找?
處理器異常解析器,將處理器執(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ì)象
(11)說一說ViewResolver ?
視圖解析器金顿,根據(jù)視圖名和國(guó)際化,獲得最終的視圖 View 對(duì)象鲤桥。Spring MVC 執(zhí)行完處理器后生成一個(gè) ModelAndView 對(duì)象揍拆,如果該對(duì)象不為?null?并且有對(duì)應(yīng)的?viewName,那么就需要通過?ViewResolver?根據(jù)?viewName?解析出對(duì)應(yīng)的 View 對(duì)象
(12)說一說MultipartResolver文件上傳
MultipartResolver?組件茶凳,內(nèi)容類型(?Content-Type?)為?multipart/*?的請(qǐng)求的解析器嫂拴,主要解析文件上傳的請(qǐng)求。例如贮喧,MultipartResolver?會(huì)將 HttpServletRequest 封裝成?MultipartHttpServletRequest?對(duì)象筒狠,
(13)Spring MVC 的核心組件大概描述一下
?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)類。例如瘤运,Spring MVC 默認(rèn)使用 MappingJackson2HttpMessageConverter
ServletRegistrationBean 和 FilterRegistrationBean 都繼成 RegistrationBean窍霞,它是 SpringBoot 中廣泛應(yīng)用的一個(gè)注冊(cè)類,負(fù)責(zé)把 Servlet拯坟,F(xiàn)ilter但金,Listener 給容器化,使它們被 Spring 托管郁季,并且完成自身對(duì) Web 容器的注冊(cè)