JDK调用工具(五)— RestTemplate

RestTemplate

1.1 简介

常见的的Http调用工具:JDK的HttpURLConnection、Square的OkHttp、Apache的HttpClient。由于这些工具使用起来,相对复杂,并且需要手动回收资源,因此Spring提供了一个Http调用工具RestTemplate。RestTemplate 是Spring3.0 开始支持的HTTP 请求工具,提供了常见的 REST请求方案的模板,例如 GET、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及execute。RestTemplate实现RestOperations 接口,RestOptions定义了基本的 RESTful 操作,这些操作在 RestTemplate 中都得到了实现。

1.2 特性

①简化HTTP请求:‌RestTemplate通过提供简单且易用的API,‌使得发送GET、‌POST、‌PUT、‌DELETE等HTTP请求变得简单。

②支持多种数据格式:‌能够处理不同的数据格式,‌如JSON、‌XML等,‌这使得RestTemplate在处理各种数据交换场景时具有高度的灵活性。‌

③请求定制化扩展支持:提供责任链的拦截机制,自定义请求扩展;提供三方外调工具的支持,支持集成HttpClient和OkHttp满足复杂的请求场景需求。

④复用连接,减少连接损耗:由于HTTP 1.1不支持多路复用,‌RestTemplate通过连接池技术,‌减少了频繁建立连接所带来的性能损耗。‌

1.3 使用示例

1.3.1 GET请求

通过RestTemplate发送GET协议请求,Spring提供了一下3种方式:getForObject - 获取协议响应体、getForEntity - 获取完整响应报文、exchange - 通用的http调用API 。

(1)发送不带请求参数的GET请求

    public void testGet1() {
        String baseUrl = "http://exmaple.com/context/path";
        String result = restTemplate.getForObject(baseUrl, String.class);
        log.info(result);

        ResponseEntity<String> responseHttpEntity = restTemplate.getForEntity(baseUrl, String.class);
        log.info(responseHttpEntity.getBody());

        ResponseEntity<String> responseHttpEntity1 = restTemplate.exchange(baseUrl, HttpMethod.GET, new HttpEntity<Void>((Void) null), String.class);
        log.info(responseHttpEntity.getBody());

    }

(2)发送带路径参数的GET请求

    public void testGet2() {
        String url1 = UriComponentsBuilder.fromHttpUrl("http://exmaple.com/context/path").pathSegment("pathVar1", "pathVar2", "pathVar3").build().toUriString();
        String forObject = restTemplate.getForObject(url1, String.class);
        log.info(forObject);

        String url2 = "http://exmaple.com/context/path";
        ResponseEntity<String> responseHttpEntity = restTemplate.getForEntity(url2, String.class, "pathVar1", "pathVar2", "pathVar3");
        log.info(responseHttpEntity.getBody());

        String url3 = UriComponentsBuilder.newInstance().scheme("http").host("exmaple.com").port(80).path("/context/path").pathSegment("pathVar1", "pathVar2", "pathVar3").build().toUriString();
        ResponseEntity<String> responseHttpEntity1 = restTemplate.exchange(url3, HttpMethod.GET, new HttpEntity<Void>((Void) null), String.class);
        log.info(responseHttpEntity.getBody());
    }

(3)发送带请求参数的GET请求

    public void testGet3() {
        String url1 = UriComponentsBuilder.fromHttpUrl("http://exmaple.com/context/path").queryParam("paramVar1", "param1").queryParam("paramVar2", "param2").queryParam("paramVar3", "param3").build().toUriString();
        String forObject = restTemplate.getForObject(url1, String.class);
        log.info(forObject);

        String url2 = "http://exmaple.com/context/path?paramVar1=param1&paramVar2=param2&paramVar3=param3";
        ResponseEntity<String> responseHttpEntity = restTemplate.getForEntity(url2, String.class);
        log.info(responseHttpEntity.getBody());

        String url3 = UriComponentsBuilder.newInstance().scheme("http").host("exmaple.com").port(80).path("/context/path").queryParam("paramVar1", "param1").queryParam("paramVar2", "param2").queryParam("paramVar3", "param3").build().toUriString();
        ResponseEntity<String> responseHttpEntity1 = restTemplate.exchange(url3, HttpMethod.GET, new HttpEntity<Void>((Void) null), String.class);
        log.info(responseHttpEntity.getBody());
    }

1.3.2 POST请求

(1)字符串/复杂对象

    public void testPost() {
        String url = "http://exmaple.com/context/path";

        HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "application/json");

        CustomRequestBody requestBody = new CustomRequestBody("xuyuan", 25);

        HttpEntity<CustomRequestBody> requestEntity = new HttpEntity<>(requestBody, headers);

        String result = restTemplate.postForObject(url, requestEntity, String.class);
        log.info(result);

        ResponseEntity<String> responseHttpEntity1 = restTemplate.postForEntity(url, requestEntity, String.class);
        log.info(responseHttpEntity1.getBody());

        ResponseEntity<String> responseHttpEntity2 = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
        log.info(responseHttpEntity2.getBody());
    }

(2)表单

    public void testPost2() {
        String url = "http://exmaple.com/context/path";

        HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "application/json");

        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("name", "xuyuan");
        map.add("age", "25");

        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(map, headers);

        String result = restTemplate.postForObject(url, requestEntity, String.class);
        log.info(result);

        ResponseEntity<String> responseHttpEntity1 = restTemplate.postForEntity(url, requestEntity, String.class);
        log.info(responseHttpEntity1.getBody());

        ResponseEntity<String> responseHttpEntity2 = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
        log.info(responseHttpEntity2.getBody());
    }

(3)文件上传

    public void testPost3() {
        String url = "http://exmaple.com/context/path";

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        File file = new File("/upload/file.txt");
        Resource resource = new FileSystemResource(file);
        MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
        map.add("file", resource);

        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);

        String result = restTemplate.postForObject(url, requestEntity, String.class);
        log.info(result);

        ResponseEntity<String> responseHttpEntity1 = restTemplate.postForEntity(url, requestEntity, String.class);
        log.info(responseHttpEntity1.getBody());

        ResponseEntity<String> responseHttpEntity2 = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
        log.info(responseHttpEntity2.getBody());
    }

1.3.3 添加报文头

RestTemplate添加协议头通过HttpHeaders实现。示例如下:

    public void addHeader() {

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("Accept", "application/json");
        headers.add("Accept-Encoding", "gzip, deflate");
        headers.add("Accept-Language", "zh-CN,zh;q=0.9");
        headers.add("Connection", "keep-alive");

        HttpEntity<String> requestHttpEntity = new HttpEntity<>("test", headers);
    }

1.3.4 定制化请求

RestTemplate支持多种Http客户端工具。

(1)基于JDK的HttpURLConnection创建定制化的RestTemplate

    @Bean("httpURLConnectionRestTemplate")
    public RestTemplate customRestTemmplateConfig1() {
        SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory();
        simpleClientHttpRequestFactory.setConnectTimeout(3000);
        simpleClientHttpRequestFactory.setReadTimeout(3000);
        RestTemplate restTemplate1 = new RestTemplate(simpleClientHttpRequestFactory);
        restTemplate.getMessageConverters().add(null); // 添加自定义的报文序列化转换器
        List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
        interceptors.add((request, body, execution) -> {

            log.info("请求前处理");
            ClientHttpResponse response = execution.execute(request, body);
            log.info("请求后处理");
            return response;
        });// 拦截责任链添加自定义拦截逻辑
        return restTemplate1;
    }

(2)基于Apache HttpClient创建定制化的RestTemplate

    @Bean("httpClientRestTemplate")
    public RestTemplate customRestTemmplateConfig2() {
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory()).build();

        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        connectionManager.setMaxTotal(100);
        connectionManager.setDefaultMaxPerRoute(20);
        connectionManager.setValidateAfterInactivity(100000);

        RequestConfig customRequestConfig = RequestConfig.custom().setConnectionRequestTimeout(3000).setSocketTimeout(3000).setConnectTimeout(1000).build();

        CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(customRequestConfig).setConnectionManager(connectionManager).build();

        ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(client);
        return new RestTemplate(requestFactory);
    }

(3)基于Square的OkHttp创建定制化的RestTemplate

    @Bean("okHttpRestTemplate")
    public RestTemplate customRestTemmplateConfig3() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder().readTimeout(3, TimeUnit.SECONDS) // 读超时时间
                .writeTimeout(3, TimeUnit.SECONDS) // 写超时时间
                .connectTimeout(1, TimeUnit.SECONDS) // 连接超时时间
                .callTimeout(5, TimeUnit.SECONDS) // 响应超时时间
                .addInterceptor(new OKHttpExample.CustomInterceptor()) // 自定义拦截器
                .cache(new Cache(new File(""), 1024 * 1024 * 100)) // 自定义缓存,CacheInterceptor会使用
                .cookieJar(new OKHttpExample.CustomCookieJar()) // 自定义Cookie,BridgeInterceptor会使用
                .followRedirects(true) // 支持RetryAndFollowUpInterceptor的重定向
                .followSslRedirects(true) // 支持SSL重定向
                .retryOnConnectionFailure(true) // 支持RetryAndFollowUpInterceptor的重试
                .connectionPool(new ConnectionPool(10, 600, TimeUnit.SECONDS)).build();

        ClientHttpRequestFactory okHttp3ClientHttpRequestFactory = new OkHttp3ClientHttpRequestFactory(okHttpClient);
        return new RestTemplate(okHttp3ClientHttpRequestFactory);
    }
  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小胖子许愿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值