一个能让人接受的BFF

type
status
date
slug
summary
tags
category
icon
password
公司几乎所有项目都会加上一个BFF,没有为什么,就是想要一个BFF,经历过几个项目,无一例外,BFF都成了一坨屎。包括不限于以下问题:
  1. request和response明明都不需要做任何修改,但就是要重新写一遍给客户端的API和调用上游的Client
  1. 需要把返回包上Code/Data/Message,然后在API层面调用无数次的Response.ok(......)
  1. 背锅侠,任何问题都会被第一时间找到,需要自证清白
在最近的一个项目中,我在客户的限制下搭建了一套不太完善的BFF框架,应该能解决上面的部分问题。
客户限制:必须要Java+Spring Boot,而且必须要WebMVC,不能是Webflux/Reactor

全局

最终成品如下
notion image
从上往下
  • Sleuth Tracing 这是一个servlet filter,用来给req加transactionId
  • 自定义的Log Filter,用来记录所有的Request和Response
  • Reverse Proxy Filter,会处理特定的path,直接进入转发流程。
  • Spring Mvc的Filter,进入Spring的处理范围。
 

Proxy

对于Proxy部分,会有一串Interceptor,这个interceptor chain是金字塔形状的,
  1. 如果对request做操作,order越优先,越接近原始,越往后,越接近转发给上游的状态
  1. 如果对response做操作,order越优先,越接近返回给客户端的状态,越往后,越接近从上游拿到的原始状态
所以
  1. Logger的优先级放最低,拿到发给上游和从上游拿到的结果。
  1. ErrorCatch放次低,在第二顺位拿到上游的错误,包装后抛出
  1. ErrorHandler放最高,在最外层捕获到所有错误,记录后给客户端友好提示
 

Spring

ResponseDataBodyAdvice负责对API包内的返回值进行包装,判断如果returnType是由Jackson处理,那就包一层。
敢于这么做的原因是,我没见过在API返回不同Code的,基本都是返回ok,非ok的情况都是抛出错误由ErrorHandler来处理。
这样做会有一个小小的问题,那就是spring会把字符串json交给StringHttpMessageConverter 处理,有个很tricky的解决方案,就是调整MappingJackson2HttpMessageConverter的优先级,使其排在第一个。
Feign相关的就是非常简单的加上类似的request/response日志,错误mapping。

关于DTO

选择在所有必须得写的DTO里面只声明“需要”的。一些额外的参数用Jackson @AnySetter,在给到客户端的时候,再用上@AnyGetter,大致就是这样
 
Loading...

© XGFan 2012-2025