1.概述

RestTemplate是spring封装的restful请求的模板,它内部封装了常用的GET、POST、DELETE、PUT等请求方式,帮助开发者更快构建HTTP请求。传统的请求方式采用Apache的HttpClient,此种方式编写http请求时需要编写大量代码,比较繁琐。本文将从代码量、以及最大访问量对比HttpClient与RestTemplate请求封装的工具类。

2.基于HttpClient封装的工具类

2.1 GET请求

利用HttpClient来发送GET请求时,需要考虑请求头的构造,资源的回收与释放等,代码量较多且操作较为繁琐。下面是封装的一个关于GET请求的方法。

public static String sendGet(String url, String params) throws Exception {
        logger.info("GET Request uri: {} params: {}", url, params);
        HttpGet httpGet = null;
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        // 响应内容
        String result = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();
            URIBuilder uriBuilder = new URIBuilder(url);
          
            uriBuilder.addParameter("params", params);
            httpGet = new HttpGet(uriBuilder.build());
            httpGet.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpGet);
            // 得到响应实例
            HttpEntity entity = response.getEntity();
            // 判断响应状态
            int statusCode = response.getStatusLine().getStatusCode();
            if (HttpStatus.SC_OK == statusCode) {
                result = EntityUtils.toString(entity, HttpClientUtil.ENCODE_UTF8);
                EntityUtils.consume(entity);
            }
            logger.info("GET Request uri: {}, params: {}, status code: {}, result: {}", url, params, statusCode, result);
            if (statusCode >= 300 || statusCode < 200) {
                throw new Exception("Response code is " + statusCode);
            }
        } catch (Exception e) {
            logger.error("GET Request uri: {}, params: {}, error: {}", url, params, e.getMessage());
            throw e;
        } finally {
            try {
                // 释放资源
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                logger.warn("释放HttpResponse资源失败");
            }
        }
        return result;
    }

2.2 POST请求

post请求与get请求类似,都需要构造消息头、获取返回结果以及考虑资源的回收等,代码与上述get请求类似,工具类如下:

public static String sendPost(String url, String bodyParams) throws Exception {
        logger.info("POST Request uri: {}  body: {}", url, bodyParams);
        String result = null;
        CloseableHttpResponse httpResponse = null;
        HttpPost httpPost = null;
        CloseableHttpClient closeableHttpClient = null;
        try {
            closeableHttpClient = HttpClientBuilder.create().build();
            URIBuilder uriBuilder = new URIBuilder(url);
            httpPost = new HttpPost(uriBuilder.build());
            // 构造消息头
            httpPost.setHeader("Content-type", "application/json; charset=utf-8");
            StringEntity stringEntity = new StringEntity(bodyParams, HttpClientUtil.ENCODE_UTF8);
            httpPost.setEntity(stringEntity);

            httpPost.setConfig(requestConfig);
            httpResponse = closeableHttpClient.execute(httpPost);
            // 判断响应状态
            int statusCode = httpResponse.getStatusLine().getStatusCode();
            if (HttpStatus.SC_OK == statusCode) {
                HttpEntity entity = httpResponse.getEntity();
                result = EntityUtils.toString(entity);
            }
            logger.info("POST Request uri: {}, body: {}, status code: {}, result: {}", url, bodyParams, statusCode, result);
            if (statusCode >= 300 || statusCode < 200) {
                throw new Exception("Response code is " + statusCode);
            }
        } catch (Exception e) {
            logger.error("POST Request uri: {}, body: {}, error: {}", url, bodyParams, e.getMessage());
            throw e;
        } finally {
            try {
                if (httpResponse != null) {
                    httpResponse.close();
                }
            } catch (IOException e) {
                logger.warn("释放HttpResponse资源失败");
            }
        }
        return result;
    }

2.3 DELETE请求

public static String sendDelete(String url, String params) throws Exception {
        logger.info("DELETE Request uri: {}  params: {}", url, params);
        HttpDelete httpDelete = null;
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        // 响应内容
        String result = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();
            URIBuilder uriBuilder = new URIBuilder(url);
     
            uriBuilder.addParameter("params", params);
            httpDelete = new HttpDelete(uriBuilder.build());

            httpDelete.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpDelete);
            // 得到响应实例
            HttpEntity entity = response.getEntity();

            // 判断响应状态
            int statusCode = response.getStatusLine().getStatusCode();
            if (HttpStatus.SC_OK == statusCode) {
                result = EntityUtils.toString(entity, HttpClientUtil.ENCODE_UTF8);
                EntityUtils.consume(entity);
            }
            logger.info("DELETE Request uri: {}, params: {}, status code: {}, result: {}", url, params, statusCode, result);
            if (statusCode >= 300 || statusCode < 200) {
                throw new Exception("Response code is " + statusCode);
            }
        } catch (Exception e) {
            logger.error("DELETE Request uri: {}, params: {}, error: {}", url, params, e.getMessage());
            throw e;
        } finally {
            try {
                // 释放资源
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                logger.warn("释放HttpResponse资源失败");
            }
        }
        return result;
    }

2.4 PUT请求

public static String sendPut(String url, String bodyParams) throws Exception {
        logger.info("PUT Request uri: {}  params: {}", url, bodyParams);
        HttpPut httpPut = null;
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        // 响应内容
        String result = null;
        try {
            // 创建默认的httpClient实例.
            httpClient = HttpClients.createDefault();
            URIBuilder uriBuilder = new URIBuilder(url);
            httpPut = new HttpPut(uriBuilder.build());
            httpPut.setHeader("Content-type", "application/json; charset=utf-8");
            StringEntity stringEntity = new StringEntity(bodyParams, HttpClientUtil.ENCODE_UTF8);
            httpPut.setEntity(stringEntity);
            httpPut.setConfig(requestConfig);
            // 执行请求
            response = httpClient.execute(httpPut);

            // 得到响应实例
            HttpEntity entity = response.getEntity();
            int statusCode = response.getStatusLine().getStatusCode();
            if (HttpStatus.SC_OK == statusCode) {
                result = EntityUtils.toString(entity, HttpClientUtil.ENCODE_UTF8);
                EntityUtils.consume(entity);
            }
            logger.info("PUT Request uri: {}, body: {}, status code: {}, result: {}", url, bodyParams, statusCode, result);
            // 判断响应状态
            if (statusCode >= 300 || statusCode < 200) {
                throw new Exception("Response code is " + statusCode);
            }

        } catch (Exception e) {
            logger.error("PUT Request uri: {}, body: {}, error: {}", url, bodyParams, e.getMessage());
            throw e;
        } finally {
            try {
                // 释放资源
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                logger.warn("释放HttpResponse资源失败");
            }
        }
        return result;
    }

3.基于RestTemplate封装的工具类

3.1 GET请求

/**
       * @Description: GET请求,参数形式params={"deviceNum":"","type":""}
       * @Author Marin
       * @Date 2020/11/4 15:05
       */
    public String sendGet(String url,String params) throws Exception {
        logger.info("GET Request uri: {} params: {}", url, params);
        Map<String, Object> map = new HashMap<>();
        map.put("params",params);
        StringBuffer buffer = new StringBuffer(url);
        buffer.append("?params={params}");
        ResponseEntity<String> result = null;
        int statusCode = 0;
        try {
            result = restTemplate.getForEntity(buffer.toString(),String.class,map);
            statusCode = result.getStatusCode().value();
        } catch (RestClientException e) {
            logger.error("GET Request uri: {}, params: {}, error: {}", url, params, e.getMessage());
        }
        if (statusCode == HttpStatus.SC_OK) {
            return result.getBody();
        }
        if (statusCode >= 300 || statusCode < 200) {
            throw new Exception("Response code is " + statusCode);
        }
        return ResponseCreator.writeJsonErr(result.getStatusCode().toString());
    }

3.2 POST请求

/**
       * @Description: POST请求,参数放于body体中,格式为{"deviceNum":"","type":""}
       * @Author Marin
       * @Date 2020/11/4 15:17
       */
    public String sendPost(String url,String params) throws Exception {
        logger.info("Post Request uri: {}, params: {}", url, params);
        ResponseEntity<String> result = null;
        int statusCode = 0;
        try {
            result = restTemplate.postForEntity(url, params, String.class);
            statusCode = result.getStatusCode().value();
        } catch (RestClientException e) {
            logger.error("POST Request uri: {}, params: {}, error: {}", url, params, e.getMessage());
        }
        if (statusCode == HttpStatus.SC_OK) {
            return result.getBody();
        }
        if (statusCode >= 300 || statusCode < 200) {
            throw new Exception("Response code is " + statusCode);
        }
        return ResponseCreator.writeJsonErr(result.getStatusCode().toString());
    }

3.3 DELETE请求

/**
       * @Description: DELETE请求,参数形式params={"deviceNum":"","type":""}
       * @Author Marin
       * @Date 2020/11/5 14:27
       */
    public String sendDelete(String url,String params) throws Exception {
        logger.info("DELETE Request uri: {} params: {}", url, params);
        ResponseEntity<String> result = null;
        HashMap<String,Object> map = new HashMap<>();
        map.put("params",params);
        StringBuffer buffer = new StringBuffer(url);
        buffer.append("?params={params}");
        int statusCode = 0;
        try {
            result = restTemplate.exchange(buffer.toString(), HttpMethod.DELETE, null, String.class, map);
            statusCode = result.getStatusCode().value();
        } catch (RestClientException e) {
            logger.error("DELETE Request uri: {}, params: {}, error: {}", url, params, e.getMessage());
        }
        if (statusCode == HttpStatus.SC_OK) {
            return result.getBody();
        }
        if (statusCode >= 300 || statusCode < 200) {
            throw new Exception("Response code is " + statusCode);
        }
        return ResponseCreator.writeJsonErr(result.getStatusCode().toString());
    }

3.4 PUT请求

/**
       * @Description: PUT请求,参数放于body体中,格式为{"deviceNum":"","type":""}
       * @Author Marin
       * @Date 2020/11/5 14:38
       */
    public String sendPut(String url,String params) throws Exception {
        logger.info("PUT Request uri: {} params: {}", url, params);
        ResponseEntity<String> result = null;
        int statusCode = 0;
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
        // 发送请求
        HttpEntity<String> entity = new HttpEntity<>(params, headers);
        try {
            result = restTemplate.exchange(url, HttpMethod.PUT, entity, String.class);;
            statusCode = result.getStatusCode().value();
        } catch (RestClientException e) {
            logger.error("PUT Request uri: {}, params: {}, error: {}", url, params, e.getMessage());
        }
        if (statusCode == HttpStatus.SC_OK) {
            return result.getBody();
        }
        if (statusCode >= 300 || statusCode < 200) {
            throw new Exception("Response code is " + statusCode);
        }
        return ResponseCreator.writeJsonErr(result.getStatusCode().toString());
    }

4.代码量对比与性能对比

4.1 代码量对比

利用apache的HttpClient封装的get、post、put、delete请求,都需要构造请求头、执行请求并得到返回结果、回收资源等,而利用RestTemplate类来进行工具类的封装,只需要关注请求的发送与结果的获取,资源回收这部分已被RestTemplate底层封装,不需要我们进行额外的操作,有效避免编写不必要的代码。

5.小结

1.RestTemplate底层支持多种方式发起请求,具体可以查看源码;
2.RestTemplate上层代码主要采用apache的httpClient,因为只是多进行了一层封装;
3.在性能上,因为两者上层相似,所以性能差距不大。