Zuul获取queryParams为null,源码分析


前言

一次SpringCloud Zuul的使用中,发现获取请求参数requestParam总是为null,遂进行了一次简单源码跟踪

一、SpringCloud中,zuul的相关配置类与功能接入类,以及部分调用链

在这里插入图片描述

  1. org.springframework.cloud.netflix.zuul.ZuulServerAutoConfiguration 中配置了一个 org.springframework.cloud.netflix.zuul.web.ZuulController
    在这里插入图片描述
  2. ZuulController继承了org.springframework.web.servlet.mvc.ServletWrappingController
    而ZuulController的构造器中,调用了方法 setServletClass(ZuulServlet.class)
    在这里插入图片描述
    在这里插入图片描述
  3. ZuulControlle同时重写了Spring-webmvc ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; 方法
    在这里插入图片描述
  4. 在netflix提供的com.netflix.zuul.http.ZuulServlet中,实例化了一个 ZuulRunner在这里插入图片描述
  5. 而ZuulServlet本质上是一个Servlet,容器会调用init方法,进而调用ZuulRunner的 init方法在这里插入图片描述
    在这里插入图片描述
  6. 该方法中调用了 Requecom.netflix.zuul.context.RequestContext的setRequest()方法(zuul的上下文封装,本质是一个map)在这里插入图片描述
  7. 而当一个请求进入zuulServlet后,会调用servlet的service()方法,这里是所有类型的ZuulFilter的调用在这里插入图片描述
  8. 这里我们只看preRoute() 方法,其他同理。可以看到,其实是调用了 zuulRunner的preRoute()方法在这里插入图片描述
  9. 接着调用com.netflix.zuul.FilterProcessor的preRoute方法,在这里插入图片描述
  10. 可以看到,这里获取了所有类型为pre的过滤器在这里插入图片描述
  11. 调用processZuulFilter(zuulFilter)方法在这里插入图片描述
    在这里插入图片描述
  12. 执行filter的runFilter方法,继而调用了 每个filter重写的run()方法在这里插入图片描述
  13. 进入我们自己实现的ZuulFilter功能代码在这里插入图片描述

二、记一次 使用 Zuul的 RequestContext获取RequestParameters为null的情况、

  1. 首先看下 RequestContext.getRequestQueryParams()方法,其实是调用ConcurrentHashMap的get(key)方法(上面说过RequestContext本质是map)在这里插入图片描述
  2. 这里走自己的过滤器,直接获取requestParam为null,可以看到取得的 RequestContext 中并没有名称为requestQueryParams的key,并且上下文中存放的request是一个org.springframework.cloud.netflix.zuul.filters.pre.Servlet30RequestWrapper的包装类在这里插入图片描述
  3. 我们继续往下走,获取Servlet30RequestWrapper对象并调用他的getParameterMap方法,而Servlet30RequestWrapper继承了com.netflix.zuul.http.HttpServletRequestWrapper,最终调用的是HttpServletRequestWrapper的getParameterMap()方法在这里插入图片描述
    在这里插入图片描述
  4. 进入parseRequest()方法,我们发现又进入了HTTPRequestUtils.getInstance().getQueryParams()这个方法调用
    在这里插入图片描述
  5. 而在HTTPRequestUtils.getQueryParams()这个方法的最后,调用了上下文的setRequestQueryParams()方法在这里插入图片描述
  6. 可以看到这里才真正把requestQueryParams这个key与value put进上下文这个map里面在这里插入图片描述
  7. 现在 再使用上下文获requestQueryParams 时,就可以获取requestParam了在这里插入图片描述

三、另一个发现:

在org.springframework.cloud.netflix.zuul.filters.pre.Servlet30RequestWrapper#getRequest中
在这里插入图片描述

四、解决方法

在过滤器中直接使用

Map<String, List<String>> queryParam = HTTPRequestUtils.getInstance().getQueryParams(); 

即可获得requestParam
这里贴上getQueryParams的源码

/**
     * returns query params as a Map with String keys and Lists of Strings as values
     * @return
     */
    public Map<String, List<String>> getQueryParams() {

        Map<String, List<String>> qp = RequestContext.getCurrentContext().getRequestQueryParams();
        if (qp != null) return qp;

        HttpServletRequest request = RequestContext.getCurrentContext().getRequest();

        qp = new LinkedHashMap<String, List<String>>();

        if (request.getQueryString() == null) return null;
        StringTokenizer st = new StringTokenizer(request.getQueryString(), "&");
        int i;

        while (st.hasMoreTokens()) {
            String s = st.nextToken();
            i = s.indexOf("=");
            if (i > 0 && s.length() >= i + 1) {
                String name = s.substring(0, i);
                String value = s.substring(i + 1);

                try {
                    name = URLDecoder.decode(name, "UTF-8");
                } catch (Exception e) {
                }
                try {
                    value = URLDecoder.decode(value, "UTF-8");
                } catch (Exception e) {
                }

                List<String> valueList = qp.get(name);
                if (valueList == null) {
                    valueList = new LinkedList<String>();
                    qp.put(name, valueList);
                }

                valueList.add(value);
            }
            else if (i == -1)
            {
                String name=s;
                String value="";
                try {
                    name = URLDecoder.decode(name, "UTF-8");
                } catch (Exception e) {
                }
               
                List<String> valueList = qp.get(name);
                if (valueList == null) {
                    valueList = new LinkedList<String>();
                    qp.put(name, valueList);
                }

                valueList.add(value);
                
            }
        }

        RequestContext.getCurrentContext().setRequestQueryParams(qp);
        return qp;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值