How Forest Simplifies Complex HTTP API Integration in Spring Boot
This article introduces the Forest HTTP client framework, showing how it abstracts diverse third‑party API differences through configuration and annotations, provides easy Spring Boot integration, and offers powerful features like template expressions, HTTPS support, and extensive request customization.
Background
When integrating many third‑party services, each provider may expose HTTP APIs with varying specifications—some follow RESTful conventions, others require custom headers, SSL authentication, JSON or XML serialization, etc. Maintaining elegant code across these differences can be painful.
The problem is how to maintain a unified, business‑agnostic HTTP calling suite that can be configured or parameterized to handle these variations.
Existing HTTP libraries such as Apache HttpClient, OkHttp, and Jersey provide low‑level capabilities, but their APIs differ, and writing repetitive code for each third‑party API is undesirable.
Forest is an open‑source HTTP framework that hides these differences and allows complex HTTP calls to be made like RPC invocations.
https://gitee.com/dromara/forest
Getting Started
Forest supports automatic Spring Boot configuration; adding a single dependency is enough.
<code><dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>spring-boot-starter-forest</artifactId>
<version>1.3.0</version>
</dependency></code>Define your API interface:
<code>public interface MyClient {
@Request(url = "http://baidu.com")
String simpleRequest();
@Request(
url = "http://ditu.amap.com/service/regeo",
dataType = "json"
)
Map getLocation(@DataParam("longitude") String longitude,
@DataParam("latitude") String latitude);
}</code>Configure package scanning in the Spring Boot application:
<code>@SpringBootApplication
@ForestScan(basePackages = "com.example.demo.forest")
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}</code>Inject and use the proxy interface like a local bean:
<code>@Autowired
private MyClient myClient;
@Override
public void yourMethod() throws Exception {
Map result = myClient.getLocation("124.730329", "31.463683");
System.out.println(JSON.toJSONString(result, true));
}</code>Forest logs the underlying HTTP client, request URL, and response, with logging controllable via configuration.
Features
Forest is especially useful for developers who need to integrate many third‑party APIs.
Wraps Apache HttpClient and OkHttp as back‑end implementations.
Allows HTTP requests to be invoked via local method calls, decoupling business logic from the HTTP protocol.
Lightweight compared with Feign; no dependency on Spring Cloud or service registries.
Supports all HTTP methods: GET, HEAD, OPTIONS, TRACE, POST, DELETE, PUT, PATCH.
Flexible template expressions.
Filters for request data.
Annotation‑ and configuration‑based request definitions.
Integrates with Spring and Spring Boot.
Handles JSON and XML serialization/deserialization, supporting Fastjson, Jackson, Gson, and JAXB.
Supports one‑way and two‑way SSL encryption.
Configurable connection pool.
Callback interfaces OnSuccess and OnError.
Simple configuration—often a single @Request annotation suffices.
Asynchronous request support.
Two Great Functions
Only two features are highlighted here.
Template Expressions and Parameter Binding
Template expressions simplify URL construction. Example using positional placeholders:
<code>@Request(
url = "${0}/send?un=${1}&pw=${2}&ph=${3}&ct=${4}",
type = "get",
dataType = "json"
)
public Map send(String base, String userName, String password, String phone, String content);
</code>Using named placeholders:
<code>@Request(
url = "${base}/send?un=${un}&pw=${pw}&ph=${3}&ct=${ct}",
type = "get",
dataType = "json"
)
public Map send(@DataVariable("base") String base,
@DataVariable("un") String userName,
@DataVariable("pw") String password,
@DataVariable("ph") String phone,
@DataVariable("ct") String content);
</code>Even more concise with @DataParam annotations:
<code>@Request(
url = "${base}/send",
type = "get",
dataType = "json"
)
public Map send(@DataVariable("base") String base,
@DataParam("un") String userName,
@DataParam("pw") String password,
@DataParam("ph") String phone,
@DataParam("ct") String content);
</code>Parameters can also be bound to headers or body, and objects can be serialized to JSON or XML directly.
<code>@Request(
url = "${base}/pay",
contentType = "application/json",
type = "post",
dataType = "json",
headers = {"Authorization: ${1}"},
data = "${json($0)}"
)
public PayResponse pay(PayRequest request, String auth);
</code>HTTPS Support
Forest simplifies HTTPS, including two‑way certificates, via configuration.
<code>@Request(
url = "${base}/pay",
contentType = "application/json",
type = "post",
dataType = "json",
keyStore = "pay-keystore",
data = "${json($0)}"
)
public PayResponse pay(PayRequest request);
</code>The keystore is defined in
application.yml:
<code>forest:
...
ssl-key-stores:
- id: pay-keystore
file: test.keystore
keystore-pass: 123456
cert-pass: 123456
protocols: SSLv3
</code>After configuration, the call works like any local method.
Conclusion
Forest offers a high‑level, easy‑to‑use HTTP client that abstracts many pain points of third‑party API integration, providing a simpler alternative to Feign for pure HTTP scenarios.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.