一涝焙、基礎(chǔ)知識(shí)介紹
1??@RequestBody
主要用來(lái)接收前端傳遞給后端的json
字符串中的數(shù)據(jù)(請(qǐng)求體中的數(shù)據(jù))
2??因?yàn)?code>GET方式無(wú)請(qǐng)求體卑笨,所以使用@RequestBody
接收數(shù)據(jù)時(shí),前端不能使用GET
方式提交數(shù)據(jù)仑撞,而是用POST
方式進(jìn)行提交赤兴。
3??在后端的同一個(gè)接收方法里,@RequestBody
與@RequestParam
可以同時(shí)使用隧哮。
4??一個(gè)請(qǐng)求桶良,只能有一個(gè)@RequestBody
,卻可以有多個(gè)@RequestParam
沮翔。
5??當(dāng)同時(shí)使用@RequestParam
和@RequestBody
時(shí)艺普,@RequestParam
指定的參數(shù)可以是普通元素、數(shù)組鉴竭、集合、對(duì)象等等(即:當(dāng)@RequestBody
與@RequestParam
可以同時(shí)使用時(shí)岸浑,原SpringMVC接收參數(shù)的機(jī)制不變搏存,只不過@RequestBody
接收的是請(qǐng)求體里面的數(shù)據(jù);而@RequestParam
接收的是key-value里面的參數(shù)矢洲,所以它會(huì)被切面進(jìn)行處理從而可以用普通元素璧眠、數(shù)組、集合读虏、對(duì)象等接收责静。)
6??如果參數(shù)是放在請(qǐng)求體中,傳入后臺(tái)的話盖桥,那么后臺(tái)要用@RequestBody
才能接收到灾螃;如果不是放在請(qǐng)求體中的話,那么后臺(tái)接收前臺(tái)傳過來(lái)的參數(shù)時(shí)揩徊,要用@RequestParam
來(lái)接收腰鬼,或形參前什么也不寫也能接收嵌赠。如果參數(shù)前寫了@RequestParam(xxx)
,那么前端必須有對(duì)應(yīng)的xxx名字才行(不管其是否有值熄赡,當(dāng)然可以通過設(shè)置該注解的required屬性來(lái)控制是否必須傳)姜挺,如果沒有xxx名的話,那么請(qǐng)求會(huì)出錯(cuò)彼硫,報(bào)400炊豪。
注:如果參數(shù)前不寫@RequestParam(xxx)
的話,那么就前端可有可無(wú)對(duì)應(yīng)的xxx名字拧篮,如果有xxx名的話词渤,那么就會(huì)自動(dòng)匹配;沒有的話他托,請(qǐng)求也能正確發(fā)送掖肋。
注意:這里與feign消費(fèi)服務(wù)時(shí)不同:
- feign消費(fèi)服務(wù)時(shí),如果參數(shù)前什么也不寫赏参,那么會(huì)被默認(rèn)是
@RequestBody
的志笼。 - 如果后端參數(shù)是一個(gè)對(duì)象,且該參數(shù)前是以
@RequestBody
修飾的把篓,那么前端傳遞json
參數(shù)時(shí)纫溃,必須滿足以下要求:后端@RequestBody
注解對(duì)應(yīng)的類在將HTTP
的輸入流(含請(qǐng)求體)裝配到目標(biāo)類(即:@RequestBody
后面的類)時(shí),會(huì)根據(jù)json
字符串中的key來(lái)匹配對(duì)應(yīng)實(shí)體類的屬性韧掩,如果匹配一致且json
中的該key對(duì)應(yīng)的值符合(或可轉(zhuǎn)換為)實(shí)體類的對(duì)應(yīng)屬性的類型要求時(shí)紊浩,會(huì)調(diào)用實(shí)體類的setter方法將值賦給該屬性。
json
字符串中疗锐,如果value為""的話坊谁,后端對(duì)應(yīng)屬性如果是String類型的,那么接受到的就是""滑臊,如果是后端屬性的類型是Integer口芍、Double等類型,那么接收到的就是null雇卷。json
字符串中鬓椭,如果value為null的話,后端對(duì)應(yīng)收到的就是null关划。如果某個(gè)參數(shù)沒有value的話小染,在傳json
字符串給后端時(shí),要么干脆就不把該字段寫到json
字符串中贮折;要么寫value時(shí)裤翩, 必須有值,null 或""都行调榄。
二岛都、@RequestBody
與前端傳過來(lái)的json
數(shù)據(jù)的匹配規(guī)則
聲明:根據(jù)不同的Content-Type
等情況律姨,Spring-MVC
會(huì)采取不同的HttpMessageConverter
實(shí)現(xiàn)來(lái)進(jìn)行信息轉(zhuǎn)換解析。下面介紹的是最常用的:前端以Content-Type
為application/json
傳遞json
字符串?dāng)?shù)據(jù)臼疫,后端以@RequestBody
模型接收數(shù)據(jù)的情況择份。
解析json數(shù)據(jù)大體流程概述:Http傳遞請(qǐng)求體信息,最終會(huì)被封裝進(jìn)com.fasterxml.jackson.core.json.UTF8StreamJsonParser
中(提示:Spring采用CharacterEncodingFilter
設(shè)置了默認(rèn)編碼為UTF-8)烫堤,然后在public class BeanDeserializer extends BeanDeserializerBase implements java.io.Serializable
中荣赶,通過 public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException
方法進(jìn)行解析。
三鸽斟、結(jié)論
-
@JsonAlias
注解拔创。實(shí)現(xiàn)json
轉(zhuǎn)模型時(shí),使json
中的特定key能轉(zhuǎn)化為特定的模型屬性富蓄;但是模型轉(zhuǎn)json
時(shí)剩燥,對(duì)應(yīng)的轉(zhuǎn)換后的key仍然與屬性名一致, -
@JsonProperty
注解立倍。實(shí)現(xiàn)json
轉(zhuǎn)模型時(shí)灭红,使json
中的特定key能轉(zhuǎn)化為指定的模型屬性;同樣的口注,模型轉(zhuǎn)json
時(shí)变擒,對(duì)應(yīng)的轉(zhuǎn)換后的key為指定的key。 -
@JsonAlias
注解需要依賴于setter寝志、getter娇斑,而@JsonProperty
注解不需要。 - 在不考慮上述兩個(gè)注解的一般情況下材部,key與屬性匹配時(shí)毫缆,默認(rèn)大小寫敏感。
- 有多個(gè)相同的key的
json
字符串中乐导,轉(zhuǎn)換為模型時(shí)悔醋,會(huì)以相同的幾個(gè)key中,排在最后的那個(gè)key的值給模型屬性復(fù)制兽叮,因?yàn)閟etter會(huì)覆蓋原來(lái)的值。 - 后端
@RequestBody
注解對(duì)應(yīng)的類在將HTTP
的輸入流(含請(qǐng)求體)裝配到目標(biāo)類(即:@RequestBody
后面的類)時(shí)猾愿,會(huì)根據(jù)json
字符串中的key來(lái)匹配對(duì)應(yīng)實(shí)體類的屬性鹦聪,如果匹配一致且json
中的該key對(duì)應(yīng)的值符合(或可轉(zhuǎn)換為)實(shí)體類的對(duì)應(yīng)屬性的類型要求時(shí),會(huì)調(diào)用實(shí)體類的setter方法將值賦給該屬性蒂秘。
四泽本、在使用Json傳值并且使用@RequestBody注解的時(shí)候需要注意的問題
1??一個(gè)方法中只能有一個(gè)@RequestBody注解。
因?yàn)镽equestBody就是request的inputStream姻僧,這個(gè)流在第一次使用該注解后會(huì)關(guān)閉规丽,后面的都會(huì)報(bào)錯(cuò)(stream closed)蒲牧。
2??默認(rèn)情況下@RequestBody標(biāo)注的對(duì)象必須包含前臺(tái)傳來(lái)的所有字段。如果沒有包含前臺(tái)傳來(lái)的字段赌莺,就會(huì)報(bào)錯(cuò):Unrecognized field xxx , not marked as ignorable冰抢,出現(xiàn)這種問題是因?yàn)槭褂胘ackson進(jìn)行json轉(zhuǎn)換時(shí),MappingJacksonHttpMessageConverter默認(rèn)要求必須存在相應(yīng)的字段艘狭。如果沒有前臺(tái)傳來(lái)的某個(gè)字段或者字段沒有提供set方法挎扰,就會(huì)報(bào)錯(cuò)。解決方法:
- 可以增加一個(gè)字段來(lái)接收前臺(tái)傳來(lái)的這個(gè)值巢音,如果存在多個(gè)字段遵倦,這種方式很不好(就算一個(gè)字段,如果沒用官撼,新增字段也不好)梧躺。
- 在前臺(tái)往后臺(tái)傳值的時(shí)候,去掉無(wú)用的字段傲绣。這樣還能減少網(wǎng)絡(luò)傳輸?shù)拇笮 ?/li>
- 使用Jackson提供的json注解:
-
@JsonIgnore
注解用來(lái)忽略某些字段掠哥,可以用在Field或者Getter方法上,用在Setter方法時(shí)斜筐,和Filed效果一樣龙致。這個(gè)注解只能用在POJO存在的字段要忽略的情況,不能滿足現(xiàn)在需要的情況顷链。 -
@JsonIgnoreProperties(ignoreUnknown = true)
目代,將這個(gè)注解寫在類上之后,就會(huì)忽略類中不存在的字段嗤练,可以滿足當(dāng)前的需要榛了。這個(gè)注解還可以指定要忽略的字段。如:@JsonIgnoreProperties({ "internalId", "secretKey"})
指定的字段不會(huì)被序列化和反序列化煞抬。