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

Краткое руководство по контроллерам Spring

· 6 мин. чтения

1. Введение

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

2. Обзор

Давайте начнем с того, что сделаем шаг назад и посмотрим на концепцию Front Controller в типичной архитектуре Spring Model View Controller .

На очень высоком уровне, вот основные обязанности, которые мы рассматриваем:

  • Перехватывает входящие запросы
  • Преобразует полезную нагрузку запроса во внутреннюю структуру данных
  • Отправляет данные в модель для дальнейшей обработки
  • Получает обработанные данные из модели и передает эти данные в представление для рендеринга .

Вот краткая диаграмма потока высокого уровня в Spring MVC :

./df2109843c7ce722d7eebaba356dff9c.png

Как видите, DispatcherServlet играет роль Front Controller в архитектуре.

Диаграмма применима как к типичным контроллерам MVC, так и к контроллерам RESTful — с некоторыми небольшими отличиями (описанными ниже).

В традиционном подходе приложения MVC не ориентированы на сервисы, поэтому существует View Resolver , который отображает окончательные представления на основе данных, полученных от контроллера .

Приложения RESTful спроектированы так, чтобы быть сервис-ориентированными и возвращать необработанные данные (обычно JSON/XML). Поскольку эти приложения не выполняют никакого рендеринга представлений, нет никаких преобразователей представлений — обычно ожидается, что контроллер будет отправлять данные напрямую через HTTP-ответ.

Начнем с контроллеров в стиле MVC0.

3. Зависимости Maven

Чтобы иметь возможность работать с Spring MVC , давайте сначала разберемся с зависимостями Maven:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.6.RELEASE</version>
<dependency>

Чтобы получить последнюю версию библиотеки, взгляните на spring-webmvc на Maven Central .

4. Веб-конфигурация проекта

Теперь, прежде чем рассматривать сами контроллеры, нам сначала нужно настроить простой веб-проект и выполнить быструю настройку сервлета .

Давайте сначала посмотрим, как можно настроить DispatcherServlet без использования web.xml , а вместо этого с помощью инициализатора:

public class StudentControllerConfig implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext sc) throws ServletException {
AnnotationConfigWebApplicationContext root =
new AnnotationConfigWebApplicationContext();
root.register(WebConfig.class);

root.refresh();
root.setServletContext(sc);

sc.addListener(new ContextLoaderListener(root));

DispatcherServlet dv =
new DispatcherServlet(new GenericWebApplicationContext());

ServletRegistration.Dynamic appServlet = sc.addServlet("test-mvc", dv);
appServlet.setLoadOnStartup(1);
appServlet.addMapping("/test/*");
}
}

Чтобы настроить без XML, убедитесь, что в вашем пути к классам есть servlet-api 3.1.0.

Вот как будет выглядеть файл web.xml :

<servlet>
<servlet-name>test-mvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/test-mvc.xml</param-value>
</init-param>
</servlet>

Здесь мы устанавливаем свойство contextConfigLocation , указывающее на файл XML , используемый для загрузки контекста Spring. Если свойства нет, Spring будет искать файл с именем {servlet_name}-servlet.xml .

В нашем случае servlet_name — это test-mvc , поэтому в этом примере DispatcherServlet будет искать файл с именем test-mvc-servlet.xml .

Наконец, давайте настроим DispatcherServlet и сопоставим его с определенным URL -адресом — чтобы закончить нашу систему на основе Front Controller :

<servlet-mapping>
<servlet-name>test-mvc</servlet-name>
<url-pattern>/test/*</url-pattern>
</servlet-mapping>

Таким образом, в этом случае DispatcherServlet будет перехватывать все запросы в шаблоне /test/* .

5. Веб-конфигурация Spring MVC

Давайте теперь посмотрим, как можно настроить Dispatcher Servlet с помощью Spring Config :

@Configuration
@EnableWebMvc
@ComponentScan(basePackages= {
"com.foreach.controller.controller",
"com.foreach.controller.config" })
public class WebConfig implements WebMvcConfigurer {

@Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}

@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver bean =
new InternalResourceViewResolver();
bean.setPrefix("/WEB-INF/");
bean.setSuffix(".jsp");
return bean;
}
}

Теперь давайте рассмотрим настройку Dispatcher Servlet с помощью XML . Снимок XML-файла DispatcherServletXML - файл, который DispatcherServlet использует для загрузки пользовательских контроллеров и других объектов Spring , показан ниже: ``

<context:component-scan base-package="com.baledung.controller" />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>

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

Обратите внимание, что мы также определяем View Resolver, отвечающий за визуализацию представлений — здесь мы будем использовать Spring InternalResourceViewResolver . Это предполагает, что имя представления будет разрешено, что означает поиск соответствующей страницы с использованием префикса и суффикса (оба определены в конфигурации XML ).

Так, например, если контроллер возвращает представление с именем « welcome» , распознаватель представлений попытается разрешить страницу с именем «welcome.jsp» в папке WEB -INF . ``

6. Контроллер MVC

Теперь давайте, наконец, реализуем контроллер в стиле MVC.

Обратите внимание, как мы возвращаем объект ModelAndView , который содержит карту модели и объект представления ; оба будут использоваться View Resolver для рендеринга данных:

@Controller
@RequestMapping(value = "/test")
public class TestController {

@GetMapping
public ModelAndView getTestData() {
ModelAndView mv = new ModelAndView();
mv.setViewName("welcome");
mv.getModel().put("data", "Welcome home man");

return mv;
}
}

Итак, что именно мы здесь установили.

Во-первых, мы создали контроллер с именем TestController и сопоставили его с путем «/test» . В классе мы создали метод, который возвращает объект ModelAndView и сопоставляется с запросом GET , поэтому любой вызов URL, заканчивающийся на « test », будет перенаправлен DispatcherServlet в метод getTestData в TestController .

И, конечно же, мы возвращаем объект ModelAndView с некоторыми данными модели.

Объект представления имеет имя, установленное на « добро пожаловать ». Как обсуждалось выше, View Resolver будет искать страницу в папке WEB-INF с именем « welcome.jsp ».

Ниже вы можете увидеть результат примера операции GET :

./f59da23aaedb946027aa32d93a631a14.png

Обратите внимание, что URL -адрес заканчивается на «test» . Шаблон URL«/test/test ».

Первый «/test» исходит от сервлета, а второй — от сопоставления контроллера.

7. Дополнительные зависимости Spring для REST

Теперь давайте рассмотрим контроллер RESTful. Конечно, неплохо бы начать с дополнительных зависимостей Maven, которые нам нужны для этого:

<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
</dependencies>

Пожалуйста, обратитесь к ссылкам jackson -core , spring-webmvc и spring-web для получения новейших версий этих зависимостей.

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

8. Контроллер REST

Настройка для приложения Spring RESTful такая же, как и для приложения MVC , с той лишь разницей, что в нем нет View Resolvers и карты модели.

Обычно API просто возвращает необработанные данные обратно клиенту — обычно представления XML и JSON — поэтому DispatcherServlet обходит преобразователи представлений и возвращает данные прямо в теле ответа HTTP .

Давайте посмотрим на простую реализацию контроллера RESTful:

@Controller
public class RestController {

@GetMapping(value = "/student/{studentId}")
public @ResponseBody Student getTestData(@PathVariable Integer studentId) {
Student student = new Student();
student.setName("Peter");
student.setId(studentId);

return student;
}
}

Обратите внимание на аннотацию @ResponseBody к методу, которая указывает Spring обойти преобразователь представления и , по сути, записать вывод непосредственно в тело HTTP-ответа .

Быстрый снимок вывода показан ниже:

./487eb6510e86a78a9464827484954b15.png

Приведенный выше вывод является результатом отправки запроса GET в API с идентификатором студента 1 .

Одно небольшое замечание: аннотация @RequestMapping — это `` одна из тех центральных аннотаций, которые вам действительно придется изучить, чтобы использовать их потенциал в полной мере.

9. Spring Boot и аннотация @RestController

Аннотация @RestController из Spring Boot — это, по сути, быстрый ярлык, который избавляет нас от необходимости всегда определять @ResponseBody .

Вот предыдущий пример контроллера, использующий эту новую аннотацию:

@RestController
public class RestAnnotatedController {
@GetMapping(value = "/annotated/student/{studentId}")
public Student getData(@PathVariable Integer studentId) {
Student student = new Student();
student.setName("Peter");
student.setId(studentId);

return student;
}
}

10. Заключение

В этом руководстве мы рассмотрим основы использования контроллеров в Spring как с точки зрения типичного приложения MVC, так и с точки зрения RESTful API.

Конечно, весь код в статье доступен на GitHub .