SpringBoot调用HTTP接口

1. RestTemplate

首先引入依赖

  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

编写配置类

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory factory){
        return new RestTemplate(factory);
    }

    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setReadTimeout(5000);//单位为ms
        factory.setConnectTimeout(5000);//单位为ms
        return factory;
    }
}

SimpleClientHttpRequestFactory类对应的HTTP库是JDK自带的HttpUrlConnection,也可以修改使用其他的HTTP库,例如HttpComponentsAsyncClientHttpRequestFactory。

这样就可以注入使用了

    @Resource
    private RestTemplate restTemplate;
      String url = "http://127.0.0.1/test";
      // 请求参数
      Map map = new HashMap<>();
      map.put("key", "111");
      // 设置请求头属性
      HttpHeaders httpHeaders = new HttpHeaders();
      httpHeaders.setContentType(MediaType.APPLICATION_JSON);
      HttpEntity httpEntity = new HttpEntity(map, httpHeaders);
      String results = restTemplate.postForObject(url, httpEntity, String.class);

2. WebClient

 Spring3.0引入了RestTemplate,WebClient是Spring Framework的一部分,但是在后来的官方源码中介绍,RestTemplate有可能在未来的版本中被弃用,所谓替代RestTemplate,在Spring5中引入了WebClient作为异步的非阻塞、响应式的HTTP客户端。

依赖

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

使用

public class TestWebClient {
    @Test
    public void doGet() {
        String userId = "郭郭";
        String url = "http://127.0.0.1:8094/masterdata/sysUser/getSysUserById?userId={userId}";
        Mono<String> mono = WebClient
                //创建WebClient实例
                .create()
                //方法调用,WebClient中提供了多种方法
                .get()
                //请求url
                .uri(url, userId)
                //获取响应结果
                .retrieve()
                //将结果转换为指定类型
                .bodyToMono(String.class);
        //返回最终结果:block是阻塞的/subscribe()非阻塞式获取响应结果
        System.out.println("响应结果:" + mono.block());
    }
    @Test
    public void doPost() {
        Map map = new HashMap<>();
        map.put("name", "郭郭");
        String requestBody = JSON.toJSONString(map);
        String url = "http://127.0.0.1:8094/masterdata/sysUser/saveUser";
        Mono<String> mono = WebClient
                //创建WebClient实例
                .create()
                //方法调用,WebClient中提供了多种方法
                .post()
                //请求url
                .uri(url)
                //指定请求的Content-Type为JSON
                .contentType(MediaType.APPLICATION_JSON)
                //使用bodyValue方法传递请求体
                .bodyValue(requestBody)
                //获取响应结果
                .retrieve()
                //将结果转换为指定类型
                .bodyToMono(String.class);
        //返回最终结果:block是阻塞的/subscribe()非阻塞式获取响应结果
        System.out.println("响应结果:" + mono.block());
    }
}

 在上述doPost请求中,我们的请求接口入参是一个Map,但是需要转换为JSON格式传递,这是因为WebClient默认是使用JSON序列化的。

3.Apache HttpClient

引入依赖

 <!-- 此处使用的是 5.x 版本,可以根据自身情况引入版本 -->
 <dependency>
      <groupId>org.apache.httpcomponents.client5</groupId>
      <artifactId>httpclient5</artifactId>
      <version>5.1.1</version>
 </dependency>
//步骤一:方式1获取默认配置的httpClient实例
CloseableHttpClient httpClient = HttpClients.createDefault();
// 方式2根据系统配置创建 HttpClient
// CloseableHttpClient httpClient = HttpClients.createSystem();
// 在项目启动时可以通过设置如下JVM启动参数:
// http.agent 配置 userAgent
// http.keepAlive 配置 keepAlive 数据
// 方式3自定义创建全局配置
// CloseableHttpClient httpClient = HttpClients.custom()
// .setDefaultHeaders(Collections.emptyList()) // 设置默认请求头
// .setDefaultRequestConfig(RequestConfig.DEFAULT) // 设置默认配置
// .build();

// 设置默认请求头
List<Header> headers = new ArrayList<>();
headers.add(new BasicHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON));
headers.add(new BasicHeader(HttpHeaders.ACCEPT_ENCODING, "gzip, x-gzip, deflate"));
headers.add(new BasicHeader(HttpHeaders.CONNECTION, "keep-alive"));
httpClient .setDefaultHeaders(headers) 
//步骤二:创建HTTP请求
HttpGet httpGet = new HttpGet("http://127.0.0.1:8080/masterdata/sysUser/getSysUserById?userId=张三");

// 创建请求配置信息
RequestConfig requestConfig = RequestConfig.custom()
// 设置连接超时时间
.setConnectTimeout(Timeout.of(3000, TimeUnit.MILLISECONDS))
// 设置响应超时时间
.setResponseTimeout(3000, TimeUnit.MILLISECONDS)
// 设置从连接池获取链接的超时时间
.setConnectionRequestTimeout(3000, TimeUnit.MILLISECONDS)
.build();
// 设置请求参数
httpGet.setConfig(requestConfig);
// 添加 Content-Type 请求头
httpPost.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_FORM_URLENCODED);
// 添加 accept 请求头
httpPost.addHeader(new BasicHeader(HttpHeaders.ACCEPT, "*/*"));
//步骤三:发送请求并获取响应数据
CloseableHttpResponse response = httpClient.execute(httpGet);
// 获取请求状态
int code = response.getCode();
//步骤四:处理响应数据
HttpEntity entity = response.getEntity();
String result = EntityUtils.toString(entity);
//步骤五:关闭httpClient和response
response.close();
httpClient.close();

 通过 URIBuilder 构建请求路径

// 构建请求路径,及参数
URL url = new URL("http://localhost:10010/user/params");
URI uri = new URIBuilder()
.setScheme(url.getProtocol())
.setHost(url.getHost())
.setPort(url.getPort())
.setPath(url.getPath())
// 构建参数
.setParameters(
new BasicNameValuePair("name", "张三"),
new BasicNameValuePair("age", "20")
).build();
​
// 创建 GET 请求对象
HttpGet httpGet = new HttpGet(uri);
// 调用 HttpClient 的 execute 方法执行请求
CloseableHttpResponse response = httpClient.execute(httpGet);
// 获取请求状态
int code = response.getCode();
// 如果请求成功
if(code == HttpStatus.SC_OK){
http://LOGGER.info("响应结果为:{}", EntityUtils.toString(response.getEntity()));
}

发送 JSON 数据

HttpClient 中发送 JSON 数据可以使用 StringHttpEntity 类实现,如下所示:
// 请求参数
String url = "http://localhost:10010/user/body";
// 创建 GET 请求对象
HttpPost httpPost = new HttpPost(url);
// 构建对象
User user = new User();
user.setName("张三")
.setAge(20)
.setAddress(new Address()
.setCounty("中国")
.setCity("北京"))
.setAihao(Arrays.asList("跑步", "爬山", "看书"));
​
// 创建 字符串实体对象
HttpEntity httpEntity = new StringEntity(JSON.toJSONString(user));
httpPost.setEntity(httpEntity);
​
// 发送 POST 请求
httpClient.execute(httpPost);

模拟form表单数据 

// 修改 contentType
// 创建 ContentType 对象为 form 表单模式
ContentType contentType = ContentType.create("application/x-www-form-urlencoded", StandardCharsets.UTF_8);
// 添加到 HttpPost 头中
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
创建请求数据 HttpEntity
// 方式一、自己拼接请求数据,并且创建 StringEntity 对象
String query = "name="+ URLEncoder.encode("张三", "utf-8") +"&age=20";
HttpEntity httpEntity = new StringEntity(query);
​
// 方式二、通过UrlEncodedFormEntity 创建 HttpEntity
HttpEntity httpEntity = new UrlEncodedFormEntity(
Arrays.asList(new BasicNameValuePair("name", "张三"),
new BasicNameValuePair("age", "20")),
StandardCharsets.UTF_8
);
​
// 把 HttpEntity 设置到 HttpPost 中
httpPost.setEntity(httpEntity);

 上传

 //要上传的文件
 File file = new File("F:/20150703212056_Yxi4L.jpeg");
 ​
 // 创建对象
 MultipartEntityBuilder builder = MultipartEntityBuilder.create();
 ​
 // 添加二进制消息体
 builder.addBinaryBody("file", file);
 ​
 // 也可以添加文本消息
 ContentType contentType = ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8);
 builder.addTextBody("name", "张三", contentType);
 ​
 // 通过 MultipartEntityBuilder 构建消息体
 HttpEntity httpEntity = builder.build();
 HttpPost httpPost = new HttpPost("http://localhost:10010/user/upload");
 httpPost.setEntity(httpEntity);
 CloseableHttpResponse response = httpClient.execute(httpPost);
 // 获取请求状态
 int code = response.getCode();
 // 如果请求成功
 if(code == HttpStatus.SC_OK){
     LOGGER.info("响应结果为:{}", EntityUtils.toString(response.getEntity()));
 }
 

下载

 // 请求下载路径
 HttpGet httpGet = new HttpGet("http://localhost:10010/user/downLoad");
 CloseableHttpResponse response = httpClient.execute(httpGet);
 ​
 // 如果请求成功
 if (response.getCode() == HttpStatus.SC_OK){
 ​
     // 获取下载文件的文件名,此处的 File-Name 头信息,需要在服务端进行自定义
     Header header = response.getFirstHeader("File-Name");
     String value = header.getValue();
 ​
     // 读取数据
     byte[] bytes = EntityUtils.toByteArray(response.getEntity());
     try (OutputStream outputStream = new FileOutputStream("F:/" + value);){
         outputStream.write(bytes);
         outputStream.flush();
     }
 }

响应处理

 // 转换为字符串
 EntityUtils.toString(response.getEntity());
 ​
 // 转换为字节数组
 EntityUtils.toByteArray(response.getEntity());

 自定义响应对象

@Data
 @Accessors(chain = true)
 class  Response {
     // 响应状态
     private int code;
     // 响应描述
     private String msg;
     // 响应体
     private String body;
 }
 ​
 // 调用  execute 时自定义 响应处理类
  Response execute = httpClient.execute(httpGet, response -> {
             return new Response().setCode(response.getCode())
                 .setMsg(response.getReasonPhrase())
                 .setBody(EntityUtils.toString(response.getEntity(),                 
                                               StandardCharsets.UTF_8));
         });

 会话保持

// 创建 HttpClientContext对象
 HttpContext httpContext = new BasicHttpContext();
 httpContext.setAttribute("name", "zhangsan");
 HttpClientContext httpClientContext = HttpClientContext.adapt(httpContext);
 ​
 // 登录
 httpClient.execute(new HttpPost(""), httpClientContext);
 ​
 // 获取数据
 httpClient.execute(new HttpGet(""), httpClientContext);

4. OkHttp

具有低内存占有和出色的性能

引入依赖

  <dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.0.0</version>
  </dependency>

5. HttpURLConnection

Java 自带的一个 HTTP 客户端工具

示例:

 @Test
    public void doGet() throws IOException {
        String userId = "张三";  // 参数值
        userId = URLEncoder.encode(userId, "UTF-8"); // 对参数值进行URL编码
        //步骤一:创建URL对象
        URL url = new URL("http://127.0.0.1:8094/masterdata/sysUser/getSysUserById?userId=" + userId);
        //步骤二:打开连接 HttpURLConnection继承自URLConnection,是它的一个子类,
        //而HttpURLConnection专门用于处理HTTP协议的连接,如果需要处理其他协议使用通用的URLConnection。
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        //步骤三:设置请求方式
        conn.setRequestMethod("GET");
        //步骤四:读取响应内容
        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        reader.close();
        System.out.println(sb.toString());
    } 
    @Test
    public void doPost() throws IOException {
        //创建URL对象
        URL url = new URL("http://127.0.0.1:8094/masterdata/sysUser/saveUser");
        //打开连接
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        //设置请求方式
        conn.setRequestMethod("POST");
        // 设置请求头
        conn.setRequestProperty("Content-Type", "application/json");
        //启用输出流
        //告诉连接对象您将使用输出流来发送数据,这样它会准备好接受输出流,并将数据发送到服务器。
        //这是发送POST请求体数据所必需的步骤。get没有请求体不需要
        conn.setDoOutput(true);
        //设置请求体数据
        Map map = new HashMap<>();
        map.put("name", "张三");
        String requestBody = JSON.toJSONString(map);
        //发送请求体数据
        try (DataOutputStream outputStream = new DataOutputStream(conn.getOutputStream())) {
            outputStream.write(requestBody.getBytes(StandardCharsets.UTF_8));
        }

        //读取响应内容
        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        reader.close();
        System.out.println(sb.toString());
    } 

6. FeignClient

引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

在 spring boot 启动类加上@EnableFeignClients注解

// name:指定Feign的名称,如果使用了注册中心,name属性会作为微服务的名称,用于服务发现
// url:Feign调用的跳转路径,可以在配置文件中设置,多用于代码调试
@FeignClient(name = "masterdata",url = "${masterdata-service-url}")
public interface ISysUserClient {

    @GetMapping(value = "/masterdata/getSysUserById")
    public Map getSysUserById(@RequestParam("userId") String userId);
}

默认是连接超时10s,读超时60s ,feign 集成了 ribbon 和 hystrix,feign 本身不带超时限制,其超时是由 ribbon 和 hystrix 控制的。

## 方法一:设置在ribbon上
ribbon:
  OkToRetryOnAllOperations: false #对所有操作请求都进行重试,默认false
  ReadTimeout: 5000   #负载均衡超时时间,默认值5000
  ConnectTimeout: 3000 #ribbon请求连接的超时时间,默认值2000
  MaxAutoRetries: 0     #对当前实例的重试次数,默认0
  MaxAutoRetriesNextServer: 1 #对切换实例的重试次数,默认1

## 方法二:设置在feign client上
feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 3000

7. AsyncHttpClient

AsyncHttpClient是一个独立的开源库,它不依赖于任何的框架或者技术栈

依赖:

<dependency>
      <groupId>org.asynchttpclient</groupId>
      <artifactId>async-http-client</artifactId>
      <version>2.12.3</version>
</dependency>

示例:

public class TestAsyncHttpClient {
    @Test
    public void doGet() throws IOException {
        try (AsyncHttpClient client = new DefaultAsyncHttpClient();) {
            BoundRequestBuilder requestBuilder = client.prepareGet("http://127.0.0.1:8094/masterdata/sysUser/getSysUserById?userId=郭郭");
            CompletableFuture<String> future = requestBuilder.execute()
                    .toCompletableFuture()
                    .thenApply(Response::getResponseBody);
            //使用join等待响应完成
            String responseBody = future.join();
            System.out.println(responseBody);
        }
    }
    @Test
    public void doPost() throws IOException {
        try (AsyncHttpClient client = new DefaultAsyncHttpClient();) {
            BoundRequestBuilder requestBuilder = client.preparePost("http://127.0.0.1:8094/masterdata/sysUser/saveUser");
            //requestBody请求入参
            Map map = new HashMap<>();
            map.put("name", "郭郭");
            String requestBody = JSON.toJSONString(map);
            requestBuilder.addHeader("Content-Type", "application/json");
            requestBuilder.setBody(requestBody);
            CompletableFuture<String> future = requestBuilder.execute()
                    .toCompletableFuture()
                    .thenApply(Response::getResponseBody);
            //使用join等待响应完成
            String responseBody = future.join();
            System.out.println(responseBody);
        }
    }
  }

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今晚哒老虎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值