总结前后端常用的HTTP接口协议传参方法

2023年 9月 16日 60.9k 0

首发:公众号《赵侠客》

前言

做了多年的后端开发,给前端提供过的接口没有1万个也有1000多个,对接过的前端开发人员没有100人也是50人,联调过的前端开发人员从刚毕业的新人到工作过10多年的老程序员,从江南萌妹到东北壮汉几乎什么样的人都遇到过,在与前端对接过程中一直都会遇到一个问题,就是我们后端接口提供好了,自测也通过了,前端却说接口不通,当我们去排查时发现大都不是接口不通,很多情况是前端使用的姿势不对,比如接口明明写的参数是放到ULR路径上,前端却传到了queryString上,接口明明写的是使用application/x-www-form-urlencoded格式,前端却传了application/json格式,所以本文总结常用的前后端传参数据格式,方便前端与后端开发人员更好的理解HTTP接口协议传参格式。

一、通过HTTP URL传参数

这种方式是最简单,也是最常用的传参方式,通常用于前端从后端获取数据,通过URL传参也分为两种,一种是将参数放在URL路径上,另一种是将参数放在QueryString上,也就是URL?后面

HTTP报文格式

GET /user/1?userName=admin&arrays=a,b,c,d&ids=1&ids=2&ids=3&ids=4

注意事项:

  • 路径 /user/1 上的1是通过URL路径传参数,这种RestFul风格的传参方式,有些前端会搞错
  • userName=admin 这种就是简单的QueryString传参,是最常见的,一般不会搞错
  • arrays=a,b,c,d 这种是通过QueryString传数组,其实就是使用,分隔
  • ids=1&ids=2&ids=3&ids=4这种也是传数组参数的一种方式,一般用的比较少,容易出错
  • 后端接口代码

    我们使用SpringMVC框架编写接口,可以通过@PathVariable@RequestParam两个注解来接收上面参数,主要有三种方法:

  • 第一种是在方法上一个一个的来接收参数;
  • 第二种是使用Map接收来参数;
  • 第三种是封装个UserDTO对象来接收。
  • 
        @GetMapping("/user/{id}")
        public UserDTO request(@PathVariable Long id, String userName, String[] arrays,@RequestParam List ids) {
            return UserDTO.builder().id(id).build();
        }
    
        @GetMapping("/user2/{id}")
        public Map user2(@PathVariable Long id,@RequestParam Map map)    {
            return map;
        }
    
        @GetMapping("/user3/{id}")
        public UserDTO user3(@PathVariable Long id, UserDTO user) {
            return user;
        }
        
        @Data
        public class UserDTO {
            private Long id;
            private String userName;
            private String[] arrays;
            private List ids;
        }
        
    

    注意事项:

  • 接收数组参数时可以使用String[]List两种数据类型;
  • 使用Map map接收参数时 Value的类型要是Object类型,并且增加@RequestParam
  • 使用User对象接收参数时不要增加@RequestParam注解
  • 前端调用接口代码

    前端对于这种传参数方式直接把所有参数拼接到URL上就好了

            var request = new XMLHttpRequest();
            request.open('GET', 'http://localhost/user/1?userName=admin&arrays=a,b,c,d&ids=1&ids=2&ids=3&ids=4', true);
            request.responseType = 'json';
            request.onload = function () {
                var data = this.response;
                console.log(data);
            };
            request.send();
    

    注意事项:

  • 如果传的参数不是URL安全的需要进行URLEncode
  • POSTPUTDELETE方法也是支持通过URL传参的
  • 使用这种URL拼接不同浏览器支持的最大参数长度是不一样的,以下是不同浏览器支持参数的最大长度:
  • 浏览器 URL长度限制
    IE浏览器 2048字节
    360极速浏览器 65536字节
    Firefox(Browser) 2118字节
    Safari(Browser) 80000字节
    Opera(Browser) 190000字节
    Google(chrome) 8182字节

    二、通过HTTP Body传参数

    通过HTTP Body传参数主要用于前端向服务端提交数据,如添加数据、修改数据、上传文件等等,通过Body传参常用的数据格式主要有以下3种:

  • application/x-www-form-urlencoded 也就是表单提交,body报文中使用key=value拼接参数;
  • application/json 将数据转成JSON格式放在Body中;
  • multipart/form-data 用于文件上传。
  • HTTP报文格式

    • application/x-www-form-urlencoded格式报文:
    POST /user3/1
    Content-Type: application/x-www-form-urlencoded
    
    userName=admin&arrays=a,b,c,d&ids=1&ids=2&ids=3&ids=4
    
    • application/json格式报文:
    GET /user4/1
    Content-Type: application/json
    
    {
        "id": 1,
        "userName": "admin",
        "arrays": [
            "a",
            "b",
            "c",
            "d"
        ],
        "ids": [
            1,
            2,
            3,
            4
        ]
    }
    

    注意事项:

  • GET方法也可以通过Body传参数,这点很多人会觉得GET方法不能通过Body传参,不过只能传application/json,使用过elasticsearch应该知道,在搜索数据是就是通过GET方法传JSON数据的。
  • 后端接口代码

    SpringMvc框架中接收Bodyapplication/x-www-form-urlencoded类型参数和在URLQueryString传参数是通用的,接收application/json需要使用@RequestBody注解。

        @RequestMapping("/user3/{id}")
        public UserDTO user3(@PathVariable Long id, UserDTO user) {
            return user;
        }
    
        @RequestMapping("/user4/{id}")
        public UserDTO user4(@PathVariable Long id,@RequestBody UserDTO user) {
            return user;
        }
    
        @RequestMapping("/user5/{id}")
        public UserDTO user4(@PathVariable Long id,@RequestBody String user) {
            return JSONUtil.toBean(user,UserDTO.class);
        }
    
    

    注意事项:

  • @RequestBody 注解可以直接使用DTO来接收,也可以使用String来接收在手动转成DTO,这个方法在不知道要接收的数据有哪些字段时非常有用,可以将对方传的完整数据打印出来。
  • 前端调用接口代码

    function sendFormUrl() {
            var request = new XMLHttpRequest();
            request.open('POST', 'http://localhost/user3/1', true);
            request.responseType = 'json';
            request.onload = function () {
                console.log(this.response);
            };
            var formData = new FormData();
            formData.append('userName', "admin");
            formData.append('arrays', "a,b,c,d");
            formData.append('ids', "1");
            formData.append('ids', "2");
            formData.append('ids', "3");
            formData.append('ids', "4");
            request.send(formData);
        }
    
        function sendJson() {
            var request = new XMLHttpRequest();
            request.open('POST', 'http://localhost/user4/1', true);
            request.responseType = 'json';
            request.setRequestHeader("Content-Type", "application/json;");
            request.onload = function () {
                console.log(this.response);
            };
            var body = {
                "userName": "admin",
                "arrays": [
                    "a",
                    "b",
                    "c",
                    "d"
                ],
                "ids": [
                    1,
                    2,
                    3,
                    4
                ]
            }
            request.send(JSON.stringify(body));
        }
    

    注意事项:

  • multipart/form-data主要用于文件上传,可以参数我的另一篇文章:
    《一个Demo搞定前后端大文件分片上传、断点续传、秒传》
  • 通过Header传参数

    通过Header传参主要用于一些通用的用户认证信息,比如常用的 Authentication: Bearer Cookie

    HTTP报文格式

    GET /user7/1
    Accept: application/json
    userName : admin
    Cookie: userName=admin;
    arrays: a,b,c,d
    ids:1
    ids:2
    ids:3
    ids:4
    

    注意事项

  • 使用SpringMVC请求报java.lang.IllegalArgumentException: The HTTP header line [username : admin] does not conform to RFC 7230. The request has been rejected.因为userName这些自
    定义请求头不符合RFC 7230标准所以被拒绝了,增加配置 reject-illegal-header: off可解决
  • application.yml中增加:

    server:
      port: 80
      tomcat:
        reject-illegal-header: off
    

    后端接口代码

    获取Header参数可以通过request.getHeader(header)依次获取,也可以通过@CookieValue@RequestHeader来获取

        @RequestMapping("/user6/{id}")
        public User user6(@PathVariable Long id, HttpServletRequest request) {
            Enumeration headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()){
                String header= headerNames.nextElement();
                log.info("{}->{}",header,request.getHeader(header));
            }
            return User.builder().id(id).build();
        }
    
        @RequestMapping("/user7/{id}")
        public User user7(@PathVariable Long id, @CookieValue String userName, @RequestHeader String[] arrays, @RequestHeader List ids) {
            return User.builder().id(id).userName(userName).arrays(arrays).ids(ids).build();
        }
    

    前端调用接口代码

        function sendHeader() {
            var request = new XMLHttpRequest();
            request.open('GET', 'http://localhost/user7/1', true);
            request.responseType = 'json';
            request.setRequestHeader("arrays","a,b,c,d");
            request.setRequestHeader("ids","1");
            request.setRequestHeader("ids","2");
            request.setRequestHeader("ids","3");
            request.setRequestHeader("ids","4");
            request.onload = function () {
                console.log(this.response);
            };
            request.send();
        }
    
    

    注意事项:

  • Cookie是浏览器自动添加了,不需要通过request.setRequestHeader("userName","admin")添加
  • 总结

    本文总结了前后端通过HTTP接口协议传参的常用方法,并从HTTP协议、后端JAVA代码、前端JS代码演示每种参数的报文格式、后端获取方法和前端调用方法,当然还有一些更高级的传参方式,比如websocketsse等基于HTTP的实时推送协议。

    相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论