Bootstrap

#GET携带Body参数发送请求 #SpringBoot整合Feign #SpringBoot整合RestTemplate #RestTemplate拓展Get请求携带Body参数

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

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

坐标如下:

   <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.17</version>
   </dependency>

关键代码:

// 携带的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
 <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
 </dependency>
 <dependency>
           <groupId>org.apache.httpcomponents</groupId>
           <artifactId>httpclient</artifactId>
           <version>4.5.3</version>
 </dependency>

添加工具类

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> 导入坐标
 <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <mybatis.plus.version>3.1.0</mybatis.plus.version>
        <hutool.version>5.4.5</hutool.version>
        <guava.version>29.0-jre</guava.version>
        <mysql.version>8.0.21</mysql.version>
        <easyexcel.version>3.2.1</easyexcel.version>
        <battcn.swagger.version>2.1.2-RELEASE</battcn.swagger.version>
    </properties>
    
   <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.3</version>
</dependency>
 <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
            <version>10.1.0</version>
</dependency>
 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.7.RELEASE</version>
 </dependency>

应该只需要上边的就行了,我这边就都贴出来了

 <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>RELEASE</version>
 </dependency>
<dependency>
            <groupId>com.alibaba.fastjson2</groupId>
            <artifactId>fastjson2</artifactId>
            <version>2.0.23</version>
</dependency>
<dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>${hutool.version}</version>
</dependency>
<dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
</dependency>
<dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.3</version>
</dependency>
 <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpmime</artifactId>
            <version>4.5.3</version>
</dependency>
 <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.3</version>
</dependency>

本项目Boot版本

 <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
        <relativePath/> 
   </parent>

问题:

  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<String> httpEntity = new HttpEntity<>(JSON.toJSONString(map), headers);

ResponseEntity<String> 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<String> entity = new HttpEntity<>(JSON.toJSONString(map), headers);
log.info("url:" + url + ",httpEntity:" + JSON.toJSONString(entity));
ResponseEntity<Object> 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

;