基于Forest实践|如何更优雅的统一处理请求签名

本文介绍了如何使用Forest Java HTTP客户端框架,结合自定义注解和拦截器,实现优雅的日志存储与链路跟踪。通过在接口方法上添加自定义注解,实现在方法执行前后进行日志记录,包括请求参数、响应数据和关键字段,便于后期查询与问题排查。此外,还展示了日志存储后的UI展示效果,方便不同角色的团队成员进行问题分析。

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

本文基于Forest实践,来源于实际业务场景需求,诞生了这篇文章。通过这篇文章,你可以学习到如何更优雅的统一处理基于Forest三方接口请求响应报文存储,如果你读完这篇文章,相信你会有所收获!

1、背景介绍

我们之所以选择Forest,而不选择Spring RestTemplate,是因为Forest支持你通过定义一个接口,通过其相关增强注解,你就可以像在本地调用方法一样,实现调用HTTP请求方法。同时,它提供了一系列缺省配置参数,使得你可以很简单的配置,就可以以最小的研发代码量实现你的需求。

Forest实现原理跟MyBatisMapperProxy类似,Spring容器初始化时,通过扫描包下使用了@BaseRequest的相关接口,通过动态代理生成Http访问类。

当我们程序调用接口方法时,就是从Forest上下文对象中获取预先初始化的代理类,然后委托OkHttp3或者HttpClient实现http调用,只不过Forest优雅的封装了这一系列背后工作,使得我们的代码更精简,更优雅,所以它也是一个非常轻量级的Http工具。

通过查阅Forest的相关开发手册,我们知道可以通过定义拦截器进而统一打印请求响应报文,但是我们希望可以实现更细粒度的定制,比如把一些关键的日志进行数据存储持久化,并非只是简单的打印输出日志。我们想要实现存储日志,可以按照一个关联字段(比如交易号),实现搜索查询。这时候,倘若我们基于MySQL存储日志,这种需求场景我们应该怎么设计呢?

2、实现方案

MethodAnnotationLifeCycle

除了可以实现Forest的拦截器接口Interceptor,其实我们可以实现MethodAnnotationLifeCycle这个接口,这个接口具体干啥的呢?

/**
 * 方法注解的生命周期
 * @param <A> 注解类
 * @param <I> 返回类型
 */
public interface MethodAnnotationLifeCycle<A extends Annotation, I> extends Interceptor<I> {
   
   

    void onMethodInitialized(ForestMethod method, A annotation);

    @Override
    default void onError(ForestRuntimeException ex, ForestRequest request, ForestResponse response) {
   
   

    }

    @Override
    default void onSuccess(I data, ForestRequest request, ForestResponse response) {
   
   

    }
}

MethodAnnotationLifeCycle该接口继承了Interceptor,它提供了方法增强注解的声明A extends Annotation,这样以来,如果一个方法通过注解增强,这个拦截器就会被执行。这个接口提供了三个方法

  • void onMethodInitialized:方法执行前,可以对从ForestMethod上下文中获取相关信息,然后做一些相关的事情,或者重写ForestMethod的相关属性值。
  • default void onError:方法执行请求错误时会回调该方法,该方法可以不需要实现,通过default关键字进行修饰。
  • default void onSuccess:方法执行成功时会回调该方法,该方法可以不需要实现,通过default关键字进行修饰。

TraceMarker

/**
 * @description: 记录链路日志的注解
 * @Date : 2021/6/21 4:31 PM
 * @Author : 石冬冬-Seig Heil
 */
@Documented
@MethodLifeCycle(TraceMarkerLifeCycle.class)
@RequestAttributes
@Retention(RetentionPolicy.RUNTIME)
@Target({
   
   ElementType.TYPE, ElementType.METHOD})
public @interface TraceMarker {
   
   
    /**
     * 订单号
     * @return
     */
    String appCode();

    /**
     * 链路日志类型
     * @return
     */
    TraceTypeEnum traceType()
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值