• 前言
    最近在和三方对接的时候发现了一些问题,这也是我写这篇文章的原因。我大概花了三天时间把这些内容了解,实践,整理,然后分享给大家,希望对大家会有所帮助。废话不多说,在和三方对接的时候我们规定使用json作为通信数据格式,而有些三方定义Content-Type而有些就不定义,这样导致我后台定义的一些接口他们无法访问,所以我自己就动手做了些实验。这篇博文的目录为:前言-结论-实验-讲解-总结五大块。之所以把讲解放后面是因为先让大家看结果,然后自己带着思考去看讲解,而且有些人只想看实验这样也不会让费大家的时间,大家可以认真的看看结论哦。
  • 结论
    1,get请求时是否定义Content-Type并无很大的影响,因为get没有请求体,所有的数据都是通过url带过去,所以必须是key=value的格式,所以在springmvc端使用@RequestParam String id这种格式即可,或者不写@RequestParam也可以,不写的话默认是@RequestParam。

    2,除get外的这几种(POST、DELETE、PUT、PATCH)都是有请求体(body)的,且他们之间的差异不大,所以归在一起:
    当请求时定义Content-Type为application/json; charset=utf-8时,请求体中的数据(不管是不是json格式)都只能用@RequestBody获取,且一个方法参数列表最多写一个@RequestBody,当然你也可以在请求url上带其他的queryString参数,然后再springmvc使用String
    id或@RequestParam String id获取。再次重申是这种情况下@RequestParam是无法获取请求体(body)中的参数的,springmvc会报错:Required
    String parameter 'name' is not present。所以这种情况只能使用
    @RequestBody获取请求体中的参数。至于你使用Bean接收还是String接收取决你的需求,Bean接收更方便,不需要再次反序列化,而String接收可以更灵活,可以对接收到的字段进行检查。
    当请求时未定义Content-Type(默认为application/x-www-form-urlencoded; charset=UTF-8),请求体中的数据都必须是key=values的类型,可以是使用@RequestBody获取整个请求体中的多个参数,也可以使用@RequestParam获取单个参数
  • 实验
    首先我说明一下我测试的思路及流程,我后台使用的是springmvc,然后我在后台定义了一个接口,然后我使用js放入chrom的console下去执行。将每次执行结果记录下来,然后改变Content-Type再实验,对于Content-Type我只实验了两种:application/json;
    charset=utf-8 和 application/x-www-form-urlencoded; charset=UTF-8因为这两种是比较常用的对我而言。HTTP方法我试验了5种:GET、POST、DELETE、PUT、PATCH相对来说这几种还是用的比较多。SpringMVC中涉及的注解:@RequestBody、@RequestParam、@RequestMapping等

    js请求代码
    $.ajax({
            url: "http://localhost:9080/api/thirdparty/policy?id=1",
            dataType: "json",
            //data: "fields='55'",
    	data: "name='abc'",
    	//data: "{'name':'abc'}",
    	//data: "{'name':'abc'}",
    	headers: {
    			'Accept': "application/json; charset=utf-8"
    		},
            type: "post",
    	//type: "get",
    	//type: "delete",
    	//type: "patch",
    	//type: "put",
            async: true,
            //contentType: "application/json; charset=utf-8",
    	contentType: "application/x-www-form-urlencoded; charset=UTF-8",
            success: function(res) {
                alert(JSON.stringify(res));
            },
            error: function(e) {
               alert('系统错误!');
            }
        });
    

    以下是不同请求的结果,不知你们能否看得懂,如果看不懂请一定在评论中告诉我,我会加以修改。

    GET
    	url//请求的url
    		http://localhost:9080/api/thirdparty/policy?id=1
    	header//请求时header中携带的参数
    		Content-Type:application/json; charset=utf-8 //是否定义没啥区别
    	queryString//请求时携带的参数
    		name=abc	//无法定义成json格式,必须是key=value格式
    	springmvc//后台接收的方式
    		String name
    		@RequestParam String name //有无@RequestParam都行
    		//无法使用@RequestBody,因为get没有body
    POST
    	url
    		http://localhost:9080/api/thirdparty/policy?id=1
    	header
    		Content-Type未定义 //默认值Content-Type:application/x-www-form-urlencoded; charset=UTF-8
    	body
    		name=abc	//若body中的是json格式数据如:"{'name':'abc'}",则后台无法获取到参数name,从而无法访问接口
    	springmvc
    		@RequestBody String name
    			name="abc"
    		String id
    			id="1"
    
    POST
    	url
    		http://localhost:9080/api/thirdparty/policy?id=1
    	header
    		Content-Type:application/json; charset=utf-8
    	body
    		{'name':'abc'}
    	springmvc
    		@RequestBody String body //@RequestBody是获取request的整个body体的数据,并且只能获取body中的数据,如果body中没有json数据,请求则报错Required request body is missing:
    			body="{'name':'abc'}"
    		String id
    			id="1"
    
    POST
    	url
    		http://localhost:9080/api/thirdparty/policy?id=1
    	header
    		Content-Type未定义 //默认值Content-Type:application/x-www-form-urlencoded; charset=UTF-8
    	body
    		{'name':'abc'}
    	springmvc
    		@RequestBody String body //这时的@RequestBody是获取queryString的参数+body参数URL编码后的值,因为有{}字符
    			body="id=1&%7B%27name%27%3A%27abc%27%7D="
    		@RequestParam String id
    			id="1"
    
    POST
    	url
    		http://localhost:9080/api/thirdparty/policy?id=1
    	header
    		Content-Type:application/x-www-form-urlencoded; charset=UTF-8
    	body
    		name=abc
    	springmvc
    		@RequestBody String body //这时的@RequestBody是获取queryString的参数+body参数URL编码后的值
    			body="id=1&name=abc"
    		@RequestParam String id
    			id="1"
    DELETE
    	url
    		http://localhost:9080/api/thirdparty/policy?id=1
    	header
    		Content-Type未定义 //默认值Content-Type:application/x-www-form-urlencoded; charset=UTF-8
    	body
    		name=abc
    	springmvc
    		@RequestBody String body //这时的@RequestBody是获取整个body数据,注意和post不同哦
    			body="name=abc"
    		@RequestParam String id
    			id="1"
    
    DELETE
    	url
    		http://localhost:9080/api/thirdparty/policy?id=1
    	header
    		Content-Type:application/json; charset=utf-8
    	body
    		{'name':'abc'}
    	springmvc
    		@RequestBody String body //这时的@RequestBody是获取整个body数据,同样请求时未有body数据就报错
    			body="{'name':'abc'}"
    		@RequestParam String id
    			id="1"
    PUT
    	url
    		http://localhost:9080/api/thirdparty/policy?id=1
    	header
    		Content-Type未定义 //默认值Content-Type:application/x-www-form-urlencoded; charset=UTF-8
    	body
    		{'name':'abc'}
    	springmvc
    		@RequestBody String body //这时的@RequestBody是获取整个body数据,同样请求时未有body数据就报错
    			body="{'name':'abc'}"
    		@RequestParam String id
    			id="1"
    PUT
    	url
    		http://localhost:9080/api/thirdparty/policy?id=1
    	header
    		Content-Type:application/json; charset=utf-8
    	body
    		{'name':'abc'}
    	springmvc
    		@RequestBody String body //这时的@RequestBody是获取整个body数据,同样请求时未有body数据就报错
    			body="{'name':'abc'}"
    		@RequestParam String id
    			id="1"
    PATCH
    	url
    		http://localhost:9080/api/thirdparty/policy?id=1
    	header
    		Content-Type:application/json; charset=utf-8
    	body
    		{'name':'abc'}
    	springmvc
    		@RequestBody String body //这时的@RequestBody是获取整个body数据,同样请求时未有body数据就报错
    			body="{'name':'abc'}"
    		@RequestParam String id
    			id="1"
    
    PATCH
    	url
    		http://localhost:9080/api/thirdparty/policy?id=1
    	header
    		Content-Type未定义 //默认值Content-Type:application/x-www-form-urlencoded; charset=UTF-8
    	body
    		{'name':'abc'}
    	springmvc
    		@RequestBody String body //这时的@RequestBody是获取整个body数据,同样请求时未有body数据就报错
    			body="{'name':'abc'}"
    		@RequestParam String id
    			id="1"
  • 讲解
    做后台快2年了才弄清Content-Type是干什么用的,我想确实有点晚了。天天和HTTP打交道,但是很少会去定义Content-Type,所以才导致自己没有关注到这方面的知识。所以查找借鉴了些资料,然后自己归纳了这些知识。

    1,Content-Type
    MediaType,即是Internet Media Type,互联网媒体类型;也叫做MIME类型,在Http协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息。
    类型格式:type/subtype(;parameter)? type
    主类型,任意的字符串,如text,如果是*号代表所有;
    subtype 子类型,任意的字符串,如html,如果是*号代表所有;
    parameter 可选,一些参数,如Accept请求头的q参数, Content-Type的 charset参数。
    例如: Content-Type: text/html;charset:utf-8;
     常见的媒体格式类型如下:
        text/html : HTML格式
        text/plain :纯文本格式
        text/xml :  XML格式
        image/gif :gif图片格式
        image/jpeg :jpg图片格式
        image/png:png图片格式
       以application开头的媒体格式类型:
       application/xhtml+xml :XHTML格式
       application/xml     : XML数据格式
       application/atom+xml  :Atom XML聚合格式
       application/json    : JSON数据格式
       application/pdf       :pdf格式
       application/msword  : Word文档格式
       application/octet-stream : 二进制流数据(如常见的文件下载)
       application/x-www-form-urlencoded : <form encType=””>中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
       另外一种常见的媒体格式是上传文件之时使用的:
        multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式
         以上就是我们在日常的开发中,经常会用到的若干content-type的内容格式。

    在如tomcat服务器的 “conf/web.xml”中指定了扩展名到媒体类型的映射,在此我们可以看到服务器支持的媒体类型。

    更多http支持的Content-type请在这里查看:http://www.runoob.com/http/http-content-type.html

    2,HTTP方法(get,post...)
    这是我在做resetFul的接口后才慢慢了解的。下面简单介绍如何使用

    获取用户列表		GET:http://xxx.xxx.xxx.x/api/v1/users
    获取单个用户		GET:http://xxx.xxx.xxx.x/api/v1/users/{uid:.{32}}
    创建单个用户 		POST:http://xxx.xxx.xxx.x/api/v1/users/{uid:.{32}}
    完全替换用户		PUT:http://xxx.xxx.xxx.x/api/v1/users/{uid:.{32}}
    局部更新用户		PATCH:http://xxx.xxx.xxx.x/api/v1/users/{uid:.{32}}
    删除单个用户		DELETE:http://xxx.xxx.xxx.x/api/v1/users/{uid:.{32}}

    更多http支持的HTTP method请在这里查看:http://www.runoob.com/http/http-methods.html
    想全面了解http请查看这里:http://www.runoob.com/http/http-tutorial.html

    3,@RequestMapp 
    首先我们来看看RequestMapping中的Class定义

    @Target({ElementType.METHOD, ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Mapping
    public @interface RequestMapping {
          String[] value() default {};
          RequestMethod[] method() default {};
          String[] params() default {};
          String[] headers() default {};
          String[] consumes() default {};
          String[] produces() default {};
    } 

    value:  指定请求的实际地址, 比如 /action/info之类。

    method:  指定请求的method类型, GET、POST、PUT、DELETE等

    consumes: 指定处理请求的提交内容类型(Content-Type),例如application/json, text/html;

    produces:    指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回,如果request请求头中的(Accept)类型中未包含produces定义数据类型的则无法访问接口

    params: 指定request中必须包含某些参数值是,才让该方法处理

    headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求其中,consumes, produces使用content-typ信息进行过滤信息;headers中可以使用content-type进行过滤和判断。

    示例:

    @RequestMapping( value = {"/policy"}, method = RequestMethod.POST, consumes="application/json", headers="Referer=http://www.csdn.com/*", produces = "application/json;charset=UTF-8")
    public String post(HttpServletRequest request, @RequestParam String name,  @RequestParam String id) {
    	System.out.println(name);
    	return BaseResultHP.jsonResultSuccess();
    }

    上述例子中:

    consumes="application/json"说明这个接口只处理Content-Type="application/json"的请求

    headers="Referer=http://www.csdn.com/*"表示request请求头中必须包含Referer=http://www.csdn.com/* produces = "application/json;charset=UTF-8"会与请求头中的Accept进行匹配,如果Accept中也包含application/json,这时才返回数据,如果Accept中没有定义application/json,则服务器端会报错:Could
    not find acceptable representation 当你有如下Accept头,将遵守如下规则进行应用:

    ①Accept:text/html,application/xml,application/json
          将按照如下顺序进行produces的匹配 ①text/html ②application/xml ③application/json
    ②Accept:application/xml;q=0.5,application/json;q=0.9,text/html
          将按照如下顺序进行produces的匹配 ①text/html ②application/json ③application/xml
          参数为媒体类型的质量因子,越大则优先权越高(从0到1)
    ③Accept:*/*,text/*,text/html
          将按照如下顺序进行produces的匹配 ①text/html ②text/* ③*/*

    即匹配规则为:最明确的优先匹配。

    参考资料:
    1.Http请求中Content-Type讲解以及在Spring MVC中的应用

    2.生产者、消费者限定

    3.菜鸟HTTP教程

  • 总结分析的差不多就这些了,希望对大家能有一些帮助。在与三方对接时,遇到了他们无法请求我们这边,然后我来解决这个问题,在解决问题的过程中深入学习,我很享受这样的过程。

HTTP请求定义不同Content-Type及在SpringMVC如何接收(必看!!!)的更多相关文章

  1. Jmeter发送post请求报错Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported

    常识普及: Content-type,在Request Headers里面,告诉服务器,我们发送的请求信息格式,在JMeter中,信息头存储在信息头管理器中,所以在做接口测试的时候,我们维护Conte ...

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

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

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

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

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

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

  5. ajax使用向Spring MVC发送JSON数据出现 org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported错误

    ajax使用向Spring MVC发送JSON数据时,后端Controller在接受JSON数据时报org.springframework.web.HttpMediaTypeNotSupportedE ...

  6. jmeter报"msg":"Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported"的解决方法

    1.报"msg":"Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supporte ...

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

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

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

    Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported告诉你,你的请求头是application/x- ...

  9. {"timestamp":"2019-11-12T02:39:28.949+0000","status":415,"error":"Unsupported Media Type","message":"Content type 'text/plain;charset=UTF-8' not supported","path":&quo

    在Jmeter运行http请求时报错: {"timestamp":"2019-11-12T02:39:28.949+0000","status&quo ...

随机推荐

  1. mysql更新字段内容

    update article set a_content = REPLACE(`a_content`,'www.abc.com','www.bcd.com')

  2. 【webpack系列】从零搭建 webpack4+react 脚手架(三)

    本章节,我们对如何在脚手架中引入CSS,如何压缩CSS,如何使用CSS Modules,如何使用less,如何使用postcss等问题进行展开学习. 1 支持css (1)在app目录,新建一个css ...

  3. html_javascript

    js:放在bady标签的底部,保证页面加载完成后才加载js js注释:// 单行注释 /*多行注释*/ js有两种存在形式: 以文件的形式存在,使用时引用在head标签里<script src= ...

  4. 原生js添加博客点击鼠标出小心心效果~~

    昨天刚申请成功JS权限,心血来潮想添加点东西,记得之前看到别人家博客首页点击鼠标的时候会出现炫酷的 “小心心”,自己也来搞一个.没有用jquery啥的框架,原生js写起来麻烦了点,不过主要是怕博客首页 ...

  5. html基础学习1

    <html> <head> <title>标题</title> </head> <body bgcolor="pink&qu ...

  6. angular之指令

    指令(Directive) 1.指令概念介绍 --  AngularJS有一套完整的.可扩展的.用来帮助web应用开发的指令集. --  在DOM编译期间和HTML关联着的指令会被检测到,并且 会被执 ...

  7. TensorFlow卷积网络常用函数参数详细总结

    卷积操作 tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, name=None) 除去name参数用以指定该操作 ...

  8. STM8L052低功耗模式

    Stm8L系列单片机的低功耗有五种模式: § wait模式 § Lowpower run模式 § Lowpower wait模式 § Active-haltwith full RTC模式 § Halt ...

  9. android studio gradle 打jar 包 (混淆+第三方库包)

    将依赖的第三方库打包进自己的jar包 1.先将第三方的库包拿到,然后添加jar包到项目的libs. 2.项目的build.gradle脚本添加下面的task: task buildJar(depend ...

  10. netcore应用程序部署程序到ubuntu

    运维需求:获取服务器的运行情况,是否CPU.内存较高等,上报到运维系统 环境:ubuntu16.04 工具::netcore2.1.supervisor 程序实现(代码就不贴了)参考:https:// ...