使用RestTemplate作为代理转发Http请求

RestTemplate是Spring提供的一个模板类,用于发送Http网络请求。利用它制作一个方向代理,可以使用RestTemplate的exchange方法来实现。具体分为以下几个步骤:

一、创建RestTemplate实例

创建RestTemplate实例直接new就行了,重要的是RestTemplate的配置。考虑到Http请求可能获取多种资源,所以在此使用byte[]来进行传输。使用byte[]进行传输数据,就要配置转换器,让程序可以将二进制数据正确的转为我们需要的数据类型。同时,我们也可以通过SimpleClientHttpRequestFactory来设置请求的超时时间。初始化RestTemplate的代码如下:

SimpleClientHttpRequestFactory srf = new SimpleClientHttpRequestFactory();
srf.setConnectTimeout(5000);
List<HttpMessageConverter<?>> converters = new ArrayList<>();

// 二进制数据转换器
converters.add(new ByteArrayHttpMessageConverter());
converters.add(new BufferedImageHttpMessageConverter());
converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
converters.add(new ResourceHttpMessageConverter());
converters.add(new AllEncompassingFormHttpMessageConverter());

this.restTemplate = restTemplateBuilder.build();
this.restTemplate.setRequestFactory(srf);
this.restTemplate.setMessageConverters(converters);

二、构造请求头,请求体和参数

构造请求参数可以通过request.getParameterMap来获取,并且通过构造字符串拼接到uri中的方法来实现。

Map<String, String[]> parameterMap = request.getParameterMap();
StringBuilder queryString = new StringBuilder();
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
    for (String value : entry.getValue()) {
        if (!queryString.isEmpty()) {
            queryString.append("&");
        }
        queryString.append(entry.getKey()).append("=").append(value);
    }
}

构造请求头可以新建HttpHeaders对象,通过request.getHeaderNames()获取到请求头名称,再使用循环获取到所有请求头内容并且添加。请求头添加时需要跳过host,conten-length,connection,transfer-encoding:

HttpHeaders headers = new HttpHeaders();
Enumeration<String> headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
    String headerName = headerNames.nextElement();
    if (!shouldSkipHeader(headerName)) {
        Enumeration<String> headerValues = request.getHeaders(headerName);
        while (headerValues.hasMoreElements()) {
            headers.add(headerName, headerValues.nextElement());
        }
    }
}

构造请求体时需要新建HttpEntity对象,可以在控制器层面获取到请求体的String,最后传入其中构造请求体。

HttpEntity<Object> requestEntity = null;
if (body != null) {
    try {
        requestEntity = new HttpEntity<>(body, headers);
    } catch (Exception e) {
        logger.error("构造请求体异常", e);
    }
} else {
    requestEntity = new HttpEntity<>(headers);
}

最后通过RestTemplate发送请求即可:

ResponseEntity<byte[]> exchange = restTemplate.exchange(
                targetUrl,
                HttpMethod.valueOf(request.getMethod()),
                requestEntity,
                byte[].class
        );
上一篇
下一篇