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

前言

在我们开发过程中,经常会遇到调用一些第三方的请求与响应,如果只是简单的两种请求与响应那么我们只需要去简单的去封装请求头与请求体即可,并且拼接第三方调用的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);
}

总结

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

相关推荐
计算机学姐2 小时前
基于python+django+vue的影视推荐系统
开发语言·vue.js·后端·python·mysql·django·intellij-idea
JustinNeil2 小时前
简化Java对象转换:高效实现大对象的Entity、VO、DTO互转与代码优化
后端
青灯文案12 小时前
SpringBoot 项目统一 API 响应结果封装示例
java·spring boot·后端
微尘83 小时前
C语言存储类型 auto,register,static,extern
服务器·c语言·开发语言·c++·后端
计算机学姐3 小时前
基于PHP的电脑线上销售系统
开发语言·vscode·后端·mysql·编辑器·php·phpstorm
码拉松4 小时前
千万不要错过,优惠券设计与思考初探
后端·面试·架构
白总Server4 小时前
MongoDB解说
开发语言·数据库·后端·mongodb·golang·rust·php
计算机学姐5 小时前
基于python+django+vue的家居全屋定制系统
开发语言·vue.js·后端·python·django·numpy·web3.py
程序员-珍5 小时前
SpringBoot v2.6.13 整合 swagger
java·spring boot·后端
海里真的有鱼6 小时前
好文推荐-架构
后端