Java8自定义Feign解码器动态为响应对象添加响应头属性实现粘性会话
Feign实现粘性会话的响应头提取/传递方案
你不需要做动态追加对象属性这种高维护成本的操作,根据业务场景选下面的实现即可,所有逻辑兼容Java8版本。
优先方案:无业务侵入的自动传递(不需要修改响应模型)
如果业务代码不需要从响应对象里读取粘性会话标识,只需要Feign客户端自动在后续请求里携带该值,完全不需要改动任何响应类,逻辑全在Feign组件层闭环:
- 先准备缓存上下文存储提取到的会话标识:全局粘性场景用
ConcurrentHashMap存储,用户/请求维度粘性场景用ThreadLocal或者链路上下文持有,避免不同用户/请求的标识串用。 - 直接在自定义解码器里提取目标响应头存入缓存即可,不需要修改反序列化后的响应对象:
public final class CustomDecoder extends JacksonDecoder { // 替换成实际要提取的响应头名称,比如负载均衡场景常用的X-Server-Id、Set-Cookie等 private static final String STICKY_HEADER = "X-Sticky-Token"; private final StickyTokenCache tokenCache; public CustomDecoder(ObjectMapper mapper, StickyTokenCache tokenCache) { super(mapper); this.tokenCache = tokenCache; } @Override public Object decode(Response response, Type type) throws IOException { // 直接复用父类JacksonDecoder的反序列化逻辑,避免自定义readValue和原有ObjectMapper配置冲突 Object result = super.decode(response, type); // 提取响应头值,Feign的响应头存储格式为Map<String, Collection<String>>,取第一个有效值即可 Collection<String> headerValues = response.headers().get(STICKY_HEADER); if (headerValues != null && !headerValues.isEmpty()) { String token = headerValues.iterator().next(); // 存入缓存,注意多用户/多租户场景要按上下文维度存储,不要用全局单值 tokenCache.setCurrentToken(token); } return result; } }
- 在已经配置的
auth2FeignRequestInterceptor里,直接从缓存读取标识,塞入后续请求的请求头即可:
// 在现有拦截器逻辑中补充 String currentToken = tokenCache.getCurrentToken(); if (currentToken != null) { requestTemplate.header(STICKY_HEADER, currentToken); }
可选方案:响应头映射到响应体字段
如果业务代码需要从响应对象中拿到这个会话标识,不要用动态追加属性的方式(Java作为静态语言,动态加属性需要依赖CGLib代理、反射等黑科技,兼容性差),用统一接口标记的方式实现即可:
- 定义统一的感知接口,所有需要承载会话标识的响应类实现该接口:
public interface StickySessionAware { String getStickyToken(); void setStickyToken(String stickyToken); }
- 在CustomDecoder提取到token的逻辑后补充判断,反序列化完成后如果对象实现了该接口,直接调用set方法注入值:
if (result instanceof StickySessionAware) { ((StickySessionAware) result).setStickyToken(token); }
- 业务代码直接调用响应对象的
getStickyToken()方法就能拿到对应值,不需要额外类型转换。
不推荐方案说明
如果强行给对象动态追加属性,只能通过CGLib生成响应类的动态子类、拦截getter方法返回头值,或者把响应对象先转成JsonNode追加字段后二次反序列化,这两种方式要么对响应类有继承限制、要么有额外的序列化性能损耗,生产环境不建议使用。
内容的提问来源于stack exchange,提问作者topgun
相关产品推荐
相关产品推荐

