FeignClient 在 spring boot 内部发起调用时,携带前端传入的请求中的请求头信息与请求体信息

业务场景

前端请求时,会在请求头header中带上一系列的校验参数,到达我负责的模块之后,需要去调用其他服务。在其他服务中, 需要对请求的请求头header中的信息做相关校验以及信息提取,再执行相关业务行为。

问题描述

在我这边配好feign调用之后,发起调用,却发现返回500错误码,查看对应错误日志,被调用方对header进行校验时NPE了,通过打印日志(嗯忘记直接debug看了)发现我方header中的信息参数都没有传过去。

思考过程

feign实质上也只是发起了一次请求罢了,底层也不过是对参数进行封装最后进行请求,正因为是一次新的请求,那么前端传入的请求中的头文件信息自然不会被传过去,那么我要做的就是找方法将前端请求中的头信息放到转发时候的请求里。

解决方案

写一个配置类,继承请求拦截器然后发起feign请求的时候把信息添加进去

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

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

/**
 * @createTime: 2020.11.27 18:27
 * @version: 1.0
 */
@Configuration
public class FeignClientConfiguration implements RequestInterceptor
{
    @Override
    public void apply(RequestTemplate requestTemplate)
    {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        if (requestAttributes == null) {
            return;
        }
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        //处理header信息
        Enumeration<String> headerNames = request.getHeaderNames();
        if (headerNames != null) {
            while (headerNames.hasMoreElements()) {
                String name = headerNames.nextElement();
                Enumeration<String> values = request.getHeaders(name);
                while (values.hasMoreElements()) {
                    String value = values.nextElement();
                    requestTemplate.header(name, value);
                }
            }
        }
        //处理请求体参数信息
        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());
        }
    }

}

最好在feign调用类上也指定一下用的配置类

@FeignClient(name = "server",configuration  = FeignClientConfiguration.class)
public interface FeignServerService
{
	//do something
}

补充

在我实装该功能之后,我又出现了一个新的错误:feign调用get接口的时候,竟然会报出405 Request method ‘POST‘ not supported的错误 , 真的挺有趣的,然后在查资料的时候,看到了一个大佬的文章,总结了feign的几个坑,我才发现这东西这么好玩。

Request method ‘POST‘ not supported解决方案如下:

当你不需要将请求体内的信息也传输过去的,可以把下面处理请求体信息的代码段注释掉

		
        //处理请求体参数信息
        /*
        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());
        }
	*/

原因是feign底层发请求的时候,发现请求体带有参数会自动转成post请求。详细原因还请看大佬的这篇博客:https://blog.csdn.net/f641385712/article/details/82431502,里面有逐步向下的分析和讲述。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值