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());

    }

返回结果:
image-1695785121233

上一篇 下一篇