【问题标题】:Cannot send JSON as request body to Spring Controller无法将 JSON 作为请求正文发送到 Spring Controller
【发布时间】:2016-06-01 23:33:37
【问题描述】:

第 1 步: Ajax 请求:

$.ajax({
  url: "url",
  type: "POST",
  dataType: 'json',
  data:{
    'id': '1',
    'type': 'BOOK_VIEWED',
    'access_token': response.response.access_token
  },
  crossDomain: true,
  success: function() { }
});

STEP 2. 在执行 Spring Controller 方法之前从请求中获取参数;这里有两种变体:

  • 变体 1: 如果我发送标头中带有 content-type: json 的 ajax 请求,这将起作用;否则它将:

    String token = request.getParameter(HEADER_SECURITY_TOKEN);
  • 变体 2: 如果我在标题中设置 content-type: json,这将起作用:

    StringBuilder sb = new StringBuilder();
    BufferedReader reader = request.getReader();
    String line;
    while ((line = reader.readLine()) != null)
        sb.append(line).append('\n');

步骤 3. 应该执行 Spring Controller bookOpened 方法:

@RequestMapping(value = "/event",
                    method = RequestMethod.POST,
                        produces = MediaType.APPLICATION_JSON_VALUE)
public void bookOpened(@RequestBody PostEvent postEvent, HttpServletRequest request) {
    // ..
}

当试图运行时,bookOpened 方法没有被执行并且一个415(unsupported media type) Exception 被抛出。如果将方法签名更改为仅接受:HttpServletRequest request 参数(没有@RequestBody 参数),它将起作用;但这对我来说不是一个可行的解决方案。

主要问题:

  • 在第 2 步中,我想从请求中获取一个参数。
  • 在第 3 步中,我想包含 @RequestBody 参数,而不仅仅是 HttpServletRequest 参数。

【问题讨论】:

  • 您的项目中是否包含依赖项:jackson-corejackson-databin
  • 那么你将如何获得 before 控制器的参数?用拦截器,还是其他方式?

标签: java json ajax spring spring-mvc


【解决方案1】:

第 3 步

要强制执行您请求的消息转换器进程,您必须指定它的内容类型。它必须是application/json。在请求的data 参数中,您必须发送String,而不是array。因此,您的请求可能如下所示:

var post = {};
post['id']=1;
post['type']='BOOK_VIEWED';
post['access_token']=response.response.access_token;

$.ajax({
       url: 'url',
       type: 'post',
       contentType : 'application/json',
       dataType:'json',
       data:JSON.stringify(post)
   })
   success: function() { ... }
})

此外,要将 json 消息转换器包含到您的项目中,您必须声明一些依赖项。如果您还没有这样做,请将此依赖项包含在您的 pom 中:

<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-core</artifactId>
   <version>2.4.1</version>
</dependency>
<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
   <version>2.4.1.1</version>
</dependency>

第 2 步

因为客户端只发送一次请求,所以您可以读取请求正文一次。所以,永远不要使用request.getReader(),除非你在HttpMessageConverter 实现中使用它。要从请求中获取价值,您可以将其作为请求参数(查询)发送。在您的情况下,要将参数添加到 url,您必须手动编写 url-string:

...

$.ajax({
       url: 'url?acces_token='+encodeURIComponent(response.response.access_token),
       type: 'post',
       contentType : 'application/json',
       dataType:'json',
       data:JSON.stringify(post)
   })
   success: function() { ... }
})

之后,您可以通过众所周知的方式获取请求参数:

String token = URLDecoder.decode(request.getParameter('acces_token'), "utf-8");

不是,您在将令牌作为 url 参数传递并在服务器端获取它时再次对其进行解码之前对其进行了编码。

希望,这会有所帮助。

【讨论】:

    猜你喜欢
    • 2021-02-09
    • 2021-02-17
    • 1970-01-01
    • 1970-01-01
    • 2020-05-09
    • 2018-07-18
    • 2015-11-17
    • 2021-02-11
    • 1970-01-01
    相关资源
    最近更新 更多