@RequestBody修饰对象几种情景测试

[TOC]

@RequestBody测试.png

问题起因:

关于 @RequestBody 注解使用的几点疑问:

事情的起因是这样的,入职新公司之后,查看代码,见到了一种写法,感到十分奇怪:

@PostMapping("/xxx/yyy")
public Result<Boolean> createXXX(PaymentServiceDTO serviceDTO, PaymentAccountDTO accountDTO) {

}
  • 按照 Restful Http请求来说,POST 请求的参数一般是放到 Body 中的,这种写法我理解是不允许的。
  • 其次,POST 请求中放入了两个请求对象,记得之前有同事告诉我 @RequestBody 用于 POST请求,作用是将请求中的 Body json 数据解析为对象类型,方便操作,但是 @RequestBody 只能在一个 Mapping 中使用一次。
  • 后来还看到类似下面的代码,更增加了我的疑惑
@PostMapping("/xxx/yyy")
public Result<Boolean> createXXX(@RequestBody PaymentServiceDTO serviceDTO, PaymentAccountDTO accountDTO) {

}

  1. 该项目 POST 请求为什么会有上面的写法?
  2. @RequestBody 能否修饰多个对象?
  3. @RequestBody 修饰一个对象,但是像上面没有修饰的对象会怎么处理?
  4. 如果像上面一样,两个对象都不用 @RequestBody 修饰,那么参数应该放在哪里?又是怎么解析为对象的?

上面已经十分明白,我还是挺佩服的,这里说下后三个问题的答案:

Answer:

  1. @RequestBody 不能修饰多个对象,在一个方法中同时使用该注解,编译能通过,运行时会抛出异常
  2. 即使是 POST 请求,默认的参数类型也是 application/x-www-form-urlencoded,即参数作为 query param,放到 url 的后面。因此这种就好解释了
  • @RequestBody 修饰的对象,会填充 Body 中的参数
  • 没有修饰的对象,会由 query param 中的参数进行填充
  1. 如果都不用,就都会由 query param 中进行解析,填充入各个对象中,唯一的问题就是对象属性名不能相同,相同的属性名会被填充相同的值。

问题测试:

下面是测试的示例:

1. 使用 @RequestBody 修饰正常的情况

后端代码:

    @PostMapping("/normal")
    public void printInfo1(@RequestBody User user) {
        log.info("user   -->" + user);
    }

调用:

curl -X POST --header "Content-Type: application/json" --header "Accept: */*" -d "{
\"firstName\": \"firstname\",
\"lastName\": \"lastname\"
}" "http://localhost:8080/normal"
2019-05-10 19:20:22.920  INFO 2129 --- [io-8080-exec-10] com.example.demo.TestController          : user   -->User(id=0, firstName=firstname, lastName=lastname)

2. 不使用 @RequestBody 修饰

后端代码:

@PostMapping("/with_no_annotation")
    public void printInfo2(User user) {
        log.info("user   -->" + user);
    }

调用:

  • 参数放到 Body 中
curl -v -X POST --header "Content-Type: application/json" --header "Accept: */*" -d "{
\"firstName\": \"firstname\",
\"lastName\": \"lastname\"
}" "http://localhost:8080/with_no_annotation"
2019-05-10 19:36:36.742  INFO 2129 --- [nio-8080-exec-5] com.example.demo.TestController          : user   -->User(id=0, firstName=null, lastName=null)
  • 参数放到查询参数中
curl -v -X POST \
  http://localhost:8080/with_no_annotation \
  -d 'firstName=firstname&lastName=lastname'
2019-05-10 19:39:09.072  INFO 2129 --- [nio-8080-exec-1] com.example.demo.TestController          : user   -->User(id=0, firstName=firstname, lastName=lastname)

3. 传递两个对象,一个使用 @RequestBody 注解,一个不使用

后端代码:

    @PostMapping("/with_one_have")
    public void printInfo3(@RequestBody User user, ProductInfo productInfo) {
        log.info("user   -->" + user);
        log.info("product-->" + productInfo);
    }

调用:

  • 参数一个放在 Body 中,一个放入到 query param中
curl -X POST \
  'http://localhost:8080/with_one_have?productName=productName&productDesc=productDesc' \
  -H 'Content-Type: application/json' \
  -d '{
"firstName": "firstname",
"lastName": "lastname"
}'
2019-05-10 19:49:56.695  INFO 2129 --- [nio-8080-exec-2] com.example.demo.TestController          : user   -->User(id=0, firstName=firstname, lastName=lastname)
2019-05-10 19:49:56.695  INFO 2129 --- [nio-8080-exec-2] com.example.demo.TestController          : product-->ProductInfo(id=0, productName=productName, productDesc=productDesc)

4. 两个对象参数都使用 @RequestBody 修饰

后端代码:

    @PostMapping("/with_all_have_annotation")
    public void printInfo4(@RequestBody User user, @RequestBody ProductInfo productInfo) {
        log.info("user   -->" + user);
        log.info("product-->" + productInfo);
    }

调用:

  • 调用方法都没有办法写。。。。。。。
  • 下面是使用一个Json作为参数传递
curl -X POST --header "Content-Type: application/json" --header "Accept: */*" -d "{
    \"productName\":\"productName\",
    \"productDesc\":\"productDesc\"
}" "http://localhost:8080/with_all_have_annotation"
2019-05-10 19:54:50.903  WARN 2129 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: I/O error while reading input message; nested exception is java.io.IOException: Stream closed]

5. 两个对象参数都不使用 @RequestBody修饰

后端代码:

    @PostMapping("/with_all_no_annotation")
    public void printInfo5(User user, ProductInfo productInfo) {
        log.info("user   -->" + user);
        log.info("product-->" + productInfo);
    }

调用:

出现问题当对象包含相同的字段时,会被覆盖为相同的值

 curl -X POST \
  'http://localhost:8080/with_all_no_annotation?id=1111&firstName=li&lastName=haifei&productName=productName&productDesc=productDesc'
2019-05-10 19:56:27.394  INFO 2129 --- [nio-8080-exec-7] com.example.demo.TestController          : user   -->User(id=1111, firstName=li, lastName=haifei)
2019-05-10 19:56:27.394  INFO 2129 --- [nio-8080-exec-7] com.example.demo.TestController          : product-->ProductInfo(id=1111, productName=productName, productDesc=productDesc)

6. 总结

看完上面,应该已经明白上面问题的答案了。其实这里如果看过源码,应该很好就解决了,奈何这里没看,只能使用比较笨的方法。还是源码大法好啊!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容