第三方http的调用-forest

我爱海鲸 2026-02-02 11:02:27 暂无标签

简介forest

https://github.com/dromara/forest

引入依赖

<!-- Source: https://mvnrepository.com/artifact/com.dtflys.forest/forest-spring-boot3-starter -->
<dependency>
    <groupId>com.dtflys.forest</groupId>
    <artifactId>forest-spring-boot3-starter</artifactId>
    <version>1.8.0</version>
    <scope>compile</scope>
</dependency>

以下是基于 Spring Boot 3 + Forest 框架,指定 OkHttp3 作为底层 HTTP 客户端、Jackson 作为 JSON 序列化工具的完整调用示例,包含核心配置、接口定义、测试验证全流程:

一、环境准备(Maven 依赖)

 
创建 Spring Boot 3 项目,在 pom.xml 中引入核心依赖(指定 OkHttp3、Jackson 相关依赖):
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
        <relativePath/>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>forest-okhttp-jackson-demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>17</java.version>
        <forest.version>1.7.6</forest.version>
        <okhttp.version>4.12.0</okhttp.version>
        <jackson.version>2.15.3</jackson.version>
    </properties>

    <dependencies>
        <!-- Spring Boot 3 Web 核心 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- Forest Spring Boot 3 启动器 -->
        <dependency>
            <groupId>com.dtflys.forest</groupId>
            <artifactId>forest-spring-boot3-starter</artifactId>
            <version>${forest.version}</version>
        </dependency>

        <!-- OkHttp3 底层依赖(Forest 底层指定使用) -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>${okhttp.version}</version>
        </dependency>

        <!-- Jackson JSON 序列化(指定为 Forest 核心转换器) -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jackson.version}</version>
        </dependency>

        <!-- Lombok(简化实体类,可选) -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- 测试依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

二、核心配置(application.yml)

 
指定 Forest 底层使用 OkHttp3,JSON 转换器使用 Jackson:
spring:
  application:
    name: forest-okhttp-jackson-demo

# Forest 核心配置
forest:
  # 指定底层 HTTP 客户端为 OkHttp3
  backend: okhttp3
  # 全局超时时间
  timeout: 3000
  # 全局编码
  charset: utf-8
  # 指定 JSON 转换器为 Jackson(覆盖默认的 Fastjson)
  json-converter: com.dtflys.forest.converter.json.JacksonConverter
  # 日志配置(可选,便于调试)
  log:
    enabled: true
    log-request: true
    log-response-status: true
    log-response-content: true

三、定义 HTTP 接口(基于 Forest 声明式)

 
创建接口类,通过注解指定 OkHttp3 作为当前接口的底层客户端,调用第三方示例接口(以 Github 开放接口为例):
 

1. 实体类(响应数据映射)

package com.example.demo.entity;

import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;

import java.util.List;

/**
 * Github 仓库信息实体(适配接口返回结构)
 */
@Data
public class GithubRepo {
    private Long id;
    private String name;
    @JsonProperty("full_name")
    private String fullName;
    private String description;
    @JsonProperty("html_url")
    private String htmlUrl;
    private Owner owner;
    @JsonProperty("stargazers_count")
    private Integer stargazersCount;

    @Data
    public static class Owner {
        private String login;
        @JsonProperty("avatar_url")
        private String avatarUrl;
    }
}

2. Forest 声明式接口

package com.example.demo.client;

import com.dtflys.forest.annotation.Backend;
import com.dtflys.forest.annotation.Get;
import com.dtflys.forest.annotation.Request;
import com.example.demo.entity.GithubRepo;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * Github API 调用接口
 * 指定底层使用 OkHttp3(优先级高于全局配置)
 */
@Component
@Backend("okhttp3") // 显式指定当前接口底层使用 OkHttp3
public interface GithubApiClient {

    /**
     * 获取用户的 Github 仓库列表
     * @param username Github 用户名
     * @return 仓库列表
     */
    @Get(
            url = "https://api.github.com/users/${username}/repos",
            dataType = "json", // 指定响应为 JSON
            headers = {
                    "Accept: application/vnd.github.v3+json",
                    "User-Agent: Forest/1.7.6"
            }
    )
    List<GithubRepo> listUserRepos(@Request("username") String username);

    /**
     * 自定义 OkHttp 客户端配置的请求(示例:带超时配置)
     */
    @Request(
            url = "https://api.github.com/repos/${owner}/${repo}",
            backend = "okhttp3", // 单个请求级别指定 OkHttp3
            timeout = 5000,
            dataType = "json"
    )
    GithubRepo getRepoInfo(String owner, String repo);
}

四、测试调用(Controller / 测试类)

 

1. 编写测试类

package com.example.demo;

import com.example.demo.client.GithubApiClient;
import com.example.demo.entity.GithubRepo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class ForestOkHttpJacksonDemoApplicationTests {

    @Autowired
    private GithubApiClient githubApiClient;

    @Test
    void testListUserRepos() {
        // 调用 Github 接口,获取指定用户的仓库列表
        List<GithubRepo> repoList = githubApiClient.listUserRepos("octocat");
        // 打印结果
        assert repoList != null;
        repoList.forEach(repo -> {
            System.out.println("仓库名:" + repo.getName());
            System.out.println("仓库地址:" + repo.getHtmlUrl());
            System.out.println("星数:" + repo.getStargazersCount());
            System.out.println("------------------------");
        });
    }

    @Test
    void testGetRepoInfo() {
        // 调用接口获取指定仓库信息
        GithubRepo repo = githubApiClient.getRepoInfo("octocat", "hello-world");
        assert repo != null;
        System.out.println("仓库全名:" + repo.getFullName());
        System.out.println("仓库描述:" + repo.getDescription());
        System.out.println("仓库拥有者:" + repo.getOwner().getLogin());
    }

}

2. 编写 Controller(可选,接口调用)

package com.example.demo.controller;

import com.example.demo.client.GithubApiClient;
import com.example.demo.entity.GithubRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/github")
public class GithubController {

    @Autowired
    private GithubApiClient githubApiClient;

    /**
     * 获取指定用户的仓库列表
     */
    @GetMapping("/repos/{username}")
    public List<GithubRepo> listRepos(@PathVariable String username) {
        return githubApiClient.listUserRepos(username);
    }

    /**
     * 获取指定仓库信息
     */
    @GetMapping("/repo/{owner}/{repo}")
    public GithubRepo getRepo(@PathVariable String owner, @PathVariable String repo) {
        return githubApiClient.getRepoInfo(owner, repo);
    }
}

五、核心说明

 
  1. OkHttp3 指定方式
     
    • 全局:application.ymlforest.backend: okhttp3
    • 接口级别:@Backend("okhttp3") 注解(优先级更高)
    • 单个请求级别:@Request(backend = "okhttp3")
     
  2. Jackson 作为 JSON 转换器
     
    • 通过 forest.json-converter: com.dtflys.forest.converter.json.JacksonConverter 指定,覆盖 Forest 默认的 Fastjson;
    • 实体类中可使用 Jackson 注解(如 @JsonProperty)适配 JSON 字段映射。
     
  3. 运行验证:
     
    • 启动 Spring Boot 应用,执行测试类 testListUserRepos/testGetRepoInfo,可看到 Github 接口返回的仓库信息;
    • 访问 HTTP 接口:http://localhost:8080/github/repos/octocat,可直接返回 JSON 格式的仓库列表。

六、扩展(自定义 OkHttp 客户端配置)

若需自定义 OkHttp 客户端参数(如连接池、代理、拦截器),可编写配置类:

package com.example.demo.config;

import com.dtflys.forest.backend.okhttp3.OkHttp3Backend;
import com.dtflys.forest.config.ForestConfiguration;
import okhttp3.OkHttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.TimeUnit;

@Configuration
public class ForestOkHttpConfig {

    /**
     * 自定义 OkHttp 客户端配置
     */
    @Bean
    public OkHttpClient customOkHttpClient() {
        return new OkHttpClient.Builder()
                .connectTimeout(3, TimeUnit.SECONDS)
                .readTimeout(3, TimeUnit.SECONDS)
                .writeTimeout(3, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true) // 开启重试
                // 可添加拦截器、代理、证书等配置
                .build();
    }

    /**
     * 将自定义 OkHttp 客户端注入 Forest
     */
    @Bean
    public ForestConfiguration forestConfiguration(ForestConfiguration defaultConfig, OkHttpClient customOkHttpClient) {
        // 获取 OkHttp3 后端,替换默认客户端
        OkHttp3Backend okHttp3Backend = (OkHttp3Backend) defaultConfig.getBackend("okhttp3");
        okHttp3Backend.getConnectionManager().setDefaultClient(customOkHttpClient);
        return defaultConfig;
    }
}

你好:我的2025