Spring MVC 面試總結(jié)

(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è)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末冷溃,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子梦裂,更是在濱河造成了極大的恐慌似枕,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件年柠,死亡現(xiàn)場(chǎng)離奇詭異凿歼,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)冗恨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門答憔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人派近,你說我怎么就攤上這事攀唯。” “怎么了渴丸?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)另凌。 經(jīng)常有香客問我谱轨,道長(zhǎng),這世上最難降的妖魔是什么吠谢? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任土童,我火速辦了婚禮,結(jié)果婚禮上工坊,老公的妹妹穿的比我還像新娘献汗。我一直安慰自己敢订,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布罢吃。 她就那樣靜靜地躺著楚午,像睡著了一般。 火紅的嫁衣襯著肌膚如雪尿招。 梳的紋絲不亂的頭發(fā)上矾柜,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音就谜,去河邊找鬼怪蔑。 笑死,一個(gè)胖子當(dāng)著我的面吹牛丧荐,可吹牛的內(nèi)容都是我干的缆瓣。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼虹统,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼捆愁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起窟却,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤昼丑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后夸赫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體菩帝,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年茬腿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了呼奢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡切平,死狀恐怖握础,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情悴品,我是刑警寧澤禀综,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站苔严,受9級(jí)特大地震影響定枷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜届氢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一欠窒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧退子,春花似錦岖妄、人聲如沸型将。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)七兜。三九已至,卻和暖如春缚俏,著一層夾襖步出監(jiān)牢的瞬間惊搏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來泰國(guó)打工忧换, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留恬惯,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓亚茬,卻偏偏與公主長(zhǎng)得像酪耳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子刹缝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容