关于JAVA中request.getParameterMap与request.getReader()获取不到请求值的解决方案


    最近比较忙,经常加班,已经有一个星期多的时间没写博客了,但是即便再忙,也要把自己认为重要的知识点通过博客的形式记录下来!

    最近在维护公司的旧系统时发现公司的旧网关的异步通知定时任务出现延迟的问题,本来异步通知定时任务每隔30秒都会将支付成功的订单信息通知给商户,按理来说,商户在进行成功支付时都会在1分钟左右的时间收到订单异步通知的结果,但是近几天来几乎所有的商户都是在间隔5分钟左右的时间才收到系统异步通知的结果,这就奇怪了!!为什么呢??

    经过仔细查看生产日志和检查代码,发现原来是我们系统没有获取到上游的签名(sign)字段,导致我们系统验签不成功,所以就出现了"inLegal data“的报错,如下图所示:

在这里插入图片描述

经过一波辛苦分析,终于找到解决方案!!原来是request.getParameterMap与request.getReader()这两个方法所带来的坑!先看一下代码:

public ActionForward execute(ActionMapping actionMapping,
			ActionForm actionForm, HttpServletRequest request,
			HttpServletResponse response) throws Exception
	{
        String publicPath = Config.getPublicKeyFile().getAbsolutePath();//公钥证书路径

        StoreOIDAO oiDAO = new StoreOIDAO();
        StoreOIVO storeOI = null;   
                String sign = map. request.getHeader("x-efps-sign");
          LOGGER.info("sign:" + sign);
          Map parameterMap = request.getParameterMap();
     LOGGER.info("parameterMap的值为:"+net.sf.json.JSONObject.fromObject(parameterMap).toString()); 
        ......此省略部分代码
        }

在生产日志中可以看到“parameterMap的值为:null"以及“sign:null”这两个输出信息,这说明使用request.getHeader(“x-efps-sign”)的方法以及使用request.getParameterMap()的方法是获取不到值的,所以才导致系统验签失败!那么为什么获取不到值呢?

1.先分析下 request.getHeader(“x-efps-sign”)的方法为什么获取不到值
经过百度一番,发现有这样的说明:

当form表单内容采用 enctype=application/x-www-form-urlencoded编码时,先通过调用request.getParameter() 方法得到参数后,再调用request.getInputStream()或request.getReader()已经得不到流中的内容,因为在调用 request.getParameter()时系统可能对表单中提交的数据以流的形式读了一次。

既然request.getReader()获取不到值,那只能说明肯定有哪里提前调用了request.getParameter()这个操作,当时我脑子里第一个想到的就是过滤器!肯定是它提前拦截了相关的请求~ 打开相关的过滤器代码一看发现果然就是这个问题,来不及了线先上图!如下所示:

在这里插入图片描述
大家可以看到上面的过滤器果然使用到了getParameter()方法和getReader()方法,所以导致了request.getHeader(“x-efps-sign”)获取不到值。
2.再分析下request.getParameterMap()的方法为什么获取不到值
通过查阅相关资料发现了这么有趣的说法:

request.getParameterMap()只能获取Get方式传入的数据。
还有如果是使用了enctype=”multipart/form-data”和method=“post” 进行请求时,我们在获取相关的请求参数时是获取不到的!

所以我仔细再看了生产的日志发现果然上游是以post的方式传给我们的,如下图所示:
在这里插入图片描述
从充分说明了,我们获取的值为空是完全有道理的,程序绝对不会欺骗我们!那么到底如何解决呢???

将以上代码改成如下所示,就完全可以解决啦!!

public ActionForward execute(ActionMapping actionMapping,
			ActionForm actionForm, HttpServletRequest request,
			HttpServletResponse response) throws Exception
	{
        String publicPath = Config.getPublicKeyFile().getAbsolutePath();//公钥证书路径

        StoreOIDAO oiDAO = new StoreOIDAO();
        StoreOIVO storeOI = null;   
         Map<String, String> map = HttpUtil.getHeadersInfo(request);
           LOGGER.info("获取的全部请求头部信息为:"+map);
               String sign = map.get("x-efps-sign");
          LOGGER.info("sign:" + sign);
            BufferedReader parameterMap= request.getReader();
               LOGGER.info("parameterMap的值为:"+br); 
        ......此省略部分代码
        }

从上图可以看出,我先是使用getHeadersInfo(request)获取全部的头部信息,然后再获取x-efps-sign这个键的值,这样sign的值就不再为null了!!!其次将request.getReader()的方法替换request.getParameterMap(),这样就可以获取到全部的请求内容了!!parameterMap的值也不再为null了!!!

    问题就这样轻轻松松地解决了!!!大家可以看下以下博客,我觉得是对于我这次描述内容的补充!
https://blog.csdn.net/tian330726/article/details/52473691
http://www.voidcn.com/article/p-wvqsmpew-bpz.html


欢迎大家随时提出宝贵意见,谢谢!!!

发布了17 篇原创文章 · 获赞 19 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Melo_FengZhi/article/details/86097014