REST API Spring 4.x/3.x (Web MVC) и JSON2 Отправляйте запросы, как сделать это правильно раз и навсегда?
Прежде чем углубляться в детали, я знаю, что было много разговоров и связанных вопросов по Stackru. Все они в некотором роде помогают мне, поэтому я решил, что я собрал свои выводы в единый организованный FAQ, чтобы подвести итоги.
Родственные концепции
Конечно, вы знаете об этом, но я просто пишу их как краткий обзор. Не стесняйтесь редактировать в случае, если я что-то упустил.
HTTP POST-запрос:
Запрос на публикацию используется, когда вы хотите отправить объект в веб-службу или на серверное приложение.
Сериализация:
Это процесс передачи объекта из вашего веб-браузера в серверное приложение. Можно использовать вызов jQuery Ajax или запрос отправки Curl.
Протоколы сериализации:
Наиболее популярными в эти дни являются JSON и XML. XML становится менее популярным, поскольку сериализованные XML-объекты имеют относительно большие размеры из-за природы тегов XML. В этом FAQ основное внимание уделяется сериализации JSON2.
Весна:
Spring Framework и его мощные аннотации позволяют эффективно использовать веб-сервис. В Spring много разных библиотек. В центре нашего внимания находится Spring Web MVC.
Керл против JQuery:
Это инструменты, которые вы можете использовать для отправки запроса на стороне клиента. Даже если вы планируете использовать JQuery AJAX-вызов, я предлагаю вам использовать Curl для целей отладки, поскольку он предоставляет вам подробный ответ после выполнения запроса на публикацию.
@RequestBody vs @ RequestParam / @ PathVariable vs @ModelAttribute:
В тех случаях, когда у вас есть веб-сервис, который не зависит от вашей модели Java EE, необходимо использовать @RequestBody. Если вы используете модель и ваш объект JSON добавлен в модель, вы можете получить доступ к объекту через @ModelAttribute. Только в тех случаях, когда ваш запрос является либо запросом GET, либо комбинацией запросов GET и POST, вам нужно использовать @ RequestParam / @ PathVariable.
@RequestBody vs @ResposeBody:
Как видно из названия, это так просто: @ResponseBody нужен только в том случае, если вы отправляете ответ клиенту после того, как метод на стороне сервера обработал запрос.
RequestMappingHandlerAdapter vs AnnotationMethodHandlerAdapter:
RequestMappingHandlerAdapter - это новый обработчик отображения для среды Spring, который заменил AnnotationMethodHandlerAdapter начиная с Spring 3.1. Если ваша существующая конфигурация все еще находится в AnnotationMethodHandlerAdapter, этот пост может оказаться полезным. Конфигурация, представленная в моем посте, даст вам представление о том, как настроить RequestMappingHandlerAdapter.
Настроить
Вам нужно будет настроить конвертер сообщений. Вот как ваше сериализованное тело сообщения JSON преобразуется в локальный объект Java на стороне вашего сервера.
Базовая конфигурация отсюда. Конвертерами были MarshallingHttpMessageConverter и CastorMarshaller в базовом примере конфигурации, я заменил их на MappingJackson2HttpMessageConverter и MappingJacksonHttpMessageConverter.
Где поставить конфигурацию
При настройке моего проекта у меня есть два конфигурационных файла:
- XML контекста приложения. Один из них - XML-файл контекста приложения, в котором находятся ваш компонент sessionFactory, компонент dataSource и т. Д.
- Сервлет-диспетчер MVC XML: здесь у вас есть bean-компонент распознавателя вида и вы импортируете XML контекста приложения.
bean-компонент hadlerAdapter должен быть расположен позднее, это XML-файл MVC Dispatcher.
<bean name="handlerAdapter"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
<ref bean="jsonConverter"/>
</list>
</property>
<property name="requireSession" value="false"/>
</bean>
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes" value="application/json"/>
</bean>
Вы можете иметь несколько конвертеров сообщений. здесь я создал обычный JSON, а также JSON 2 конвертер сообщений. В XML-файле использовался как Ref, так и обычный bean-формат (лично я предпочитаю тег ref в качестве более аккуратного).
REST API
Вот пример контроллера, который предоставляет REST API.
Контроллер
Вот где раскрывается ваш REST API для HTTP-запроса.
@Component
@Controller
@RequestMapping("/api/user")
public class UserController {
@RequestMapping(value = "/add", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String insertUser(@RequestBody final User user) {
System.out.println(user.toString());
userService.insertUser(user);
String userAdded = "User-> {" + user.toString() + "} is added";
System.out.println(userAdded);
return userAdded;
}
}
Объект Java
@JsonAutoDetect
public class User {
private int id;
private String username;
private String name;
private String lastName;
private String email;
public int getId() {
return externalId;
}
public void setId(final int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(final String email) {
this.email = email;
}
public String getUsername() {
return username;
}
public void setUsername(final String username) {
this.username = username;
}
public String getLastName() {
return lastName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return this.getName() + " | " + this.getLastName() + " | " + this.getEmail()
+ " | " + this.getUsername() + " | " + this.getId() + " | ";
}
}
CURL Почтовый звонок
curl -i -H "Content-Type: application/json" -X POST -d '{"id":100,"username":"JohnBlog","name":"John","lastName":"Blog","email":"JohnBlog@user.com"}' http://localhost:8080/[YOURWEBAPP]/api/user/add
Похожие посты и вопросы
Этот FAQ был бы невозможен, если бы не все люди, которые предоставили следующие посты и вопросы (этот список расширится, если я найду полезные связанные посты / вопросы):
- Каков правильный тип содержимого JSON?
- Spring 3.0 делает JSON-ответ с использованием конвертера сообщений Джексона
- Как отправить данные JSON с помощью Curl из терминала / командной строки для тестирования Spring REST?
- Отправка JSON в REST API
- https://github.com/geowarin/spring-mvc-examples
- Как опубликовать JSON в PHP с помощью curl
- Весенний ОТДЫХ | MappingJacksonHttpMessageConverter создает недопустимый JSON
- https://github.com/eugenp/REST
- Spring Web MVC - проверка отдельных параметров запроса
- Как отправить данные JSON с помощью Curl из терминала / командной строки для тестирования Spring REST?
- Как вы возвращаете объект JSON из сервлета Java
- Какой тип MIME, если JSON возвращается REST API?
2 ответа
CURL Почтовый звонок
curl -i -H "Content-Type: application/json" -X POST -d '{"id":100,"username":"JohnBlog","name":"John","lastName":"Blog","email":"JohnBlog@user.com"}' http://localhost:8080/[YOURWEBAPP]/api/user/add
Различные сценарии ошибок:
Здесь я исследую различные ошибки, с которыми вы можете столкнуться после того, как вы сделали вызов curl, и что могло произойти не так.
Сценарий первый:
HTTP/1.1 404 Not Found
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 949
Date: Tue, 04 Jun 2013 02:59:35 GMT
Это означает, что REST API не существует в предоставленном вами URL.
Первопричина:- У вас может быть опечатка в вашем запросе (поверьте мне, это может произойти)!
- Возможно, ваша весенняя конфигурация не верна. Если дело обстоит именно так, нужно еще глубже разобраться в том, что на самом деле пошло не так, но я предоставил некоторые начальные действия, которые вам нужно сделать, прежде чем начинать более сложное расследование.
После того, как вы убедились, что все сделано совершенно правильно, и нет ничего плохого в вашей конфигурации, ни в вашем URL: - Запустите maven clean. - Разверните ваше веб-приложение или просто удалите его. - Повторно разверните веб-приложение. - Убедитесь, что в вашем maven / gradle используется только одна версия Spring.
Сценарий второй:
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 968
Date: Tue, 04 Jun 2013 03:08:05 GMT
Connection: close
Единственная причина этого заключается в том, что ваш запрос отформатирован неправильно. Если вы извлечете подробный ответ curl, вы должны увидеть "Запрос, отправленный клиентом, был синтаксически неверным".
Первопричина:Либо у вас неправильный формат JSON, либо у вас отсутствует обязательный параметр для объекта JAVA.
Действия:Убедитесь, что вы предоставили объект JSON в правильном формате и с правильным количеством параметров. Обнуляемые свойства не являются обязательными, но вы должны предоставить данные для всех свойств NotNullable. ОЧЕНЬ важно помнить, что Spring использует отражение Java, чтобы превратить ваш файл JSON в объекты Java, что это значит? это означает, что имена переменных и методов являются CasE SensItiVe. Если ваш JSON-файл отправляет переменную "userName", соответствующая переменная в вашем Java-объекте ДОЛЖНА также иметь имя "userName". Если у вас есть геттеры и сеттеры, они также должны следовать одному и тому же правилу. getUserName и setUserName соответствуют нашему предыдущему примеру.
Senario Three:
HTTP/1.1 415 Unsupported Media Type
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 1051
Date: Wed, 24 Aug 2011 08:50:17 GMT
Первопричина:Тип мультимедиа Json не поддерживается вашим веб-сервисом. Это может быть связано с тем, что в вашей аннотации не указан тип носителя или вы не указали тип носителя в команде Curl post.
Действия:Проверьте, правильно ли настроен конвертер сообщений, и убедитесь, что аннотация веб-службы соответствует приведенному выше примеру. Если все в порядке, убедитесь, что вы указали тип содержимого в своем запросе на публикацию Curl.
Тип мультимедиа json не поддерживается вашим веб-сервисом.
Senario N (!):
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 04 Jun 2013 03:06:16 GMT
Поздравляю, пользователь фактически отправляет на ваш сервер REST API.
Для получения более подробной информации о том, как настроить пружину, обратитесь к руководству MVC Spring.
Похожие посты и вопросы
Этот FAQ был бы невозможен, если бы не все люди, которые предоставили следующие посты и вопросы (этот список расширится, если я найду полезные связанные посты / вопросы):
- Каков правильный тип содержимого JSON?
- Spring 3.0 делает JSON-ответ с использованием конвертера сообщений Джексона
- Как отправить данные JSON с помощью Curl из терминала / командной строки для тестирования Spring REST?
- Отправка JSON в REST API
- https://github.com/geowarin/spring-mvc-examples
- Как опубликовать JSON в PHP с помощью curl
- Весенний ОТДЫХ | MappingJacksonHttpMessageConverter создает недопустимый JSON
- https://github.com/eugenp/REST
- Spring Web MVC - проверка отдельных параметров запроса
- Как отправить данные JSON с помощью Curl из терминала / командной строки для тестирования Spring REST?
- Как вы возвращаете объект JSON из сервлета Java
- Какой тип MIME, если JSON возвращается REST API?
Должно быть замечено, что класс bean нельзя обрабатывать, если он имеет 2 или более сеттера для одного поля без @JsonIgnore
на дополнительные. Весна / Джексон бросить HttpMediaTypeNotSupportedException
и http status 415 Unsupported Media Type.
Пример:
@JsonGetter
public String getStatus() {
return this.status;
}
@JsonSetter
public void setStatus(String status) {
this.status = status;
}
@JsonIgnore
public void setStatus(StatusEnum status) {
if (status == null) {
throw new NullPointerException();
}
this.status = status.toString();
}
Обновление: мы также должны указать @JsonGetter
а также @JsonSetter
в этом случае не должно быть проблем при использовании в качестве возвращаемого типа.
Только что протестировал его с Spring 3.2.2 и Jackson 2.2. Работает нормально как параметр (@RequestBody
) и / или в качестве типа возврата (@ResponseBody
).
Обновление 2:
Если @JsonGetter
а также @JsonSetter
указаны, @JsonIgnore
кажется, не требуется.