当前位置: 首页 > 工具软件 > open-registry > 使用案例 >

springcloud open-feign添加、传递请求头

封弘伟
2023-12-01

当我们feign调用提供者需要携带自定义的请求头,或者想继续传递上游服务的请求头信息时,可进行如下方式处理

  1. 实现RequestInterceptor,并Configuration注解标记为配置类
  2. 复写apply 方法,将我们的自定义的请求头 通过header存进去即可
  3. 可根据请求信息遍历请求头信息,选择是否将上游请求头信息向下游服务传递
  4. 该配置类需要能被扫包扫到(主启动函数 子侄包路径)
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

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

/**
* @author lei
* @version 1.0
* @desc feign 设置请求头
* @date 2020-12-04 13:36
*/
@Configuration
public class FeignRequestConfig implements RequestInterceptor {
   @Override
   public void apply(RequestTemplate template) {
       ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
       HttpServletRequest request = attributes.getRequest();
       Enumeration<String> headerNames = request.getHeaderNames();
       template.header(自定义请求头Key, 自定义请求头值);
       if (headerNames == null) {
           return;
       }
       //处理上游请求头信息,传递时继续携带
       while (headerNames.hasMoreElements()) {
           String name = headerNames.nextElement();
           String values = request.getHeader(name);
           template.header(name, values);
       }
   }
}

实战示例

例如,我们需要获取到从外部请求的用户信息进行数据存储时填充(过网关的则为外部请求,在网关层做了用户JWT解析操作),这个时候呢,需要传递我们的用户信息至下游相关服务

定义拦截器

拦截网关传递的自定义的用户请求头信息

/**
 * @author lei
 * @version 1.0
 * @desc 操作用户拦截器
 * @date 2020-12-04 15:36
 */
@Log4j2
public class InterceptorConfig implements HandlerInterceptor {
    
    public static final ThreadLocal<AccessUserInfo> ACCESS_USER_INFO = new ThreadLocal<>();
    public static final String ACCESS_USER_INFO_HEADER = "access-user-info";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        AccessUserInfo accessUserInfo = JSON.parseObject(request.getHeader(ACCESS_USER_INFO_HEADER), AccessUserInfo.class);
        log.debug("InterceptorConfig::preHandle {} {}", accessUserInfo, request.getRequestURI());
        ACCESS_USER_INFO.set(accessUserInfo);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        ACCESS_USER_INFO.remove();
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // Do nothing
    }

    public static String getCurrentUserId() {
        return Optional.of(InterceptorConfig.ACCESS_USER_INFO).map(ThreadLocal::get).map(AccessUserInfo::getUserId).orElse(null);
    }

    public static String getCurrentUserIdAndThrow() {
        return Optional.of(InterceptorConfig.ACCESS_USER_INFO).map(ThreadLocal::get).map(AccessUserInfo::getUserId).orElseThrow(() -> new RuntimeException("未获取到用户ID"));
    }
}
@Configuration
public class WebAppConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new InterceptorConfig()).addPathPatterns("/**");
    }
}

自定义请求头传递(OpenFeign透传到下游服务,以便下游服务继续使用该用户信息)

@Component
@Log4j2
public class FeignInterceptor implements RequestInterceptor {

    @Override
    public void apply(RequestTemplate template) {
        Optional.of(InterceptorConfig.ACCESS_USER_INFO)
                .map(ThreadLocal::get)
                .filter(accessUserInfo -> accessUserInfo.getUserId() != null)
                .ifPresent(accessUserInfo -> {
                    log.debug("FeignInterceptor::apply InterceptorConfig::preHandle {} {}", accessUserInfo, template.toString());
                    template.header(InterceptorConfig.ACCESS_USER_INFO_HEADER, JSON.toJSONString(accessUserInfo));
                });
    }
}
 类似资料: