调用第三方服务如何优雅的封装请求响应?

前言

在我们开发过程中,经常会遇到调用一些第三方的请求与响应,如果只是简单的两种请求与响应那么我们只需要去简单的去封装请求头与请求体即可,并且拼接第三方调用的key即可,但是遇到一些流程比较繁琐的调用就显得非常的麻烦了。

而高效的去封装这些服务的请求与响应实体不仅能提高代码的可维护性,还能提升整体的开发效率。在这篇博客中,我们将探讨如何有效地实现这一目标。

目标实现

这里我推荐使用第三方的发送请求的工具就是okhttp,下面是在项目中引入的pom文件

xml 复制代码
<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.9.3</version>
</dependency>

还有就是在请求和响应中需要序列化文件

xml 复制代码
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.5</version>
</dependency>

创建请求方法

这里我们一般会将统一请求的参数(例如:appId,key)等参数统一的封装到这个里面

java 复制代码
private static final String CONTENT_TYPE = "application/json; charset=UTF-8";
/**
 * 发起请求
 * @param path 请求拼接路径
 * @param method 请求类型
 * @param payload 请求体
 * @return 响应体
 */
@NotNull
@SneakyThrows
protected String request(String path, String method, String payload) {
    //获取统一的请求前缀
    String url = getUrl(path);
    String pathAndParameters = url.replace(getUrl(""), "");

    Request.Builder builder = new Request.Builder()
            .url(url)
            .header("X-Tsign-Open-App-Id", appId)
            .header("X-Tsign-Open-Auth-Mode", "Signature")
            .header("X-Tsign-Open-Ca-Timestamp", String.valueOf(System.currentTimeMillis()))
            .header("Date", "")
            .header("Accept", "*/*")
            .header("Content-MD5", contentMD5)
            .header("Content-Type", CONTENT_TYPE);



    RequestBody body = null;
    if (StringUtils.isNotBlank(payload)) {
        body = RequestBody.create(payload.getBytes(), MediaType.parse(CONTENT_TYPE));
    }
    builder.method(method, body);

    Request httpRequest = builder.build();
    Response r = httpClient.newCall(httpRequest).execute();
    if (!r.isSuccessful()) {
        System.err.println("请求异常: r=" + r);
        return null;
    }

    String text = r.body().string();
    return text;
}

通过这段代码我们就可以统一将填充的内容封装到请求当中了。

配置请求参数

我们的请求参数如果是微服务就可以配置参数到配置中心,然后供我们后续使用如下示例:

  • 添加yml配置
yml 复制代码
config:
  appId: 123
  secret: ***
  • 预设配置 创建一个类去接收这些配置
java 复制代码
@Data
@ConfigurationProperties("config")
public class PropertiesConfig{

    /**
     * appId
     */
    String appId;

    /**
     * 密钥
     */
    String secret;

}
  • 用bean的方式在项目启动的时候填充到这个类中
less 复制代码
@Configuration
@AllArgsConstructor
@EnableConfigurationProperties(PropertiesConfig.class)
public class UseAutoConfiguration {

    private final PropertiesConfig properties;

    @Bean
    @ConditionalOnProperty(value = "fastesign.appId")
    FastEsignService esignService() {
    //需要配置的config类
        UseConfig bean = new UseConfig();
        bean.setSecret(properties.getSecret());
        bean.setAppId(properties.getAppId());
        return bean;
    }
  • 预设类 让我们再来看看useConfig中要添加那些属性呢?
java 复制代码
public class UseConfig {
/**
 * appId
 */
@Setter
String appId;

/**
 * 密钥
 */
@Setter
String secret;

为需要注入的方法添加一个set方法,在项目启动的时候将属性注入到里面,然后供上面去调用

Json序列化

因为在服务之间传输基本都是使用的序列化,这里我也直接提供json序列化util工具了,后续我们使用直接调用这些工具类了

typescript 复制代码
//序列化
public static String toJson(Object object) {
    try {
        return objectMapper.writeValueAsString(object);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

//反序列化
public static <T> T parseObject(String text, Class<T> mainType, Class<?> clazz) {
    try {
        JavaType type = objectMapper.getTypeFactory().constructParametricType(mainType, clazz);
        return objectMapper.readValue(text, type);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

封装不同的请求

因为基本都是一些post和get请求所以这里我就拿这两个请求进行演示了,其他的请求都类似这两请求了

还是那上面已经封装好的请求,然后传入我们需要调用请求方法

vbnet 复制代码
@SuppressWarnings("ALL")
public <T> EsignResponse<T> post(String path, Object request, Class<T> clazz) {
    String text = request(path, "POST", JsonUtils.toJson(request));
    return JsonUtils.parseObject(text, EsignResponse.class, clazz);
}


@SuppressWarnings("ALL")
public <T> EsignResponse<T> get(String path, Class<T> clazz) {
    String text = request(path, "GET", null);
    return JsonUtils.parseObject(text, EsignResponse.class, clazz);
}

这里可以看到它的入参出参类都使用了范型,就是为了方便我们去更好的扩展接口

使用

上面基本就是我们封装的一些基本信息了,我们如何去使用呢?

我们只需要去定义好它的入参出参的类然后按照上面的方法给传入即可

typescript 复制代码
/**
 * post示例
 *
 * @param request
 * @return
 */
public EsignResponse<TestResponse> test(TestRequest request) {
    String path = "/v2/url";
    return UseConfig.post(path, request, TestResponse.class);
}

/**
 * get示例
 *
 * @param request
 * @return
 */
public EsignResponse<TestResponse> get(String request) {
    String path = "/v3/url" + request;
    return fastEsignService.get(path, TestResponse.class);
}

总结

通过这些方法,我们可以高效、安全且优雅地与第三方服务交互,从而提升整个应用程序的质量和可靠性。

相关推荐
齐 飞28 分钟前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
LunarCod1 小时前
WorkFlow源码剖析——Communicator之TCPServer(中)
后端·workflow·c/c++·网络框架·源码剖析·高性能高并发
码农派大星。1 小时前
Spring Boot 配置文件
java·spring boot·后端
杜杜的man2 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*2 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
llllinuuu2 小时前
Go语言结构体、方法与接口
开发语言·后端·golang
cookies_s_s2 小时前
Golang--协程和管道
开发语言·后端·golang
为什么这亚子2 小时前
九、Go语言快速入门之map
运维·开发语言·后端·算法·云原生·golang·云计算
想进大厂的小王2 小时前
项目架构介绍以及Spring cloud、redis、mq 等组件的基本认识
redis·分布式·后端·spring cloud·微服务·架构
customer083 小时前
【开源免费】基于SpringBoot+Vue.JS医院管理系统(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·开源·intellij-idea