Расшифровка параметров тела с помощью Spring - PullRequest
0 голосов
/ 30 августа 2018

Я разрабатываю бэкэнд API REST для Spring с приложением Slack. Мне удалось получить сообщения от Slack (команды слэша), но я не могу правильно получать взаимодействия компонентов (нажатия кнопок).

Официальная документация гласит:

Ваш URL-адрес действия получит HTTP-запрос POST, включая параметр тела полезной нагрузки, который сам содержит строку JSON application / x-www-form-urlencoded.

поэтому я написал следующее @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 голосов
/ 30 августа 2018

Для простоты вы можете использовать кодовый блок ниже. @ Request body отображает полезную нагрузку в класс Action . Он также проверяет, чтобы убедиться, что тип не пустой. @ Действительный и @ 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;
    }
}
0 голосов
/ 30 августа 2018

Вы получаете строку, содержащую содержимое JSON. Вы не получаете ввод JSON, поскольку application/x-www-form-urlencoded используется в качестве типа контента, а не application/json, как указано:

Ваш URL-адрес действия получит HTTP-запрос POST, включая полезную нагрузку. параметр body, сам содержащий приложение / x-www-form-urlencoded Строка JSON.

Поэтому измените тип параметра на String и используйте Джексона или любую библиотеку 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, вы могли бы заменить @RequestParam на @RequestBody, если бы могли передавать строку JSON непосредственно в теле запроса POST, а не в качестве значения параметра, но, похоже, это не так есть.
На самом деле, используя @RequestBody, тело запроса передается через HttpMessageConverter для разрешения аргумента метода.

Чтобы ответить на ваш комментарий, Spring MVC не предоставляет очень простой способ удовлетворить ваши требования: сопоставить String JSON с вашим Action классом.
Но если вам действительно нужно автоматизировать это преобразование, у вас есть длинная альтернатива, как указано в документации Spring MVC , такой как Formatters (выделено мое):

Некоторые аннотированные аргументы метода контроллера, которые представляют на основе строк ввод запроса - например, @RequestParam, @RequestHeader, @PathVariable, @MatrixVariable, и @CookieValue, может потребоваться преобразование типа, если Аргумент объявляется как нечто отличное от String.

В таких случаях преобразование типа автоматически применяется на основе настроил конвертеры. По умолчанию простые типы, такие как int, long, Дата и т. Д. Поддерживаются. Тип преобразования может быть настроен через WebDataBinder, см. DataBinder, или путем регистрации средств форматирования с помощью FormattingConversionService, см. Форматирование весенних полей.

Создавая форматтер (подкласс FormatterRegistry) для вашего Action класса, вы можете добавить его в веб-конфигурацию Spring , как описано :

@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) 
{...}
...