当内容类型为 application/x-www-form-urlencoded 时,Java 读取 POST 数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33384245/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 21:36:03  来源:igfitidea点击:

Java read POST data when content-type is application/x-www-form-urlencoded

javaspring-mvcpostmime-typescontent-type

提问by drimk

I have an API that I'm testing. The API receives POST requests and reads it like this

我有一个正在测试的 API。API 接收 POST 请求并像这样读取它

      StringBuffer jb = new StringBuffer();
      String line = null;
      try {
        BufferedReader reader = request.getReader();
        while ((line = reader.readLine()) != null)
            jb.append(line);

        System.out.println("jb: "+jb);
        System.out.println("request.getHeader('content-type'): "+request.getHeader("content-type"));

      } catch (Exception e) { /*report an error*/ }

All works fine when I send a POST request in "application/json;charset=utf-8"

当我在“application/json;charset=utf-8”中发送 POST 请求时一切正常

httpPost.setHeader("content-type", "application/json;charset=utf-8");

It prints this:

它打印这个:

jb: {"client_domain":"=....); //proper Json data
request.getHeader('content-type'): application/json;charset=utf-8

And I can read the data properly.

我可以正确读取数据。

However my problem is when I send the data the same way but I set the content-type "application/x-www-form-urlencoded;charset=utf-8"

但是我的问题是当我以相同的方式发送数据但我设置了内容类型“application/x-www-form-urlencoded;charset=utf-8”

httpPost.setHeader("content-type", "application/x-www-form-urlencoded;charset=utf-8");

The test is the same just the content-type is different but then it seems that I don't receive any data anymore:

测试相同,只是内容类型不同,但似乎我不再收到任何数据:

jb: 
request.getHeader('content-type'): application/x-www-form-urlencoded;charset=utf-8

Any idea?

任何的想法?

/// Update

/// 更新

Here is the Spring Controller

这是弹簧控制器

@RequestMapping(value = {"user/add"}, method = RequestMethod.POST, produces="application/json; charset=utf-8")
@ResponseBody
public ResponseEntity<String> getNewUserApi(HttpServletRequest request,
        HttpServletResponse response) throws Exception {

    Map<String, Object> jsonObj = new HashMap<String, Object>();

    StringBuffer jb = new StringBuffer();
      String line = null;
      try {
        BufferedReader reader = request.getReader();
        while ((line = reader.readLine()) != null)
            jb.append(line);

        System.out.println("jb: "+jb);
        System.out.println("request.getHeader('content-type'): "+request.getHeader("content-type"));

      } catch (Exception e) { /*report an error*/ }
    ///I create my JSon that will be sent back
    return JsonUtils.createJson(jsonObj);

//UPDATE 2 Here is how I send the data

//更新2这是我发送数据的方式

public static void main(String[] args) throws Exception {

    String url = "http://localhost:8080/child/apiv1/user/add";
    CloseableHttpClient client = HttpClientBuilder.create().build();

    HttpPost httpPost = new HttpPost(url);
    httpPost.setHeader("content-type", "application/x-www-form-urlencoded;charset=utf-8");

    try {
        //we had to the parameters to the post request
        JSONObject json = new JSONObject();

        json.put("client_id", "fashfksajfhjsakfaskljhflakj");
        json.put("client_secret", "9435798243750923470925709348509275092");
        json.put("client_domain", "dummy.localhost.com");

        //create the user json object
        JSONObject userObj = new JSONObject();
        userObj.put("email", "[email protected]");
        userObj.put("name", "Anna Sax");

        JSONArray childrenArray = new JSONArray();

        JSONObject child1 = new JSONObject();
        child1.put("name", "Iphone 6");
        child1.put("age", "2");
        childrenArray.put(child1);
        userObj.put("children", childrenArray);
        json.put("user", childObj);

        StringEntity params = new StringEntity(json.toString());
        httpPost.setEntity(params);

        System.out.println("executing request: " + httpPost.getRequestLine());
        HttpResponse response;
        response = client.execute(httpPost);

   //[...]       

} //End main

I know it doesn't really make sense to create Json and send it in "application/x-www-form-urlencoded" but it's just that one of our users can't fix his issue and it will only send "application/x-www-form-urlencoded".

我知道创建 Json 并在“application/x-www-form-urlencoded”中发送它真的没有意义,但只是我们的一个用户无法解决他的问题,它只会发送“application/x -www-form-urlencoded”。

回答by THelper

When using Spring, request.getReader()will not work for reading application/x-www-form-urlencodeddata. Instead this data is available as parameters, so you can read it with:

使用 Spring 时,request.getReader()将无法读取application/x-www-form-urlencoded数据。相反,此数据可用作参数,因此您可以使用以下命令读取它:

@PostMapping(path = "/mypostendpoint", consumes = "application/x-www-form-urlencoded")
public void handleFormData(HttpServletRequest request) {
    Enumeration<String> params = request.getParameterNames();
    while (params.hasMoreElements()) {
        String param = params.nextElement();
        System.out.println("name = " + param + ", value = " + request.getParameter(param));
    }
}

You can test this with curl for example:

例如,您可以使用 curl 进行测试:

curl -X POST http://localhost:8080/mypostendpoint -d 'myparam1=X' -d 'myparam2=Y'

curl -X POST http://localhost:8080/mypostendpoint -d 'myparam1=X' -d 'myparam2=Y'

will print

将打印

name = myparam1, value = X
name = myparam2, value = Y

Alternatively, if you know the possible parameters in advance you can use something like this:

或者,如果您事先知道可能的参数,则可以使用以下方法:

@PostMapping(path = "/mypostendpoint", consumes = "application/x-www-form-urlencoded")
public void handleMyPost(@RequestParam("myparam1") String value1,
                         @RequestParam("myparam2") String value2) {
    System.out.println("value of myparam1 = " + value1);
    System.out.println("value of myparam2 = " + value2);
}

回答by Eric

The 'produces' attribute of @RequestMapping shows that the client could only accept application/json data, so you can remove it or change it into 'application/x-www-form-urlencoded'.

@RequestMapping的'produces'属性表明客户端只能接受application/json数据,所以可以去掉或者改成'application/x-www-form-urlencoded'。