HTTP1.1中GET请求已经可以在body里发送数据,但是既然用了RestTemplate,就要看一下RestTemplate是否提供了实现,这里我们用的httpclient,默认用的HttpComponentsClientHttpRequestFactory工厂,查看了HttpComponentsClientHttpRequestFactory的createHttpUriRequest方法,发现GET请求是HttpGet,HttpGet继承HttpRequestBase,HttpRequestBase是不支持传递body的。
查了资料发现HttpEntityEnclosingRequestBase是可以传递body的,那就自定义一个工厂继承HttpComponentsClientHttpRequestFactory,重写createHttpUriRequest方法,当发送的请求是GET请求时,创建自定义的继承HttpEntityEnclosingRequestBase的类,这样GET请求就可以传送body。
具体如下:
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import javax.net.ssl.SSLContext;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
@SuppressWarnings("ALL")
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(3000);
factory.setReadTimeout(5000);
return factory;
}
@SuppressWarnings("AliDeprecation")
public static HttpComponentsClientHttpRequestFactory generateHttpRequestFactory()
throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
TrustStrategy acceptingTrustStrategy = (x509Certificates, authType) -> true;
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
SSLConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
new NoopHostnameVerifier());
HttpClientBuilder httpClientBuilder = HttpClients.custom();
httpClientBuilder.setSSLSocketFactory(connectionSocketFactory);
CloseableHttpClient httpClient = httpClientBuilder.build();
//关键
HttpComponentsClientHttpRequestCRMFactory factory = new HttpComponentsClientHttpRequestCRMFactory(httpClient);
factory.setHttpClient(httpClient);
return factory;
}
//重写
private static final class HttpComponentsClientHttpRequestCRMFactory extends HttpComponentsClientHttpRequestFactory {
public HttpComponentsClientHttpRequestCRMFactory(HttpClient httpClient) {
super(httpClient);
}
@Override
protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) {
if (httpMethod == HttpMethod.GET) {
return new HttpGetRequestForBody(uri);
}
return super.createHttpUriRequest(httpMethod, uri);
}
}
private static final class HttpGetRequestForBody extends HttpEntityEnclosingRequestBase {
public HttpGetRequestForBody(final URI uri) {
super.setURI(uri);
}
@Override
public String getMethod() {
return HttpMethod.GET.name();
}
}
}
@Slf4j
public class RestTemplateUtils {
public static <T> ResponseEntity<T> getHttpBody(URI url, HttpMethod method, HttpEntity<String> httpEntity, Class<T> responseType) throws URISyntaxException {
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
//内部实际实现为 HttpClient
RestTemplate restTemplate = null;
try {
restTemplate = new RestTemplate(RestTemplateConfig.generateHttpRequestFactory());
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
e.printStackTrace();
}
return restTemplate.exchange(url, method, httpEntity, responseType);
}
}
具体使用
public Result test() throws URISyntaxException {
// 示例网关接入参数
TreeMap<String, Object> map2 = new TreeMap<>();
map2.put("token", RSAUsing.token);
map2.put("serviceId", 105);
map2.put("lat", 127.000001);
map2.put("lng", 39.7777777);
String encrypt =JSON.toJSONString(map2);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
HttpEntity<String> httpEntity = new HttpEntity<>(encrypt,headers);
URI url = new URI("http://127.0.0.1:9216/xxxxx")
ResponseEntity<String> json = RestTemplateUtils.getHttpBody(url, HttpMethod.GET, httpEntity, String.class);
log.info("----请求返回体:" + JSON.toJSONString(json));
return new Result(json.getBody());
}
返回结果: