【问题标题】:How do you access posted form data in a servlet?如何访问 servlet 中发布的表单数据?
【发布时间】:2011-10-27 18:40:13
【问题描述】:

如果我有一个运行 JVM1.4.2 的 servlet,它正在接收一个带有表单数据字段的 POST 请求。我使用 req.getParameterNames() 来获取我所期望的所有查询字符串和表单数据。但是,我得到的只是查询字符串参数。

文献我是来自各种sourcesreadinggetParameterNames() 和getParameterValues(String) 应该是获取JDK 1.4 浏览器发送的所有查询字符串和发布的表单数据的方式。这是我用来提取所有参数的方法,我希望这些参数包括发布的表单数据:

public Map getParameterMap(HttpServletRequest req) {
        Map params= new HashMap();
        String name = null;
        System.out.println("<< Getting Parameter Map.>>");
        Enumeration enumParams = req.getParameterNames();
        for (; enumParams.hasMoreElements(); ) {
            // Get the name of the request parameter
            name = (String)enumParams.nextElement();

            // Get the value of the request parameters

            // If the request parameter can appear more than once 
            //   in the query string, get all values
            String[] values = req.getParameterValues(name);
            params.put(name, values);
            String sValues = "";
            for(int i=0;i<values.length;i++){
                if(0<i) {
                    sValues+=",";
                }
                sValues +=values[i];
            }
            System.out.println("Param " + name + ": " + sValues);
        }
        System.out.println("<< END >>");
        return params;
    }

This 的问题也符合我的预期,但是 servlet 没有获取表单数据。显然我错过了一些东西......

更新:帖子数据非常直接,不是多部分形式或富媒体。只是通过 AJAX POST 提交的纯文本,在帖子正文中看起来像这样

c1=Value%20A&c2=Value%20B&c3=Value%20C

【问题讨论】:

  • 表单是什么样的?特别是 form 元素本身,以及上面的 input / select / textarea 元素的示例。
  • @TJ 你是说不是所有的表单数据都是“相等的”吗?现代浏览器对旧 JVM 下的 servlet 未检测到的表单数据进行区分?
  • 尽管我想使用当前的 JVM,但业务需求另有规定。他们为“正确答案”点数提出了挑战。
  • @T.J. Crowder 以后尽量不要在 cmets 前面加上“off topic -”,因为标志可能不会被删除 :) 评论是临时的,在问题和答案方面是二等公民。如果一个人被移除,不要伤害你的感情。
  • @TJ。好吧,“过度节制”和“离题”的玩笑并没有太大的区别,这对产生答案没有作用

标签: java forms servlets post jdk1.4


【解决方案1】:

确实如此。 getParameterNames()、getParameterValues() 和 getParameter() 方法是访问表单数据的方法除非它是一个多部分表单,在这种情况下,您必须使用类似 Commons Fileupload 的东西来解析在您可以访问所有参数之前的多部分请求。

编辑:您可能没有在 AJAX 调用中正确编码 POST 数据。 POST 数据必须携带 application/x-www-form-urlencoded 的 Content-Type 或 multipart/form-data。如果您将其作为其他内容发送,则它不符合请求参数的条件,我希望您会看到您所描述的行为。您设计的解决方案基本上包括设置自定义内容的自定义解析。

【讨论】:

  • 好的..这是一个新的调查途径。我将设置内容类型,然后重新运行 getParameterNames 的原始代码并尝试。
  • 我检查了内容类型,它返回为“application/x-www.form-urlencoded”,所以问题不是由内容类型引起的。感谢您的考虑。
  • application/x-www.form-urlencoded != application/x-www-form-urlencoded;就是它 ”。”错字?如果你复制/粘贴了那个值,那就错了。
【解决方案2】:

我设法找出了问题所在。因为来自 JDK 1.5+ 的讨论太多了,并且谈到了 1.5 的 getParameterMaps() 方法,所以关于 1.4 如何处理表单发布数据的信息很少且模棱两可。 (如果您发现特定于 1.4 的内容,请发表评论)。

Pre-1.5 你必须通过getInputStream手动获取表单数据,然后解析出来。我从 java sun 站点找到了this 方法(发布在下面),它使用哈希表做得很好。我不得不为已弃用的方法制作一个小模组。但似乎工作得相当稳健,“开箱即用”,所以你应该可以直接剪切粘贴。我知道这是“老技术”,但我认为对于那些可能与我处于相同情况并坚持解决(似乎是)直截了当的问题的人来说,这是值得的。

public Hashtable parsePostData(int length, ServletInputStream instream) {
                String valArray[] = null;
                int inputLen, offset;
                byte[] postedBytes = null;
                boolean dataRemaining=true;
                String postedBody;
                Hashtable ht = new Hashtable();
                //Vector paramOrder = new Vector(10);
                StringBuffer sb = new StringBuffer();

                if (length <=0) {
                  return null;
                }
                postedBytes = new byte[length];
                try {
                   offset = 0;
                   while(dataRemaining) {
                     inputLen = instream.read (postedBytes, offset, length - offset);
                     if (inputLen <= 0) {
                       throw new IOException ("read error");
                     }
                     offset += inputLen;
                     if((length-offset) ==0) {
                       dataRemaining=false;
                     }
                   }
                } catch (IOException e) {
                  System.out.println("Exception ="+e);
                  return null;
                }

                postedBody = new String (postedBytes);
                StringTokenizer st = new StringTokenizer(postedBody, "&");

                String key=null;
                String val=null;

                while (st.hasMoreTokens()) {
                  String pair = (String)st.nextToken();
                  int pos = pair.indexOf('=');
                  if (pos == -1) {
                    throw new IllegalArgumentException();
                  }
                  try {
                     key = URLDecoder.decode(pair.substring(0, pos),"UTF8");
                     val = java.net.URLDecoder.decode(pair.substring(pos+1,pair.length()),"UTF8");
                  } catch (Exception e) {
                     throw new IllegalArgumentException();
                  }
                  if (ht.containsKey(key)) {
                    String oldVals[] = (String []) ht.get(key);
                    valArray = new String[oldVals.length + 1];
                    for (int i = 0; i < oldVals.length; i++) {
                       valArray[i] = oldVals[i];
                    }
                    valArray[oldVals.length] = val;
                  } else {
                    valArray = new String[1];
                    valArray[0] = val;
                  }
                  ht.put(key, valArray);
                  String sValues = "";
                  for(int i=0;i<valArray.length;i++) {
                      if (0<i) {
                          sValues+=",";
                      }
                      sValues = valArray[i];
                  }
                  System.out.println("Form data field " + key + ":" +sValues); 
                  //paramOrder.addElement(key);
                }
                return ht;
              }

【讨论】:

  • 这是不正确的。首先,您将 J2EE 与 J2SE 混淆了。 J2EE 的版本与 J2SE 开发工具包分开。其次,检索发布数据的方式至少从 J2EE 1.3 版(大约 8 或 10 年)起没有改变。手动解析响应肯定会起作用,但这绝不是必需或推荐的。正如其他人所提到的,如果您显示相关的 HTML,您将获得更好的答案。
  • 标准 POST 数据。这没什么异国情调。使用 Fiddler 2,我得到了一些非常直接的帖子数据,例如 c1=Value%20A&c2=Value%20B&c3=Value%20C 。很高兴承认我对 J2SE/J2EE 时间线和特性集一无所知。到目前为止,每个人都在说什么是错的,而不是如何去做。我已经发布了一个实际有效的解决方案。当然,它可能不是“最好的方法”,但它有效并且看起来很健壮。帮我改进一下......
  • 您还没有显示 HTML。请求标头也可以提供帮助。我只能建议你尝试一些更简单的东西——比如Enumeration names = request.getParameterNames(); System.out.println("Param names:"); while (names.hasMoreElements()) System.out.println(names.nextElement()); 如果那没有给出预期的输出,请尝试在调试器中检查请求对象之后调用参数相关之一方法。
  • @Ryan。您引用的代码也与我在问题中列出的原始示例代码相同。调用不是来自 HTML 表单。这是作为“POST”事务完成的 AJAX 调用。我设法找到了一个可能是很长的路要走的解决方案。对于这个问题的受访者来说,剩下的机会是指出使用 JDK 1.4 的更好方法。
  • +1 这个人刚刚投了你一票,因为他认为他非常好,我认为这些自负巨大的人应该把他们的名声放在阳光不照耀的地方。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-20
  • 1970-01-01
  • 2013-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多