使用Spring解码主体参数

时间:2018-08-30 07:52:30

标签: java spring slack slack-api spring-rest

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

official documentation说:

  

您的操作网址将收到一个HTTP POST请求,其中包括一个有效载荷主体参数,该参数本身包含一个application / x-www-form-urlencoded JSON字符串。

因此,我写了以下@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

这是什么意思,以及如何解决?

2 个答案:

答案 0 :(得分:4)

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

  

您的操作网址将收到HTTP POST请求,包括有效负载   主体参数,本身包含一个application / x-www-form-urlencoded   JSON字符串。

因此将参数类型更改为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字符串,则可以用@RequestParam替换@RequestBody那里不是这种情况。
实际上,通过使用@RequestBody,请求的主体将通过HttpMessageConverter传递,以解析方法参数。

要回答您的评论,Spring MVC没有提供一种非常简单的方法来满足您的要求:将String JSON映射到您的Action类。
但是,如果您确实需要自动执行此转换,则可以按照the Spring MVC documentation中的说明使用冗长的替代方法,例如Formatters(强调是我的):

  

一些带注释的控制器方法参数,它们表示基于字符串的字符串   请求输入-例如@RequestParam@RequestHeader@PathVariable,   @MatrixVariable,@CookieValue,如果   参数被声明为不是String的其他东西。

     

在这种情况下,根据   配置的转换器。默认情况下,简单类型如int,long,   日期等。 可以通过以下方式自定义类型转换   WebDataBinder,请参阅DataBinder,或通过   FormattingConversionService,请参阅Spring字段格式。

通过为FormatterRegistry类创建格式化程序(Action子类),您可以在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) 
{...}

答案 1 :(得分:0)

为简单起见,您可以使用下面的代码块。 @Request 正文将有效负载映射到 Action 类。它还可以验证以确保类型不为空。 @Valid @NotBlank 来自 javax.validation 包。

    @PostMapping("actions")
public ResponseEntity<?> startApplication(@RequestBody @Valid Action payload) {
    // use your payload here 
    return ResponseEntity.ok('done');
}


class Action {

    @NotBlank
    private String type;

    public Action() {
    }

    public String getType() {
        return type;
    }
}