【问题标题】:Spring @RequestMapping method without @RequestBody没有@RequestBody的Spring @RequestMapping方法
【发布时间】:2018-03-18 13:31:21
【问题描述】:

在 Spring Boot Controller 方法中,我如何获取 POST 的主体?我见过的所有示例都使用@RequestBody。如何在不使用@RequestBody 的情况下获取正文?

我正在编写一个处理 Slack 事件的方法。当 Slack 发布一个事件时,正文是 JSON 格式,并且通常包含一个“用户”键。根据事件的类型,“user”的值可以是字符串或对象。因此,我无法创建单个类并编写

@RequestMapping(path = "/slackRequest", method = RequestMethod.POST)
    public String handleSlackRequest(@RequestBody final SlackRequest slackRequest)

答案:实现@ChiDov建议的方法,解决方案是保留@RequestBody,导入

import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

定义用户字段(如果它是一个简单的字符串值,则定义一个新字段来存储“用户”)

@OneToOne
private SlackEventUser user;
private String slackUserId;

并将其Setter方法定义为

@JsonSetter("user")
public void setUser(JsonNode userNode) {
    ObjectMapper mapper = new ObjectMapper();
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    if (userNode.isObject()) {
        SlackEventUser slackEventUser = mapper.convertValue(userNode, SlackEventUser.class);
        this.user = slackEventUser;
    } else {
        String userString = mapper.convertValue(userNode, String.class);
        this.slackUserId = userString;
        this.user = null;
    }
}

【问题讨论】:

  • 只接受String 并根据内容手动映射?
  • @DarrenForsythe 反序列化器知道“{”是对象的开头,而不是字符串:“无法读取 HTTP 消息:org.springframework.http.converter.HttpMessageNotReadableException:无法读取文档: 无法从 START_OBJECT 令牌中反序列化 java.lang.String 的实例”

标签: spring spring-boot slack-api


【解决方案1】:

更新:我会让你的 DTO 像这样:

Class SlackRequest{
    ...
    private String eventType;
    private JsonNode user;
    ...
    public String getUser(){
        return user.asText();
    }
}

在控制器中:

@RequestMapping(path = "/slackRequest", method = RequestMethod.POST)
    public String handleSlackRequest(@RequestBody final SlackRequest slackRequest){
    if(slackRequest.getEventType == "objectEvent"){
      SomeObject user = mapper.convertValue(slackRequest.getUser(), SomeObject.class);
      // do something with the object
    }else{
     // do something with the user string
   }
}

How to deserialize dynamic field using Jackson?获取灵感

【讨论】:

  • 处理程序永远不会被调用。反序列化器知道“{”是对象的开始,而不是字符串:“无法读取 HTTP 消息:org.springframework.http.converter.HttpMessageNotReadableExc‌​eption:无法读取文档:无法反序列化 java.util. lang.String out of START_OBJECT token"
  • 谢谢。我将研究 1)“无类型”映射和 2)自定义反序列化器
  • 不客气,希望我的回答对您有所帮助。如果您在 slackRequest 中没有很多字段,我建议您使用自定义反序列化器。因此您可以根据 eventType 将其反序列化为字符串或对象。
猜你喜欢
  • 1970-01-01
  • 2017-12-05
  • 2021-12-23
  • 1970-01-01
  • 2016-01-07
  • 1970-01-01
  • 1970-01-01
  • 2018-01-23
  • 1970-01-01
相关资源
最近更新 更多