#GET携带Body参数发送请求 #SpringBoot整合Feign #SpringBoot整合RestTemplate #RestTemplate拓展Get请求携带Body参数
作者:mmseoamin日期:2023-12-25

GET携带Body发送请求的各种方式

1. 使用Hutool工具类, 最方便

坐标如下:

   
            cn.hutool
            hutool-all
            5.8.17
   

关键代码:

// 携带的body数据构造
Map body = new HashMap<>();
Map head = new HashMap<>();
head.put("username","username");
head.put("password","password");
body.put("head",head);
String bodyStr = JSON.toJSONString(body);
String reponse = "";
HttpResponse result = HttpUtil.createGet(url)
                    .header(Header.ACCEPT_ENCODING,"gzip, deflate, br")
                    .header(Header.ACCEPT,"*/*")
                    .header(Header.CONTENT_TYPE,"application/json")
                    .header(Header.CONNECTION,"keep-alive")
                    .body(bodyStr) //携带数据
                    .execute();
  response = result.body();
2. 使用HttpComponent
 
            commons-httpclient
            commons-httpclient
            3.1
 
 
           org.apache.httpcomponents
           httpclient
           4.5.3
 

添加工具类

package com.hong.util;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.GzipDecompressingEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class SendGet {
    public static String sendJsonByGetReq(String url,String param,String encoding)throws  Exception{
        String body = "";
        CloseableHttpClient client = HttpClients.createDefault();
        HttpGetWithEntity myGet = new HttpGetWithEntity(url);
        //String tmp = "{ \"head\": {\"password\":\"Sczh!2021\",\"username\":\"sczh\"} }";
        HttpEntity httpEntity = new StringEntity(param, ContentType.APPLICATION_JSON);
        myGet.setEntity(httpEntity);
        myGet.setHeader("Content-Type","application/json");
        myGet.setHeader("Accept","*/*");
        myGet.setHeader("Accept-Encoding","gzip, deflate, br");
        myGet.setHeader("Connection","keep-alive");
        CloseableHttpResponse response = client.execute(myGet);
        HttpEntity entity = response.getEntity();
        if(entity!= null){
            body = EntityUtils.toString(entity,encoding);
            System.out.println("直接接收到的数据:"+body);
        }
        response.close();
        return body;
    }
}

使用

// 携带的body数据构造
Map body = new HashMap<>();
Map head = new HashMap<>();
head.put("username","username");
head.put("password","password");
body.put("head",head);
String respJson = "";
  try {
            //使用Http
            respJson = SendGet.sendJsonByGetReq(url, JSON.toJSONString(body), "utf-8");
 }catch (Exception e) {
          e.printStackTrace();
 }

SpringBoot整合Fegin

注意点: Cloud-Feign与parent-SpringBoot的版本冲突问题, 拓展时候使用github的openfeign

3. 使用Fegin调用 Get携带Body参数
<1> 导入坐标
 
        8
        8
        UTF-8
        UTF-8
        1.8
        3.1.0
        5.4.5
        29.0-jre
        8.0.21
        3.2.1
        2.1.2-RELEASE
    
    
   
            org.apache.httpcomponents
            httpclient
            4.5.3

 
            io.github.openfeign
            feign-httpclient
            10.1.0

 
            org.springframework.cloud
            spring-cloud-starter-openfeign
            2.2.7.RELEASE
 
应该只需要上边的就行了,我这边就都贴出来了
 
            org.projectlombok
            lombok
            RELEASE
 

            com.alibaba.fastjson2
            fastjson2
            2.0.23


            cn.hutool
            hutool-all
            ${hutool.version}


            commons-httpclient
            commons-httpclient
            3.1


            org.apache.httpcomponents
            httpclient
            4.5.3

 
            org.apache.httpcomponents
            httpmime
            4.5.3

 
            commons-io
            commons-io
            2.3

本项目Boot版本

 
        org.springframework.boot
        spring-boot-starter-parent
        2.3.1.RELEASE
         
   

问题:

  1. Cloud-OpenFeign 的版本和SpringBoot的版本冲突问题, 有冲突会会报如下错误, 届时需要自行找自己的Boot版本对应的Cloud-OpenFeign 版本

    NoSuchMethodError: feign.Response.create(ILjava/lang/Strin

    creating bean with name ‘configurationPropertiesBeans’ de

  2. Feign拓展Get携带Body时, 需要导入io.github.openfeign和org.apache.httpcomponents, 注意导入的是github的openfeign, 当时找资源的时候, 有的导入的是netflix的, 结果不行;
<2> 写配置类

感觉写不写都可以吧, 反正就是弄个debug级别, 方便看调用, 贴tm一下吧

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CcusFeignConfig {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}
<3> 写配置

主要是为了拓展fegin的Get携带Body功能, enabled改成true

logging:
  level:
    com.hong.feign: DEBUG
feign:
  httpclient:
    enabled: true
server:
  port: 8888
<4> 启动类开启功能
@EnableFeignClients
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
<5> 试试好用不

feign包的远程接口类

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@FeignClient(name = "TestFegin", url = "http://localhost:8082")
public interface TestFeign {
    @GetMapping("/body")
    String test(@RequestBody Map map);
    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello(@RequestParam String name);
}

使用feign调用

@Slf4j
@RestController
public class HelloController {
    @Autowired
    private TestFeign testFeign;
    
    @GetMapping("test/fegin")
    public String testFegin(){
        Map map = new HashMap();
        map.put("aa","bbb");
        //String test = testFeign.hello("张三");
        //System.out.println("result --> "+test);
        String test2 = testFeign.test(map);
        System.out.println("resutl -> "+ test2);
        return "ok-feign";
    }
    @GetMapping("/body")
    public String body(@RequestBody Map map){
        return "body";
    }
    @GetMapping("/hello")
    public String hello(String name){
        return "hello"+name;
    }
4. 使用RestTemplate发送Get请求携带Body参数

写配置类

import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import java.net.URI;
public class HttpComponentsClientRestfulHttpRequestFactory extends HttpComponentsClientHttpRequestFactory {
    @Override
    protected HttpUriRequest createHttpUriRequest(HttpMethod httpMethod, URI uri) {
        if (httpMethod == HttpMethod.GET) {
            return new HttpGetRequestWithEntity(uri);
        }
        return super.createHttpUriRequest(httpMethod, uri);
    }
    /**
     * 定义HttpGetRequestWithEntity实现HttpEntityEnclosingRequestBase抽象类,以支持GET请求携带body数据
     */
    private static final class HttpGetRequestWithEntity extends HttpEntityEnclosingRequestBase {
        public HttpGetRequestWithEntity(final URI uri) {
            super.setURI(uri);
        }
        @Override
        public String getMethod() {
            return HttpMethod.GET.name();
        }
    }
}

后续为了拓展成一个可以继续加配置类

@Configuration
public class RestTemplateConfig {
    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
        restTemplate.setRequestFactory(new HttpComponentsClientRestfulHttpRequestFactory());
        return restTemplate;
    }
    // 设置超时时间
    private SimpleClientHttpRequestFactory getClientHttpRequestFactory() {
        SimpleClientHttpRequestFactory clientHttpRequestFactory = new SimpleClientHttpRequestFactory();
        // Connect timeout 3s
        clientHttpRequestFactory.setConnectTimeout(60000);
        // Read timeout 3s
        clientHttpRequestFactory.setReadTimeout(60000);
        return clientHttpRequestFactory;
    }
}

开始使用

Map map = new HashMap();
Map header = new HashMap();
header.put("password","password");
header.put("username","username");
map.put("header",header);
        
RestTemplate restTemplate = new RestTemplate();
//修改restTemplate的RequestFactory使其支持Get携带body参数
restTemplate.setRequestFactory(new HttpComponentsClientRestfulHttpRequestFactory());
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Accept-Encoding","gzip,deflate,br");
headers.set("Accept-Encoding","deflate");
HttpEntity httpEntity = new HttpEntity<>(JSON.toJSONString(map), headers);
ResponseEntity exchange = restTemplate.exchange(domain+beng, HttpMethod.GET, httpEntity, String.class);
System.out.println(exchange.getBody());

如果配置了第二个配置类, 使用可以试试

HttpHeaders head = new HttpHeaders();
head.setContentType(MediaType.APPLICATION_JSON);
HttpEntity entity = new HttpEntity<>(JSON.toJSONString(map), headers);
log.info("url:" + url + ",httpEntity:" + JSON.toJSONString(entity));
ResponseEntity response = restTemplate.exchange(domain+beng, HttpMethod.GET, httpEntity, Object.class);
log.info("{}请求的返回内容:{}", url, JSON.parseObject(JSON.toJSONString(response.getBody())));
  
 

写个B文章真NM累, 还NM找不到工作, CTMD

总有写B崽子, 搞些奇奇怪怪的东西, Get请求?传参不就行了, 非搞点新花样

这篇文章的诞生就是由于领导无能, 团队不合作, NM累死ND, 场景就是, 第三方搞了个Get+Body, Response用Gzip压缩响应, 搞他妈半天

  • 一开始, 寻思直接拓展一个GET+Body完事, 结果拓展完了调用第三方一直乱码, 我擦嘞, 这什么情况, 以为是工具类不行, 公司站着说话不腰疼的B, 说你用RestTemplate, 这个好, 我寻思不也是http请求嘛, 整, 然后不行, 又说, 你用Feign调用, 这个B更叼, 我寻思不还是Ribbon+RestTemplate嘛, 整, 结果还不行;Response还是乱码

  • 我擦嘞, 搞了半天, 怎么都是乱码, 后来一看, 大哥tm写的账号密码写反了, 账号成密码, 密码成账号, 我擦嘞

  • 改完以后结果发现还不行, 但是发现不能太相信大哥了, 然后仔细对各种参数, 发现, header携带参数不对, 对象都是用fastjson2转的, 我tm怀疑过fastjson2不行, 都没怀疑过公司的dm大哥, 后来发现, 他特么不知道在啥时候已经把对象转成字符串了, 然后我处理Get拓展的时候, 又进行了转换, 变成双引号+引号, 出现了双引号转义, 我擦嘞…DisuNM