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