spring MVC中接口參數(shù)解析的過程詳解
前言
前天工作中遇到了這樣一個(gè)問題,我在接口的參數(shù)封裝了一個(gè)pojo,這是很常見的,當(dāng)參數(shù)一多,慣性的思維就是封裝一個(gè)pojo.那么在參數(shù)前有很多注解可以添加,比如:@requestParam,@requestBody,@pathvariable等。我的理解是這樣的,首先我先申明,我并是沒有看過源碼,只是憑經(jīng)驗(yàn)理解。@requestParam試用于get請(qǐng)求,參數(shù)在http的header中的URL上,具體放在?后面以key=value的形式存在。@requestBody適用于post請(qǐng)求中參數(shù)在http的body中。@pathvariable比較特別是restful的寫法,把參數(shù)放在URL上,不用問號(hào)區(qū)分是參數(shù)還是URL。也許我這樣說不是很準(zhǔn)確。但我通常也是這么用的。與此同時(shí),還有一種常見的寫法,就是參數(shù)前不加注解,比如參數(shù)是基本類型的不加@requestParam,參數(shù)是bean的不加requestBody,也能被springmvc解析得到。我的接口被小組長看到之后他叫我去掉這個(gè)@requestBody,因?yàn)楹蠖思由线@個(gè)之后,前端的ajax請(qǐng)求需要顯示的聲明content-type:"application/json",才能被springmvc解析得到,這樣似乎多做了一件不必要的事情。雖然我按照他的要求去掉了,但是我覺得我得弄清楚這到底是怎么回事,加與不加到底有什么區(qū)別,對(duì)性能有什么影響,或者各自的最佳適用場景,除了百度,還得問問大神。
spring MVC接口參數(shù)解析的過程
首先我自己慢慢的通過debug研究了一下源碼。在不添加任何注解的情況下:
在開發(fā)的過程中consumes和produces一般都沒有加,按道理應(yīng)該要加上,因?yàn)榭梢詼p少對(duì)接口的查找范圍。這是一個(gè)簡單的demo,我只是需要他來檢查springmvc接收請(qǐng)求的流程。
首先在tomcat啟動(dòng)之后,所有controller類中的請(qǐng)求路徑也就是@requestMapping隨著Controller這個(gè)bean加載到了spring的容器中。頁面請(qǐng)求過來之后找到DispatcherServlet這個(gè)servlet,請(qǐng)求走到servlet之后大家都知道servlet有兩種初始化方式,一種是隨著立即加載,一種是延遲加載,但是無論怎樣,都是只調(diào)用一次init方法,然后再以后每次都會(huì)直接調(diào)用service方法,當(dāng)tomcat關(guān)閉之后servlet的destroy方法被調(diào)用生命周期就結(jié)束了。所以springmvc是對(duì)servlet的封裝就必定要繼承service方法,DispatcherServlet也就是doDispatch這個(gè)方法。這個(gè)方法中通過HttpServletRequest對(duì)象獲得請(qǐng)求路徑也就是/notJson,然后與容器中的所有url對(duì)比,最終取得Controller中的接口所在。找到了接口自然就知道了接口的參數(shù),我這里就是Display,為了方便簡單,Display中只有兩個(gè)參數(shù),就是下面ajax請(qǐng)求中的兩個(gè)。
springmvc會(huì)通過反射的方式獲取到pojo中的屬性。在這個(gè)過程中首先springmvc會(huì)先聲明一個(gè)數(shù)組,這個(gè)數(shù)組的大小是參數(shù)的個(gè)數(shù),我這里只有一個(gè),其實(shí)我相信很多人會(huì)和我遇到相同的問題就是,當(dāng)參數(shù)中同時(shí)存在bean和基本類型的參數(shù),springmvc將怎么解析,這個(gè)我遇到過幾次,在沒有看源碼的情況下,把基本類型也封裝到bean中去了,讓前端把屬性也寫在一個(gè)對(duì)象中。當(dāng)然我相信這個(gè)不是每個(gè)人都能接受的做法,我們都希望搞清楚他究竟是怎樣解析的,到時(shí)候我們就可以任意擺弄了。下面是反射過程,將我的pojo反射之后獲得里面的屬性和方法。解析了參數(shù)之后,為參數(shù)賦值。這里也許是最重要的地方了。究竟是怎么賦值的。
從這個(gè)方法debug了解到,name為display,也就是pojo類名的小寫,這里不知道為什么springmvc做了這個(gè)處理(以后再看)。attribute為帶有age和name的對(duì)象。不過此時(shí)都是null。WebDataBinding用于從Web請(qǐng)求參數(shù)到JavaBean對(duì)象的數(shù)據(jù)綁定的特殊DataBinder。接上圖bindRequestParameters這個(gè)方法,跟進(jìn)去會(huì)發(fā)現(xiàn)一個(gè)很熟悉的地方就是下圖,通過String[] values = request.getParameterValues(paramName);
獲得參數(shù)名,這個(gè)是servlet的獲取參數(shù)方法,那么就可以知道請(qǐng)求的參數(shù)的屬性名和屬性值。
接下來可想而知就是把這個(gè)參數(shù)名name換成bean的屬性name,參數(shù)名age換成屬性名age。再跟到這個(gè)地方,這個(gè)oragina就是上面serclet拿到的屬性名值對(duì),把這個(gè)map在這轉(zhuǎn)化成PropertyValue。(PropertyValue是用于保存單個(gè)bean屬性的信息和值的對(duì)象。 在此處使用對(duì)象,而不是僅將所有屬性存儲(chǔ)在由屬性名稱鍵入的映射中,允許更靈活,并且能夠以優(yōu)化的方式處理索引屬性等。請(qǐng)注意,該值不需要是最終所需的類型:BeanWrapper實(shí)現(xiàn)應(yīng)該處理任何必要的轉(zhuǎn)換,因?yàn)榇藢?duì)象不知道它將應(yīng)用于哪些對(duì)象。),如此一來就有兩個(gè)PropertyValue對(duì)象了。
轉(zhuǎn)化的時(shí)候會(huì)忽略不知道的屬性
上圖是具體轉(zhuǎn)化的方法,方法比較長。下面一句直接給bean賦值。從這個(gè)過程來看。只要前端的json對(duì)象的屬性和后端的bean屬性一樣,ajax不寫content-type,用默認(rèn)的application/x-www-form-urlencoded; charset=UTF-8
,就能直接賦值。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- Spring Boot配置接口WebMvcConfigurer的實(shí)現(xiàn)
- Spring MVC接口防數(shù)據(jù)篡改和重復(fù)提交
- SpringMVC編程使用Controller接口實(shí)現(xiàn)控制器實(shí)例代碼
- Springmvc Controller接口代碼示例
- SpringMVC Restful api接口實(shí)現(xiàn)的代碼
- Spring MVC的優(yōu)點(diǎn)與核心接口_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- Spring MVC 使用支付寶接口完成在線支付的示例代碼
- springMVC利用FastJson接口返回json數(shù)據(jù)相關(guān)配置詳解
- 基于Mock測(cè)試Spring MVC接口過程解析
相關(guān)文章
Spring Boot中利用JavaMailSender發(fā)送郵件的方法示例(附源碼)
這篇文章主要介紹了Spring Boot中利用JavaMailSender發(fā)送郵件的方法示例, 相信使用過Spring的眾多開發(fā)者都知道Spring提供了非常好用的JavaMailSender接口實(shí)現(xiàn)郵件發(fā)送。在Spring Boot的Starter模塊中也為此提供了自動(dòng)化配置。需要的朋友可以參考借鑒。2017-02-02Idea如何關(guān)閉或開啟引用提示Usages和Annotations
這篇文章主要介紹了Idea如何關(guān)閉或開啟引用提示Usages和Annotations問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01IntelliJ IDEA使用教程從入門到上癮(2019圖文版)
這篇文章主要介紹了IntelliJ IDEA使用教程從入門到上癮(2019圖文版),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12Java 對(duì) Properties 文件的操作詳解及簡單實(shí)例
這篇文章主要介紹了Java 對(duì) Properties 文件的操作詳解及簡單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-02-02SpringBoot+MinIO實(shí)現(xiàn)對(duì)象存儲(chǔ)方式
這篇文章主要介紹了SpringBoot+MinIO實(shí)現(xiàn)對(duì)象存儲(chǔ)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08