Forest实战

 

1.Forest简介

2.SpringBoot集成Forest

3.常用注解

1.Forest简介

官方网站:http://forest.dtflyx.com/

forest是什么?

Forest 是一个开源的 Java HTTP 客户端框架,它能够将 HTTP 的所有请求信息(包括 URL、Header 以及 Body 等信息)绑定到您自定义的 Interface 方法上,能够通过调用本地接口方法的方式发送 HTTP 请求。

Forest的好处

一个轻量级的类似于RPC的HTTP客户端的API框架,是feign之外的另一个好的选择。同时支持OKhttp和HTTPClient,比这两种更高层。封装了http调用的细节,使用简单。

Forest的工作原理

Forest会将定义好的接口通过动态代理的方式生成一个具体的实现类,然后组织、验证 HTTP 请求信息,绑定动态数据,转换数据形式,SSL 验证签名,调用后端 HTTP API(httpclient 等 API)执行实际请求,等待响应,失败重试,转换响应数据到 Java 类型等脏活累活都由这动态代理的实现类给包了。 请求发送方调用这个接口时,实际上就是在调用这个干脏活累活的实现类。

 

HTTP请求过程分为前端和后端部分,Forest是处理前端过程的框架,是对后端HTTP API的进一步封装。

前端部分:

  1. Forest 配置: 负责管理 HTTP 发送请求所需的配置。

  2. Forest 注解: 用于定义 HTTP 发送请求的所有相关信息,一般定义在 interface 上和其方法上。

  3. 动态代理: 用户定义好的 HTTP 请求的interface将通过动态代理产生实际执行发送请求过程的代理类。

  4. 模板表达式: 模板表达式可以嵌入在几乎所有的 HTTP 请求参数定义中,它能够将用户通过参数或全局变量传入的数据动态绑定到 HTTP 请求信息中。

  5. 数据转换: 此模块将字符串数据和JSONXML形式数据进行互转。目前 JSON 转换器支持JacksonFastjsonGson三种,XML 支持JAXB一种。

  6. 拦截器: 用户可以自定义拦截器,拦截指定的一个或一批请求的开始、成功返回数据、失败、完成等生命周期中的各个环节,以插入自定义的逻辑进行处理。

  7. 过滤器: 用于动态过滤和处理传入 HTTP 请求的相关数据。

  8. SSL: Forest 支持单向和双向验证的 HTTPS 请求,此模块用于处理 SSL 相关协议的内容。

后端部分:

后端为实际执行 HTTP 请求发送过程的第三方 HTTP API,目前支持okHttp3httpclient两种后端 API。

版本说明

Forest 1.0.x 和 Forest 1.1.x 基于 JDK 1.7, Forest 1.2.x及以上版本基于 JDK 1.8

2.SpringBoot集成Forest

添加Maven依赖

 <!--Forest依赖-->
 <dependency>
     <groupId>com.dtflys.forest</groupId>
     <artifactId>forest-spring-boot-starter</artifactId>
     <version>1.5.0-RC7</version>
 </dependency>
 <!-- JSON依赖 :版本>= 1.2.48 -->
 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>1.2.48</version>
 </dependency>

增加配置

application.yml

 forest:
   bean-id: config0 # 在spring上下文中bean的id, 默认值为forestConfiguration
   backend: okhttp3 # 后端HTTP API: okhttp3
   max-connections: 1000 # 连接池最大连接数,默认值为500
   max-route-connections: 500 # 每个路由的最大连接数,默认值为500
   timeout: 3000 # 请求超时时间,单位为毫秒, 默认值为3000
   connect-timeout: 3000 # 连接超时时间,单位为毫秒, 默认值为2000
   retry-count: 1 # 请求失败后重试次数,默认为0次不重试
   ssl-protocol: SSLv3 # 单向验证的HTTPS的默认SSL协议,默认为SSLv3
   logEnabled: true # 打开或关闭日志,默认为true
   log-request: true # 打开/关闭Forest请求日志(默认为 true)
   log-response-status: true # 打开/关闭Forest响应状态日志(默认为 true)
   log-response-content: true # 打开/关闭Forest响应内容日志(默认为 false)

配置一般有三种:

  • application.yml或通过ForestConfiguration配置类配置,这两种方式都是全局配置。针对全局所有请求,作用域最大,配置读取的优先级最小。

  • 接口配置: 作用域为某一个interface中定义的请求,读取的优先级最小。您可以通过在interface上修饰@BaseRequest注解进行配置。

  • 请求配置:作用域为某一个具体的请求,读取的优先级最高。您可以在接口的方法上修饰@Request注解进行 HTTP 信息配置的定义。

配置的优先级:优先级值的是是否优先读取该配置。比如您优先级最高@Request中定义了timeout500,那么即便在全局配置中定了timeout1000,最终该请求实际的timeout为优先级配置最高的@Request中定义的500

编写http请求的接口

通过@Request注解,将上面的MyClient接口中的helloWorld()方法绑定了一个 HTTP 请求, 其 URL 为http://localhost:2222/hello-world ,并默认使用GET方式,且将请求响应的数据以String的方式返回给调用者。

 package com.snail.study.rpc.client;
 ​
 import com.dtflys.forest.annotation.Request;
 ​
 public interface HelloClient {
 ​
     @Request(url = "http://localhost:2222/hello-world")
     String helloWorld();
 }

在启动类添加注解

Forest 会扫描@ForestScan注解中basePackages属性指定的包下面所有的接口

 package com.snail.study;
 ​
 import com.dtflys.forest.springboot.annotation.ForestScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 ​
 @ForestScan(basePackages = "com.snail.study.rpc.client")
 @SpringBootApplication
 public class ForestApplication {
     public static void main(String[] args) {
         SpringApplication.run(ForestApplication.class, args);
     }
 }

Service层

 package com.snail.study;
 ​
 import com.snail.study.rpc.client.HelloClient;
 import org.springframework.stereotype.Service;
 ​
 import javax.annotation.Resource;
 ​
 @Service
 public class HelloService {
 ​
     @Resource
     private HelloClient helloClient;
 ​
     public String helloWorld(){
         String helloWorld = helloClient.helloWorld();
         return helloWorld;
     }
 }

Controller层

 import com.dtflys.forest.annotation.GetRequest;
 import com.snail.study.service.HelloService;
 import org.springframework.web.bind.annotation.RestController;
 ​
 import javax.annotation.Resource;
 ​
 @RestController
 public class HelloController {
     
     @Resource
     private HelloService helloService;
     @GetRequest("/hello")
     public String helloWorld(){
         return helloService.helloWorld();
     }
 }

3.常用注解

@Request

@Request用于修饰接口方法,表示绑定方法和一个HTTP请求,其属性url表示远端的地址,默认是GET请求。属性type可以为GET POST PATCH PUT等请求方式。headers可添加请求头

@Post,@Get,@GetRequest,@PostRequest

相当于@Request设置了type值,用法和@Request类似。除了GETPOST,也可以指定成其他几种 HTTP 请求方式(PUT, HEAD, OPTIONS, DELETE)。

其中type属性的大小写不敏感,写成POSTpost效果相同。

@GetRequest, @PostRequest等注解代替@Request注解,这样就可以省去写type属性

@DataVariable

@DataVariable修饰接口方法的参数

@Query

使用 @Query 注解,可以直接将该注解修饰的参数动态绑定到请求url中。

使用 @Query 注解,可以修饰 Map 类型的参数。Map 的 Key 将作为 URL 的参数名, Value 将作为 URL 的参数值,这时候 @Query 注解不定义名称。

@Query 注解也可以修饰自定义类型的对象参数,依据对象类的 Getter 和 Setter 的规则取出属性,其属性名为 URL 参数名,属性值为 URL 参数值。这时候 @Query 注解不定义名称

 @Get("http://localhost:8080/hello")
 String send2(@Query User user);

@Query 与 @DataParam 不同,@Query 注解修饰的参数一定会出现在 URL 中,而 @DataParam 修饰的参数则要视情况而定。

@Header

@Header 注解把方法的参数直接绑定到请求体中

 /**
  * 使用 @Header 注解将参数绑定到请求头上
  * @Header 注解的 value 指为请求头的名称,参数值为请求头的值
  * @Header("Accept") String accept将字符串类型参数绑定到请求头 Accept 上
  * @Header("accessToken") String accessToken将字符串类型参数绑定到请求头 accessToken 上
  */
 @Post("http://localhost:8080/hello/user?username=foo")
 void postUser(@Header("Accept") String accept, @Header("accessToken") String accessToken);

如果有很多请求头参数

 /**
  * 使用 @Header 注解可以修饰 Map 类型的参数
  * Map 的 Key 指为请求头的名称,Value 为请求头的值
  * 通过此方式,可以将 Map 中所有的键值对批量地绑定到请求头中
  */
 @Post("http://localhost:8080/hello/user?username=foo")
 void headHelloUser(@Header Map<String, Object> headerMap);
 ​
 ​
 /**
  * 使用 @Header 注解可以修饰自定义类型的对象参数
  * 依据对象类的 Getter 和 Setter 的规则取出属性
  * 其属性名为 URL 请求头的名称,属性值为请求头的值
  * 以此方式,将一个对象中的所有属性批量地绑定到请求头中
  */
 @Post("http://localhost:8080/hello/user?username=foo")
 void headHelloUser(@Header MyHeaderInfo headersInfo);

@Body

@Body注解修饰的参数一定会绑定到请求体中。

@JSONBody

该注解自1.5.0-RC1版本起可以使用。 使用@JSONBody注解的同时就可以省略 contentType = "application/json"属性设置。

 /**
  * 被@JSONBody注解修饰的参数会根据其类型被自定解析为JSON字符串
  * 使用@JSONBody注解时可以省略 contentType = "application/json"属性设置
  */
 @Post("http://localhost:8080/hello/user")
 String helloUser(@JSONBody User user);

 

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值