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\n 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, 如果同时存在, 那么会组装成一个数组, 或者逗号分隔的字符串..

Http的那些事: Content-Type的更多相关文章

  1. Jsoup问题---获取http协议请求失败 org.jsoup.UnsupportedMimeTypeException: Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml.

    Jsoup问题---获取http协议请求失败 1.问题:用Jsoup在获取一些网站的数据时,起初获取很顺利,但是在访问某浪的数据是Jsoup报错,应该是请求头里面的请求类型(ContextType)不 ...

  2. Jsoup获取部分页面数据失败 org.jsoup.UnsupportedMimeTypeException: Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml.

    用Jsoup在获取一些网站的数据时,起初获取很顺利,但是在访问某浪的数据是Jsoup报错,应该是请求头里面的请求类型(ContextType)不符合要求. 请求代码如下: private static ...

  3. SharePoint自动化系列——Add content type to list.

    转载请注明出自天外归云的博客园:http://www.cnblogs.com/LanTianYou/ 将创建好的content type(若是跨web application需要事先publish c ...

  4. SharePoint自动化系列——Content Type相关timer jobs一键执行

    转载请注明出自天外归云的博客园:http://www.cnblogs.com/LanTianYou/ 背景: 在SharePoint Central Administration->Monito ...

  5. 转载 SharePoint【Site Definition 系列】– 创建Content Type

    转载原地址:  http://www.cnblogs.com/wsdj-ITtech/archive/2012/09/01/2470274.html Sharepoint本身就是一个丰富的大容器,里面 ...

  6. the request doesn't contain a multipart/form-data or multipart/form-data stream, content type header

    the request doesn't contain a multipart/form-data or multipart/form-data stream, content type header ...

  7. Springs Element 'beans' cannot have character [children], because the type's content type is element-only

    Springs Element 'beans' cannot have character [children], because the type's content type is element ...

  8. springboot 报错 Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported

    开始 controller 方法写的是 @RequestMapping( value = "/add", method = RequestMethod.POST ) public ...

  9. .NET获取文件的MIME类型(Content Type)

    第一种:这种获取MIME类型(Content Type)的方法需要在.NET 4.5之后才能够支持,但是非常简单. 优点:方便快捷 缺点:只能在.NET 4.5之后使用 public FileResu ...

  10. 万能的ctrl+shift+F(Element 'beans' cannot have character [children], because the type's content type is element-only.错误)

    今天在spring-servlet.xml文件中出现了一个莫名其妙的错误:Element 'beans' cannot have character [children], because the t ...

随机推荐

  1. 2 第一个Django应用 第1部分(数据库与模型)

    目标应用: 一个公开的网站,可以让访客查看投票的结果并让他们进行投票. 一个后台管理网站,你可以添加.修改和删除选票. 查看django版本 python -c "import django ...

  2. Selenium+Eclipse+Python 环境搭建

    第一步:安装Python 根据下面的地址,直接一键安装,全部默认方式. 下载地址:http://www.python.org/ftp/python/2.7.5/python-2.7.5.msi 安装到 ...

  3. Verilog中的$display和$write任务

    $display(p1,p2, …,pn); $write(p1,p2, …,pn); 这两个函数和系统任务的作用都是用来输出信息,即将参数p2到pn按参数p1给定的格式输出.参数p1通常称为:“格式 ...

  4. 马凯军201771010116《面向对象程序设计Java》第八周学习总结

    一,理论知识学习部分 6.1.1 接口概念 两种含义:一,Java接口,Java语言中存在的结构,有特定的语法和结构:二,一个类所具有的方法的特征集合,是一种逻辑上的抽象.前者叫做“Java接口”,后 ...

  5. Windows10 VS2017 C++ ini解析(使用simpleini头文件)

    simpleini项目地址: https://github.com/brofield/simpleini 下载,新建项目,并将SimpleIni.h文件通过包含目录的方式加载进来. 创建test.in ...

  6. RPi 3B Aduio 3.5mm output

    /********************************************************************** * RPi 3B Aduio 3.5mm output ...

  7. 深入理解使用synchronized同步方法和同步代码块的区别

    一.代码块和方法之间的区别 首先需要知道代码块和方法有什么区别: 构造器和方法块,构造器可以重载也就是说明在创建对象时可以按照不同的构造器来创建,那么构造器是属于对象,而代码块呢他是给所有的对象初始化 ...

  8. PythonStudy——名称空间 Name space

    # 名称空间:就是名字与地址的对应关系,可以被Python解释器遍历查找,采用堆栈存储方式 # 三种名称空间# Built-in:内置名称空间:系统级,一个:随解释器执行而产生,解释器停止而销毁# G ...

  9. awk命令过滤tomcat的访日日志中IP地址

    1. 命令如下 批量过滤日志文件,grep -v是要排除10网段开头的IP地址 sort会自动按ip排序 uniq -c去重并计数 sort -n 按数值从小到大排序 [root@linux-node ...

  10. Python Django orm操作数据库笔记之QuerySet API

    什么时候Django会将QuerySet转换为SQL去执行: 根据Django的数据库机制,对于QuerySet来说,当QuerySet被第一次构建,然后又调用他的filter方法,接着在对其进行切片 ...