Backend Development 10 min read

Mastering Forest: A Practical Guide to Declarative HTTP Calls in Spring Boot

This article introduces the Forest Java HTTP client, explains its architecture and dynamic‑proxy mechanism, and provides step‑by‑step Spring Boot examples—including dependency setup, configuration, declarative interfaces, request annotations, parameter handling, and programmatic usage—so developers can quickly adopt declarative HTTP calls in their backend services.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Forest: A Practical Guide to Declarative HTTP Calls in Spring Boot

1. Introduction

Forest is a Java HTTP client framework that supports both declarative and programmatic styles, allowing developers to send HTTP requests using interface definitions similar to RPC frameworks like Dubbo.

2. What is Forest?

Forest decouples HTTP request details from business code, managing URLs, headers, and other request metadata centrally. Callers invoke methods without worrying about the underlying HTTP implementation.

3. How Forest Works

Forest generates a concrete implementation of a user‑defined interface via dynamic proxies. The proxy validates request data, binds dynamic values, handles SSL, retries, and converts responses to Java types.

4. Architecture

The framework handles the front‑end part of HTTP request processing, wrapping lower‑level HTTP API frameworks.

5. Practical Example

5.1 Dependency Management

<code>&lt;dependency&gt;
  &lt;groupId&gt;com.dtflys.forest&lt;/groupId&gt;
  &lt;artifactId&gt;forest-spring-boot3-starter&lt;/artifactId&gt;
  &lt;version&gt;1.5.36&lt;/version&gt;
&lt;/dependency&gt;</code>

The example uses Spring Boot’s default Jackson JSON mapper; other mappers can be added as needed.

5.2 Simple Configuration

<code>forest:
  backend: okhttp3
  max-connections: 100
  connect-timeout: 5000
  read-timeout: 6000</code>

Further configuration options are available in ForestConfigurationProperties .

5.3 Declarative Interface

<code>public interface UserClient {
  @Request(
        url = "http://localhost:8080/users",
        headers = "Accept: application/json"
  )
  List&lt;Map&lt;String, Object&gt;&gt; list(@Query("area") String area);
}</code>

The interface can be injected and used directly:

<code>@RestController
@RequestMapping("/forests")
public class ForestController {
  private final UserClient userClient;
  public ForestController(UserClient userClient) {
    this.userClient = userClient;
  }
  @GetMapping("/users/{area}")
  public Object users(@PathVariable String area) {
    return this.userClient.list(area);
  }
}</code>

Testing the endpoint shows request details and timing in the console.

5.4 Supported Request Methods

Forest provides annotations such as @Get , @Post , @Put , and their @*Request equivalents. Example:

<code>@Get("http://localhost:8080/users")
Object get1();

@Post("http://localhost:8080/users")
Object post(@JSONBody User user);

@Put("http://localhost:8080/users")
Object put(@JSONBody User user);</code>

5.5 Request Parameters

URL parameters can be supplied via placeholders, @Var annotations, or @Query annotations:

<code>@Get("http://localhost:8080/abc?a={0}&b={1}&id=0")
String send1(String a, String b);

@Get("http://localhost:8080/abc?a={a}&b={b}&id=0")
String send2(@Var("a") String a, @Var("b") String b);

@Get("http://localhost:8080/abc?id=0")
String send(@Query("a") String a, @Query("b") String b);
</code>

Body parameters use @Body , @JSONBody , or @Form annotations. Example of form‑encoded body:

<code>@Post("http://localhost:8080/login")
Object login(@Body("username") String username, @Body("password") String password);
</code>

Example of JSON body:

<code>@Post("http://localhost:8080/user")
Object save(@JSONBody User user);
</code>

5.6 Interface‑Level Annotations

<code>@BaseRequest(
    baseURL = "http://localhost:8080/users",
    headers = {"Accept:application/json"},
    sslProtocol = "TLS"
)
public interface UserClient {
  @Request(url = "")
  List&lt;Map&lt;String, Object&gt;&gt; list(@Query("area") String area);

  @Post("")
  R save(@JSONBody User user);
}</code>

5.7 Programmatic Usage

<code>Object ret = Forest.get("http://localhost:8080/users").execute();
System.out.println(ret);

ForestRequest<?> request = Forest.get("http://localhost:8080/users");
request.backend("httpclient");
Object ret2 = request.execute();

request.addBody(new User("admin", 66));</code>

Programmatic calls support extensive configuration; refer to the official documentation for more details.

Javabackend developmentSpring BootDeclarative APIHTTP ClientForest
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.