Spring 4.x/3.x(Web MVC) REST API и JSON2 Почтовые запросы, как правильно это сделать один раз для всех?

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

Понятия, связанные с данным

Конечно, вы знаете об этом, но я просто пишу их как быстрый обзор. Не стесняйтесь редактировать, если я что-то не хватает.

Запрос HTTP POST:

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

Сериализация:

Является процессом получения объекта из вашего веб-браузера до вашего приложения на стороне сервера. Можно использовать вызов jQuery Ajax или запрос на публикацию Curl.

Протоколы сериализации:

Наиболее популярными тезисами являются JSON и XML. XML становится менее популярным, поскольку сериализованные объекты xml относительно большие по размеру из-за характера тегов XML. В этом FAQ основное внимание уделяется сериализации JSON2.

Spring:

Spring и его мощная аннотация позволяет эффективно публиковать веб-службу. В Spring существует множество разных библиотек. Здесь мы сосредоточены на Spring веб-MVC.

Curl vs 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 bean, dataSource bean и т.д.
  • MVC Dispatcher Servlet XML: Здесь вы обнаружите свой преобразователь вида bean и импортируете XML-контекст приложения.

haslerAdapter bean должен быть расположен в более поздней версии, это файл MVC Dispatcher XML.

<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. Оба формата Ref и normal bean в файле XML были использованы (лично я предпочитаю тег ref как его опрятный).

API REST

Вот пример контроллера, который предоставляет API REST.

Контроллер

Здесь отображается ваш 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":"[email protected]"}' http://localhost:8080/[YOURWEBAPP]/api/user/add

Связанные сообщения и вопросы

Этот FAQ не был возможен, если бы это было не для всех людей, которые предоставили следующие должности и вопросы (этот список будет расширяться, если я столкнусь с полезными сообщениями/вопросами):

Ответ 1

CURL Почтовый вызов

curl -i -H "Content-Type: application/json" -X POST -d '{"id":100,"username":"JohnBlog","name":"John","lastName":"Blog","email":"[email protected]"}' http://localhost:8080/[YOURWEBAPP]/api/user/add

Различные сценарии ошибок:

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

Сценарий первый:

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

Это означает, что API REST не существует в указанном вами URL-адресе.

Основная причина:
  • У вас может быть опечатка в вашем запросе (поверьте, это может случиться)!
  • Возможно, ваша конфигурация spring неверна. Если это так, ему нужно еще больше углубиться в то, что на самом деле пошло не так, но я предусмотрел некоторые начальные действия, которые вам нужно предпринять, прежде чем начинать более сложное исследование.
Действия:

После того, как вы убедитесь, что все сделано совершенно правильно, и ничего не случилось с вашей конфигурацией или вы не указали URL: - Запустите maven clean. - Разверните свое веб-приложение или просто удалите его. - Повторное развертывание веб-приложения - Обязательно используйте только одну версию spring в своем maven/gradle

Сценарий второй:

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

Единственная причина этого заключается в том, что ваш запрос не отформатирован правильно. Если вы проверите подробный отклик, вы сможете увидеть "Запрос, отправленный клиентом, был синтаксически неправильным".

Основная причина:

Либо ваш формат JSON не прав, либо у вас отсутствует обязательный параметр для объекта JAVA.

Действия:

Убедитесь, что вы предоставили объект JSON в правильном формате и с правильным количеством параметров. Неверные свойства не являются обязательными, но вам необходимо предоставить данные для всех свойств NotNullable. ОЧЕНЬ важно помнить, что spring использует отражение Java, чтобы превратить ваш JSON файл в объекты Java, что это значит? это означает, что имена переменных и методов являются CasE SensItiVe. Если ваш JSON файл отправляет переменную "userName", то ваша соответствующая переменная в вашем Java-объекте ДОЛЖНА также быть названа "userName". Если у вас есть получатели и сеттеры, они также должны следовать тому же правилу. getUserName и setUserName, чтобы соответствовать нашему предыдущему примеру.

Сенарио три:

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 не поддерживается вашей веб-службой. Это может быть связано с вашей аннотацией, не указывающей тип носителя, или вы не указываете тип носителя в команде Post Curl.

Действия:

Проверьте правильность настройки вашего конвертера сообщений и убедитесь, что аннотация веб-службы соответствует приведенному выше примеру. Если все было в порядке, убедитесь, что вы указываете тип контента в запросе на отправку 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 вашей серверной части.

Подробнее о настройке spring руководства spring mvc.

Связанные сообщения и вопросы

Этот FAQ не был возможен, если бы это было не для всех людей, которые предоставили следующие должности и вопросы (этот список будет расширяться, если я столкнусь с полезными сообщениями/вопросами):

Ответ 2

Следует отметить, что класс bean может обрабатывать NOT, если он имеет 2 или более сеттера для одного поля без @JsonIgnore на дополнительных. Spring/Jackson throw HttpMediaTypeNotSupportedException и статус http 415 Неподдерживаемый тип носителя.

Пример:

@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, похоже, не требуется.