zoukankan      html  css  js  c++  java
  • Http的那些事: Content-Type

    Content-Type 无疑是http中一个非常重要的属性了, request 中可以存在, 也可以不存在( request的Content-Type 默认是 */*, 实际上呢, 如果不存在Content-Type请求头, 那么 就是text.. 待确定 ), response也是这样. 如果是普通text/ css/ img, 响应头Content-Type 好像是找不到的了,  如果是json 返回, 那么 Content-Type 肯定是存在的 . 这, 非常的灵活...

    @PostMapping("add")
    @ApiOperation(value = "新增")
    public String add(@RequestBody String groupName) {
    return "hi" + groupName;
    }
    对应url : http://10.10.10.76:5555/mq-service-lk/test

    参数应该怎么传呢? @RequestBody 表明了 Content-Type 应该是 application/json , 即
    Content-Type: application/json

    对于@RequestBody, Content-Type必须是 application/json 否则后端返回 415:
    {
    "timestamp": 1531815175323,
    "status": 415,
    "error": "Unsupported Media Type",
    "exception": "org.springframework.web.HttpMediaTypeNotSupportedException",
    "message": "Content type 'text/plain;charset=UTF-8' not supported",
    "path": "/test/bbb"
    }

    如果想使用 @RequestBody, 但是只有一个参数, 而且是 String, 那么只有把参数进行封装了(这样做确实非常别扭不情愿), 或者使用Map 参见: https://www.oschina.net/question/227902_162591

    但是呢, 如果我们使用 postman, 我们发现:
    1 不设置 Content-Type, body 填: { "groupaName": "aaaasdfsadf"} 完全是没问题的.. 也就是说, springmvc 的@RequestBody 并没有强制作用, 但是, 后端接收到的数据, 并不是json, 而是 一个字符串..
    2 设置Content-Type: application/json, body 填: { "groupaName": "aaaasdfsadf"}, 出现400, 前端收到返回:

    {
    "timestamp": "2018-07-17 12:45:54",
    "status": 400,
    "error": "Bad Request",
    "exception": "org.springframework.http.converter.HttpMessageNotReadableException",
    "message": "JSON parse error: Can not deserialize instance of java.lang.String out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token at [Source: java.io.PushbackInputStream@3e291882; line: 1, column: 1]",
    "path": "/test"
    }

    后端出现:
    2018-07-17 11:14:59.233 WARN 18384 --- [nio-8083-exec-5] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not deserialize instance of java.lang.String out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
    at [Source: java.io.PushbackInputStream@7744171e; line: 1, column: 1]
    (注意, 这里是 WARN, 不仔细看是发现不了的..)

    为什么出现这样的情况呢? 非常奇怪了, 一样的代码, 在别的项目中没有重现,

    @RestController
    @RequestMapping("/test")
    public class DemoController {

    @PostMapping(value = "aaa")
    public String add(@RequestBody String groupName) {
    System.out.println("groupName = " + groupName);
    return "hi, " + groupName;
    }
    ...

    参考了 https://blog.csdn.net/fzz1022/article/details/78649020, 好像是... jar 问题?


    方法改成这样:
    add(@Valid String groupName)
    发现,

    不管Content-Type 是什么, groupName 的值一直都是 null, 就是说, 根本传值不了..

    方法改成这样:
    add(String groupName), 再尝试:

    post请求自动变成了 get 请求一样: http://10.10.10.76:5555/mq-service-lk/test?groupName=asdff 这时候PostMapping 跟 GetMapping 完全一样.. swagger 似乎也有坑.. 有时候需要刷新, 有时候有不需要..

    注意, 此时, Content-Type: application/x-www-form-urlencoded 必须这样才可以!!!!!!!!! 其他 都不行, 而且 body 应该是这样的:
    groupName=g1


    坑爹了, 为啥我传递一个json 参数就这么难,, 我想做的只是, 传递这样格式的数据啊:
    type 为 Content-Type: application/json, body 为:

    {"groupaName": "g1"}
    { groupaName: "g1"}

    groupaName 是否有引号, 好像不用紧的...

    后面终于明白, add(@RequestBody String groupName) , 因为 groupName 类型是 String, 是无论如何无法 接收json 的,,, 必须把 groupName 进行封装, 比如封装到一个对象里面, 而后提供getter/setter.. 或者使用Map.

    PostMapping 方法又是不允许 get 方式请求的..

    非常蛋疼了, postman 的body 格式, 从 Content-Type: application/x-www-form-urlencoded 切换 到 Content-Type: application/json 的时候, 有个bug, 坑爹, Content-Type 竟然没有改变..


    问题是, 为啥body 有时候要求是这样:
    groupName=g1
    有时候是:
    { groupaName: "g1"} 或 {"groupaName": "g1"}

    而有时候是
    g1 或"g1"

    因为springmvc 可以对 Content-Type 设置一定的要求, 而且, 不同Content-Type 要求的body 也是不一样的..


    改成这样:
    add(@Valid String groupName) 发现 @Valid 有奇怪的作用, 导致完全接受不到 参数了. . 不管请求头的 Content-Type 怎么设置, groupName 都是null, 底层原因待查

    总结:

    1 对于 @RequestBody, body 是不能少的, 也就是说, 如果有@RequestBody 那么请求方法不能是get, 因为get 会忽略 已经设置的body, 不传送..
    2 springmvc 可以对 Content-Type 设置一定的要求, 而且, 不同Content-Type 要求的body 也是不一样的
    3 如果@RequestBody, GetMapping 同时添加到一个方法上, 那么会出现:
    {"timestamp":"2018-07-17 13:15:14","status":400,"error":"Bad Request","exception":"org.springframework.http.converter.HttpMessageNotReadableException","message":"Required request body is missing: public String com.xx.add(java.lang.String)","path":"/test"}
    4 post 方法既传递url query string, 也传递request body, 如果同时存在, 那么会组装成一个数组, 或者逗号分隔的字符串..

  • 相关阅读:
    Python学习之列表
    Python学习笔记
    Linux基础命令总结
    CentOS6.6安装mysql-5.7.25二进制安装包简易教程
    执行 cobbler get-loaders报错
    windows下 Qt 安装 taglib 获取媒体信息windows
    Qt dropEvent和dragEnterEvent问题
    Qt---去掉标题栏后,最大化应用程序窗口时,窗口遮住了任务栏的问题
    Qt 单击任务栏图标实现最小化
    Qt 无边框窗口的两种实现
  • 原文地址:https://www.cnblogs.com/FlyAway2013/p/9322848.html
Copyright © 2011-2022 走看看