前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >与OKHttp共舞:网络编程的华丽篇章

与OKHttp共舞:网络编程的华丽篇章

原创
作者头像
花花Binki
发布2023-09-26 22:52:29
3981
发布2023-09-26 22:52:29
举报
文章被收录于专栏:岚的工作随笔岚的工作随笔

前言

OkHttp是一个基于HTTP的用于访问网络服务的Java库。它旨在通过取消HTTP连接池以及支持连接和请求超时来提高性能。它还支持SSL和TLS,以及HTTP/2和HTTP/3。OkHttp提供了连接管理器、请求对象、缓存以及响应对象等工具,以便开发人员可以轻松地执行HTTP请求和响应。

在传统的单体应用开发中,后端常常作为接收请求的一端。但当我们需要依赖于另一个应用,比如连接工作流的时候,需要后端来发送请求。如果没有做过网络编程,这是个很令人困扰的问题。那么就有了这样一种方便使用的框架:OKHttp。

一. 慢速入门

场景:模拟一个请求发出后,client端接收并向server端发起请求。

1.1 准备两个Spring boot工程

工程结构
工程结构

父工程pom文件,省略部分

代码语言:html
复制
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modules>
        <module>server</module>
        <module>client</module>
    </modules>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

client 端的pom引入OKHttp

代码语言:html
复制
    <dependency>
        <groupId>com.squareup.okhttp3</groupId>
        <artifactId>okhttp</artifactId>
        <version>4.10.0</version>
    </dependency>

1.2 核心代码

client 端,/controller/HelloController

代码语言:java
复制
    @GetMapping("/hello")
    @ResponseBody
    public String hello() {
        OkHttpClient client = new OkHttpClient();
        // 请求参数
        Request request = new Request.Builder()
                .url("http://localhost:8080/client")
                .build();

        // 返回结果
        String result = "";
        try (Response response = client.newCall(request).execute()) {
            if (response.isSuccessful()) {
                result = response.body().string();
            } else {
                result = STR."请求失败: \{response.message()}";
            }
        } catch (IOException e) {
            result = STR."请求失败: \{e}";
        }

        return result;
    }

server端,/controller/AnswerClient

代码语言:java
复制
    @GetMapping("/client")
    @ResponseBody
    public String hello(String msg) {
        return "我很好";
    }

1.3 测试

使用curl命令发起请求

代码语言:shell
复制
curl http://localhost:8082/hello

结果

测试结果
测试结果

二. 浅入应用

2. 1 更多参数

核心代码中构建一个request对象为参数,在使用的时候发现,有更多的属性可以加入。

代码语言:java
复制
class Request internal constructor(
  @get:JvmName("url") val url: HttpUrl,
  @get:JvmName("method") val method: String,
  @get:JvmName("headers") val headers: Headers,
  @get:JvmName("body") val body: RequestBody?,
  internal val tags: Map<Class<*>, Any>

  • url: 目标服务地址
  • method:请求方法
  • head:请求头
  • body:请求参数

简单post示例

代码语言:java
复制
Request request = new Request.Builder()
                .url(url)
                .header("name", "value")
                .post(requestBody)
                .build();

2.2 泛化调用

目标:我们通过“一个”URL访问不同的REST接口

代码语言:java
复制
final static String WORK_FLOW_URL = "http://localhost:8080/workflow/{0}/{1}"

看起来只是少些一些代码,其更多意义是针对业务做再封装。

更多重点是另一方的统一实现接口,使得更加灵活。

2.3 序列化参数

有些时候需要的参数很多,层级关系复杂,这时候往往需要序列化成json。

fastjson举例。

代码语言:java
复制
    Person person = new Person("张三", 18);
    String jsonString = JSON.toJSONString(person); // {"age":18,"name":"张三"}

2.4 请求重试

这次从OKHttp的构建出发。主要思路是加入自定义拦截器。代码如下:

代码语言:java
复制
    HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
    loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

    OkHttpClient.Builder builder = new OkHttpClient.Builder()
            .addInterceptor(loggingInterceptor)
            .addInterceptor(new RetryInterceptor())
            .retryOnConnectionFailure(true);

自定义的拦截器。

代码语言:java
复制
public class RetryInterceptor implements Interceptor {
    private static final int MAX_RETRIES = 3; // 设置最大重试次数
    private int retries;

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Response response = chain.proceed(request);

        if (!Objects.requireNonNull(response.body()).contentLength() > 0) {
            return response;
        }

        while (!response.isSuccessful() && retries < MAX_RETRIES) {
            retries++;
            response = chain.proceed(request);
        }

        if (retries == MAX_RETRIES) {
            throw new IOException("请求失败,已达到最大重试次数");
        }

        return response;
    }
}

测试使用

代码语言:java
复制
        client.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (!response.isSuccessful()) {
                    throw new IOException("请求失败,代码:" + response.code());
                }

                // 处理响应
                System.out.println(response.body().string());
            }
        });

总结

这只是使用了一部分,框架还提供了:多种协议,连接池,缓存,同步异步等处理。有点初具RPC的影子。在简单的场景,是很好的RPC的替代。


我正在参与2023腾讯技术创作特训营第二期有奖征文,瓜分万元奖池和键盘手表

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一. 慢速入门
    • 1.1 准备两个Spring boot工程
      • 1.2 核心代码
        • 1.3 测试
        • 二. 浅入应用
          • 2. 1 更多参数
            • 2.2 泛化调用
              • 2.3 序列化参数
                • 2.4 请求重试
                • 总结
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档