Сегодняшняя статья рассмотрит основные вопросы про 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?

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


  • GET
  • HEAD
  • OPTIONS

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

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


То есть, результат после 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.


URI: http://localhost:8080/getById/23


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


@GetMapping("getById/{id}") public User getUserById(@PathVariable("id") String id) {     //some logic 
}

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

GET — 200 OK


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() {
    return new ResponseEntity("Hello World!", HttpStatus.OK);
}

Зачем нужны @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);

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

Комментарии (4)


  1. Mishiko
    11.10.2019 15:36

    Вопрос — где можно сдать сабж?
    Как я понял, нужен авторизованный центр PSI, но в РФ из таких вроде только в Питере: Центр сертификации Tune IT. Принимают ли там такой экзамен? Может есть что то в Москве?


    1. Anton23 Автор
      13.10.2019 18:17

      habr.com/ru/post/471140/#comment_20748938

      Думаю, раз есть в Питере то есть и в Москве.


  1. MonkeyClicker
    13.10.2019 18:15

    У автора большое количество статей по сертификации Spring. Было бы замечательно если бы автор поделился личным опытом сдачи экзамена. Очень интересует организационные моменты, это очень слабо раскрыто или не раскрыто вовсе, т.е. в какая компания организует экзамен, номера экзаменов, какими тренажерами пользовался для подготовки. По Java этой информации в разы больше и есть достаточно много компаний в которых можно сдать сертификационный экзамен.


    1. Anton23 Автор
      13.10.2019 18:17

      Это перевод, автор не я. Экзамен я не сдавал. Тренажеры обычно платные. Есть хорошая статья на эту тему.

      По поводу сдачи в россии — советую написать на почту Pivotal. До 2017 года это точно можно было сделать, как сейчас — не знаю.