2017-02-09 14 views
0

Я хочу сделать PUT-вызов весной.ни @RequestBody, ни @RequestParam работа

это мой код контроллера:

@RequestMapping(value = "/magic", method = RequestMethod.PUT) 
    TodoDTO magic(@RequestBody String id){ 
     return service.magic(id); 
    } 

, потому что я хочу, чтобы передать строку идентификатора в вызове.

проблема, я получаю эту

{ 
    "timestamp": 1486644310464, 
    "status": 500, 
    "error": "Internal Server Error", 
    "exception": "java.lang.NullPointerException", 
    "message": "{\n\t\"id\":\"589c5e322abb5f28631ef2cc\"\n}", 
    "path": "/api/todo/magic" 
} 

если я изменить код так:

@RequestMapping(value = "/magic", method = RequestMethod.PUT) 
    TodoDTO magic(@RequestParam(value = "id") String id){ 
     return service.magic(id); 
    } 

я получить

{ 
    "timestamp": 1486644539977, 
    "status": 400, 
    "error": "Bad Request", 
    "exception": "org.springframework.web.bind.MissingServletRequestParameterException", 
    "message": "Required String parameter 'id' is not present", 
    "path": "/api/todo/magic" 
} 

я сделать такой же вызов, пута по ссылке http://localhost:8080/api/todo/magic с телом

{ 
    "id":"589c5e322abb5f28631ef2cc" 
} 

, который является идентификатором одного объекта в моем db.

мой вопрос в том, как я могу достичь своей цели? если я прохожу Пары в ссылке, как API/Todo/магия/589c5e322abb5f28631ef2cc, с @PathVariable, он работает

+0

_ "с @PathVariable, он работает" _ Затем используйте его. И не используйте 'PUT', если вы не отправляете данные. – zeroflagL

+0

@zeroflagL это не шаблон для отправки данных в URL? это был просто тест, это причина метода «не делать ничего» :) – AvramPop

+0

Если точкой вашего метода является возврат элемента с определенным идентификатором или на его основе, то идентификатор - это не данные , Если идентификатор фактически является данными, тогда вы правы, и его следует отправить как тело. Но на основании сообщения об ошибке вы этого не сделали. – zeroflagL

ответ

5

Создайте свой собственный класс, как показано ниже

Class Request 
{ 
private String id; 
//getter and setter 
} 

И изменить метод

@RequestMapping(value = "/magic", method = RequestMethod.PUT) 
    TodoDTO magic(@RequestBody Request request){ 
     return service.magic(request.getId()); 
    } 

Вы можете взять идентификатор в URL также и использовать @Pathvariable в подписи метода

@RequestMapping(value = "/magic/{id}", method = RequestMethod.PUT) 
     TodoDTO magic(@PathVariable String id){ 
      return service.magic(request.getId()); 
     } 
+0

есть ли случай, когда это нужно предпочесть вместо простой карты? – AvramPop

+3

Причина ** ** ** с использованием карты: 1) Предлагаемое решение предлагает вам безопасный доступ к ожидаемому входу, карта вынуждает вас использовать данные, используя ключ, и проверьте, является ли тип тем, что вы ожидаете , прежде чем они будут использоваться. 2) Также понятно для других разработчиков, которые читают код. 3) Он позволяет автоматически генерировать API-doc (используя весеннюю лису). 4) Если сконфигурировано правильно, картограф Jackson может предупредить пользователей, если они используют неправильные значения запроса, в то время как карта принимает любое свойство из тела. 5) Если у вас есть вложенные структуры JSON, вы получите карты на картах (или даже ошибки преобразования). –

+0

Тогда это правильный ответ! Спасибо! – AvramPop

2

Когда вы используете @RequestBody String id он ожидает, просто строка:

"589c5e322abb5f28631ef2cc" 

Если вы хотите отправить объект с id поля как

{ 
    "id":"589c5e322abb5f28631ef2cc" 
} 

вы должны создать класс с id полем и изменить подпись метода, для получения этого класса вместо String.

+0

и если у меня есть 2 параметра, просто отделите их запятой? – AvramPop

+1

Нет, поскольку '@ RequestBody' представляет весь объект запроса, в случае 2 params вам нужно создать для них класс (или вы« Карта »). –

+0

, поэтому этот параметр предназначен только для одного параметра. спасибо за этот ярлык! – AvramPop

0

При создании класса оболочки, как предложено в других ответах, будет работать, я думаю, что можно избежать этих накладных расходов и просто использовать карту.

@RequestMapping(value = "/magic", method = RequestMethod.PUT) 
    TodoDTO magic(@RequestBody Map<String, String> data){ 
     return service.magic(data.get("id"); 
} 
+0

кажется, что это лучший вариант, потому что ему не нужны дополнительные классы. и если я хочу 2 параметра, просто позвоните, data.get ("foo")? – AvramPop