Forest-极简的轻量级HTTP框架

是不是一想到要对接第三方系统接口就发愁,尤其是与其他系统有大量接口交互时,不得不应对各种请求方式、设置各种不同的头、不同的返回、需要权限或token验证等等,将头疼不已,即使有Httpclient似乎还是要写很多的代码,那么Forest将解决你这一烦恼。

一、简介
Forest是专注于简化HTTP客户端访问的一套极简好用的java语言框架,它以Java 接口+注解的形式将繁复的 HTTP 请求细节隐藏于背后,将HTTP请求与业务之间极度松耦合,使得开发人员既能专注自己的业务,又能轻松得搞定五花八门的HTTP请求,通过注解和拦截器的方式,能对极其方便的改造其请求URL、Header、Body,例如第三方系统接口一般都要鉴权,传token之类的,而Forest可以对访问做拦截,往有需要鉴权的访问中加入token。

二、使用

由于目前流行springboot,现在就以此为基础框架进行讲解。

1、引入

如果是maven构建的springboot项目,那么只需在pom.xml引入如下配置即可:

<dependency>
    <groupId>com.dtflys.forest</groupId>
    <artifactId>forest-spring-boot-starter</artifactId>
    <version>1.5.2-BETA</version>
</dependency>

同时加入json解析框架:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.73</version>
</dependency>

2、入门

在 Forest 中,请求绑定到某一接口方法上,调用该接口方法时,底层会去方式具体的请求,我们只需要关注接口方法上需要绑定的参数,请求头,返回值即可。

我们建一个接口类HelloClient:

package com.zl.demo.client;
 
import com.dtflys.forest.annotation.Request;
 
public interface HelloClient {
    @Request(url = "http://localhost:8088/hello")
    String helloForest();
}

如图:@Request直接将请求http://localhost:8088/hello绑定到HelloClient接口helloForest()方法上,默认GET请求,请求返回String值。

springboot只需在启动类中加入@ForestScan,并指向上面接口包的路径即可生效:
 

@SpringBootApplication
@Configuration
@ForestScan(basePackages = "com.zl.demo.client")
public class DemoSpringBoot {
    SpringApplication.run(DemoSpringBoot.class, args);
}

在业务代码中,直接调用

@Component
public class HelloService {
    
    // 注入自定义的 Forest 接口实例
    @Resource
    private HelloClient helloClient;
 
    public void testClient() {
        // 调用自定义的 Forest 接口方法
        // 等价于发送 HTTP 请求,请求地址和参数即为 helloForest 方法上注解所标识的内容
        String result = helloClient.helloForest();
        // result 即为 HTTP 请求响应后返回的字符串类型数据
        System.out.println(result);
    }
 
}

模板表达式

Forest的模板表达式是在普通的Java字符串中嵌入{表达式}来实现字符串和数据的动态绑定。

@Request(url = "http://localhost:8080/hello/{name}")
String send(@Var("name") String name);

@Request(url = "http://localhost:8080/hello/${name}")
String send(@Var("name") String name);

通过@Var或全局定义的变量名进行绑定

比如:send("world"),发送的真实请求就是:http://localhost:8080/hello/world

3、进阶

连接的简单配置

forest:
  backend: httpclient          # 配置后端HTTP API为 httpclient(默认为 okhttp3)
  max-connections: 1000        # 连接池最大连接数
  connect-timeout: 3000        # 连接超时时间,单位为毫秒
  read-timeout: 3000           # 数据读取超时时间,单位为毫秒

连接重试配置

forest:
  retry-count: 1 # 请求失败后重试次数,默认为0次不重试
  max-retry-interval: 1000 #重试间隔时间

类似spring拦截器,Forest支持针对Forest请求的拦截,可以进行统一的日志打印,token鉴权的处理,只需要实现com.dtflys.forest.interceptor.Interceptor接口

@Slf4j
@Component
public class AccessTokenInterceptor implements Interceptor {
 
    @Autowired
    private AccessConfig accessConfig;
    @Autowired
    private ClubService memberService;
 
    /**
     * 该方法在请求发送之前被调用, 若返回false则不会继续发送请求
     */
    @Override
    public boolean beforeExecute(ForestRequest request) {
        String uri = request.getUrl().replace("http://", "");
        log.info(">>>>>>>>>>>>>>>>>>>>>>>>uri:{}", uri);
        if (!Arrays.asList(accessConfig.getFileUplodUrl()).contains(uri)) {
            request.setDataType(ForestDataType.JSON);
            request.setContentType("application/json");
        }
        // 添加请求参数token
        if (Arrays.asList(accessConfig.getMemberTokenUrl()).contains(uri)) {
            String token = memberService.getToken();
            if (ObjectUtil.isEmpty(request.getHeader("token"))) {
              request.addHeader("token", token);
            }
        }
        //添加服务器统一请求地址
        request.setUrl(accessConfig.getMemberServerUrl() + uri);
        return true;
    }
 
    /**
     * 请求发送失败时被调用
     * @param e
     * @param forestRequest
     * @param forestResponse
     */
    @Override
    public void onError(ForestRuntimeException e, ForestRequest forestRequest, ForestResponse forestResponse) {}
 
    /**
     * 请求成功调用(错误异常统一处理)
     * @param o
     * @param forestRequest
     * @param forestResponse
     */
    @Override
    public void onSuccess(Object o, ForestRequest forestRequest, ForestResponse forestResponse) {
        log.info("url:【{}】,result:【{}】", forestRequest.getUrl(), "...");
        ClubResultDto weResultDto = JSONUtil.toBean(forestResponse.getContent(), ClubResultDto.class);
        if (null != weResultDto.getStatus() && null != weResultDto.getStatus().getCode() && !weResultDto.getStatus().getCode().equals(10000)) {
            throw new ForestRuntimeException(forestResponse.getContent());
        }
    }

更多请参考:Forest

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值