tomcat与jetty接收请求参数的区别

【场景】
服务端点对点通知。
A服务发起请求B服务,B同步返回接收成功;然后B开始处理逻辑;B处理完成后异步通知给A;A接收请求并处理,同步回写响应给B;完成。

【先上代码】
服务端(接收端)代码:

客户端(请求端)HttpUtil工具类:

客户端测试方法:

【测试结论】
Tomcat和jetty对于HttpServletRequest.getParameterMap()的处理不同。jetty可以直接获取到请求参数;而Tomcat获取不到。下面是Tomcat的日志:

六月 11, 2019 10:11:53 上午 org.apache.tomcat.util.http.Parameters processParameters
信息: Character decoding failed. Parameter [{"interfaceName":"RegisterNotify","merSignMsg":"APrWHHydX41atXjfadKBfDPUhKBQbZ6fTKcnHGtVBhe9qpSfArVqRFrlf2wgw9gzmMnGo3x15XKXAZnC51WU60FXNVj2kaxpWYzpuh6rvUDrDVQV6Z7SHEI8GvrMLE8uOG2TPR0Xu6v71o8u8TJsWsiVOP/ncsAHSzSz%%2B2Ch7N3E5ePCQi84To7LvSO5HrtUUmTbc%2BrmG2frJfYJNfvsxuGvt9U2MqmFeWFE98fK5e5SFUSSZLtqj42N18ppSZWSxN3MleGDTsy75zR3JxO6ol99lCPea4zqLmnUoEFlnJ3J6vXXUVXnMuSX5Mw%3D%3D","merchantId":"M100002734","tranData":"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iR0JLIiA%2FPjxCMkNSZXM%2BPHN0YXR1cz4wPC9zdGF0dXM%2BPGJpbmRTdHM%2BMTwvYmluZFN0cz48Y3VzdG9tZXJJZD5DMTAwMDE0Mjc1PC9jdXN0b21lcklkPjxjb21wYW55PtDs1t3TzrHpzOzPwsLD087Qxc%2Bi18nRr9PQz965q8u%2BPC9jb21wYW55PjxyZWZ1c2VSZWFzb24vPjwvQjJDUmVzPg%3D%3D","version":"B2C1.0"}] with value [] has been ignored. Note that the name and value quoted here may be corrupted due to the failed decoding. Use debug level logging to see the original, non-corrupted values.
Note: further occurrences of Parameter errors will be logged at DEBUG level.

map count:0

Character decoding failed.Parameter [dd] with value [] has been ignored. 百度翻译为:字符解码失败。已忽略值为[]的参数[dd]。

我的Tomcat版本是7.0.93;jetty版本是6.1.26。通过比较两者的servlet-api.jar,发现Tomcat7的servlet-api的版本是3.0,而jetty的servlet-api的版本是2.5。或许是这种版本的差异导致结果不同。试图跟踪源码来一识庐山真面目,jetty的进去了,但从RequestWapper类里也看不到什么;Tomcat的则进不去。

进一步通过Tomcat测试发现:请求参数里的merSignMsg,当我改变其值(去掉开头的一些字符)时,Tomcat就能获取到了。看来还是Tomcat处理字符编码的问题。

【话说回来】
话说回来,上面案例content-type用form实在不合适,因为想获取到请求数据,得取key的值而不是value,这不符合常用的套路啊,由此我的同事那天在接收数据时很费了一番折腾。像这种上送json字符串的,改用text/plain更合适。这样的话,接收端通过读取HttpServletRequest的输入流就可以获取到请求数据。

附上读取HttpServletRequest流的代码:

package com;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class ReadHttpRequest {

    /**
     * 从request.ParameterMap获取数据---适用于表单请求
     * @param request
     * @return
     * @throws UnsupportedEncodingException
     * @throws Exception
     */
    public static Map getRequestMap(HttpServletRequest request) throws UnsupportedEncodingException,Exception {
        Map result = new HashMap();
        Map<String, String[]> map = request.getParameterMap();
        if (0 == map.size()) {
            System.out.println("未获取到任何请求参数.");
//            throw new  Exception("未获取到任何请求参数.");
            return result;
        }

        for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); ) {
            Map.Entry element = (Map.Entry) iter.next();
            Object strKey = element.getKey();  //key值
            String[] value = (String[]) element.getValue(); //value,数组形式
            String values = "";
            for (int i = 0; i < value.length; i++) {
                values += "," + value[i];
            }
            result.put(strKey.toString(), values.replaceFirst(",", ""));
        }
        return result;
    }

    /**
     * 从输入流获取数据---适用于流请求
     * @param request
     * @return
     */
    public static String getRequestInputStream(HttpServletRequest request) {
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try {
            in = request.getInputStream();
            out = new ByteArrayOutputStream();
            in2OutStream(in, out, 1024 * 1024);
            return out.toString("UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (in != null) in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    private static void in2OutStream(InputStream in, OutputStream out,
                                     int bufferSize) throws IOException {
        byte[] buffer = new byte[bufferSize];// 缓冲区
        for (int bytesRead = 0; (bytesRead = in.read(buffer)) != -1; ) {
            out.write(buffer, 0, bytesRead);
            Arrays.fill(buffer, (byte) 0);
        }
    }
}

原文地址:https://www.cnblogs.com/buguge/p/11002836.html

时间: 2024-08-29 13:34:22

tomcat与jetty接收请求参数的区别的相关文章

action接收请求参数

一.采用基本类型接收请求参数(get/post)在Action类中定义与请求参数同名的属性,struts2便能接收自动接收请求参数并赋给同名属性. action的代码: Java代码   public class ParamAction { private Integer id; private String name; public String execute(){ return "success"; } public void setId(Integer id) { //通过反射

struts2 action接收请求参数和类型转换

1,action接收请求参数 在struts2中action是什么?(struts2是一个mvc框架)         V:jsp        M:action         C:action  StrutsPrepareAndExecuteFilter 在struts2中获取请求参数: a.属性驱动            1.直接将action做一个model,就可以得到请求参数.                问题1:action封装请求参数,会不会存在线程安全问题?          

接收请求参数及数据回显

接收请求参数及数据回显 接收一个参数 //http://localhost:8080/r/user/t1?username=julia @GetMapping("/user/t1") public String test1(@RequestParam("username") String name, Model model) { return "test"; } 接受一个对象 //http://localhost:8080/r/user/t2?i

SpringMVC——接收请求参数和页面传参

转自:http://blog.csdn.net/z69183787/article/details/41653875 1.接收请求请求 (1)使用HttpServletRequest获取,如request.getParameter("name") (2)@RequestParam("pass")String password,或@Param("pass")String password.表单参数也可以用这种方式获取,Spring会自动将表单参数注

SpingMVC_注解式开发_接收请求参数

一.逐个接收 1 import org.springframework.stereotype.Controller; 2 import org.springframework.web.bind.annotation.RequestMapping; 3 import org.springframework.web.servlet.ModelAndView; 4 5 @Controller // 表示当前类是一个处理器 6 @RequestMapping("/test") 7 public

springmvc中@requestbody注解接收请求参数

一.POST请求的四种常用方式 1.application/x-www-form-urlencoded 浏览器原生的表单,值为urlencoded之后的  key1=value1&key2=value2...... 2.multipart/form-data 浏览器原生的文件表单,用于传输文件 3.application/json 常用的请求头格式,值为json串  {"key1":"value1","key2":"value2

struts2 请求参数接收

1. 采用基本类型接受请求参数(get/post)在Action类中定义与请求参数同名的属性,struts2便能自动接收请求参数并赋予给同名的属性.请求路径:http://localhost:8080/action/register.action?id=33 public class HelloWorldAction { private Integer id; public Integer getId() { return id; } public void setId(Integer id)

Java Web应用请求参数编码

我们知道,当拼写要跳转的url中含有中文时,一般地需要转码处理,才能到服务器端正确的接收并处理,这是客户端与服务器端通讯时对数据格式的规约. 一般地,使用encodeURIComponent或者encodeURI来处理中文参数(这两者的区别,以及和escape的区别后面再说),编码后,在客户端,成为ISO-8859-1数据格式,一般表现在URL上为%XX这种形式的. var url = "hello.do?person=" + encodeURIComponent("小明&q

JavaEE----Action接受请求参数

一. Action中如何接受请求参数 parameter * 实际开发中 不推荐在Action中 去使用Servlet API 1.三种方式: 1) 通过Action 成员变量, 自动接收请求参数 在Action中定义成员变量,变量名称和form元素 name属性一致,并为成员变量 提供setter <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterc