Перейти к содержимому

Postmapping spring как работает

  • автор:

Обработка данных формы

Этот урок освещает процесс использования Spring для создания и отправки web формы.

Что вы создадите

В этом уроке вы создадите web форму, которая будет доступна по URL:

http://localhost:8080/greeting

При просмотре этой страницы отобразится форма. Вы сможете отправить сообщение, заполнив поля id и content . Результирующая страница будет отображена, когда форма будет отправлена.

Что вам потребуется

  • Примерно 15 минут свободного времени
  • Любимый текстовый редактор или IDE
  • JDK 6 и выше
  • Gradle 1.11+ или Maven 3.0+
  • Вы также можете импортировать код этого урока, а также просматривать web-страницы прямо из Spring Tool Suite (STS), собственно как и работать дальше из него.

Как проходить этот урок

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

Чтобы начать с нуля, перейдите в Настройка проекта.

  • Загрузите и распакуйте архив с кодом этого урока, либо кнонируйте из репозитория с помощью Git: git clone https://github.com/spring-guides/gs-handling-form-submission.git
  • Перейдите в каталог gs-handling-form-submission/initial
  • Забегая вперед, создайте web контроллер

Когда вы закончите, можете сравнить получившийся результат с образцом в gs-handling-form-submission/complete .

Настройка проекта

Для начала вам необходимо настроить базовый скрипт сборки. Вы можете использовать любую систему сборки, которая вам нравится для сборки проетов Spring, но в этом уроке рассмотрим код для работы с Gradle и Maven. Если вы не знакомы ни с одним из них, ознакомьтесь с соответсвующими уроками Сборка Java-проекта с использованием Gradle или Сборка Java-проекта с использованием Maven.

Создание структуры каталогов

В выбранном вами каталоге проекта создайте следующую структуру каталогов; к примеру, командой mkdir -p src/main/java/hello для *nix систем:

└── src └── main └── java └── hello

Создание файла сборки Gradle

Ниже представлен начальный файл сборки Gradle. Файл pom.xml находится здесь. Если вы используете Spring Tool Suite (STS), то можете импортировать урок прямо из него.

Если вы посмотрите на pom.xml , вы найдете, что указана версия для maven-compiler-plugin. В общем, это не рекомендуется делать. В данном случае он предназначен для решения проблем с нашей CI системы, которая по умолчанию имеет старую(до Java 5) версию этого плагина.

buildscript < repositories < maven < url "http://repo.spring.io/libs-release" >mavenLocal() mavenCentral() > dependencies < classpath("org.springframework.boot:spring-boot-gradle-plugin:1.1.8.RELEASE") >> apply plugin: 'java' apply plugin: 'eclipse' apply plugin: 'idea' apply plugin: 'spring-boot' jar < baseName = 'gs-handling-form-submission' version = '0.1.0' >repositories < mavenLocal() mavenCentral() maven < url "http://repo.spring.io/libs-release" >> dependencies < compile("org.springframework.boot:spring-boot-starter-thymeleaf") testCompile("junit:junit") >task wrapper(type: Wrapper)

Spring Boot gradle plugin предоставляет множество удобных возможностей:

  • Он собирает все jar’ы в classpath и собирает единое, исполняемое «über-jar», что делает более удобным выполнение и доставку вашего сервиса
  • Он ищет public static void main() метод, как признак исполняемого класса
  • Он предоставляет встроенное разрешение зависимостей, с определенными номерами версий для соответсвующих Spring Boot зависимостей. Вы можете переопределить на любые версии, какие захотите, но он будет по умолчанию для Boot выбранным набором версий

Создание web контроллера

В подходе Spring к построению web сайтов, HTTP запросы обрабатываются контроллером. Эти компоненты легко идентифицируются по @Controller аннотации. Ниже представленный GreetingController обрабатывает GET запросы для /greeting , возвращая название View , в данном случае это «greeting». View ответственнен за рендеринг HTML контента.

package hello; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; @Controller public class GreetingController < @RequestMapping(value="/greeting", method=RequestMethod.GET) public String greetingForm(Model model) < model.addAttribute("greeting", new Greeting()); return "greeting"; >@RequestMapping(value="/greeting", method=RequestMethod.POST) public String greetingSubmit(@ModelAttribute Greeting greeting, Model model) < model.addAttribute("greeting", greeting); return "result"; >>

Этот контроллер лаконичен и прост, но в нем много чего происходит. Давайте подробнее рассмотрим шаг за шагом.

Аннотация @RequestMapping позволяет вам связать HTTP запросы с определенными методами контроллера. В этом контроллере два метода и оба они относятся к /greeting . По умолчанию, @RequestMapping соответствует всем HTTP операциям, таким как GET , POST и так далее. Но в данном случае метод greetingForm() явно связан с GET , используя @RequestMapping(method=GET) , в то время как greetingSubmit() связан с POST через @RequestMapping(method=POST) . Эти соответствия позволяют контроллеру различать типы запросов к /greeting .

Метод greetingForm() использует объект Model для предоставления доступа к новому Greeting в шаблоне представления. Greeting объект в приведенном ниже коде содержит поля id и content , соответствующие полям формы в greeting представлении, и которые будут использованы для извлечения информации из формы.

package hello; public class Greeting < private long id; private String content; public long getId() < return id; >public void setId(long id) < this.id = id; >public String getContent() < return content; >public void setContent(String content) < this.content = content; >>

Реализация тела метода основана на View Technology, в данном случае на Thymeleaf, чтобы выполнять рендеринг HTML на стороне сервера. Thymeleaf парсит шаблон greeting.html , приведенный ниже, и вычисляет различные выражения для рендеринга формы.

   Getting Started: Handing Form Submission  

Form

Id: " />

Message: " />

Выражение th:action=»@» направляет форму к POST запросу /greeting , в то время как выражение th:object=»$» описывает модель объекта для сбора данных. Два поля формы, выраженные в th:field=»*» и th:field=»*» , соответствуют полям объекта Greeting .

Это то, за что отвечает контроллер, модель и представление для отображения формы. Теперь давайте рассмотрим процесс отправки формы. Как уже отмечалось выше, форма отправляется на /greeting , используя POST . Метод greetingSubmit() получает объект Greeting , который был заполнен формой. Затем он добавляет этот объект в модель для того, чтобы отправленные данные могли быть отображены в представлении result , как показано ниже. id представлен в выражении

» />

   Getting Started: Handing Form Submission  

Result

" /> " /> Submit another message

Для наглядности, этот пример использует два отдельных шаблона представления для рендеринга формы и отображения отправленных данных; однако никто вам не мешает использовать одно представление для обеих целей.

Создание приложения исполняемым

Несмотря на то, что пакет этого сервиса может быть в составе web-приложения и WAR файлов, более простой подход, продемонстрированный ниже создает отдельное самостоятельное приложение. Вы упаковываете все в единый, исполняемый JAR-файл, который запускается через хорошо знакомый старый main() Java-метод. Попутно, вы используете поддержку Spring для встроенного Tomcat контейнера сервлетов как HTTP среду выполнения вместо развертывания на сторонний экземпляр.

package hello; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; @ComponentScan @EnableAutoConfiguration public class Application < public static void main(String[] args) < SpringApplication.run(Application.class, args); >>

Метод main() передает управление вспомогательному классу SpringApplication , предоставляя Application.class как аргумент его run() методу. Это говорит Spring о том, чтобы прочитать аннотацию метаданных из Application и управлять им как компонентом в Spring Application Context.

Аннотация @ComponentScan сообщает Spring о запуске рекурсивного поиска в пакете hello и потомках классов, отмеченных прямо или косвенно Spring аннотацией @Component . При этом гарантируется, что Spring найдет и зарегистрирует GreetingController , потому что он отмечен @Controller , что в свою очередь является своего рода @Component аннотацией.

@EnableAutoConfiguration аннотация переключает на доступные по умолчанию настройки, основанные на содержимом вашего classpath. К примеру, т.к. приложение зависит от встраиваемой версии Tomcat(tomcat-embed-core.jar), то Tomcat сервер установлен и настроен по умолчанию от вашего имени. И также, т.к. приложение зависит от Spring MVC (spring-webmvc.jar), Spring MVC DispatcherServlet настроен и зарегистрирован за вас — web.xml не нужен! Автонастройка является мощным и гибким механизмом. Более подробно вы можете ознакомиться в API документации.

Сборка исполняемого JAR

Вы можете собрать единый исполняемый JAR-файл, который содержит все необходимые зависимости, классы и ресурсы. Это делает его легким в загрузке, версионировании и развертывании сервиса как приложения на протяжении всего периода разработки, на различных средах и так далее.

./gradlew build

Затем вы можете запустить JAR-файл:

java -jar build/libs/gs-handling-form-submission-0.1.0.jar

Если вы используете Maven, вы можете запустить приложение, используя mvn spring-boot:run , либо вы можете собрать приложение с mvn clean package и запустить JAR примерно так:

java -jar target/gs-handling-form-submission-0.1.0.jar

Процедура, описанная выше, создает исполняемый JAR. Вы также можете вместо него собрать классический WAR-файл.

Если вы используете Gradle, вы можете запустить ваш сервис из командной строки:

./gradlew clean build && java -jar build/libs/gs-handling-form-submission-0.1.0.jar

Если вы используете Maven, то можете запустить ваш сервис таким образом: mvn clean package && java -jar target/gs-handling-form-submission-0.1.0.jar .

Как вариант, вы можете запустить ваш сервис напрямую из Gradle примерно так:

./gradlew bootRun

С mvn — mvn spring-boot:run .

Выходные данные отображены. Сервис должен быть поднят и запущен через несколько секунд.

Тестирование сервиса

Теперь, когда web сайт запущен, перейдите по адресу http://localhost:8080/greeting, где вы увидите форму:

Отправьте id и message, чтобы посмотреть на результат:

Итог

Поздравляем! Вы только что использовали Spring для создания и отправки формы.

С оригинальным текстом урока вы можете ознакомиться на spring.io.

Добавление записи через POST-запрос в Spring Boot

В статье Работа с БД в Spring Boot на примере postgresql мы узнали как читать данные из БД. Но чтение данных – это лишь малая часть всех операций, которые встречаются в типичном java-приложении. Теперь попробуем создать полноценный rest-интерфейс для добавления новых записей, их модификации и удаления.

За основу возьмём наше приложение из указанной статьи. Оно состоит из трёх слоёв: работа с БД (repository), бизнес-логика приложения (service) и сам rest-интерфейс (controller), который обрабатывает входящий json и генерирует исходящий.

Репозиторий

Начнём с доработки репозитория (интерфейс ProfileRepository), где до сих пор был только один метод чтения данных. Добавим метод вставки записи в БД:

void insertProfile(String firstName, String secondName, int age);

При добавлении новой записи нам достаточно всего три поля. id будет сгенерирован в БД автоматически.

В реализацию интерфейса ProfileRepositoryImpl добавляем sql-запросы в виде констант, которые принято размещать в начале класса:

private static final String SQL_INSERT_PROFILE =
«insert into profile (first_name, last_name, age) values (:firstName, :lastName, :age)» ;

Имена параметров, которые мы будем подставлять в sql-запрос, начинаются с двоеточия.

Вот реализация добавления записи в БД:

@Override
public void insertProfile(String firstName, String lastName, int age) var params = new MapSqlParameterSource();
params.addValue( «firstName» , firstName);
params.addValue( «lastName» , lastName);
params.addValue( «age» , age);
jdbcTemplate.update( SQL_INSERT_PROFILE , params);
>

Всё предельно просто: сначала собираем параметры, затем передаём их вместе с запросом в метод jdbcTemplate.update(), который вопреки своему названию отвечает вообще за любые изменения данных (и insert, и update, и delete). Обратите внимание, что jdbcTemplate у нас имеет тип NamedParameterJdbcTemplate – именно он позволяет использовать именованные параметры. Иначе пришлось бы писать знаки вопроса.

Сервисный слой

Перейдём к сервисному слою. Интерфейс ProfileService не отличается оригинальностью:

void createProfile(String firstName, String secondName, int age);

Его реализация в ProfileServiceImpl. Здесь по сути только вызываем метод репозитория:

@Override
public void createProfile(String firstName, String secondName, int age) profileRepository.insertProfile(firstName, secondName, age);
>

Контроллер

Согласно архитектуре restful-сервисов, чтение данных мы делаем при помощи GET-запросов, а создание – при помощи POST. Также хотелось бы отметить, что у GET-запроса не может быть тела запроса (body), все его параметры перечисляются в строке запроса. А POST-запрос может иметь тело, в которое мы будем помещать целевой json.

Сперва нам нужно добавить в проект ещё одну зависимость spring-boot-starter-validation, которая позволяет валидировать входящие запросы:


org.springframework.boot
spring-boot-starter-validation

Перейдём к нашему контроллеру ProfileController и добавим в него метод создания профиля.

@PostMapping
@ResponseStatus (HttpStatus. CREATED )
public void createProfile( @Valid @RequestBody ProfileRequest request) profileService.createProfile(
request.firstName(),
request.lastName(),
request.age()
);
>

В качестве аргумента метод принимает объект ProfileRequest, реализованный как record-class:

public record ProfileRequest(
@NotNull
String firstName,
@NotNull
String lastName,
@NotNull
@Min ( 1 )
Integer age
) >

Эта модель представляет собой ровно тот объект, который мы ожидаем в теле запроса. Имена полей в json должны совпадать с именами полей в классе (при желании это можно переопределить дополнительной аннотацией). Дополнительно накладываем ограничения из пакета javax.validation.constraints на каждое поле.

Аннотация @NotNull применима для ссылочных типов и означает обязательность этого поля в запросе. Обратите внимание, что тут мы специально используем ссылочный Integer, который допускает null, а не примитивный int, который по умолчанию равен нулю. Ссылочный числовой тип вместе с @NotNull позволяет проверять обязательность числовых типов.

Аннотация @Min говорит сама за себя и ограничивает числовые типы снизу. Тем самым мы никогда не допустим, чтобы нам передали отрицательное число в качестве возраста.

Чтобы эти проверки работали для входящего json, параметр метода надо снабдить аннотацией @Valid, а чтобы именно в этот класс был преобразован входящий json, также добавляем @RequestBody. Внутри просто вызываем сервисный слой.

Аннотация @PostMapping указывает на то, что это обработчик POST-запроса. В скобках можно указать относительный урл, но в данном случае мы его не указали, поэтому запрос надо будет кидать по тому адресу, который указан на уровне контроллера, то есть /profiles. @ResponseStatus показывает, какой http-код нужно вернуть в ответ. В данном случае мы опять следуем rest-соглашениям и возвращаем код 201 – «Created».

Теперь мы готовы к тому, чтобы выполнить rest-запрос на создание новой записи в БД. Запускаем приложение и отравляем указанный POST-запрос по адресу http://127.0.0.1:8080/profiles. В http-заголовках обязательно указываем Content-Type: application/json.

<
«firstName» : «Петр» ,
«lastName» : «Сидоров» ,
«age» : 14
>

В ответ в случае успеха получаем http-статус 201. Если же мы попытаемся нарушить наши ограничения по полям, то получим json с подробным описанием ошибки.

Таким образом, Spring Boot позволяет буквально за 5 минут создать полноценный обработчик POST-запроса с валидацией входящих параметров.

В следующей статье Обновление записи через PUT-запрос в Spring Boot рассмотрим как можно обновлять записи.

REST API с использованием Spring

Spring Framework WebMVC позволяет разрабатывать не только классические веб-приложения, но и реализовывать REST API. В этой статье я опишу процесс разработки REST API простого проекта на Java с использованием Spring Boot и Spring Framework.

О REST и его поддержке в Spring

REST — это архитектурный стиль взаимодействия приложений в сети. Но в отличии от SOAP, у REST отсутствует какой-либо стандарт, а данные между клиентом и сервером могут предаваться в любом виде, будь то JSON, XML, YAML и т.д.

Spring Framework предоставляет богатый набор инструментов, упрощающий разработку REST API: инструменты для маршрутизации запросов, классы-кодеки для преобразования JSON/XML в объекты требуемых типов и т.д.

HTTP-методы

В отличии от классических веб-приложений, в которых используются только методы GET и POST, в REST API используются практически все HTTP-методы, например:

  • GET — для получения объекта или списка объектов
  • HEAD — проверка существования объекта
  • OPTIONS — проверка доступных методов для указанного пути
  • POST — для создания нового объекта
  • PUT — для полного изменения объекта или помещения объекта в список
  • PATCH — для частичного изменения объекта
  • DELETE — для удаления объекта

Стоит помнить, что хорошей практикой является использование GET только для запросов, которые не изменяют состояние объекта. Если запрос должен изменить состояние объекта, то должен использоваться соответствующий HTTP-метод, хотя бы POST.

Для маршрутизации запросов в Spring Framework используется аннотация @RequestMapping с указанием HTTP-метода при помощи свойства method или более простые аннотации вроде
@GetMapping, @PostMapping, @DeleteMapping и т.д.

HTTP-заголовки

Очень важными при разработке REST API являются и HTTP-заголовки. Например, клиент может, указывать MIME-тип содержимого отправляемого запроса при помощи заголовка Content-type или ожидаемый MIME-тип ответа или даже его версию при помощи заголовка Accept.

Возможности Spring Framework WebMVC позволяют маршрутизировать запросы в зависимости не только от их пути или методов, но и в зависимости от заголовков:

Базовый проект

Проект будет реализовывать REST API списка задач. В проекте мы будем использовать Spring Boot, из которого нам понадобятся стартеры:

  • Web — для поддержки веб
  • JDBC — для работы с базой данных
  • H2 — в качестве тестовой базы данных

Код pom.xml приведён ниже:

Поскольку в проекте будет использоваться реляционная база данных, нам потребуется описать SQL-схему таблицы, в которой будут храниться задачи:

Класс, описывающий эту структуру:

REST контроллер

Теперь, когда у нас есть вся необходимая структура, мы можем приступить непосредственно к разработке REST API. Для этого создадим заготовку класса TodoRestController:

  • Контекст приложения создаст и зарегистрирует экземпляр класса, поскольку указана аннотация @RestController. Кроме этого аннотация подсказывает, что возвращаемые методами значения являются телом ответов на запросы. Эта аннотация заменяет собой пару @Controller + @ResponseBody.
  • Аннотация @RequestMapping указывает на маршрутизацию запросов: все запросы, начинающиеся с api/todo будут обрабатываться этим контроллером.
  • Объект типа JdbcOperations будет внедрён через конструктор.

Получение списка задач

Метод получения списка задач должен быть вызван при GET-запросе по пути /api/todo, он должен обратиться к базе данных и вернуть полученный список с HTTP-кодом 200 OK.

  • @GetMapping указывает, что метод getTodoList должен обрабатывать GET-запросы с путём /api/todo. Альтернативно может быть использована аннотация @RequestMapping(method = RequestMethod.GET).
  • При помощи объекта типа ResponseEntity, возвращаемого методом, можно тонко настроить ответ, включая коди заголовки ответа. Фактически можно просто вернуть список задач, не оборачивая его в ResponseEntity.

Получение одной задачи

Метод получения одной задачи по её идентификатору должен быть вызван при GET-запросе по пути /api/todo/ ; он должен обратиться к базе данных и вернуть задачу с HTTP-кодом 200 OK или 404 Not Found, если задачи нет в БД.

  • @GetMapping(«») указывает, что метод getTodo должен обрабатывать GET-запросы с путём /api/todo/ . Фигурные скобки в данном случае указывают, что todoId — переменная пути (Path variable) и может быть использована в аргуметах метода. Можно задать более строгие правила валидации пути, добавив после todoId через двоеточие регулярное выражение, которое будет использоваться для валидации пути.
  • @PathVariable указывает, что значение аргумента todoId должно браться из пути запроса. По умолчанию все значения являются строковыми, но при помощи классов-конвертеров строка преобразуется в объект класса java.util.UUID. Обратите внимание, что имя аргумента соответствует плейсхолдеру, указанному в @GetMapping, в противном случае нам пришлось бы указать плейсхолдер в свойстве name аннотации @PathVariable.
  • Исключение IncorrectResultSizeDataAccessException выбрасывается в случае, если база данных вернула в ответ на запрос количество строк неравное 1. Если актуальное количество строк рано 0, то соответствующая запись в БД отсутствует, и мы можем вернуть ответ с HTTP-кодом 404 Not Found; если строк больше 1, то мы имеем дело с какой-то ошибкой и можем вернуть ответ с HTTP-кодом 500 Internal Server Error.

Создание задачи

Метод создания задачи должен быть вызван при POST-запросе по адресу /api/todo; он должен сохранить в БД полученные данные и вернуть сохранённую задачу в ответ.

  • Аннотация @PostMapping указывает, что данный метод обрабатывает все POST-запросы с путём /api/todo. Свойство consumes задаёт список MIME-типов, которые может обрабатывать данный метод.
  • Аннотация @RequestBody указывает, что отмеченный аргумент является телом запроса. Тело запроса преобразуется в объект нужного класса при помощи конвертеров.
  • Тело запроса автоматически преобразуется в объект типа TodoPayload при помощи класса-кодека.

Изменение задачи

Метод изменения задачи должен быть вызван при PUT-запросе по адресу /api/todo/ ; он должен сохранить изменения в БД и вернуть ответ со статусом 204 No Content, либо вернуть ответ со статусом 404 Not Found, если задача не найдена.

Этот метод может возвращать ответ, содержащий какую-то информацию, например, изменённую задачу, но клиент и так знает о внесённых изменениях.

Удаление задачи

Метод удаления задачи должен быть вызван при DELETE-запросе по адресу /api/todo/ ; он должен удалить задачу из БД и вернуть ответ со статусом 204 No Content, либо вернуть ответ со статусом 404 Not Found, если задача не найдена.

Я рассмотрел в этой статье только базовые моменты разработки REST API при помощи Spring Framework WebMVC. В следующих постах я постараюсь описать тестирование, управление доступом, применение гипермедиа и реактивных API, поскольку все эти темы достаточно объёмны и требуют отдельных статей

Полезные ссылки

  • Исходный код проекта
  • REST
  • Документация Spring Framework

Подготовка к Spring Professional Certification. Spring REST

Сегодняшняя статья рассмотрит основные вопросы про REST в Spring. Она будет особенно полезна для начинающих программистов.

Официальный гид от Pivotal, в котором написано про темы для подготовки.

Оглавление

  1. Внедрение зависимостей, контейнер, IoC, бины
  2. AOP (аспектно-ориентированное программирование)
  3. JDBC, транзакции, JPA, Spring Data
  4. Spring Boot
  5. Spring MVC
  6. Spring Security
  7. REST
  8. Тестирование

Spring REST — это часть Spring MVC. Поэтому многое из Spring MVC будет применяться в REST и наоборот. Для более подробного ознакомления со Spring MVC можно прочитать эту статью.

Для чего был создан REST?

Чтобы понять концепцию REST, нужно разобрать акроним на его составляющие:

  • Representational — ресурсы в REST могут быть представлены в любой форме — JSON, XML, текст, или даже HTML — зависит от того, какие данные больше подходят потребителю
  • State — при работе с REST вы должны быть сконцентрированы на состоянии ресурса, а не на действиях с ресурсом
  • Transfer — REST включает себя передачу ресурсных данных, в любой представленной форме, от одного приложения другому.

REST это передача состояний ресурса между сервером и клиентом.

Что такое ресурс?

Ресурс в REST — это все, что может быть передано между клиентом и сервером.
Вот несколько примеров ресурсов:

  • Новость
  • Температура в Санкт-Петербурге в понедельник в 4 утра
  • Зарплата сотрудника
  • Выборка из базы данных
  • Результат поиска

Что обозначает CRUD?

Действия в REST определяются http-методами.
Get , Post , Put , Delete , Patch , и другие.

Самые часто-используемые обозначаются аббревиатурой CRUD:

  • Create — POST
  • Read — GET
  • Update — PUT
  • Delete — DELETE

REST безопасен? Как вы можете защитить его?

По умолчанию REST не защищен.

Вы можете настроить безопасность с помощью Basic Auth, JWT, OAuth2

Что такое save operations?

Это операции, которые не модифицируют ресурсы. Вот их список:

Что такое идемпотентая операция? Почему идемпотентность важна?

Идемпотентые методы — это методы, при каждом вызове которых результат будет одинаковый.

То есть, результат после 1 вызова такого метода будет такой же, как и результат после 10 вызовов этого метода.

Это важно для отказоустойчевого API. Предположим, что клиент хочет обновить ресурс с помощью POST-запроса? Если POST не идемпотентный метод, то при многократном вызове возникнут непредвиденные обновления ресурса. Используя идемпотентные методы, вы ограждаете себя от многих ошибок.

REST хорошо масштабируется?

Да. REST хорошо масштабируется потому что он не хранит состояние.

Это значит что он не хранит информацию о пользовательских сессиях на сервере.

Информация о клиенте не должна хранится на стороне сервера, а должна передаваться каждый раз туда, где она нужна. Вот что значит ST в REST, State Transfer. Вы передаете состояние, а не храните его на сервере.

REST также интероперабельный — это значит, что на нем могут взаимодействовать разные программы написанные на разных языках. Это исходит из 2ух факторов:

  • Интероперабельные HTTP-клиенты. Разные клиенты должны отправлять одинаковые http-запросы.
  • Интероперабельность на уровне медиа-типов. Различные клиенты должны корректно отправлять и получать одни и те же ресурсы.

Что такое HttpMessageConverter?

HttpMessageConverter конвертирует запрос в объект и наоборот.

Spring имеет несколько реализаций этого интерфейса, а вы можете создать свою.

В этом случае DispatcherServlet не использует Model и View.

В REST вообще не существует Model и View. Есть только данные, поставляемые контроллером, и представление ресурса, когда сообщение конвертируется из медиа-типа(json, xml. ) в объект.

BufferedImageHttpMessageConverter — конвертирует BufferedImage в(из) код изображения.

Jaxb2RootElementHttpMessageConverter — конвертирует xml в(из) объект, помеченный jaxb2 аннотациями. Регистрируется, если jaxb2 находится в classpath.

MappingJackson2HttpMessageConverter — конвертирует JSON в(из) объект. Регистрируется, если Jackson 2 находится в classpath.

StringHttpMessageConverter — конвертирует все медиа-файлы в text/plain.

Как работает аннотация @RestController?

@RestController ставится на класс-контроллер вместо @Controller . Она указывает, что этот класс оперирует не моделями, а данными. Она состоит из аннотаций @Controller и @RequestBody .

@Controller @ResponseBody public interface RestController

Зачем нужна @ResponseBody?

Аннотация @ResponseBody ставится на методы, которые работают с данными, а не с моделями. Ее не требуется указывать явно, если используется @RestController .

Обычные методы возвращают Model , а методы аннотированные @ResponseBody возвращают объекты, которые конвертируются в медиа-файлы с помощью HttpMessageConverter .

Что делает аннотация @RequestMapping?

Эта аннотация служит для маппинга запросов на классы-контроллеры и методы.
Раньше ее использовали для методов класса, чтобы указать URI, http-метод, тип отправляемых данных, и т.п. В более новых версиях Spring ее заменили на аннотации @GetMapping , @PostMapping , и т.п.

Теперь она используется только для указания URI до класса-контроллера.

Что за аннотации @GetMapping, @PostMapping, @DeleteMapping и прочие?

Это более узкие аннотации для маппинга http-методов.

  • @GetMapping — Обрабатывает get-запросы
  • @PostMapping — Обрабатывает post-запросы
  • @DeleteMapping — Обрабатывает delete-запросы
  • @PutMapping — Обрабатывает put-запросы
  • @PatchMapping — Обрабатывает patch-запросы

Все написанное ниже характерно также и для других аннотаций.

Аннотация @GetMapping — это просто аннотация которая содержит @RequestMapping(method = RequestMethod.GET).
Она также позволяет более глубоко настроить метод-обработчик.
Ее параметры(они конвертируются в аналогичные параметры @RequestMapping):

  • path — URI
  • headers — заголовки
  • name — имя обработчика
  • params — параметры
  • produces — тип возвращаемых данных(JSON, XML, текст). Используется в REST
  • consumes — тип принимаемых данных. Используется в REST
    По умолчанию аннотация принимает путь до метода.
    @GetMapping(«managers») = @GetMapping(path = «managers»)

Зачем используется аннотация @RequestParam?

Эта аннотация используется для того, чтобы методы обработчики могли получить параметры из http-запроса.

Запрос с параметрами: http://localhost:8080/getByName/name=Ivan .
Следующий код поместит в переменную name строку Ivan .

@GetMapping("getByName") public User getUserByName(@RequestParam("name") String name) < //some logic >

Зачем нужна аннотация @PathVariable?

Эта аннотация получает определенную часть из URI.

Следующий код поместит в переменную id значение 23 .

@GetMapping("getById/") public User getUserById(@PathVariable("id") String id) < //some logic >

Что обозначают разные коды для http-ответов?

POST — 200 OK, 201 Created, 204 No Content

PUT — 200 OK, 201 Created, 204 No Content

DELETE — 204 No Content, 202 Accepted

Зачем нужна аннотация @ResponseStatus?

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

@PostMapping @ResponseStatus(HttpStatus.CREATED) public void add(. )

Вместо использования аннотации можно возвращать ResponseEntity и вручную устанавливать код ответа.

Не рекомендуется использовать ResponseEntity и @ReponseStatus вместе.

Что такое ResponseEntity?

Это специальный класс, который представляет http-ответ. Он содержит тело ответа, код состояния, заголовки. Мы можем использовать его для более тонкой настройки http-ответа.

Он является универсальным типом, и можно использовать любой объект в качестве тела:

@GetMapping("/hello") ResponseEntity hello()

Зачем нужны @RequestBody?

Вы можете использовать аннотацию @RequestBody на параметре метода, для того чтобы тело запроса конвертировалось в этот параметр.

@PostMapping("accounts") //Например, запрос с JSON конвертируется в объект Account public void handle(@RequestBody Account account)

Вы можете использовать @Validated вместе с @RequestBody , для проверки пришедшего запроса.

Что такое RestTemplate? Какие у него преимущества?

RestTemplate это специальный клиент в Spring для отправки http-запросов. Он предоставляет удобные API для легкого вызова конечных точек REST’а в одну строку.

RestTemplate restTemplate = new RestTemplate(); String fooResourceUrl = "http://localhost:8080/spring-rest/foos"; ResponseEntity response = restTemplate.getForEntity(fooResourceUrl + "/1", String.class);

Более подробно об использовании можно узнать в этой статье.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *