天天看点

RestTemplate中post请求实用分析

RestTemplate中post请求实用分析

1、最近在做相关平台对接工作。对接第一步需要在后端完成认证,拿到对方平台的access_token。由于对方文档不是很详细,根据认证需要的参数进行了多种尝试。顺带学习一下RestTemplate发post的请求的各种姿势。记录在此,以便查看。

2、往后端发post请求一般分为两种,

一种是普通的表单提交(Content-Type: application/x-www-form-urlencoded)。

另一种是JSON提交(Content-Type: application/json)。

当然后台接收的方式也不同,

普通表单提交从request.getParameter()就能获取。

JSON提交的的数据在io流中,可以通过request.getInputStream()获取。spring为我们提供了@RequestBody注解,简单易用。

3、了解上述内容之后,下面进行试验

①模拟表单提交(要知道,post请求也可以使用url传参奥)

/**
 * 1、使用uri传参形式,把参数拼接到url后面,并在占位符里给每个参数赋值一定意义的名字。然后把参数封装到 
 * Map中。 占位符中的参数名会去对应Map中的key找到参数的值以完成替换。
 * 传参并携带请求头
 */
 @GetMapping("/auth1")
    public void auth1() {
        try {
            Map uriVariables = new LinkedHashMap(4);
            uriVariables.put("username", "name");
            uriVariables.put("password", "1234");
            uriVariables.put("type", "client");
            uriVariables.put("grant_type", "password");
            HttpHeaders headers = new HttpHeaders();
            headers.add("Authorization", "Basic aW90OmlvdA==");
            HttpEntity httpEntity = new HttpEntity(null, headers);
            ResponseEntity<String> entity = restTemplate.postForEntity("http://192.168.1.111:8086/auth/server?username={username}&password={password}&type={type}&grant_type={grant_type}", httpEntity, String.class, uriVariables);
            if (entity.getStatusCode().is2xxSuccessful()) {
                System.out.println(entity.getBody());
            } else {
                log.error("认证失败:[{}]", entity);
            }
        } catch (Exception e) {
            log.error("认证异常:[{}]", e.getMessage());
        }
    }

/**
 * 2、使用uri传参形式,把参数拼接到url后面,在占位符里写上参数的索引位置。然后把参数放在可变长变量中。
 * 实际参数会根据参数索引位置完成替换
 * 传参并携带请求头
 */
    @GetMapping("/auth2")
    public void auth2() {
        try {
            final String username = "name";
            final String password = "1234";
            final String type = "client";
            final String grant_type = "password";
            HttpHeaders headers = new HttpHeaders();
            headers.add("Authorization", "Basic aW90OmlvdA==");
            HttpEntity httpEntity = new HttpEntity(null, headers);
            ResponseEntity<String> entity = restTemplate.postForEntity("http://192.168.1.111:8086/auth/server?username={0}&password={1}&type={2}&grant_type={3}", httpEntity, String.class, username, password, type, grant_type);
            if (entity.getStatusCode().is2xxSuccessful()) {
                System.out.println(entity.getBody());
            } else {
                log.error("认证失败:[{}]", entity);
            }
        } catch (Exception e) {
            log.error("认证异常:[{}]", e.getMessage());
        }
    }

/**
 * 3、把参数封装到LinkedMultiValueMap中,使用HttpEntity一并封装表单数据和请求头
 * 传参并携带请求头
 */
    @GetMapping("/auth3")
    public void auth3() {
        try {
            MultiValueMap body = new LinkedMultiValueMap(4);
            body.add("username", "name");
            body.add("password", "1234");
            body.add("type", "client");
            body.add("grant_type", "password");
            HttpHeaders headers = new HttpHeaders();
            headers.add("Authorization", "Basic aW90OmlvdA==");
            HttpEntity httpEntity = new HttpEntity(body, headers);
            ResponseEntity<String> entity = restTemplate.postForEntity("http://192.168.1.111:8086/auth/server", httpEntity, String.class);
            if (entity.getStatusCode().is2xxSuccessful()) {
                System.out.println(entity.getBody());
            } else {
                log.error("认证失败:[{}]", entity);
            }
        } catch (Exception e) {
            log.error("认证异常:[{}]", e.getMessage());
        }
    }


/**
 * 4、把参数封装到LinkedMultiValueMap中,只发送表单数据可以不使用HttpEntity 
 * 传参不携带请求头
 */
    @GetMapping("/auth4")
    public void auth4() {
        try {
            MultiValueMap body = new LinkedMultiValueMap(4);
            body.add("username", "name");
            body.add("password", "1234");
            body.add("type", "client");
            body.add("grant_type", "password");
            ResponseEntity<String> entity = restTemplate.postForEntity("http://192.168.1.111:8086/auth/server", body, String.class);
            if (entity.getStatusCode().is2xxSuccessful()) {
                System.out.println(entity.getBody());
            } else {
                log.error("认证失败:[{}]", entity);
            }
        } catch (Exception e) {
            log.error("认证异常:[{}]", e.getMessage());
        }
    }

           
②JSON提交的形式
/**
   * 5、数据可以用map封装、可以用实体类封装、也可以是json格式的字符串
   *    携带请求头
   */
    @GetMapping("/auth5")
    public void auth5() {
        try {
            Map body = new LinkedHashMap(4);
            body.put("username", "name");
            body.put("password", "1234");
            body.put("type", "client");
            body.put("grant_type", "password");
            HttpHeaders headers = new HttpHeaders();
            headers.add("Authorization", "Basic aW90OmlvdA==");
            HttpEntity httpEntity = new HttpEntity(body, headers);
            ResponseEntity<String> entity = restTemplate.postForEntity("http://192.168.1.111:8086/auth/server2", httpEntity, String.class);
            if (entity.getStatusCode().is2xxSuccessful()) {
                System.out.println(entity.getBody());
            } else {
                log.error("认证失败:[{}]", entity);
            }
        } catch (Exception e) {
            log.error("认证异常:[{}]", e.getMessage());
        }
    }

  /**
   * 5、数据可以用map封装、可以用实体类封装、也可以是json格式的字符串
   *    不携带请求头
   */
    @GetMapping("/auth6")
    public void auth6() {
        try {
            Map body = new LinkedHashMap(4);
            body.put("username", "name");
            body.put("password", "1234");
            body.put("type", "client");
            body.put("grant_type", "password");
            ResponseEntity<String> entity = restTemplate.postForEntity("http://192.168.1.111:8086/auth/server2", body, String.class);
            if (entity.getStatusCode().is2xxSuccessful()) {
                System.out.println(entity.getBody());
            } else {
                log.error("认证失败:[{}]", entity);
            }
        } catch (Exception e) {
            log.error("认证异常:[{}]", e.getMessage());
        }
    }
           
4、附上后台接收代码
@PostMapping("/server")
    public String server(String username, String password, String type, String grant_type, HttpServletRequest request) {
        System.out.println(username);
        System.out.println(password);
        System.out.println(type);
        System.out.println(grant_type);

        String header = request.getHeader("Authorization");
        System.out.println(header);

        return "ok";
    }

    @PostMapping("/server2")
    public String server(@RequestBody Object obj, HttpServletRequest request) {
        System.out.println(obj);

        String header = request.getHeader("Authorization");
        System.out.println(header);

        return "ok";
    }
           
5、最后附上抓包数据,可以清楚的观察到数据的传送格式以及Content-Type的形式
POST /auth/server?username=name&password=1234&type=client&grant_type=password HTTP/1.1
Accept: text/plain, application/json, application/*+json, */*
Authorization: Basic aW90OmlvdA==
Content-Length: 0
Host: 192.168.1.111:8086
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.8 (Java/1.8.0_131)
Accept-Encoding: gzip,deflate


POST /auth/server?username=name&password=1234&type=client&grant_type=password HTTP/1.1
Accept: text/plain, application/json, application/*+json, */*
Authorization: Basic aW90OmlvdA==
Content-Length: 0
Host: 192.168.1.111:8086
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.8 (Java/1.8.0_131)
Accept-Encoding: gzip,deflate


POST /auth/server HTTP/1.1
Accept: text/plain, application/json, application/*+json, */*
Authorization: Basic aW90OmlvdA==
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Length: 59
Host: 192.168.1.111:8086
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.8 (Java/1.8.0_131)
Accept-Encoding: gzip,deflate

username=name&password=1234&type=client&grant_type=password


POST /auth/server HTTP/1.1
Accept: text/plain, application/json, application/*+json, */*
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Content-Length: 59
Host: 192.168.1.111:8086
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.8 (Java/1.8.0_131)
Accept-Encoding: gzip,deflate

username=name&password=1234&type=client&grant_type=password


POST /auth/server2 HTTP/1.1
Accept: text/plain, application/json, application/*+json, */*
Authorization: Basic aW90OmlvdA==
Content-Type: application/json;charset=UTF-8
Content-Length: 77
Host: 192.168.1.111:8086
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.8 (Java/1.8.0_131)
Accept-Encoding: gzip,deflate

{"username":"name","password":"1234","type":"client","grant_type":"password"}


POST /auth/server2 HTTP/1.1
Accept: text/plain, application/json, application/*+json, */*
Content-Type: application/json;charset=UTF-8
Content-Length: 77
Host: 192.168.1.111:8086
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.5.8 (Java/1.8.0_131)
Accept-Encoding: gzip,deflate

{"username":"name","password":"1234","type":"client","grant_type":"password"}
           

6、总结:

在做平台对接的时候,一开始使用的是第三种形式发送post请求。经过一番调试,没有认证成功。但是我通过postman请求是成功的。通过抓包,发现postman发送数据的形式是前面两种形式,即把参数放在url上。后来在程序中切换到前两种形式,成功认证并获取到对方平台的accessToken。由于不知道对方代码的实现方式,故无法进一步分析。

在我的试验中以前三种形式进行表单提交都能正常获取到数据,若今后遇到类似问题,要做到举一反三、触类旁通。

7、小尾巴~~

只要有积累,就会有进步

继续阅读