springcloud Feign调用拦截器(统一处理拷贝请求头实现透传信息、内部调用鉴权、打印feign调用日志)
实现接口Feign.RequestInterceptor
实现接口 feign.RequestInterceptor 并注入到IOC容器即可生效
示范代码如下
- 拷贝请求头,将原请求信息透传下去给被调用的feign服务,部分头不拷贝,例如content-length
- 内部调用鉴权标记,在发起feign调用时加上标记(每天一个token,64位随机字符,在redis记录了今天的和昨天的,都有效),让内部调用时有权限调用被调服务
- 打印feign调用目标的日志
/*** @author humorchen* date: 2024/5/27* description: feign 请求拦截器**/
@Slf4j
public class FeignInterceptor implements RequestInterceptor {/*** 跳过某些 header* 比对时会忽略大小写*/private static final Set<String> SKIP_HEADER_NAMES = new HashSet<>(Arrays.asList("transfer-encoding", "content-length", "accept", "accept-encoding", "connection"));static {// 转换为小写,避免大小写不一致HashSet<String> lowCaseSet = new HashSet<>(SKIP_HEADER_NAMES.size());SKIP_HEADER_NAMES.forEach(name -> lowCaseSet.add(name.toLowerCase()));SKIP_HEADER_NAMES.clear();SKIP_HEADER_NAMES.addAll(lowCaseSet);}/*** Called for every request. Add data using methods on the supplied {@link RequestTemplate}.** @param template*/@Overridepublic void apply(RequestTemplate template) {ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();// 拷贝请求头信息,透传信息if (requestAttributes != null) {HttpServletRequest request = requestAttributes.getRequest();Enumeration<String> headerNames = request.getHeaderNames();if (headerNames != null) {while (headerNames.hasMoreElements()) {// 跳过某些 headerString name = headerNames.nextElement();if (SKIP_HEADER_NAMES.contains(name.toLowerCase())) {continue;}String values = request.getHeader(name);template.header(name, values);}}}// 内部调用鉴权标记template.header(SaSameUtil.SAME_TOKEN, SaSameUtil.getToken());// 测试环境打印log.debug("【新版权限日志】FeignInterceptor 发起Feign调用({}),请求头已拷贝,same-token已颁发。", template.url());}
}