SpringCloud分布式RPC调用openFeign实现,转发请求头引发java.lang.IllegalArgumentException

本篇内容是关于SpringCloud的RPC调用方案中的OpenFeign使用过程的,我个人碰上的一个问题,希望对于一些刚接触这个矿机的朋友,有一定的启发作用;
这个问题是由于服务间的调用往往就涉及到请求头中一些参数的转发,常见例如:访问令牌;接下来,就是我在实际使用过程中对于请求头转发的处理和碰到问题的描述,相应的解决方式,希望能够为一些人提供借鉴。

  1. 请求头转发 处理
/**
 * @author Eden4J
 * @description Feign相关配置类
 * @date 2021-09-25 11:00
 */
@Configuration
public class FeignConfig {
	// feign的日志级别配置
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
	//让DispatcherServlet向子线程传递RequestContext
    @Bean
    public ServletRegistrationBean<DispatcherServlet> dispatcherRegistration(DispatcherServlet servlet) {
        servlet.setThreadContextInheritable(true);
        return new ServletRegistrationBean<>(servlet, "/**");
    }
	//覆写拦截器,在feign发送请求前取出原来的header并转发,问题就是出现在复制之后
    @Bean
    public RequestInterceptor requestInterceptor() {
        return (template -> {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            //获取请求头
            Enumeration<String> headerNames = request.getHeaderNames();
            if (headerNames != null) {
                while (headerNames.hasMoreElements()) {
                    String name = headerNames.nextElement();
                    String value = request.getHeader(name);
                    //直接复制请求头到模板
                     template.header(name, value);
                }
            }
        });
    }
  1. 出现的问题
    A服务调用B服务时,在服务B上出现如下问题:
java.lang.IllegalArgumentException: Invalid character found in method name [XXXX]. HTTP method names must be tokens
  1. 解决方式
    我首先先把feign间的调用日志全部打开,在控制台去看日志,果然发现了问题所在,所以开发一定要仔细去看日志,也学会去看日志,即使不知道怎么下手解决问题,能定位到问题就能更精准找到解决方案
    如下图:
    控制台输出的feign调用日志
    通过观察,发现了请求头有两个content-length,而且大小不一致;所以问题就是出在这个地方上,因为前端通过Ajax 提交会把content-length 带上来,在第1点中的拦截器中,又会把参数复制一遍,因此出现了两个content-length,其他如果有类似参数也会有此可能;所以最终解决的方式是在拦截器中把这个参数剔除,不做此项参数复制;其次如果是服务间的调用完全可以把没有必要的参数剔除,可以不用复制,例如是把content-type也剔除掉,
    @Bean
    public RequestInterceptor requestInterceptor() {
        return (template -> {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            Enumeration<String> headerNames = request.getHeaderNames();
            if (headerNames != null) {
                while (headerNames.hasMoreElements()) {
                    String name = headerNames.nextElement();
                    String value = request.getHeader(name);
                    // 剔除content-length的复制
                    if (!"content-length".equalsIgnoreCase(name)) {
                        template.header(name, value);
                    }
                }
            }
        });
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值