zoukankan      html  css  js  c++  java
  • HTTP请求 、 Form提交、Ajax提交

    HTTP请求的格式:

      
    请求行:描述请求方式、请求资源的名称、http协议的版本号。 例如: GET/BOOK/JAVA.HTML HTTP/1.1
    请求头:描述服务器主机名,客户机的环境信息等
    • Accept:                  告诉服务器,客户机支持的数据类型  (例如:Accept:text/html,image/*)
    • Accept-Charset:    告诉服务器,客户机的编码格式
    • Accept-Encoding:  告诉服务器,客户机支持的数据压缩格式
    • Accept-Language: 告诉服务器,客户机语言环境
    • Host:                      主机
    • Content-Type           指定不同格式的请求信息
    • If-Modified-Since:告诉服务器,资源的缓存时间
    • Referer:告诉服务器,它(客户端)是从哪个资源来访问服务器的(防盗链)
    • User-Agent:告诉服务器,客户机的软件环境(操作系统及版本、浏览器类型及版本、浏览器内核等),通过这个标识,网站可以显示不同的排版从而为用户提供更好的体验或者进行信息统计。
    • Cookie:客户机通过这个头,将Coockie信息带给服务器
    • Connection:告诉服务器,请求完成后,是否保持连接
    • Date:告诉服务器,当前请求的时间

     HTTP响应格式:

    HTTP响应也由四个部分组成,分别是:状态行、消息头、空行和响应正文。

    消息头包含:

    Location:这个头配合302状态吗,用于告诉客户端找谁
    Server:服务器通过这个头,告诉浏览器服务器的类型
    Content-Encoding: 告诉浏览器,服务器的数据压缩格式
    Content-Length:     告诉浏览器,回送数据的长度
    Content-Type:        告诉浏览器,回送数据的类型
    Transfer-Encoding:告诉浏览器,传送数据的编码格式
    Last-Modified:        告诉浏览器当前资源缓存时间
    Refresh:告诉浏览器,隔多长时间刷新
    Content-Disposition:告诉浏览器以下载的方式打开数据。例如: context.Response.AddHeader("Content-Disposition","attachment:filename=aa.jpg"); context.Response.WriteFile("aa.jpg");
    ETag:缓存相关的头(可以做到实时更新)
    Expries:告诉浏览器回送的资源缓存多长时间。如果是-1或者0,表示不缓存
    Cache-Control:控制浏览器不要缓存数据 no-cache
    Pragma:控制浏览器不要缓存数据 no-cache
    Connection:响应完成后,是否断开连接。 close/Keep-Alive
    Date:告诉浏览器,服务器响应时间

     
     

    http请求头中的content-type属性

    什么是Content-Type

    Internet Media Type即互联网媒体类型,也叫做MIME类型,使用两部分标识符来确定一个类型。

    在HTTP请求头中用Content-Type说明具体的媒体类型,即Content-Type是Internet Media Type在HTTP协议中的别称。

    Content-Type的格式

    type/subtype(;parameter)? type

    Content-Type的格式为三个部分,分别是主类型(type)、子类型(subtype)和参数(parameter)。

    主类型(type):主类型可以是任意的字符串,比如text。如果是*号则代表所有类型。

    子类型(subtype):子类型可以是任意的字符串,比如html。如果是*号则代表所有类型。

    参数(parameter):参数是可选的,可以在Content-Type中加入一些特殊的参数,比如Accept请求头的参数,常见的有用于设置字符编码的charset参数。

    Content-Type: text/html;charset:utf-8;

    Content-Type中常见的媒体格式类型

    以text开头的媒体格式类型:

    text/html: HTML格式。

    text/plain:纯文本格式。

    text/xml:  XML格式。

    以image开头的媒体格式类型

    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的内容格式。

    Spring MVC中关于Content-Type类型信息的使用

    在Spring MVC中,主要就是使用@RequestMapping注解来处理请求,因此首先我们来看看@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:指定请求的实际地址, 比如/yanggb/info之类的请求路由。

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

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

    produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回。

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

    headers:指定request中必须包含某些指定的header值,才能让该方法处理请求。

    其中,consumes、produces可以使用Content-type中的信息对不需要的信息进行过滤,仅接受需要的数据;headers则可以使用Content-Type中的信息对请求进行过滤和判断。

    Request Headers和Response Headers中的候选属性

    Request Headers的候选属性

    候选属性说明示例
    Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html
    Accept-Charset 浏览器可以接受的字符编码集 Accept-Charset: iso-8859-5
    Accept-Encoding 指定浏览器可以支持的web服务器返回内容压缩编码类型 Accept-Encoding: compress, gzip
    Accept-Language 浏览器可接受的语言 Accept-Language: en,zh
    Accept-Ranges 可以请求网页实体的一个或者多个子范围字段 Accept-Ranges: bytes
    Authorization HTTP授权的授权证书 Authorization: Basic QWxhZLRpbjpvcGVuIHNoc2FtZQ==
    Cache-Control 指定请求和响应遵循的缓存机制 Cache-Control: no-cache
    Connection 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) Connection: close
    Cookie HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器 Cookie: $Version=1; Skin=new;
    Content-Length 请求的内容长度 Content-Length: 348
    Content-Type 请求的与实体对应的MIME信息 Content-Type: application/x-www-form-urlencoded
    Date 请求发送的日期和时间 Date: Tue, 15 Nov 2018 08:22:31 GMT
    Expect 请求的特定的服务器行为 Expect: 100-continue
    From 发出请求的用户的Email From: user@email.com
    Host 指定请求的服务器的域名和端口号 Host: www.yanggb.com
    If-Match 只有请求内容与实体相匹配才有效 If-Match: "737060ff8c284d8af7ad2082f209582d"
    If-Modified-Since 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 If-Modified-Since: Sat, 29 Oct 2018 19:43:31 GMT
    If-None-Match 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 If-None-Match: "737060cd8c284d8af7ad3082f209582d"
    If-Range 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag If-Range: "737060cd8c284d8af7ad3082f209582d"
    If-Unmodified-Since 只在实体在指定时间之后未被修改才请求成功 If-Unmodified-Since: Sat, 29 Oct 2018 19:23:11 GMT
    Max-Forwards 限制信息通过代理和网关传送的时间 Max-Forwards: 10
    Pragma 用来包含实现特定的指令 Pragma: no-cache
    Proxy-Authorization 连接到代理的授权证书 Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
    Range 只请求实体的一部分,指定范围 Range: bytes=500-999
    Referer 先前网页的地址,当前请求网页紧随其后,即来路 Referer: http://www.yanggb.com/yanggb1.html
    TE 客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 TE: trailers,deflate;q=0.5
    Upgrade 向服务器指定某种传输协议以便服务器进行转换(如果支持) Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
    User-Agent User-Agent的内容包含发出请求的用户信息 User-Agent: Mozilla/5.0 (Linux; X11)
    Via 通知中间网关或代理服务器地址,通信协议 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
    Warning 关于消息实体的警告信息 Warn: 199 Miscellaneous warning

    可以看到,Content-Type是Request Headers中的一个候选属性。

    Response Headers的候选属性

    候选属性说明示例
    Accept-Ranges 表明服务器是否支持指定范围请求及哪种类型的分段请求 Accept-Ranges: bytes
    Age 从原始服务器到代理缓存形成的估算时间(以秒计,非负) Age: 12
    Allow 对某网络资源的有效的请求行为,不允许则返回405 Allow: GET, HEAD
    Cache-Control 告诉所有的缓存机制是否可以缓存及哪种类型 Cache-Control: no-cache
    Content-Encoding web服务器支持的返回内容压缩编码类型 Content-Encoding: gzip
    Content-Language 响应体的语言 Content-Language: en,zh
    Content-Length 响应体的长度 Content-Length: 348
    Content-Location 请求资源可替代的备用的另一地址 Content-Location: /index.htm
    Content-MD5 返回资源的MD5校验值 Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
    Content-Range 在整个返回体中本部分的字节位置 Content-Range: bytes 21010-47021/47022
    Content-Type 返回内容的MIME类型 Content-Type: text/html; charset=utf-8
    Date 原始服务器消息发出的时间 Date: Tue, 15 Nov 2018 08:22:22 GMT
    ETag 请求变量的实体标签的当前值 ETag: "737060cd8c284d8af7ad3082f209582d"
    Expires 响应过期的日期和时间 Expires: Thu, 01 Dec 2018 16:00:00 GMT
    Last-Modified 请求资源的最后修改时间 Last-Modified: Tue, 15 Nov 2018 12:25:26 GMT
    Location 用来重定向接收方到非请求URL的位置来完成请求或标识新的资源 Location: http://www.yanggb.com/yanggb2.html
    Pragma 包括实现特定的指令,它可应用到响应链上的任何接收方 Pragma: no-cache
    Proxy-Authenticate 它指出认证方案和可应用到代理的该URL上的参数 Proxy-Authenticate: Basic
    refresh 应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持)
    Refresh: 5; url=
    http://www.yanggb.com/yanggb9.html
    Retry-After 如果实体暂时不可取,通知客户端在指定时间之后再次尝试 Retry-After: 120
    Server web服务器软件名称 Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
    Set-Cookie 设置Http Cookie Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
    Trailer 指出头域在分块传输编码的尾部存在 Trailer: Max-Forwards
    Transfer-Encoding 文件传输编码 Transfer-Encoding:chunked
    Vary 告诉下游代理是使用缓存响应还是从原始服务器请求 Vary: *
    Via 告知代理客户端响应是通过哪里发送的 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
    Warning 警告实体可能存在的问题 Warning: 199 Miscellaneous warning
    WWW-Authenticate 表明客户端请求实体应该使用的授权方案 WWW-Authenticate: Basic

    具体使用示例

    这里通过几个具体的实例来了解怎么在Spring MVC中使用两个Headers中的信息。

    示例1:headers属性取Request Headers中的Referer属性。

    @RequestMapping(value = "/yanggb2", method = RequestMethod.GET, headers="Referer=http://www.yanggb.com/yanggb1")
    public void yanggb2() {   
        // 如果上一个页面的地址不是上面headers属性中Referer指定的地址,不会执行此方法
    } 

    这里的headers里面可以匹配所有Headers里面可以出现的信息,不局限于Referer信息。

    示例2:headers属性取Request Headers中的Accept属性。

    复制代码
    @RequestMapping(value = "/yanggb2", headers = "Accept=application/json") 
    public void yanggb3(HttpServletResponse response) throws IOException { 
        // 表示响应的内容区数据的媒体类型为json格式,且编码为utf-8(客户端应该以utf-8解码)
        response.setContentType("application/json;charset=utf-8"); 
        // 写出响应体内容
        String jsonData = "{"username":"yanggb","password":"123"}"; 
        response.getWriter().write(jsonData);
    }
    复制代码

    这样,服务器就会根据请求头【Accept=application/json】生产json数据。

    当你有如下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/* ③*/*。

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

    示例3:params属性取参数。

    @RequestMapping(value = "/yanggb/{userId}", method = RequestMethod.GET, params = "yanggb1=yanggb2") 
    public void findUser(@PathVariable String userId) {
        // 当请求中包含参数yanggb1时才会执行此方法
    }

    在上面的代码中,就起到了一个过滤的作用。

    实例4:consumes/produces属性过滤请求。

    复制代码
    @Controller 
    @RequestMapping(value = "/users", method = RequestMethod.POST, consumes="application/json", produces = "application/json") 
    @ResponseBody
    public List<User> addUser(@RequestBody User userl) {   
        return List<User> users;
    }
    复制代码

    上面这个方法仅处理请求Content-Type为【application/json】类型的请求,produces标识处理请求中Accept头中包含了【application/json】的请求,同时暗示了返回的内容类型为【application/json】。



    浏览器行为:Form表单提交

    1、form表单常用属性

    1
    2
    3
    4
    action:url 地址,服务器接收表单数据的地址
    method:提交服务器的http方法,一般为post和get
    name:最好好吃name属性的唯一性
    enctype: 表单数据提交时使用的编码类型,默认使用"pplication/x-www-form-urlencoded",如果是使用POST请求,则请求头中的content-type指定值就是该值。如果表单中有上传文件,编码类型需要使用"multipart/form-data",类型,才能完成传递文件数据。

     enctype为form表单数据的编码格式,Content-type为Http传输的数据的编码格式。分清两者

    2、浏览器提交表单时,会执行如下步骤

    1
    2
    3
    4
    1、识别出表单中表单元素的有效项,作为提交项
    2、构建一个表单数据集
    3、根据form表单中的enctype属性的值作为content-type对数据进行编码
    4、根据form表单中的action属性和method属性向指定的地址发送数据

    3、提交方式

    1
    2
    1、get:表单数据会被encodeURIComponent后以参数的形式:name1=value1&name2=value2 附带在url?后面,再发送给服务器,并在url中显示出来。
    2、post:enctype 默认"application/x-www-form-urlencoded"对表单数据进行编码,数据以键值对在http请求体重发送给服务器;如果enctype 属性为"multipart/form-data",则以消息的形式发送给服务器。

     

    Http协议行为:Http1.1协议

    我们知道,HTTP 协议是以 ASCII 码传输,建立在 TCP/IP 协议之上的应用层规范。规范把 HTTP 请求分为三个部分:请求行、请求头、消息主体。类似于下面这样:

    1
    <method> <request-URL> <version> <headers> <entity-body>  

    协议规定 POST 提交的数据必须放在消息主体(entity-body)中,但协议并没有规定数据必须使用什么编码方式。实际上,开发者完全可以自己决定消息主体的格式,只要最后发送的 HTTP 请求满足上面的格式就可以。

    但是,数据发送出去,还要服务端解析成功才有意义。一般服务端语言如 php、python 等,以及它们的 framework,都内置了自动解析常见数据格式的功能。服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码,再对主体进行解析。

    所以说到 POST 提交数据方案,包含了 Content-Type 和消息主体编码方式两部分

     Post请求下的Content-Type类型(编码类型)

    1.application/x-www-form-urlencoded      键-值对

    这应该是最常见的 POST 提交数据的方式了。浏览器的原生 <form> 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。请求类似于下面这样(无关的请求头在本文中都省略掉了):

    1
    2
    3
    4
    POST http://www.example.com HTTP/1.1
    Content-Type: application/x-www-form-urlencoded;charset=utf-8
     
    title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3

    首先,Content-Type 被指定为 application/x-www-form-urlencoded;其次,提交的数据按照 key1=val1&key2=val2 的方式进行编码,key 和 val 都进行了 URL 转码。大部分服务端语言都对这种方式有很好的支持。例如 PHP 中,$_POST['title'] 可以获取到 title 的值,$_POST['sub'] 可以得到 sub 数组。

    很多时候,我们用 Ajax 提交数据时,也是使用这种方式。例如 JQuery 和 QWrap 的 Ajax,Content-Type 默认值都是「application/x-www-form-urlencoded;charset=utf-8」。

    2.multipart/form-data

    这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 <form> 表单的 enctype 等于 multipart/form-data。

    直接来看一个请求示例:

    form表单:

    1
    2
    3
    4
    5
    6
    <form action="/upload" enctype="multipart/form-data" method="post">
        Username: <input type="text" name="username">
        Password: <input type="password" name="password">
        File: <input type="file" name="file">
        <input type="submit">
    </form>

     Http协议请求:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    POST http://www.example.com HTTP/1.1
    Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
     
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
    Content-Disposition: form-data; name="text"
     
    title
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
    Content-Disposition: form-data; name="file"; filename="chrome.png"
    Content-Type: image/png
     
    PNG ... content of chrome.png ...
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

     

    这个例子稍微复杂点。首先生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。然后 Content-Type 里指明了数据是以 multipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 --boundary-- 标示结束。关于 multipart/form-data 的详细定义,请前往 rfc1867 查看。

    这种方式一般用来上传文件,各大服务端语言对它也有着良好的支持。

    上面提到的这两种 POST 数据的方式,都是浏览器原生支持的,而且现阶段标准中原生 <form> 表单也只支持这两种方式(通过 <form> 元素的 enctype 属性指定,默认为 application/x-www-form-urlencoded。其实 enctype 还支持 text/plain,不过用得非常少)。

    随着越来越多的 Web 站点,尤其是 WebApp,全部使用 Ajax 进行数据交互之后,我们完全可以定义新的数据提交方式,给开发带来更多便利。

    3.application/json

    application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。

    JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。记得我几年前做一个项目时,需要提交的数据层次非常深,我就是把数据 JSON 序列化之后来提交的。不过当时我是把 JSON 字符串作为 val,仍然放在键值对里,以 x-www-form-urlencoded 方式提交。

    Google 的 AngularJS 中的 Ajax 功能,默认就是提交 JSON 字符串。例如下面这段代码:

    1
    2
    3
    4
    var data = {'title':'test''sub' : [1,2,3]};
    $http.post(url, data).success(function(result) {
        ...
    });

    最终发送的请求是:

    1
    2
    3
    4
    POST http://www.example.com HTTP/1.1
    Content-Type: application/json;charset=utf-8
     
    {"title":"test","sub":[1,2,3]}
    这种方案,可以方便的提交复杂的结构化数据,特别适合 RESTful 的接口。各大抓包工具如 Chrome 自带的开发者工具、Firebug、Fiddler,都会以树形结构展示 JSON 数据,非常友好。但也有些服务端语言还没有支持这种方式,例如 php 就无法通过 $_POST 对象从上面的请求中获得内容。这时候,需要自己动手处理下:在请求头中 Content-Type 为 application/json 时,从 php://input 里获得原始输入流,再 json_decode 成对象。一些 php 框架已经开始这么做了。

    当然 AngularJS 也可以配置为使用 x-www-form-urlencoded 方式提交数据。如有需要,可以参考这篇文章

    4.text/xml

    它是一种使用 HTTP 作为传输协议,XML 作为编码方式的远程调用规范。典型的 XML-RPC 请求是这样的:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    POST http://www.example.com HTTP/1.1
    Content-Type: text/xml
     
    <?xml version="1.0"?>
    <methodCall>
        <methodName>examples.getStateName</methodName>
        <params>
            <param>
                <value><i4>41</i4></value>
            </param>
        </params>
    </methodCall>

     XML-RPC 协议简单、功能够用,各种语言的实现都有。它的使用也很广泛,如 WordPress 的 XML-RPC Api,搜索引擎的 ping 服务等等。JavaScript 中,也有现成的库支持以这种方式进行数据交互,能很好的支持已有的 XML-RPC 服务。不过,我个人觉得 XML 结构还是过于臃肿,一般场景用 JSON 会更灵活方便。

      相比之下,get方式的数据提交方式(编码方式)只有一种,就是application/x-www-form-urlencoding

    MIME

    "Multipurpose Internet Mail Extensions"多功能Internet邮件扩充服务,它是一种多用途网际邮件扩充协议。

    1.作用

    服务器会将它们发送的多媒体数据的类型告诉浏览器,而通知手段就是说明该多媒体的MIME类型,从而让浏览器知道接受到的信息哪些是MP3,哪些是Shockwave文件等等。

    服务器将MIME标识符放入传送的数据中来告诉浏览器使用哪个插件读取相关文件

    2.通用格式

    type/subtype

     

    3.细分

     

    类型描述典型示例
    text 表明文件是普通文本,理论上是可读的语言 text/plaintext/htmltext/css, text/javascript
    image 表明是某种图像。不包括视频,但是动态图(比如动态gif)也使用image类型 image/gifimage/pngimage/jpegimage/bmpimage/webp
    audio 表明是某种音频文件 audio/midiaudio/mpeg, audio/webm, audio/ogg, audio/wav
    video 表明是某种视频文件 video/webmvideo/ogg
    application 表明是某种二进制数据

    application/octet-streamapplication/pkcs12application/vnd.mspowerpointapplication/xhtml+xmlapplication/xml,  application/pdf,

    application/json

    对于text文件类型若没有特定的subtype,就使用 text/plain。类似的,二进制文件没有特定或已知的 subtype,即使用 application/octet-stream



    application/x-www-form-urlencoded与application/json

    java_xxxx 2018-07-30 14:37:16 147712 收藏 142
    文章标签: ajax请求 post anxious
    版权
    今天写项目的时候,前台发送数据到后端。前台的数据是发送了,但是后端收不到数据,后端我用@RequestBody,一直为null,然后去掉该注解,还是为null,再后来索性,只用一个IntegerNumber去接收,然而还是null…。最后请教了公司的程大神,才将bug解决掉了。
    错误代码如下
    js

    getUserList:function(){
    $.ajax({
    type:"post",
    url:this.api.userListUrl,
    dateType:"json",
    contentType : 'application/json',
    data:this.queryParam,
    success:function(result){
    app.userList=result.data.rows;
    app.pagination.total=result.data.total;
    },
    error:function(result){
    }
    });
    }

    controller代码:注意,一下代码其实没什么问题,但是接受参数的时候,自定义类前面的用@RequestBody才能接受,但问题就是,springmvc中,如果用了@RequestBody,就不能再接受单个的参数了,如 Integer i。

    @RequestMapping("/user/page.do")
    @ResponseBody
    public ApiResult userPage(
    @RequestBody MyPage page,
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime,
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime
    ){
    System.out.println(page.getPageNumber());
    System.out.println(page.getPageSize());
    System.out.println(startTime);
    System.out.println(endTime);
    ApiResult apiResult = new ApiResult();
    apiResult.setData(userService.userPage(page));
    return apiResult;
    }

    改进,将ajax发送请求的application/json改为application/x-www-form-urlencoded,然后controller里的MyPage,就不用添加@RequesyBody了,于是既可以接受自定义的对象参数,又可以接受单个的参数。完美解决问题

    application/x-www-form-urlencoded
    1
    下面我们来看看application/x-www-form-urlencoded与application/json的区别

    说明:这两个都是发送请求的格式说明

    1.application/x-www-form-urlencoded

    在Form元素的语法中,EncType表明提交数据的格式 用 Enctype 属性指定将数据回发到服务器时浏览器使用的编码类型。 下边是说明: application/x-www-form-urlencoded: 窗体数据被编码为名称/值对。这是标准的编码格式。 multipart/form-data: 窗体数据被编码为一条消息,页上的每个控件对应消息中的一个部分。 text/plain: 窗体数据以纯文本形式进行编码,其中不含任何控件或格式字符。
    补充
    form的enctype属性为编码方式,常用有两种:application/x-www-form-urlencoded和multipart/form-data,默认为application/x-www-form-urlencoded。 当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1&name2=value2…),然后把这个字串append到url后面,用?分割,加载这个新的url。 当action为post时候,浏览器把form数据封装到http body中,然后发送到server。 如果没有type=file的控件,用默认的application/x-www-form-urlencoded就可以了。 但是如果有type=file的话,就要用到multipart/form-data了。浏览器会把整个表单以控件为单位分割,并为每个部分加上Content-Disposition(form-data或者file),Content-Type(默认为text/plain),name(控件name)等信息,并加上分割符(boundary).

    application/json
    有的时候发现 ajax请求中 content-type:application/json,这样也能在后台接受前台提交的数据,其实这个时候前端提交的数据是 json格式的字符串,后端要用@requestbody注解来接收

    推荐链接:https://www.cnblogs.com/qlhMeiMei/p/6846392.html

    content-type:application/json的数据格式:json字符串

    application/x-www-form-urlencoded的数据格式:键值对:key-value


    发现服务器的接口接收的数据的格式是form表单形式,而Angular的$http服务发送的post请求默认是json数据格式所以数据接收不到

    推荐连接:https://blog.csdn.net/leftfist/article/details/79053389
    https://blog.csdn.net/wopelo/article/details/78783442

    /
    ps:经过本人的试验总结,终于发现了一些东西,就是,当前台传递的参数,在后台不能由一个类全部接受的时候,就用application/x-www-form-urlencoded。
    例如,我们在初次打开页面,且页面需要分页的功能的时候,后台接受代码如下。此时就有很多的参数,并且,如果此时用application/json的话,接受page就必须时候RequestBody,于是问题又来了,springmvc中共,如果使用了RequestBody,那么就不能有其他的不能有类接受的单个参数,于是下面的代码中的时间接受就为null。显然这用情况更适合使用application/x-www-form-urlencoded:发送的数据格式为键值对。而application/json为json字符串。

    public ApiResult receive(Page page, ReportReceive filter,
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime,
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime) {

    return new ApiResult(receiveService.page(page, filter, startTime, endTime));
    }

    如果前端发送给后台的数据只是一个对象(使用场景:如注册,保存空户,修改信息),那么我们就大课放心的使用application/json来处理数据,即:只需要在后台接受的时候添加@RequestBody即可

    @RequestMapping("/reply/save.do")
    @ResponseBody
    public ApiResult replySave(@RequestBody ReportReceive receive) {

    receive.setReplyTime(new Date());
    if (receive.getReplyStatus() == 1) {
    reportService.updateReplyCount(receive.getReportId());
    }
    return new ApiResult(receiveService.updateSelective(receive));
    }

    注:axios默认使用的是application/json格式,所以大家在向后台发送数据的时候,要小心喽。所以呢如果大家直接用$.ajax来提交post请求的话,最好好设置响应头contentType的值。

    $.ajax({
    type:"post",
    url:this.api.treeListUrl,
    dateType:"json",
    contentType : 'application/json',
    success:function(result){
    app.options=result.data;
    console.log(app.treeList);
    },
    error:function(result){
    }
    });
    ————————————————
    版权声明:本文为CSDN博主「java_xxxx」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/java_xxxx/article/details/81205315

  • 相关阅读:
    2017-2018-1 团队名称 第一周 作业
    20162307 2017-2018-1 《程序设计与数据结构》第3周学习总结
    20162307 2017-2018-1 《程序设计与数据结构》第1周学习总结
    20161207 结对编程-马尔可夫链-自动生成短文
    20162307 2016-2017-2《程序设计与数据结构》课程总结
    20162307 实验五 网络编程与安全
    20162307 结对编程-四则运算(挑战出题)
    20162306 2016-2017-2《程序设计与数据结构》课程总结
    实验五 网络编程与安全实验报告 20162306陈是奇
    实验补充
  • 原文地址:https://www.cnblogs.com/wfy680/p/15164808.html
Copyright © 2011-2022 走看看