feign远程调用时如何在请求头加入数据

1.先提出问题的解决方案
   通过实现Feign的RequestInterceptor(拦截器)接口,重写里面的apply方法,为RequestTemplate添加自定义的请求头的参数及数据的传入。请求最开始进来的时候,就会进入到这个拦截器中,业务代码中进行远程调用的时候还会进入到这个请求里面来。
@Component
public class FeignClientsExtendInterceptor implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
    // 此种方式是线程安全的
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
                .getRequestAttributes();
    // 不为空时取出请求中的header 原封不动的设置到feign请求中
        if (null != attributes) {
            HttpServletRequest request = attributes.getRequest();
            if (null != request) {
        // 遍历设置 也可从request取出整个Header 写到RequestTemplate 中
                Enumeration<String> headerNames = request.getHeaderNames();
                if (headerNames != null) {
                    while (headerNames.hasMoreElements()) {
                        String name = headerNames.nextElement();
                        String values = request.getHeader(name);
                        requestTemplate.header(name, values);
                    }
                }
            }
        }

        // 处理请求体参数信息
        // feign调用get接口的时候,会报出405 Request method ‘POST‘ not supported的错误
        // 当你不需要将请求体内的信息也传输过去的,可以通过注释处理请求体信息的代码来解决
        // 原因是feign底层发请求的时候,发现请求体带有参数会自动转成post请求。
       
        /*
        Enumeration<String> bodyNames = request.getParameterNames();
        StringBuilder body = new StringBuilder();
        if (bodyNames != null) {
            while (bodyNames.hasMoreElements()) {
                String name = bodyNames.nextElement();
                String values = request.getParameter(name);
                body.append(name).append("=").append(values).append("&");
            }
        }
        if (body.length() != 0) {
            body.deleteCharAt(body.length() - 1);
            requestTemplate.body(body.toString());
        }
        */

    }
}

2.业务场景(保证后面的请求中,调用者的信息一致)

(1)消费了MQ消息,发起了远程调用。

        也就是这个时候是没有请求相关的信息的,但是在feign发起请求的时候,需要保证请求头里的信息是当前线程的相关信息,这个时候可以把需要的相关信息放入一个线程副本中去,通过继承RequestContextHolder或者重写一个相似的类,将当前线程的信息放置进去,然后在feign发起远程调用的时候,将所需信息取出来,放入请求头中。

(2)同一线程

        前端请求时,会在请求头中带上一系列的校验参数,调用我的服务,需要再去调用其他服务。在其他服务中, 需要对请求头中的信息做提取或者校验。

        feign远程调用的时候,底层是对参数进行了封装然后进行请求,是一次新的请求,那么前端传入请求中的头文件信息自然不会被传过去,所以可以通过重写RequestInterceptor,将请求头的信息原封不动的复制进去。

(3)多线程异步调用其他微服务

        上述重写的代码可能就获取不到主线程的请求信息了,主要原因是:RequestContextHolder来获取request信息,发现异步调用时,主线程结束后,子线程就获取不到request,会报出错误信息。

解决方式1:

        通过获取到主线程的请求,在前端调用的时候,前端请求会进来,这个时候开启子线程共享,那么在后面的业务执行时,发现异步调用时,主线程结束后,子线程是可以获取request的相关信息的。

ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
// 在上面代码后面开启子线程共享
RequestContextHolder.setRequestAttributes(servletRequestAttributes,true);//设置子线程共享

解决方式2:

        与(2)同一线程的处理方式类似,将主线程的request和session信息放进ThreadLocal里,透传到子线程再去获取。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值