美文网首页
Http请求中Accept、Content-Type讲解以及在S

Http请求中Accept、Content-Type讲解以及在S

作者: vailter | 来源:发表于2018-11-26 14:44 被阅读0次

    title: Http请求中Accept、Content-Type讲解以及在Spring MVC中的应用
    tags: http,spring mvc
    grammar_cjkRuby: true


    1.名词解释

    • Accept:发送端(客户端)希望接受的数据类型。

      比如:
      text/xml(application/json)代表客户端希望接受的数据类型是xml(json )类型

    • Content-Type:发送端(客户端|服务器)发送的实体数据的数据类型。

      比如:
      text/html(application/json)代表发送端发送的数据格式是html(json)。
      二者合起来,Accept:text/xml;Content-Type:text/html即代表希望接受的数据类型是xml格式,本次请求发送的数据的数据格式是html。

    2.HTTP协议传输的媒体类型及如何表示媒体类型

    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;

    常见的MediaType:

    • text/html:HTML格式
    • text/plain:纯文本格式
    • text/xml: XML格式
    • image/gif:gif图片格式
    • image/jpeg:jpg图片格式
    • image/png:png图片格式
    • 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: 需要在表单中进行文件上传时,就需要使用该格式

    Conteny-Type:内容类型,即请求/响应的内容区数据的媒体类型
    Accept:用来指定什么媒体类型的响应是可接受的,即告诉服务器我需要什么媒体类型的数据,此时服务器应该根据Accept请求头生产指定媒体类型的数据。
    问题:

    • 服务器端可以通过指定【headers = “Content-Type=application/json”】来声明可处理(可消费)的媒体类型,即只消费Content-Type指定的请求内容体数据;
    • 客户端如何告诉服务器端它只消费什么媒体类型的数据呢?即客户端接受(需要)什么类型的数据呢?服务器应该生产什么类型的数据?此时我们可以请求的Accept请求头来实现这个功能。
    @RequestMapping(value = "/response/ContentType", headers = "Accept=application/json")
    public void response2(HttpServletResponse response) throws IOException {
        //表示响应的内容区数据的媒体类型为json格式,且编码为utf-8(客户端应该以utf-8解码)
        response.setContentType("application/json;charset=utf-8");
        //写出响应体内容
        String jsonData = "{\"username\":\"zhang\", \"password\":\"123\"}";
        response.getWriter().write(jsonData);
    }
    
    @Controller    
    @RequestMapping(value = "/users", method = RequestMethod.POST, consumes="application/json", produces="application/json")    
    @ResponseBody  
    public List<User> addUser(@RequestBody User userl) {        
        // implementation omitted    
        return List<User> users;  
    }
    

    上面两个例子都表示了request请求中Accept头中包含了"application/json"的请求,同时暗示了返回的内容类型为application/json:

    • produces标识:produces="application/json"
    • headers = "Accept=application/json"

    其中request Content-Type为“application/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.Spring MVC中关于关于Content-Type类型信息的使用

    总结:

    • Spring MVC中主要基于@RequestMapping标注使用,其中headers, consumes,produces,都是使用Content-Type中使用的各种媒体格式内容,来进行访问的控制和过滤。
      Spring MVC 中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)类型中包含该指定类型才返回
      params: 指定request中必须包含某些参数值是,才让该方法处理
      headers: 指定request中必须包含某些指定的header值,才能让该方法处理请求
      其中,consumes, produces使用content-typ信息进行过滤信息;headers中可以使用content-type进行过滤和判断。

      基于@RequestMapping衍生版:

      • @GetMapping
      • @PostMapping
      • @PutMapping
      • @PatchMapping
      • @DeleteMapping
    • GET请求时是否定义Content-Type并无很大的影响,因为GET没有请求体,所有的数据都是通过url带过去,所以必须是"key=value"的格式,所以在springmvc端使用@RequestParam String id这种格式即可,或者不写@RequestParam也可以,不写的话默认是@RequestParam

    • 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获取单个参数

    4.案例

    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"
    

    ^[footnote text]
    参考资料:
    https://blog.csdn.net/u014044812/article/details/78455053

    相关文章

      网友评论

          本文标题:Http请求中Accept、Content-Type讲解以及在S

          本文链接:https://www.haomeiwen.com/subject/pxjbqqtx.html