rest controller spring что это

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

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

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

rest controller spring что это. Смотреть фото rest controller spring что это. Смотреть картинку rest controller spring что это. Картинка про rest controller spring что это. Фото rest controller spring что это

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

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

consumes — тип принимаемых данных. Используется в REST

По умолчанию аннотация принимает путь до метода.
@GetMapping(«managers») = @GetMapping(path = «managers»)

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

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

POST — 200 OK, 201 Created, 204 No Content

PUT — 200 OK, 201 Created, 204 No Content

DELETE — 204 No Content, 202 Accepted

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

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

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

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

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

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

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

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

Источник

Построение REST сервисов с помощью Spring

REST быстро стал де-факто стандартом для создания web-сервисов, поскольку таким они легки для создания и обработки.

Существует большое обсуждение о том, как REST вписывается в мир микросервисов, но в этом уроке просто описывается создание RESTful сервисов.

Почему REST? Из REST на практике, заимствуется фраза Martin Flower: «Понятие того, что web является доказательством очень масштабируемой распределенной системы, которая работает действительно хорошо и мы можем брать идеи, исходя из того, чтобы создавать системы более легко.» Я думаю, что это довольно веская причина: REST охватывает указания самого web, его архитектуры и его приемуществ.

Какие преимущества? Главным образом все те, какие несет в себе HTTP как платформа сама по себе. Безопасность приложений(шифрование и аутентификация), для которой известно некоторое количество решений. Кеширование встроено в протокол. Маршрутизация, через DNS, гибкая и хорошо известная система уже поддерживается повсеместно.

REST, несмотря на повсеместность использования, не является стандартом, как таковой, а подходом, стилем, ограниечением HTTP протокола. Его реализация может различаться в стиле, подходе. Для клиента такого API это может быть разочарованием. Качество REST сервисов дико варьируется.

Dr. Leonard Richardson собрал воедино модель, которая объясняет различные уровни соответствующих понятий REST и сортирует их. Она описывает 4 уровня, начиная с level 0. Martin Fowler очень хорошо написал про модель

Начало работы

Spring Boot может работать с любой IDE. Вы можете использовать Eclipse, IntelliJ IDEA, Netbeans и другие. Spring Tool Suite является IDE с открытым исходным кодом, основанной на Eclipse, которая предоставляет расширенные возможности Java EE. Она включает возможности для ещё более простого создания Spring приложений. Но присмотритесь к нему, если вы хотите обрести дополнительное преимущество к вашим ключевым действиям. Ниже представлено видео, которое демонстрирует как начать работу с STS и Spring Boot. Это общая инструкция для ознакомления с инструментами.

В предыдущих сериях.

Мы не будем погружаться в слишком большое количество кода. Мы используем две JPA сущности для моделирования записи в БД. Мы используем стандартную SQL БД для сохранения наших записей, чтобы имелась возможность использовать их как можно большему числу клиентов.

Первый класс моделирует учетную запись пользователя.

Каждый Account может не иметь, либо иметь один или множество Bookmark сущностей. Это связь 1:N. Код сущности Bookmark показан ниже:

Мы будем использовать два Spring Data JPA репозитория для обработки рутинных взаимодействий с БД. Spring Data репозитории как правило являются интерфейсами с методами, поддерживающими чтение, обновление, удаление и создание записей. Некоторые репозитории также поддерживают разделение на страницы и сортировку. Spring Data реализации основанных на соглашении именования методов в интерфейсе. Существует множество реализаций репозиториев, кроме тех двух. Вы можете использовать Spring Data MongoDB, Spring Data GemFire, Spring Data Cassandra и другие.

Ниже представлен репозиторий для работы с Bookmark сущностью:

Мы можем использовать HTTP глаголы для манипуляции данными, представленными по этим URI.

Конечно, некоторые вещи идут не по плану. Скорее всего будет ошибка времени выполнения браузера или сервиса. Мы все получаем раздражающую 404(«Страница не найдена») ошибку, когда пытаемся открыть страницу, которая не существует или ссылка на которую неправильна. 404 является кодом статуса. Она передает информацию о состоянии действия. многие коды статуса разделены различными диапазонами по назначению. Когда вы делаете запрос к web-странице в браузере, он вызывает HTTP GET и если страница отображается, вернется 200 код статуса. 200 означает OK ; вы можете не знать этого, но это так и есть.

Создание REST сервиса

Во первых, REST сервис закладок должен поддерживать выборку и добавление закладок, а также чтение какой-либо конкретной из них. Ниже представлен первоначальный вид нашего REST сервиса:

В Spring MVC это делается простым написанием сервисно-ориентированного кода, в котором фигурирует чистый HttpServlet API. Этот код может быть легко протестирован, расширен через Spring AOP. Мы посмотрим, как протестировать эти Spring MVC компоненты в следующей секции.

Использование HTTP для указания ошибок

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

Для всех тестов указаны application/json content-type и ответы ожидаются такого же типа. Тесты используют метод MockMvcResultMatchers#jsonPath для проверки структуры и содержания JSON ответов, что в свою очередь использует Jayway JSON Path API для запуска обхода с тиле X-Path по JSON структурам, как мы делаем в различных частях unit-тестов.

Создание HATEOAS REST сервиса

Но мы можем сделать лучше. Сервисы остаются соответствовать задачам, но отсутствует. надежность. Как сказано в Википедии: Клиенты должны знать API. Изменения в API отталкивают клиентов и они не обращаются к документации сервиса. Гипермедиа как двигатель состояния приложения(a.k.a. HATEOAS) является ещё одним ограничением, который адресован и удаляет эту нестыковку. Клиенты создают состояния переходов только через действия, которые динамически идентифицируются в гипермедиа сервером.

Улучшенная обработка ошибок с использованием VndErrors

HATEOAS передает клиентам улучшенные метаданные о самом сервисе. Мы можем также улучшить ситуацию обработки ошибок. Коды HTTP статусов 400-499, к примеру, говорят клиенту, что клиент сделал что-то неправильнное, коды 500-599 говорят о чем-то нехорошем на стороне сервера. Если вы знаете ваши коды статусов, то это может быть началом к пониманию, как работать с API. Но мы можем сделать лучше. В конце концов, перед тем, как клиент запустится, кому-то необходимо разработать его и сообщения об ошибках могут быть бесценными для понимания API. Ошибки могут быть обработаны последовательным способом даже лучше!

Обеспечение защиты REST сервиса

До сих пор мы исходили из предположения, что все клиенты надежны и что они должны обладать полным доступом ко всем данным. На самом деле такое редко бывает. Открытое REST API незащищено. Хотя это нетрудно исправить. Spring Security предоставляет фундамент для защиты доступа к приложению. Spring Security необходимо иметь представление о пользователях вашего приложения и их правах. Эти права отвечают на вопрос: что может пользователь приложения видеть или делать?

Авторизация и аутентификация клиента в Open Web с использование Spring Security OAuth

Мы можем выпонить запросы аутентификации клиента бесчисленным количеством способов. Клиенты могут отправлять, к примеру имя пользователя и пароль в каждом HTTP-запросе. Они могут передавать х509 сертификат в каждом запросе. В действительности существует множество подходов, которые могут быть использованы здесь.

Наш API предназначен для работы поверх open-web. Он предназначен для использования всевозможных HTML5 и нативных мобильных и настольных клиентов, которые мы намерены создать. Мы будем использовать разнообразные клиенты с различной степенью защиты и любое решение какое бы мы не выбрали, должно соответствовать этому. Мы должны также отделить имя пользователя и пароль из сессии приложения. В итоге, если сбросить пароль на Twitter, не хочется, чтобы клиенту пришлось повторно аутентифицироваться. С другой стороны, если кто-то угонит его у одного из наших клиентов(к примеру, если пользователь потерял телефон), то мы не хотим, чтобы злоумышленник смог заблокировать нашего пользователя.

В этом примере любой старый клиент может обратиться к Facebook, а по окончании иметь ключ доступа. Этот ключ доступа передается через все последующие REST запросы, наподобие HTTP cookie. Имя пользователи и пароль не нужно будет передавать и клиент может кешировать ключ доступа на определенный или неопределенный период. Пользователям клиента нет необходимости повторно аутентифицироваться каждый раз при открытии приложения. А ещё лучше, ключ доступа определять к каждому клиенту. Это может быть использовано для определения того, что одному клиенту требуется больше разрешений, чем другим. В этом и есть преимущество, состоящее в том, что любая конфиденциальная информация, как имя пользователь и пароль, никогда не будет в открытом виде у ненадежных приложений, которые могут использовать её в злонамеренных целях. Мы можем быть уверены в том, что любой клиент будет дружественным. OAuth поддерживает простейший этап проверки подлинности пользователя( обычно отправляя имя пользователя и пароль) от клиента и сервис возвращает ключ доступа OAuth без необходимости перенаправления на доверенный домен. Этот подход мы и возьмем: результатом будет то, что наши клиенты будут иметь ключ доступа, который отделен от имени пользователя и пароля, и который может быть использован для присвоения различных уровней защиты различным клиентам.

OAuth очень гибок. Вы можете, к примеру, развернуть сервер авторизации, общий для множества REST API. В этом случае, наша OAuth реализация живет рядом с нашим REST API закладок, т.к. они одни и те же. Именно поэтому мы использовали оба @EnableResourceServer и @EnableAuthorizationServer в одном и том же конфигурационном классе.

Вы сказали что-то про Open Web?

Использование HTTPS (SSL/TLS) для предотвращения Man-in-the-Middle атак

Spring Boot предоставляет встроенный web-сервер(Apache Tomcat по умолчанию), который может быть настроен программно делать что-либо, что и отдельный Apache Tomcat web-сервер может делать. Раньше требовалось выполнить несколько нудных шагов для настройки HTTPS (SSL/TLS). Теперь, Spring Boot делает это супер просто. Для начала, создайте следующее:

HTTPS требует подписанный сертификат, который мы предъявляем, используя значения свойств. Для этого мы можем использовать из JDK keytool:

Собираем все вместе

Заключение

REST является наиболее естесственным способом для повсеместного, распределенного взаимодействия с клиентами. Он работает потому что работает HTTP. Когда вы поймете, как REST встраивается в приложение, тогда вам не трудно будет представить архитектуру с многочисленными, отдельновзятыми API, открытыми поверх REST, с балансировкой нагрузки, каким и должен быть любой другой HTTP сервис. Не удивительно, что REST(часто, но не обязательно) образует важнейшую основу для микросервисов, которые рассмотрены на протяжении всего урока.

Источник

Spring MVC: создание веб-сайтов и RESTful сервисов

Вы можете использовать эту статью, чтобы понять, как использовать Spring MVC для создания веб-сайтов или RESTful сервисов. А также получить обзор часто задаваемых вопросов, охватывающих наиболее распространенные задачи Spring MVC.

7500 слов, вероятно, не стоит читать ее на мобильном устройстве. Добавьте ее в закладки и вернитесь позже.

Содержание

Введение

Что такое Spring MVC?

Spring MVC — это веб-фреймворк Spring. Он позволяет создавать веб-сайты или RESTful сервисы (например, JSON/XML) и хорошо интегрируется в экосистему Spring, например, он поддерживает контроллеры и REST контроллеры в ваших Spring Boot приложениях.

Это не очень помогло, не так ли?

К счастью, есть и более длинный ответ: остальная часть этого документа.

(Если вы не уверены, что знаете что такое Spring или Spring Boot, вы можете сначала прочитать, Что такое Spring Framework?)

HttpServlets 101

При написании веб-приложений на Java с использованием Spring или без него (MVC/Boot) вы в основном имеете в виду написание приложений, которые возвращают два разных формата данных:

Как бы вы написали такие приложения без каких-либо фреймворков? Только на простой Java?

На самом низком уровне каждое веб-приложение Java состоит из одного или нескольких HttpServlets. Они генерируют ваш HTML, JSON или XML. Фактически, каждый отдельный фреймворк из 1 миллиона доступных веб-фреймворков на Java (Spring MVC, Wicket, Struts) построена на основе HttpServlets.

(Примечание для придир: это может быть сделано без HttpServlets, но мы пока проигнорируем это.)

Создание HTML-страниц с помощью HttpServlets

Давайте посмотрим на супер простой HttpServlet, который возвращает очень простую статическую HTML-страницу.

Давайте разберемся с этим кодом.

Ваш сервлет расширяет класс Java HttpServlet.

Чтобы обработать (любой) запрос GET, вам необходимо переопределить метод doGet () из суперкласса. Для запросов POST вы должны переопределить doPost (). Аналогично для всех других HTTP методов.

Ваш сервлет должен убедиться, что входящий URL-адрес является запросом, который он знает как обрабатывать. Пока сервлет обрабатывает только «/», то есть он обрабатывает www.marcobehler.com, но НЕ www.marcobehler.com/hello.

Вам нужно установить правильный тип контента в ServletResponse, чтобы браузер знал, какой контент вы отправляете. В данном случае это HTML.

Помните: веб-сайты — это просто строки HTML! Поэтому вам нужно сгенерировать HTML-строку любым удобным вам способом и отправить ее обратно с помощью ServletResponse. Один из способов сделать это с помощью response writer.

После написания вашего сервлета вы должны зарегистрировать его в контейнере сервлетов, таком как Tomcat или Jetty. Если вы используете встроенную версию любого контейнера сервлета, весь код, необходимый для запуска вашего сервлета, будет выглядеть следующим образом:

Давайте разберемся с этим кодом.

Вы настраиваете новый сервер Tomcat, который будет слушать порт 8080.

Так вы регистрируете свой сервлет в Tomcat. Это первая часть, где вы просто сообщаете Tomcat о своем сервлете.

Вторая часть сообщает Tomcat, за какие запросы отвечает сервлет, то есть за отображение. Отображение /* означает, что оно отвечает за любой входящий запрос (/users, /register, /checkout).

Вот и все. Теперь вы запускаете метод main(), переходите на порт 8080 в своем любимом веб-браузере (http://localhost:8080 /), и вы увидите красивую страницу HTML.

Таким образом, по сути, пока вы продолжаете расширять методы doGet () и doPost (), все ваше веб-приложение может состоять только из одного сервлета. Давайте попробуем это.

Создание JSON с помощью HttpServlets

Представьте себе, что помимо вашей (довольно пустой) HTML-страницы индекса вы теперь также хотите предложить REST API для вашего готовящегося к разработке внешнего интерфейса. Так что ваш интерфейс React или AngularJS будет вызывать URL-адрес примерно так:

Эта конечная точка должна возвращать данные в формате JSON для пользователя с заданным userId. Как мы могли бы доработать наш MyServlet для этого, опять же, без каких-либо фреймворков?

Давайте разберемся с этим кодом.

Мы добавляем еще один if в наш метод doGet для обработки вызовов /api/users/.

Мы делаем очень слабый разбор URL. Последняя часть URL — это идентификатор пользователя userID, например, 5 для /api/users/5. Здесь мы просто предполагаем, что пользователь всегда передает действительный int, что нам в действительности нужно проверить!

Запись JSON в браузер означает установку правильного типа контента.

Опять же, JSON — это просто текст, поэтому мы можем записать его непосредственно в HTTPServletResponse. Возможно, мы бы использовали библиотеку JSON для преобразования нашего пользовательского Java-объекта в эту строку, но для простоты я не буду показывать это здесь.

Проблема с нашим подходом «один сервлет для всего»

Хотя наш сервлет выше работает, на горизонте вас ожидает немало проблем:

Довольно много разных обязанностей, не так ли? Разве не было бы лучше, если бы вам не приходилось заботиться обо всем этом стандартом коде? Больше нет парсинга URI запроса и параметров, нет больше преобразований JSON, больше нет ответов сервлета?

Именно здесь на помощь приходит Spring MVC.

DispatcherServlet

Мы расскажем о Spring MVC немного нетрадиционно и не будем подробно останавливаться на том, что означает Model-View-Controller. Вместо этого немного раздразним вас.

Что если я скажу вам, что Spring MVC — это всего лишь один сервлет, как наш выше супер-сервлет?

Встречайте DispatcherServlet.

(О да, в этом, конечно, немного обмана)

Что делает Spring MVC DispatcherServlet?

Как уже упоминалось выше, почти все веб-фреймворки Java основаны на сервлетах, поэтому Spring MVC также нужен сервлет, который обрабатывает каждый входящий HTTP-запрос (поэтому DispatcherServlet также называется фронт-контроллером).

Что же в точности означает обрабатывать HTTP-запрос, точно? Представьте себе «рабочий процесс регистрации пользователя», при котором пользователь заполняет форму и отправляет ее на сервер и в ответ получает небольшую HTML страницу об успешной регистрации.

В этом случае ваш DispatcherServlet должен выполнить следующие действия:

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

rest controller spring что это. Смотреть фото rest controller spring что это. Смотреть картинку rest controller spring что это. Картинка про rest controller spring что это. Фото rest controller spring что это

До сих пор изложение было немного расплывчато в отношении некоторых частей этого процесса. Что такое ModelAndView на рисунке выше? Как именно DispatcherServlet преобразует данные?

Как выглядит реальный процесс Let’s-write-HTML? Об этом узнаем в следующем разделе.

Контроллеры — создание HTML

Всякий раз, когда вы хотите написать HTML на клиенте, таком как браузер с Spring MVC (включая Spring Boot), вы захотите написать класс контроллера. Давайте сделаем это сейчас.

Как написать контроллер в Spring

Для нашего рабочего процесса регистрации пользователей выше (POST/register?name=john&age33) мы бы написали следующий класс.

Давайте разберемся с этим кодом.

Класс контроллера в Spring просто аннотируется аннотацией Controller, ему не нужно реализовывать определенный интерфейс или расширяться из другого класса.

Примечание Наименование нашего метода на самом деле не имеет значения, его можно назвать как угодно.
Однако мы указываем, что каждый запрос должен включать два параметра запроса, которые могут быть либо частью URL (?age=10&name=Joe), либо находиться в теле запроса POST. Кроме того, требуется только параметр name (параметр age является необязательным)

И параметр age, если пользователь предоставил его, автоматически преобразуется в Integer (исключение выдается, если предоставленное значение не является допустимым Integer)

Наконец, что не менее важно, Spring MVC автоматически внедряет параметр model в наш метод контроллера. Эта модель представляет собой простую карту, на которой вам нужно поместить все данные, которые вы хотите отобразить на вашей окончательной HTML-странице, но об этом чуть позже.

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

Вы добавляете своего пользователя в модель с ключом «user». Это означает, что вы сможете ссылаться на него в своем HTML-шаблоне позже, например, «$». Подробнее об этом через секунду.

Ваш метод возвращает простую строку со значением registration-success. Это не просто строка, это ссылка на ваше представление, т.е. шаблон HTML, который вы хотите, чтобы Spring отображал.

Views (представления)

Давайте пока проигнорируем, как (или, скорее, где) Spring MVC попытается найти это представление, т.е. ваш шаблон, вместо этого давайте посмотрим, как должен выглядеть ваш шаблон registration-success.html.

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

Вопрос в том, что означает синтаксис th:text=? Он специфический для Spring? Или это что-то еще?

И ответ таков: Spring MVC ничего не знает о шаблонах HTML. Для работы с HTML-шаблонами требуется сторонняя библиотека шаблонов, и не нужно заботиться о том, какую библиотеку вы выберете.

В приведенном выше примере вы видите шаблон Thymeleaf, который очень популярен при работе над проектами Spring MVC.

Spring MVC и библиотеки шаблонов

Существует несколько различных библиотек шаблонов, которые хорошо интегрируются с Spring MVC, из которых вы можете выбрать: Thymeleaf, Velocity, Freemarker, Mustache и даже JSP (хотя это не библиотека шаблонов).

Фактически, вы должны явно выбрать библиотеку шаблонов, потому что если у вас нет такой библиотеки шаблонов, добавленной в ваш проект и настроенной правильно, то ваш метод контроллера не будет отображать вашу HTML-страницу — потому что он не знает, как это сделать.

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

Что такое ViewResolver?

На секунду давайте подумаем, где Spring на самом деле попытается найти ваши HTML-шаблоны, которые возвращает ваш контроллер.

Класс, который пытается найти ваш шаблон, называется ViewResolver. Поэтому всякий раз, когда запрос поступает в ваш контроллер, Spring проверяет настроенные ViewResolvers и запрашивает их, чтобы найти шаблон с заданным именем. Если у вас нет настроенных ViewResolvers, это не сработает.

Представьте, что вы хотите интегрироваться с Thymeleaf. Следовательно, вам нужен ThymeleafViewResolver.

Давайте разберемся с этим кодом.

В конце концов, ThymeleafViewResolver просто реализует интерфейс Spring ViewResolver. Учитывая имя шаблона (помните: registration-success), ViewResolvers может найти фактический шаблон.

Для правильной работы ThymeleafViewResolver требуется несколько других специфичных для Thymeleaf классов. Одним из этих классов является SpringResourceTemplateResolver. Это делает фактическую работу по поиску вашего шаблона.

Примечание SpringResourceTemplateResolver является классом Thymeleaf

Всякий раз, когда наш контроллер возвращает String, подобный registration-success, ThymeleafViewResolver будет искать шаблон: classpath:/templates/registration-success.html.

Заметка на полях: Spring Boot

Вы можете подумать: Марко, мне никогда не приходилось настраивать такой ViewResolver, работая над проектами Spring Boot. И это правильно. Потому что Spring Boot автоматически настраивает его для вас каждый раз, когда вы добавляете в свой проект зависимость, такую как spring-boot-starter-thymeleaf.

Он также настраивает ViewResolver так, чтобы он по умолчанию просматривал ваш каталог src/main/resources/template.

Итак, Spring Boot действительно предварительно настраивает Spring MVC для вас. Запомните.

Резюме: Model-View-Controller

Посмотрев полный пример Controller & ViewResolver, становится намного проще говорить о концепции Spring Model-View-Controller.

Это все о разделении ответственностей.

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

Подробнее о контроллерах

Мы уже видели небольшое удобство, которое предоставляет нам Spring MVC при обработке входов HTTP.

Давайте рассмотрим наиболее распространенные аннотации, которые помогут вам обрабатывать входящие HTTP-запросы.

@GetMapping и @RequestMappping

@GetMapping, @[Post|Put|Delete|Patch]Mapping эквивалентно @RequestMapping(method=XXX). Это просто более новый способ (Spring 4.3+) для определения мапинга (связывания) с URL, поэтому вы найдете, что аннотация @RequestMapping часто используется в более старых, унаследованных проектах Spring.

@RequestParam

Для параметров HTTP-запроса, будь то в вашем URL (?Key=value) или в отправленном теле запроса формы, можно прочитать с помощью аннотации @RequestParam.

Вы уже видели, что он выполняет базовое преобразование типов (например, из параметра HTTP String в int), а также проверяет обязательные или дополнительные параметры.

Если вы забудете указать в запросе обязательный параметр, вы получите код ответа 400 Bad Request и, при использовании Spring Boot, объект ошибки по умолчанию, который выглядит следующим образом:

Если вы хотите еще большего удобства, вы можете позволить Spring напрямую преобразовывать все @RequestParams в объект без каких-либо необходимых аннотаций. Просто укажите ваш объект как «параметр метода«.

Вам просто нужно убедиться, что у вашего класса есть соответствующие методы getter/setter.

@PathVariable

Помимо параметров запроса, другим популярным способом указания переменных является непосредственное задание их в URI запроса, как @PathVariable. Поэтому, чтобы получить профиль пользователя с userId=123, вы должны вызвать следующий URL: GET / users/123

Кроме того, PathVariables также может быть обязательным или необязательным.

И PathVariables, конечно, может быть напрямую преобразованы в Java-объект (при условии, что у объекта есть соответствующие методы getter/setter).

Резюме: Контроллеры

Короче говоря, при написании HTML-страниц с помощью Spring MVC вам придется сделать всего несколько вещей:

REST контроллеры — создание XML/JSON

Когда вы разрабатываете RESTFul сервисы, все немного по-другому. Ваш клиент, будь то браузер или другой веб-сервис, будет (обычно) создавать запросы JSON или XML. Клиент отправляет, скажем, запрос JSON, вы обрабатываете его, а затем отправитель ожидает возврата JSON.

Таким образом, отправитель может отправить вам этот фрагмент JSON как часть тела HTTP-запроса.

Но на стороне Java (в вашей программе Spring MVC) вы не хотите иметь дело с JSON строками. Ни при получении запросов, как указано выше, ни при отправке ответов обратно клиенту. Вместо этого вы хотели бы просто иметь объекты Java, в которые Spring автоматически конвертирует JSON.

Это также означает, что вам не нужна вся эта обработка модели и представления, которые вам приходилось делать при рендеринге HTML в ваших контроллерах. Для RESTful сервисов у вас нет библиотеки шаблонов, читающей шаблон HTML и заполняющей его данными модели, чтобы сгенерировать для вас ответ JSON.

Вместо этого вы хотите перейти непосредственно из HTTP запросJava объект и из Java объектHTTP ответ.

Как вы уже догадались, это именно то, что Spring MVC обеспечивает при написании REST контроллера.

Как написать REST контроллер

Первое, что вам нужно сделать для вывода XML/JSON, это написать аннотацию @RestController вместо Controller. (Хотя @RestController является Controller, см. FAQ для точной разницы).

Если бы мы написали REST-контроллер для банка, который возвращает список транзакций пользователя, он мог бы выглядеть примерно так:

Давайте разберемся с этим кодом.

Вы снабдили класс BankController аннотацией @RestController, которая сообщает Spring, что вы не хотите писать HTML-страницы через обычный процесс ModelAndView. Вместо этого вы хотите записать XML/JSON (или какой-либо другой формат) непосредственно в тело ответа HTTP.

Ваш контроллер больше не возвращает String (представление). Вместо этого он возвращает List, который Spring необходимо преобразовать в соответствующую структуру JSON или XML. По сути, вы хотите, чтобы ваши Java объекты Transaction стали такими (кто-то жаждал фаст-фуд очень рано утром):

Но как Spring MVC узнает, что ваш список транзакций должен быть преобразован в JSON? Почему не XML? Или YAML? Как ваш метод REST контроллер знает, каким должен быть предполагаемый формат ответа?

Для этого у Spring есть концепция согласования контента.

Согласование контента ответа — Accept Header

Короче говоря, согласование контента означает, что клиент должен сообщить вашему серверу, какой формат ответа он хочет получить от вашего REST контроллера.

Как? Указав заголовок Accept в HTTP-запросе.

Spring MVC разберет этот заголовок Accept и узнает: клиент хочет вернуть JSON (application/json), поэтому мне нужно преобразовать мой List в JSON. (Краткое примечание. Существуют и другие способы согласования содержимого, но заголовок Accept используется по умолчанию.)

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

Но согласование контента также работает для входящих запросов. Посмотрим как.

Согласование контента запроса — Content-Type Header (заголовок типа контента)

При создании RESTful API очень высока вероятность того, что ваши клиенты также смогут отправлять запросы в формате JSON или XML. Давайте снова возьмем пример из начала главы, где вы предлагаете конечную точку REST для регистрации новых пользователей:

Как Spring узнает, что тело запроса выше содержит JSON, а не XML или YAML? Возможно, вы догадались, вам нужно добавить еще один заголовок, на этот раз это заголовок Content-Type.

Как будет выглядеть соответствующий REST контроллер для этого запроса?

Давайте разберемся с этим кодом.

Подобно @RequestParam или @Pathvariable, вам понадобится другая аннотация, называемая @RequestBody.

@RequestBody в сочетании с правильным Content-Type будет сигнализировать Spring о том, что ему необходимо просмотреть тело HTTP-запроса и преобразовать его в любой Content-Type, указанный пользователем: JSON в нашем случае.

Тогда вашему методу больше не нужно заботиться об необработанной строке JSON, он может просто работать с TransactionDTO, сохранять его в базе данных, преобразовывать в объект Transaction, что угодно. В этом сила Spring MVC.

Сам Spring не может конвертировать форматы данных

Есть только одна небольшая проблема: Spring знает о заголовках Accept и Content-Type, но не знает, как конвертировать между объектами Java и JSON. Или XML. Или ЯМЛ.

Для этой грязной работы требуется соответствующая сторонняя библиотека (также называемая маршалинг / демаршаллинг или сериализация / десериализация.)

А классы, которые интегрируются между Spring MVC и этими сторонними библиотеками, называются HttpMessageConverters.

Что такое HttpMessageConverter?

HttpMessageConverter — это интерфейс с четырьмя методами (обратите внимание, я немного упростил интерфейс для более простого объяснения, так как он выглядит немного более продвинутым в реальной жизни).

Короче говоря, MessageConverter должен знать, какие MediaTypes он поддерживает (например, application/json), а затем должен реализовать два метода для фактического чтения / записи в этом формате данных.

Какие есть HttpMessageConverters?

К счастью, вам не нужно писать эти конвертеры сообщений самостоятельно. Spring MVC поставляется с классом, который автоматически регистрирует пару стандартных HTTPMessageConverters для вас — если у вас есть соответствующие сторонние библиотеки в пути к классам.

Если вы не знаете об этом, это будет выглядеть как магия. В любом случае, взгляните на Spring AllEncompassingFormHttpMessageConverter (мне нравится это имя).

Давайте разберемся с этим кодом.

Spring MVC проверяет наличие класса javax.xml.bind.Binder и, если он есть, предполагает, что вы добавили в свой проект необходимую библиотеку для выполнения преобразований JAXB.

Spring MVC проверяет наличие двух классов ..jackson..ObjectMapper и ..jackson..JsonGenerator и, если это так, предполагает, что вы добавили библиотеку Jackson в свой проект для выполнения преобразований JSON.

Spring MVC проверяет наличие класса ..jackson..XmlMapper и, если это так, предполагает, что вы добавили поддержку XML библиотеки Jackson s в свой проект для выполнения преобразований XML.

И так далее. И через пару строк Spring просто добавляет HttpMessageConverter для каждой библиотеки, которую он «обнаружил».

Заметка на полях: Spring Boot

При создании проектов Spring Boot вы автоматически будете использовать Spring MVC под капотом. Но Spring Boot также вызывает Jackson по умолчанию.

Вот почему вы можете сразу написать конечные точки JSON с помощью Spring Boot, потому что необходимые HttpMessageConverts будут добавлены автоматически для вас.

Резюме: REST контроллеры

По сравнению с HTML использование JSON / XML немного проще, так как вам не нужен рендеринг Model и View.

Вместо этого ваши контроллеры напрямую возвращают объекты Java, которые Spring MVC будет удобно сериализовать в JSON / XML или любой другой формат, который пользователь запросил с помощью HttpMessageConverters.

Однако вы должны убедиться в двух вещах, однако:

Часто задаваемые вопросы

Вы где-нибудь публиковали исходный код этой статьи?

Вы можете найти рабочий исходный код для большей части этой статьи в следующем репозитории GitHub:
https://github.com/marcobehler/spring-mvc-article

Просто клонируйте проект и запустите класс SpringMvcArticleApplication, чтобы запустить веб-приложение.

В чем разница между Spring MVC и Spring Boot?

Вкратце: нет никакой разницы, Spring Boot использует и строит приложение поверх Spring MVC.

Для более подробного объяснения вам нужно сначала прочитать статью Что такое Spring Framework?.

Какой самый быстрый способ создать новое приложение Spring MVC?

Если вы хотите упростить использование Spring MVC, самым быстрым способом будет создание нового Spring Boot проекта.

Это позволит вам создавать веб / RESTful-приложения с помощью Spring MVC.

Какой тип ввода HTTP-запроса понимает Spring MVC?

Spring MVC понимает практически все, что предлагает HTTP — с помощью сторонних библиотек.

Это означает, что вы можете добавить в него тела запросов JSON, XML или HTTP (Multipart) Fileuploads, и Spring будет удобно конвертировать этот ввод в объекты Java.

Какие HTTP-ответы может создавать Spring MVC?

Spring MVC может записывать все что угодно в HttpServletResponse — с помощью сторонних библиотек.

Будь то HTML, JSON, XML или даже тела ответов WebSocket. Более того, он берет ваши объекты Java и генерирует эти тела ответов для вас.

В чем разница между контроллером и REST контроллером

Примечание. XML и JSON — это просто самые популярные форматы данных, которые вы будете использовать в приложении Spring MVC. Однако ваши контроллеры / REST контроллеры могут возвращать что-либо еще, например, YAML. Вам нужно только убедиться, что правильный HttpMessageConverter зарегистрирован в вашем ApplicationContext.

Какую библиотеку шаблонов мне выбрать?

На протяжении многих лет я лично работал почти со всеми библиотеками шаблонов, и, хотя есть определенное стимулирование к использованию Thymeleaf в проектах Spring, у меня нет сильных предпочтений. Итак, либо воспользуйтесь Thymeleaf (если у вас нет опыта работы с другими системами), либо выберите тот, который вам наиболее удобен.

Почему мой контроллер выводит 404? Все мапинги верны.

Относительно распространенной ошибкой является то, что контроллер возвращает объекты, которые вы хотите преобразовать в JSON или XML, но вам не хватает аннотации @ResponseBody.

Spring возвратит довольно бессмысленное исключение 404 Not Found в этом случае.

Исправление: добавьте @ResponseBody или превратите ваш контроллер в REST контроллер.

Что произойдет, если вы определите один и тот же мапинг запросов для двух разных методов?

Если эти два метода имеют разные HTTP методы, это не будет проблемой.

Однако если вы сопоставите однотипные HTTP методы с одним и тем же путем, у вас возникнет проблема.

При запуске приложения это приведет к исключению IllegalStateException, что намекает на ваше неоднозначное отображение.

Нужно ли в URL кодировать @RequestParams?

Да, потому что Spring автоматически декодирует их из URL. Распространенная ошибка:

Представьте, что ваше приложение отправляет электронные письма с подтверждением всякий раз, когда новый пользователь регистрируется, и пользователь указывает знак «+» на своем адресе электронной почты, например, marco+wantsnospam@marcobehler.com.

Если вы забыли правильно закодировать знак ‘+’ в URL в своем письме-подтверждении и отправляете строку как есть на свой контроллер, какое значение будет содержать электронная почта @RequestParam?

Это будет «marco[space]wantnospam@marcobehler.com», так как Spring заменит + пробелом, что является правильной обработкой RFC3986.

Исправление: Убедитесь, что URL-адреса, которые вы вводите в свое приложение, правильно закодированы: marco%2Bwantsnospam@marcobehler.com, так как Spring будет автоматически их декодировать.

Как получить доступ к текущей HttpSession пользователя?

В Spring MVC контроллере или REST контроллере вы можете просто указать HttpSession в качестве аргумента метода, и Spring автоматически вставит его (создав его, если он еще не существует).

Вы не можете сделать это со произвольными компонентами или сервисами, но вы все равно можете внедрить HttpSession в них.

Как получить доступ к HttpServletRequest?

В вашем Spring MVC контроллере или REST контроллере вы можете просто указать HttpServletRequest в качестве аргумента метода, и Spring автоматически вставит его (создавая, если он еще не существует)

Вы не можете сделать это с произвольными компонентами или сервисами, но вы все еще можете внедрить HttpServletRequest в них.

Как читать HTTP заголовки?

Существует множество способов получить доступ к заголовкам запросов, в зависимости от того, хотите ли вы только один или карту со всеми из них. В любом случае вам нужно аннотировать их с помощью @RequestHeader.

Какую бы версию вы ни выбрали, постарайтесь быть последовательным с вашим выбором.

Как читать и писать cookie?

Для чтения файлов cookie вы можете использовать аннотацию @CookieValue в своих контроллерах. Вы должны будете писать cookie прямо в HttpServletResponse.

Как получить IP-адрес пользователя?

Это вопрос с подвохом. Существует метод с именем httpServletRequest.getRemoteAddr(), который, однако, возвращает только IP-адрес пользователя или последнего прокси-сервера, отправившего запрос, в 99,99% случаев это ваш Nginx или Apache.

Следовательно, вам нужно проанализировать заголовок X-Forwarded-For для получения правильного IP-адреса. Но что произойдет, если ваше приложение, кроме того, будет работать за CDN, например CloudFront? Тогда ваш X-Forwarded-For будет выглядеть так:

Проблема в том, что вы не можете прочитать заголовок слева направо, поскольку пользователи могут предоставить и, следовательно, подделать свой собственный заголовок X-Forwarded-For. Вам всегда нужно идти справа налево и исключать все известные IP-адреса. В случае CloudFront это означает, что вам необходимо знать диапазоны IP-адресов CloudFront и удалить их из заголовка. Ага!

Это приводит к довольно сложному коду, разрешающему IP. Угадайте, сколько проектов сделали это неправильно!

Как вы можете управлять загрузкой файлов в приложении Spring MVC?

Предположим, что у вас есть правильная форма загрузки HTML-файла, которая выглядит примерно так:

Вам просто нужен контроллер с аннотацией @PostMapping и соответствующим параметром MultiPartFile, который содержит ваши данные для загрузки и удобные методы для сохранения файла на вашем диске.

Как обрабатывать загрузку бинарных файлов (xls, pdf, csv, jpg, zip) с помощью Spring контроллеров?

Есть множество способов заставить это работать, от записи непосредственно в HttpServletResponse или возвращения массива byte[] в результате.

Тем не менее, самая Spring-и и гибкая версия заключается в возврате ‘ResponseEntity ‘. В зависимости от того, где вы сохранили файл, вы будете использовать различные ресурсы.

Все, что осталось сделать, это установить соответствующие HTTP-заголовки ответа (имя файла, тип контента и т.д.).

Как я могу глобально обрабатывать исключения в моих контроллерах?

В Spring MVC есть несколько способов обработки исключений, если вы не хотите обрабатывать их непосредственно в своих контроллерах, а в одном центральном месте.

Создайте класс ControllerAdvice или RestControllerAdvice в сочетании с аннотациями @ResponseStatus и @ExceptionHandler. Несолько замечаний:

Как вернуть любой код состояния (400, 404 и т.д.) из ваших контроллеров?

Создайте исключение ResponseStatusException с соответствующим кодом состояния и, возможно, причиной.

Альтернативой будет возвращение объекта ResponseEntity, но в большинстве случаев исключение лучше.

Как насчет концепции XYZ в Spring MVC?

Официальная документация Spring MVC буквально содержит сотни страниц, описывающих, как работает веб-фреймворк.

Поэтому, если вы хотите узнать больше о моделях, представлениях, ViewHandlers, InitBinders, RootContexts, фильтрах, кэшировании и т.д., я предлагаю вам прочитать документацию Spring MVC. Это просто выходит за рамки данного руководства, невозможно охватить это все.

Заключение

Это была хорошая прогулка. Наконец я надеюсь, что вы узнали множество вещей из этой статьи:

Вот и все на сегодня. Спасибо за чтение.

Благодарности

Большое спасибо Patricio «Pato» Moschcovich, который не только выполнил корректуру этой статьи, но и дал бесценный отзыв!

Источник

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

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