Занятие №8

Spring MVC. Rest API

Михаил

Павлов

План занятия

  • Задача - сделать приложение для отображения списка вопросов
  • Теория шаблона MVC
  • Описание HTTP и REST
  • Tomcat
  • Разбираем пример приложения
  • Аннотации Spring Web
  • Полезные ссылки

На прошлом занятии вы узнали о том, как работать с консолью

shell:>joke
Chuck Norris hosting is 101% uptime guaranteed.
shell:>joke
Product Owners never ask Chuck Norris for more features.
They ask for mercy.

Консоль - хорошо,

а интерфейс еще лучше!

Давайте сделаем приложение с интерфейсом!

Задача:

Сделать веб-приложение со списком вопросов

Требования:

  • Отображать список вопросов
  • Поиск вопросов по подстроке
  • Фильтрация по количеству доступных ответов (*)
  • Постраничная навигация (*)

(*) - Опционально

Для решения этой задачи хорошо подходит шаблон -

MVC

Отделить бизнес-логику от ее визуализации

MVC (Model - View - Controller)

Паттерн MVC

Вернемся к нашей задаче

Задача:

Сделать веб-приложение со списком вопросов

Варианты решения задачи

1. Создавать страницы на сервере (шаблонизатор)

 

2. Отдельное SPA, с которым можно работать через REST

Язык общения для веб-приложений -

HTTP

Всё начинается с адреса - URL

http://my-site.ru/folder/index.html

Протокол

Доменное имя

Путь

По определенному URL отправляется HTTP-запрос

GET /security/auth HTTP/1.1
Host: www.my-site.ru
Accept-Language: en-us

Метод

Путь

Версия протокола

Заголовки

* Для некоторых типов запросов есть еще тело (Body)

HTTP

Метод Описание
GET Получить данные объекта
PUT Изменить / обновить объект
POST Создать объект
DELETE Удалить объект

Протокол взаимодействия приложений

(HyperText Transfer Protocol)

Основные методы:

Подробнее об адресации в Интернет можно узнать в нашей прошлогодней лекции из курса по Angular

REST + HTTP =

Что же такое REST?

REST

(Representational State Transfer)

Набор договоренностей о взаимодействии

Ключевые моменты:

  • Модель Клиент-Сервер
  • Отсутствие состояния (stateless)
  • Кэширование

Примеры Rest-запросов

Метод Описание
GET /books/ получить список всех книг
GET /books/3/ получить книгу номер 3
POST /books/ добавить книгу (данные в теле запроса)
PUT /books/3 изменить книгу номер 3 (данные в теле запроса)
DELETE /book/3 удалить книгу номер 3

Спецификация HTTP (RFC 2616)

Содержит 176 страниц

176 страниц, Карл!

Пусть эту спецификацию реализует кто-нибудь другой

Например Tomcat

Какой-нибудь веб-сервер

Tomcat

  • Принимает http-запросы от клиента и передает их нашему приложению
  • Возвращает http-ответы клиенту

Веб-сервер (open-source)

*Продуктовый сервер энтерпрайз уровня

Хватит теории

Практика

  • Скачать и установить nodeJS
  • Выкачать репозиторий по ссылке (папка unit-8)
  • Перед первым запуском клиента выполнить команду npm i
  • Запускаем клиент через консоль в папке app-client
    • ng serve
  • Запускаем сервер через консоль в папке app-server  (или через Идею)
    • gradlew bootRun

Практика

Клиент использует 2 http-запроса:

  • Получение метаданных журнала

  • Получение строк журнала

Сейчас на клиенте есть только один журнал:

- Вопросы (id = questions)

Получение метаданных журнала

Тип метода: GET

URL: http://localhost:8080/api/journal/<строка с id журнала>

Пример: http://localhost:8080/api/journal/questions

Ожидаемый ответ:

Пример ответа (JSON):

{
  id: string;
  name: string;
  defaultPageSize?: number;
}
{ 
  "id": "questions",
  "name": "Вопросы",
  "defaultPageSize": 15 
}

Получение строк журнала

Тип метода: PUT

URL: http://localhost:8080/api/journal/<строка с id журнала>/rows

Пример: http://localhost:8080/api/journal/questions/rows

Тело запроса:

Пример тела запроса (JSON):

{ journalId: string;
  search: string;
  filters: JournalFilterItem[];
  page: number;
  pageSize: number; }
{ type: string;
  code: string;
  value: string; }

JournalFilterItem:

{ "journalId": "questions",
  "search": "someText",
  "filters": [{
    "code": "question-answer-count",
    "type": "single-select",
    "value": 2
    }],
  "page": 1,
  "pageSize": 15 }

Получение строк журнала

Ожидаемые ответ:

Пример тела ответа (JSON):

{
  total: number;
  items:
  [{ 
    id: string;
    name: string;
    answersCount: number; 
  }]
}
{
  "total" : 2,
  "items":
  [{ 
    "id": 1,
    "name": "Вопрос 1",
    "answersCount": 4 
  }, {
    "id": 2,
    "name": "Вопрос 2",
    "answersCount": 3 
  }] 
}

Давайте покотдим

А теперь разберем, как это работает

MVC в приложении

Client

Application

Request (HTTP)

Dispatcher Servlet

Handler Mapping

Response (HTTP)

REST controller

Database

Service (BL)

Поиск нужного контроллера

Ответ

Tomcat

Аннотации класса

  • @RestController - основная аннотация для рест-класса, сама добавляет аннотацию @Controller и несколько специфических аннотаций для работы с Rest
  • @RequestMapping("api/journal") - определяет URL, для которого будет вызван данный контроллер
@RestController
@RequestMapping("api/journal")
public class JournalRestController {
	...
}
  1. http://localhost:8080/api/journal/questions
  2. http://localhost:8080/api/journal/questions/rows

Аннотации метода

  • @GetMapping("{id}") - определяет URL, для которого будет вызван метод (только http-запросы GET)
  • @PutMapping("{id}/rows") - только http-запросы PUT

и др. http-методы

@GetMapping("{id}")
public JournalEntityDTO getJournalEntity(@PathVariable String id) {
	return journals.get(0);
}

@PutMapping("{id}/rows")
public JournalResultDTO getRows(
	@PathVariable String id, @RequestBody JournalRequestDTO dto) {
	return new JournalResultDTO(questions);
}
  1. http://localhost:8080/api/journal/questions
  2. http://localhost:8080/api/journal/questions/rows

Аннотации параметров метода

  • @PathVariable - берет определенное значение из URL
  • @RequestParam - берет одно значение из параметров запроса
  • @RequestBody - берет содержимое тела запроса
@PutMapping("{id}/rows")
public JournalResultDTO getRows(
	@PathVariable String id, 
	@RequestParam(required = false, name = "q") String queryString,
	@RequestBody JournalRequestDTO dto
    ) {
	return new JournalResultDTO(questions);
}

http://localhost:8080/api/journal/questions/rows?q=someText

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

Вопросы

Спасибо за внимание!

Made with Slides.com