Feign常用的请求拦截器

IFeignAutoConfiguration

@Configuration
@ConditionalOnClass({Feign.class})
@Order(Ordered.LOWEST_PRECEDENCE - 10000)
public class IFeignAutoConfiguration {

    private final ObjectMapper objectMapper;

    public IFeignAutoConfiguration(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    /**
     * 用户信息传递,feign发起请求时,将当前用户信息放到请求头
     * @return RequestInterceptor
     */
    @Bean
    public RequestInterceptor headerUserFeignRequestInterceptor() {
        return new HeaderUserFeignRequestInterceptor();
    }

    /**
     * feign 不支持 GET 方法传 POJO, json body转query
     * 名为charlesRequestInterceptor的bean不存在时才装配
     * @return RequestInterceptor
     */
    @Bean
    @ConditionalOnMissingBean(name = "charlesRequestInterceptor")
    public RequestInterceptor charlesRequestInterceptor() {
        return new CharlesRequestInterceptor(objectMapper);
    }
}

CharlesRequestInterceptor


/**
 * feign 不支持 GET 方法传 POJO, json body转query
 */
public class CharlesRequestInterceptor implements RequestInterceptor {

    private static Logger log = LoggerFactory.getLogger(CharlesRequestInterceptor.class);

    private ObjectMapper objectMapper;

    public CharlesRequestInterceptor(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public void apply(RequestTemplate template) {
        // feign 不支持 GET 方法传 POJO, json body转query
        if (template.method().equals("GET") && template.body() != null) {
            try {
                JsonNode jsonNode = objectMapper.readTree(template.body());
                template.body(null);

                Map<String, Collection<String>> queries = new HashMap<>();
                buildQuery(jsonNode, "", queries);
                template.queries(queries);
            } catch (IOException e) {
//                e.printStackTrace();
                log.error(e.getMessage());
            }
        }
    }

    private void buildQuery(JsonNode jsonNode, String path, Map<String, Collection<String>> queries) {
        if (!jsonNode.isContainerNode()) {   // 叶子节点
            if (jsonNode.isNull()) {
                return;
            }
            Collection<String> values = queries.get(path);
            if (null == values) {
                values = new ArrayList<>();
                queries.put(path, values);
            }
            values.add(jsonNode.asText());
            return;
        }
        if (jsonNode.isArray()) {   // 数组节点
            Iterator<JsonNode> it = jsonNode.elements();
            while (it.hasNext()) {
                buildQuery(it.next(), path, queries);
            }
        } else {
            Iterator<Map.Entry<String, JsonNode>> it = jsonNode.fields();
            while (it.hasNext()) {
                Map.Entry<String, JsonNode> entry = it.next();
                if (StringUtils.hasText(path)) {
                    buildQuery(entry.getValue(), path + "." + entry.getKey(), queries);
                } else {  // 根节点
                    buildQuery(entry.getValue(), entry.getKey(), queries);
                }
            }
        }
    }
}

HeaderUserFeignRequestInterceptor

/**
 * 用户信息传递,feign发起请求时,将当前用户信息放到请求头
 **/
public class HeaderUserFeignRequestInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {

        String userInfo = ExtractUserInfoUtil.getUserInfoHeader();

        //feign请求时将当前的用户信息回填到request中,前提是当前请求不包含"user-info"这个header的情况下
        Map<String, Collection<String>> headers = requestTemplate.headers();
        if(!headers.containsKey(ExtractUserInfoUtil.USER_INFO_HEADER) || CollectionUtils.isEmpty(headers.get(ExtractUserInfoUtil.USER_INFO_HEADER))) {
            //填充请求头
            requestTemplate.header(ExtractUserInfoUtil.USER_INFO_HEADER, userInfo);
        }
    }
}

留下个思考题:假设我需要在某些指定的feign客户端接口方法(使用注解标注),才需要应用上述的请求拦截器该如何实现(也就是不要让它们应用到全局,而只在调用具体的方法才决定是否使用拦截器)?
可以继承子SpringMvcContract,复用并重写解析的方法;使用@RequestHeader注解(这个需要试试)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值