likes
comments
collection
share

Spring中使用RestTemplate发送Http请求

作者站长头像
站长
· 阅读数 22

作为一个Java开发选手,平时调用外部服务都是通过PRC接口,而这次业务下游只提供Http接口,就有点捉急...

RestTemplate的基本使用

RestTemplate是spring实现的,基于restful风格的http请求模板。使用RestTemplate可以简化请求操作的复杂性,同时规范了代码风格。

Get请求

// 将返回结果转换成POJO对象
public <T> T getForObject(String url, Class<T> responseType)

// 返回Http原生信息(状态码、请求头、body)
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType)

实践:获取掘金今日格言

@Data
public class Result<T> implements Serializable {
    private int err_no;
    private String err_msg;
    private T data;
}

private String urlFormat = "https://api.juejin.cn/growth_api/v1/get_coder_calendar?aid=%s&uuid=7037140143551399436";

private RestTemplate restTemplate = new RestTemplate();

@Test
public void testGet() {
    String url = String.format(urlFormat, "xxx");
    Result result = restTemplate.getForObject(url, Result.class);
    System.out.println(result);
}

掘金今日签到格言:

Result(err_no=0, err_msg=success, data={aphorism=文档书写能力对工程师来说,与代码能力一样重要, should_or_not=宜追查到底})

Post请求

// 将返回结果转换成POJO对象
public <T> T postForObject(String url, Object request, Class<T> responseType)

// 返回Http原生信息(状态码、请求头、body)
public <T> ResponseEntity<T> postForEntity(String url, Object request, Class<T> responseType)

实践:掘金自动抽奖

private String urlFormat = "https://api.juejin.cn/growth_api/v1/lottery/draw?aid=%s&uuid=6994739894300935684&_signature=_02B4Z6wo00901IFbWBAAAIDCsQ1vhfdqjSiBXlyAAEICZNX6.YFOgtHG7h9uKHxa1gwR5xaQh55ytA4gMUM6N9JboQDq5siTnpplhowAUX5HCv6Raat44rC31FskryqQD2bKbOyfkMoyJXev06";
private String cookie = "xxx";

private RestTemplate restTemplate = new RestTemplate();

public void testPost() {
    String url = String.format(urlFormat, "2608");
    // 请求头
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.set(HttpHeaders.COOKIE, cookie);
    // 请求体
    JSONObject body = new JSONObject();
    HttpEntity<String> request = new HttpEntity(body.toString(), headers);
    Result result = restTemplate.postForObject(urlFormat, request, Result.class);
    System.out.println(((Map) result.getData()).get("lottery_name"));
}

RestTemplate的扩展知识

  1. getForObject()方法无法为请求头hearder传值,可以使用底层通用方法exchange()或excute();(获取掘金剩余矿石数,大家可以用这两种方法:支持Get请求+header传参
  2. RestTemplate入门博客: #Spring之RestTemplate使用小结 #Springboot -- 用更优雅的方式发HTTP请求(RestTemplate详解)
  3. RestTemplate原理博客: #RestTemplate添加超时处理ClientHttpRequestFactory的选择 #restTemplate源码解析(目录) # HttpClient连接池的一些思考

RestTemplate开发模板

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate(clientHttpRequestFactory());
    }

    @Bean
    public HttpClientConnectionManager poolingConnectionManager() {
        PoolingHttpClientConnectionManager poolingConnectionManager = new PoolingHttpClientConnectionManager();
        // 整个线程池中最大连接数
        poolingConnectionManager.setMaxTotal(200);
        // 路由到某台主机最大并发数
        poolingConnectionManager.setDefaultMaxPerRoute(100);
        return poolingConnectionManager;
    }

    @Bean
    public ClientHttpRequestFactory clientHttpRequestFactory() {
        HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
        httpClientBuilder.setConnectionManager(poolingConnectionManager());
        clientHttpRequestFactory.setHttpClient(httpClientBuilder.build());
        // 客户端和服务器建立连接的超时时间
        clientHttpRequestFactory.setConnectTimeout(1000);
        // 客户端从服务器读取数据的超时时间
        clientHttpRequestFactory.setReadTimeout(3000);
        return clientHttpRequestFactory;
    }
}