解决Feign异步调用丢失请求头问题

解决方式:将请求头存入本地线程中

网上看了类似的Feign传输请求头的案例,同步发送的只需要加拦截器即可

/**
 * feign 配置文件
 * 将请求头中的参数,全部作为 feign 请求头参数传递
 * @author: linjinp
 * @create: 2020-06-28 09:54
 **/
@Configuration
public class FeignConfiguration implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        HttpServletRequest request = SpringContextUtils.getHttpServletRequest();
        Enumeration<String> headerNames = request.getHeaderNames();
        if (headerNames != null) {
            while (headerNames.hasMoreElements()) {
                String name = headerNames.nextElement();
                String values = request.getHeader(name);
                requestTemplate.header(name, values);
            }
        }
    }
}

转载于 Spring Cloud Feign 请求时附带请求头_乐之终曲的博客-CSDN博客_feign带请求头

异步调用采用了一些方式,类似于

RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

传到子线程中,再重新赋值RequestContextHolder.setRequestAttributes(requestAttributes); 

 但是我用这种方法无法成功,但也给出了一些方案,通过获取请求头的方式来加载本地请求头。

首先是注册拦截器

import feign.RequestInterceptor;
import feign.RequestTemplate;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

@Configuration
@Slf4j
public class FeignHeaderInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate template) {
        try {
            //获取本地加载过的请求头
            Map<String, String> headerMap = RequestHeaderHandler.getHeaderMap();
            if (headerMap != null) {
                for (String key : headerMap.keySet()) {
                    String values = headerMap.get(key);
                    template.header(key, values);
                }
            }
        }catch (Exception e){
            log.error("获取请求头失败->{}","FeignHeaderInterceptor");
            log.error(e.getMessage());
        }

    }
}

第二步 构造两个工具类

import lombok.extern.slf4j.Slf4j;

import java.util.Map;


@Slf4j
public class RequestHeaderHandler {

    public static final ThreadLocal<Map<String, String>> THREAD_LOCAL = new ThreadLocal<>();

    public static void setHeaderMap(Map<String, String> headerMap) {
        THREAD_LOCAL.set(headerMap);
    }

    public static Map<String, String> getHeaderMap() {
        return THREAD_LOCAL.get();
    }

    public static void remove() {
        THREAD_LOCAL.remove();
    }

}
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.Map;

@Slf4j
public class RequestContextUtil {

    /**
     * 获取请求头数据
     *
     * @return key->请求头名称 value->请求头值
     * @author 
     */
    public static Map<String, String> getHeaderMap() {
        Map<String, String> headerMap = Maps.newLinkedHashMap();
        try {
            ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if (requestAttributes == null) {
                return headerMap;
            }
            HttpServletRequest request = requestAttributes.getRequest();
            Enumeration<String> enumeration = request.getHeaderNames();
            while (enumeration.hasMoreElements()) {
                String key = enumeration.nextElement();
                String value = request.getHeader(key);
                headerMap.put(key, value);
            }
        } catch (Exception e) {
            log.error("《RequestContextUtil》 获取请求头参数失败:", e);
        }
        return headerMap;
    }

}

实战例子

手打案例 供参考

/**
 *案例
**/    
@Override
public void test() {
   Map<String, String> headerMap = RequestContextUtil.getHeaderMap();
   pool.execute(()->{
       //共享之前分享的数据
       RequestHeaderHandler.setHeaderMap(headerMap);
       //todo  业务代码
     });
 }

参考连接:Error(17) 解决多线程异步Feign调用请求头丢失问题_郑清的博客-CSDN博客_多线程feign调用

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值