java - 使用 Spring 解码主体参数

标签 java spring slack slack-api spring-rest

我正在使用 Spring 为 Slack 应用程序开发 REST API 后端。我能够从 Slack 接收消息(斜线命令),但我无法正确接收组件交互(按钮点击)。

official documentation说:

Your Action URL will receive a HTTP POST request, including a payload body parameter, itself containing an application/x-www-form-urlencoded JSON string.

因此我写了下面的@RestController:

@RequestMapping(method = RequestMethod.POST, value = "/actions", headers = {"content-type=application/x-www-form-urlencoded"})
public ResponseEntity action(@RequestParam("payload") ActionController.Action action) {
    return ResponseEntity.status(HttpStatus.OK).build();
}

@JsonIgnoreProperties(ignoreUnknown = true)
class Action {

    @JsonProperty("type")
    private String type;

    public Action() {}

    public String getType() {
        return type;
    }

}

但是我得到以下错误:

Failed to convert request element: org.springframework.web.method.annotation.MethodArgumentConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'controllers.ActionController$Action'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'controllers.ActionController$Action': no matching editors or conversion strategy found

什么意思,如何解决?

最佳答案

您收到一个包含 JSON 内容的字符串。您没有收到 JSON 输入,因为 application/x-www-form-urlencoded 用作内容类型,而不是 application/json ,如所述:

Your Action URL will receive a HTTP POST request, including a payload body parameter, itself containing an application/x-www-form-urlencoded JSON string.

因此将参数类型更改为 String 并使用 Jackson 或任何 JSON 库将 String 映射到您的 Action 类:

@RequestMapping(method = RequestMethod.POST, value = "/actions", headers = {"content-type=application/x-www-form-urlencoded"})
public ResponseEntity action(@RequestParam("payload") String actionJSON) {
    Action action = objectMapper.readValue(actionJSON, Action.class);  
    return ResponseEntity.status(HttpStatus.OK).build();
}

正如 pvpkiran 所建议的,如果您可以直接在 POST 请求的正文中传递 JSON 字符串,而不是作为参数的值,但似乎并非如此。
实际上,通过使用 @RequestBody,请求的主体通过 HttpMessageConverter 传递以解析方法参数。

为了回答您的评论,Spring MVC 没有提供一种非常简单的方法来实现您的要求:将 String JSON 映射到您的 Action 类。
但是如果你真的需要自动化这个转换,你有一个冗长的选择,如 the Spring MVC documentation 中所述。例如格式化程序(重点是我的):

Some annotated controller method arguments that represent String-based request input — e.g. @RequestParam, @RequestHeader, @PathVariable, @MatrixVariable, and @CookieValue, may require type conversion if the argument is declared as something other than String.

For such cases type conversion is automatically applied based on the configured converters. By default simple types such as int, long, Date, etc. are supported. Type conversion can be customized through a WebDataBinder, see DataBinder, or by registering Formatters with the FormattingConversionService, see Spring Field Formatting.

通过为您的Action 类创建格式化程序(FormatterRegistry 子类),您可以将其添加到Spring web 配置中as documented :

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        // ... add action formatter here
    }
}

并在你的参数声明中使用它:

public ResponseEntity action(@RequestParam("payload") @Action Action actionJ) 
{...}

关于java - 使用 Spring 解码主体参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52091841/

相关文章:

java - 匿名内部对象中的 "This"

java - Spring启动Thymeleaf : How do I display an entity name from the database and make that name a hyperlink?

java - 如何将 Spring Bean 的生命周期与 Web 应用程序的生命周期联系起来?

spring - 在 Spring 中使用 Cache Abstraction 进行编译时编织

google-app-engine - 从 Golang AppEngine 快速轻松地发布到 Slack Webhook

markdown - Slack Markdown 链接无法解析

java - 短 c#'s alternative to Java' s Path.ResolveSibling。不可能吗?

java - 创建后在 hibernate 中更改模型对象的数据类型

java - ReactiveSecurityContextHolder.getContext() 为空但@AuthenticationPrincipal 有效

javascript - 如何在Windows上使用node.js将图像上传到Slack?