Wiki for course "Java with Spring".

1. Spring Core

Spring Framework – это framework, который облегчает и ускоряет разработку приложений на Java.

Ключевым элементом Spring Framework является Spring Container, который выполняет основные функции:

  • IoCInversion of Control (Создание и управление объектами);

  • DIDependency Injection (внедрение зависимостей).

Container создаёт объекты, связывает их вместе, настраивает и управляет ими от создания до момента уничтожения. Эти объекты называются Spring Bean. Beans после создания помещаются в Spring Container.

spring container

В Spring имеется 2 различных вида контейнеров:

  • BeanFactory;

  • ApplicationContext.

BeanFactory Container самый простой контейнер, обеспечивающий базовую поддержку DI и который основан на интерфейсе org.springframework.beans.factory.BeanFactory. Такие интерфейсы, как BeanFactoryAware и DisposableBean всё ещё присутствуют в Spring для обеспечения обратной совместимости. Наиболее часто используемая реализация интерфейса BeanFactoryXmlBeanFactory. XmlBeanFactory получает метаданные из конфигурационного XML файла и использует его для создания настроенного приложения или системы.

BeanFactory Container обычно используется тогда, когда ресурсы ограничены (мобильные устройства). Поэтому, если ресурсы не сильно ограничены, то лучше использовать ApplicationContext.

Для того чтобы Spring Container мог создать и поместить в себя Beans необходимы:

  • Java классы (POJO), из которых создаются Beans

  • метаданные, которые подсказывают что и как создавать

spring ioc container

Эти метаданные можно сконфигурировать несколькими способами:

  • Xml конфигурация;

  • Groovy конфигурация;

  • Конфигурация через аннотации;

  • Конфигурация через Java-код.

  • и т.д.

1.1. Bean и его атрибуты

Bean – это объект, экземпляр которого создается, собирается и иным образом управляется контейнером IoC Spring (создание, вызов методов инициализации и конфигурирование объектов путем связывания между собой).

Объекты, которые составляют основу приложения и управляются контейнером IoC Spring, называются Components (компонентами или управляемые Java-объект).

Определение Beans содержит метаданные конфигурации, которые необходимы управляющему контейнеру для получения следующей информации:

  • Как создать бин;

  • Информацию о жизненном цикле бина;

  • Зависимости бина.

С помощью этих метаданных (атрибуты бина) мы можем настраивать бины.

Bean имеет следующие атрибуты:

  • class - этот атрибут является обязательным и указывает конкретный класс Java-приложения, который будет использоваться для создания бина.

  • id/name- уникальный идентификатор бина. В случае конфигурации с помощью xml-файла, вы можете использовать свойство id и/или name для идентификации бина.

  • scope - это свойство определяет область видимости создаваемых объектов.

  • constructor-arg - определяет конструктор, использующийся для внедрения зависимости. Имеет атрибут ref, который указывает на id бина с которым нужно связываться.

  • properties - определяет свойства внедрения зависимости.

  • initialization method - здесь определяется метод инициализации бина

  • destruction method - метод уничтожения бина, который будет использоваться при уничтожении контейнера, содержащего бин.

  • autowiring mode - определяет режим автоматического связывания при внедрении зависимости.

  • lazy-initialization mode - режим ленивой инициализации даёт контейнеру IoC команду создавать экземпляр бина при первом запросе, а не при запуске приложения.

1.2. Bean Scopes

Очень важной особенностью является задание области применения бинов. По умолчанию всегда используется singleton.

Scope (область видимости) определяет:

  • жизненный цикл бина;

  • возможное количество создаваемых бинов.

Разновидности bean scope:

  • Singleton – тип бина, при котором, создается одна сущность на Spring-контейнер (значение по умолчанию)

  • Prototype – тип бина, при котором, каждый раз создается новая сущность бина.

  • Request – тип бина, при котором сущность бина создается одна на request. Такой тип бина справедлив для контекста веб-приложения.

  • Session – тип бина, при котором сущность бина создается только одна на объект http-session. Такой тип бина справедлив для контекста веб-приложения.

  • Global-session – тип бина, при котором сущность бина одна создается на приложение. Такой тип бина справедлив для контекста портлета.

  • Application – тип бина, задаваемый в единственном экземпляре на контекст сервлета. Действителен для контекста веб-приложения.

1.3. Конфигурация

Как указывалось выше, существует 4 вида конфигурации метаданных для создания бинов:

  • Xml конфигурацияClassPathXmlApplicationContext("context.xml");

  • Groovy конфигурацияGenericGroovyApplicationContext("context.groovy");

  • Конфигурация через аннотации с указанием пакета для сканирования — AnnotationConfigApplicationContext("package.name");

  • JavaConfig — конфигурация через аннотации с указанием класса (или массива классов) помеченного аннотацией @ConfigurationAnnotationConfigApplicationContext(JavaConfig.class).

1.3.1. Xml конфигурация

Чтобы использовать настройку через xml-файл, необходимо создать ClassPathXmlApplicationContext и в параметры передать CLASSPATH xml-файла.

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

Ниже приведен пример простого конфигурационного файла xml applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id = "villain" class = "film.Villain" lazy-init= "true">
        <property name = "name" value = "Vasily"/>
    </bean>
</beans>

1.3.2. Groovy конфигурация

При конфигурации контекста с помощью groovy-файла, необходимо сформировать GenericGroovyApplicationContext, который принимает на вход строку с конфигурацией контекста. Эта конфигурация работает по сути так же, как и xml, только с groovy-файлами. К тому же, GroovyApplicationContext нормально работает и с xml-файлом.

Пример простого конфигурационного Groovy-файла:

beans {
    goodOperator(film.Operator) {bean - >
            bean.lazyInit = 'true' >
            name = 'Good Oleg'
         }
    badOperator(film.BadOperator){bean - >
            bean.lazyInit = 'true' >
            name = 'Bad Oleg' / >
        }
}

1.3.3. Конфигурация через аннотации

При конфигурации через аннотации используются следующие аннотации:

  • @Component

  • @Repository

  • @Service

  • @Controller

  • @RestController

@Repository
public class CoolDaoImpl implements CoolDao {
    @Override
    public void doCRUD() {
        //some logic here
    }
}
@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class CoolServiceImpl implements CoolService {
    @Autowired
    private CoolDao dao;

    @PostConstruct
    public void init() {
        //init logic here
    }

    @PreDestroy
    public void closeResources() {
        //close resources here
    }

    @Override
    public void doWork() {
        dao.doCRUD();
    }
}

1.3.4. Конфигурация через Java-код

Центральными артефактами при конфигурации через Java в Spring являются @Configuration и @Bean

@Configuration
public class JavaConfig {
    @Bean
    public ClassName getClassName() {
        return new ClassName();
    }

    @Bean(initMethod = "init", destroyMethod = "closeResources")
    @Scope(BeanDefinition.SCOPE_PROTOTYPE)
    public ClassName2 getClassName2() {
        ClassName2 className = new ClassName2();
        className.getClassName();
        return service;
    }
}

1.4. ApplicationContext

ApplicationContext — это главный интерфейс в Spring-приложении, который предоставляет информацию о конфигурации приложения.

ApplicationContext представляет собой Spring Container, место, где хранятся все созданные бины. Поэтому для получения бина из Spring Container нам нужно создать ApplicationContext

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

Чаще всего используются следующие реализации ApplicationContext:

  • FileSystemXmlApplicationContext - загружает данные о бине из xml-файла. При использовании этой реализации в конструкторе необходимо указать полный адрес конфигурационного файла.

  • ClassPathXmlApplicationContext - этот контейнер также получает данные о бине из xml-файла. Но в отличие от FileSystemApplicationContext, в этом случае необходимо указать относительный адрес конфигурационного файла (CLASSPATH).

  • WebXmlApplicationContext - эта реализация ApplicationContext получает необходимую информацию из веб-приложения.

  • AnnotationConfigApplicationContext - конфигурация через аннотации с указанием пакета для сканирования

  • GenericGroovyApplicationContext - конфигурация через groovy-файл

На рисунке ниже приведены этапы формирования ApplicationContext:

stages of context initialization

1.4.1. Парсинг конфигурации и создание BeanDefinition

На первом этапе происходит чтение конфигураций и создание BeanDefinition.

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

XML config

Для xml конфигурации используется класс — XmlBeanDefinitionReader, который реализует интерфейс BeanDefinitionReader. XmlBeanDefinitionReader получает InputStream и загружает Document через DefaultDocumentLoader. Далее обрабатывается каждый элемент документа и если он является бином, то создается BeanDefinition на основе заполненных данных (id, name, class, alias, init-method, destroy-method и др.)

Каждый BeanDefinition помещается в map. Map хранится в классе DefaultListableBeanFactory.

Groovy config

Конфигурация через groovy очень похожа на конфигурацию через xml, за исключением того, что в файл не xml, а groovy. Чтением и парсинг groovy конфигурации занимается класс GroovyBeanDefinitionReader.

Annotations-based config

Для конфигурации через аннотации с указанием пакета для сканирования или JavaConfig используется класс AnnotationConfigApplicationContext. Этот класс имеет следующие поля, с помощью которых происходит создание BeanDefinition:

  • AnnotatedBeanDefinitionReader;

  • ClassPathBeanDefinitionScanner.

ClassPathBeanDefinitionScanner сканирует указанный пакет на наличие классов помеченных аннотацией @Component (или любой другой аннотацией которая включает в себя @Component). Найденные классы парсятся и для них создаются BeanDefinition.

Чтобы сканирование было запущено, в конфигурации должен быть указан пакет для сканирования. Вся магия работы с аннотациями, как в случае с xml и groovy, заключается именно в классе ClassReader.class из пакета springframework.asm. Специфика этого ридера заключается в том, что он умеет работать с байт-кодом. То есть, ридер достает InputStream из байт-кода, сканирует его и ищет там аннотации.

AnnotatedBeanDefinitionReader работает в несколько этапов.

  • Первый этап: регистрация всех @Configuration для дальнейшего парсинга.
    Если в конфигурации используются @Conditional, то будут зарегистрированы только те конфигурации, для которых Condition вернет true. Аннотация @Conditional появилась в четвертой версии Spring Framework. Она используется в случае, когда на момент поднятия контекста нужно решить, создавать бин/конфигурацию или нет. Причем решение принимает специальный класс, который обязан реализовать интерфейс Condition.

  • Второй этап: регистрация специального BeanFactoryPostProcessor
    Если точнее, регистрация BeanDefinitionRegistryPostProcessor, который при помощи класса ConfigurationClassParser парсит JavaConfig и создает BeanDefinition.

Каждый BeanDefinition помещается в map, который хранится в классе DefaultListableBeanFactory.

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();

1.4.2. Настройка созданных BeanDefinition (BeanFactoryPostProcessor)

После первого этапа у нас имеется map, в котором хранятся BeanDefinition. На этом этапе у нас есть возможность повлиять на то, какими будут наши бины еще до их фактического создания, иначе говоря мы имеем доступ к метаданным класса. Для этого существует специальный интерфейс BeanFactoryPostProcessor, реализовав который, мы получаем доступ к созданным BeanDefinition и можем их изменять.

В этом интерфейсе всего один метод:

  • postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory).

Метод postProcessBeanFactory() принимает параметром ConfigurableListableBeanFactory. Данная фабрика содержит много полезных методов, в том числе getBeanDefinitionNames(), через который мы можем получить все BeanDefinitionNames, а уже потом по конкретному имени получить BeanDefinition для дальнейшей обработки метаданных

1.4.3. Создание собственных FactoryBean

На этом этапе, если не устраивает BeanFactory из-под капота, можно создать собственные FactoryBean.

FactoryBean — это generic интерфейс, которому можно делегировать процесс создания бинов необходимого типа. В те времена, когда конфигурация была исключительно в xml, разработчикам был необходим механизм с помощью которого они бы могли управлять процессом создания бинов. Именно для этого и был сделан этот интерфейс.

Чтобы создать свою фабрику бинов (собственный FactoryBean), необходимо реализовать интерфейс FactoryBean и переопределить три его метода.

@Component
public class ClassNameFactory implements FactoryBean<ClassName> {
    @Override
    public ClassName getObject() throws Exception {
        return new ClassName();
    }

    @Override
    public Class<?> getObjectType() {
        return ClassName.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

1.4.4. Создание экземпляров бинов

На этом этапе происходит создание бинов.

  • Созданием экземпляров бинов занимается BeanFactory при этом, если нужно, делегирует это кастомным FactoryBean.

  • Экземпляры бинов создаются на основе ранее созданных BeanDefinition.

  • При этом важно знать, что на этапе поднятия контекста создаются только бины с областью видимости Singleton.

  • Остальные бины создаются тогда, когда необходимы.

create bean by bean factory

1.4.5. Настройка созданных бинов (BeanPostProcessor)

На данном этапе можно производить дополнительную настройку созданных бинов. Настройка производиться через интерфейс BeanPostProcessor.

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

  • postProcessBeforeInitialization(Object bean, String beanName);

  • postProcessAfterInitialization(Object bean, String beanName).

BeanFactory вызывает оба метода для каждого бина, и прогоняет бин через все BeanPostProcessor. У обоих методов параметры абсолютно одинаковые. Разница только в порядке их вызова. Первый вызывается до init-метода, второй, после.

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

Важно понимать, что на данном этапе экземпляр бина уже создан и идет его донастройка. Процесс донастройки показан на рисунке ниже.

bean post processor

@Component
public class ClassBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

1.5. Схема создания бинов

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

lifecycle bean

  • Spring создает bean.

  • Spring задает значения и ссылки в поля bean.

  • Если bean реализует BeanNameAware, Spring передает ID бина в метод setBeanName().

  • Если bean реализует BeanFactoryAware, Spring вызывает setBeanFactory(), передавая туда bean factory.

  • Если bean реализует интерфейс ApplicationContextAware, Spring вызовет setApplicationContext(), передавая по ссылке контекст приложения.

  • Если bean реализует интерфейс BeanPostProcessor, Spring вызывает метод бина postProcessBeforeInitialization().

  • На этом происходит вызов методов init(). Если bean реализуют интерфейс InitializingBean, Spring вызывает метод afterPropertiesSet().

public class CachingMovieLister {
    @PostConstruct
    public void populateMovieCache() {
    }
}
  • Если bean реализует BeanPostProcessor, Spring вызовет метод бина postProcessAfterInitialization().

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

  • На этом происходит вызов методов destroy(). Если bean реализует интерфейс DisposableBean, Spring вызовет destroy() метод.

public class CachingMovieLister {
    @PreDestroy
    public void clearMovieCache() {
    }
}
  • Компонент перестает существовать.

1.6. IoC, DI, @Autowired

Как было описано выше, ядром Spring является контейнер Inversion of Control, функция которого создать и управлять объектами (бинами), а благодаря основной реализации Dependency Injection и связывать различные объекты между собой.

Связывать объекты между собой можно несколькими способами:

  • С помощью конструктора

public class MovieRecommender {
    private final CustomerPreferenceDao customerPreferenceDao;

    @Autowired
    public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
        this.customerPreferenceDao = customerPreferenceDao;
    }
}
  • С помощью метода (сеттер)

public class SimpleMovieLister {
    private MovieFinder movieFinder;

    @Autowired
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
}
  • Через поле

public class MovieRecommender {
    @Autowired
    private MovieCatalog movieCatalog;
}

По умолчанию внедрение зависимостей через методы или поля рассматриваются как обязательные зависимости. Однако, Вы можете изменить это поведение, устанавливая для required атрибута @Autowired значение false:

public class SimpleMovieLister {
    private MovieFinder movieFinder;

    @Autowired(required = false)
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
}

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

  • @Primary - указывает, что текущий бин будет внедряться по умолчанию, если их несколько

@Configuration
public class MovieConfiguration {
    @Bean
    @Primary
    public MovieCatalog firstMovieCatalog() { ... }

    @Bean
    public MovieCatalog secondMovieCatalog() { ... }
}
  • @Qualifier - указывает какой бин необходимо использовать для внедрения

@Component
@Qualifier("Action")
public class ActionMovieCatalog implements MovieCatalog {
}
public class MovieRecommender {
    @Autowired
    @Qualifier("Action")
    private MovieCatalog movieCatalog;
}

1.7. @Component, @Service и другие аннотации

В Spring используются следующие аннотации:

  • @Component
    Аннотация для любого компонента фреймворка.

  • @Repository
    (Доменный слой) Аннотация показывает, что класс функционирует как репозиторий и требует наличия прозрачной трансляции исключений. Преимуществом трансляции исключений является то, что слой сервиса будет иметь дело с общей иерархией исключений от Spring (DataAccessException) вне зависимости от используемых технологий доступа к данным в слое данных.

  • @Service
    (Сервис-слой приложения) Аннотация, объявляющая, что этот класс представляет собой сервис – компонент сервис-слоя. Сервис является подтипом класса @Component. Использование данной аннотации позволит искать бины-сервисы автоматически.

  • @Controller
    (Слой представления) Аннотация для маркировки java класса, как класса контроллера. Данный класс представляет собой компонент, похожий на обычный сервлет (HttpServlet) (работающий с объектами HttpServletRequest и HttpServletResponse), но с расширенными возможностями от Spring Framework.

  • @RestController
    Аннотация аккумулирует поведение двух аннотаций @Controller и @ResponseBody (показывает что данный метод может возвращать собственный объект в виде xml, json и другие).

annotation

Данные аннотации используются при конфигурации приложения через аннотации.

Основной считается @Component, общий стереотип для любого компонента, управляемого Spring. @Repository, @Service И @Controller являются специализациями @Component для более конкретных случаев применения (в настойчивости, обслуживании и презентации слоев, соответственно).

Бины, получившиеся при помощи @Repository, дополнительно имеют обработку для JDBC Exception.

@RestController = @Controller + @ResponseBody. Этот бин для конвертации входящих/исходящих данных использует Jackson message converter. Как правило, целевые данные представлены в json или xml.

2. Spring MVC

Spring MVC – это фреймворк для создания web-приложений на Java, в основе которого лежит шаблон проектирования MVC.

  • Spring MVC — это старый добрый MVC-фреймворк, который позволяет довольно легко писать web-сайты или web-сервисы.

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

  • Главным образом он позволяет вам сосредоточиться на написании своей бизнес-логики, не беспокоясь о стандартном коде для Servlet, разборе HTTP-запросов/ответов и преобразовании данных.

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

  • Model (Модель) инкапсулирует (объединяет) данные приложения, в целом они будут состоять из POJO.

  • View (Отображение, Вид) отвечает за отображение данных Модели, — как правило, генерируя HTML, которые мы видим в своём браузере.

  • Controller (Контроллер) обрабатывает запрос пользователя, создаёт соответствующую Модель и передаёт её для отображения в Вид.

Рабочий процесс обработки запроса проиллюстрирован на следующей диаграмме:

schema working dispatcher servlet

После получения HTTP-запроса DispatcherServlet выполняет следующие действия.

  • После получения HTTP-запроса DispatcherServlet даёт указание объекту HandlerMapping (обработка связывания), который вызывает следующий объект.

  • DispatcherServlet посылает запрос контроллеру и вызывает соответствующие методы. Эти методы возвращают объект, в соответствии с бизнес-логикой метода и передают название ссылки обратно в DispatcherServlet.

  • C помощью ViewResolver, DispatcherServlet подбирает необходимый вид для запроса.

  • Когда внешний вид сформирован, DispatcherServlet передаёт эти данные в модуль View, который обрабатывается браузером пользователя.

2.1. DispatcherServlet

Вся логика работы Spring MVC построена вокруг DispatcherServlet.

DispatcherServlet — полностью интегрированный Servlet в Spring IoC контейнер и таким образом получает доступ ко всем возможностям Spring.

При обработке запросов используется паттерн pattern-savvy reader, который распознает DispatcherServlet как выражение из шаблона проектирования Front Controller.

front contreoller

DispatcherServlet является основным контроллером Spring MVC Application. Все входящие веб-запросы проходят через DispatcherServlet перед обработкой отдельными контроллерами Spring, то есть классами, аннотированными с помощью аннотации @Controller.

DispatcherServlet — это обычный Servlet (наследуется от базового класса HttpServlet). Как и любой другой Servlet, DispatcherServlet необходимо зарегистрировать и настроить. Сделать это можно или в файле web.xml

web.xml
<web-app>
    <servlet>
        <servlet-name>SpringMVC</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>SpringMVC</servlet-name>
        <url-pattern>*</url-pattern>
    </servlet-mapping>
</web-app>

Либо в Java-коде переопределив метод onStartup() интерфейса WebApplicationInitializer:

public class WebInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(WebConfiguration.class);
        DispatcherServlet servlet = new DispatcherServlet(context);
        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", servlet);
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }
}

WebApplicationInitializer — интерфейс, предоставляемый Spring MVC, который гарантирует инициализацию при старте контейнера.

Servlet диспетчера настроен как load-on-startup = 1, что означает, что этот Servlet должен создаваться контейнером Servlets при развертывании приложения, а не при получении запроса на этот запрос.

2.2. HandlerMapping

Одним из важных интерфейсов в Spring является HandlerMapping.

DispatcherServlet с помощью HandlerMapping определяет какой контроллер он должен использовать для определенного request.

schema spring mvc detail

По определению HandlerMapping — интерфейс реализующийся объектами, которые определяют отображение между запросами и объектами обработчиков.

Реализации HandlerMapping могут поддерживать перехватчики (interceptors), но не содержат их. Обработчик будет всегда обернут в экземпляре HandlerExecutionChain, возможно в сопровождении некоторых экземпляров HandlerInterceptor. DispatcherServlet сначала вызывает метод preHandle() каждого HandlerInterceptor в заданном порядке, и в конце, внедряет обработчик, если все методы preHandle() вернули true.

Возможность параметризации такого отображения является мощной и необычной способностью в рамках MVC фреймворка. Например, можно написать пользовательское отображение на основе состояния session, состояние cookie или многих других переменных.

По умолчанию интерфейс HandlerMapping в Spring MVC реализуется классом RequestMappingHandlerMapping. Существуют другие реализации интерфейса, которые используют другие параметры для поиска контроллера, соответствующего запросу. В Spring MVC вы можете встретить реализацию интерфейса, когда применяете аннотацию @RequestMapping

@RequestMapping(value = "/", method = RequestMethod.GET)
public class Main{
    public ModelAndView main() {
        ModelAndView modelAndView = new ModelAndView();
        return modelAndView;
    }
}

2.3. Controller

DispatcherServlet отправляет запрос контроллерам для выполнения определённых функций.

Request Lifecycle

Аннотации @Controller или @RestController указывают, что конкретный класс является контроллером. Аннотация @RestController равна одновременно @Controller + @ResponseBody.

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

Аннотация @RequestMapping используется для mapping (связывания) с URL для всего класса или для конкретного метода обработчика.

@Controller
@RequestMapping("/hello")
public class HelloController {
   @RequestMapping(method = RequestMethod.GET)
   public String printHello(ModelMap model) {
      model.addAttribute("message", "Hello Spring MVC Framework!");
      return "hello";
   }
}

В первом случае, @RequestMapping указывает, что все методы в данном Controller относятся к URL-адресу /hello, а во втором как дефолтного метода для обработки HTTP-запросов GET (в данном Controller). Также можно данную аннотацию объявить над методом @RequestMapping(value = "/hello", method = RequestMethod.GET).

Также в контроллере может использоваться аннотация @ModelAttribute, которая ставится над методом или в аргументах методов.

@Controller
public class HelloController {
    @RequestMapping("/processForm")
    public String processForm(@ModelAttribute("student") Student theStudent) {
        System.out.println("theStudent :"+ theStudent.getLastName());
        return "form-details";
    }

    @ModelAttribute("object")
    public Object checkOptions() {
        return new Object();
    }
}
<form:form action="processForm" modelAttribute="student">
    First Name : <form:input path="firstName" />
    <br><br>
    Last Name : <form:input path="lastName" />
    <br><br>
    <input type="submit" value="submit"/>
</form:form>

В зависимости от места ее применения, работать она будет по-разному. В первом случае она позволяет связать html-форму с java-объектом. А во втором случае, добавит в модель каждого метода контроллера объект с ключ-значением - object и new Object().

2.3.1. @RequestParam и @PathVariable

Часто используются аннотации @RequestParam и @PathVariable.

@Controller
@RequestMapping("api/test")
public class HelloController {
    @GetMapping(path = "/filter")
    public Test getByFilter(@RequestParam(name = "text", required = false) String text) {
        return testService.getByFilter(filterTest);
    }

    @GetMapping(path = "/{id}")
    @ResponseBody
    public Test findById(@PathVariable String id) {
        return testService.findById(id);
    }
}

При использовании @RequestParam передача значений будет в виде http://localhost:8080/api/test/filter?id=abc. В этом случае данный параметр является не обязательным, но при установке атрибута required = true (по умолчанию false) станет обязательным для заполнения.

При использовании @PathVariable передача значений будет в виде http://localhost:8080/api/test/abc. В этом случае данный параметр является обязательным, но при установке атрибута required = false (по умолчанию true) станет не обязательным для заполнения.

2.4. ViewResolver

DispatcherServlet с помощью ViewResolver определяет какое представление необходимо использовать на основании полученного имени.

ViewResolver — интерфейс, реализуемый объектами, которые способны находить представления View по имени View Name

Spring MVC поддерживает множество типов View для различных технологий отображения страницы. В том числе — JSP, HTML, PDF, Excel, XML, Velocity templates, XSLT, JSON, каналы Atom и RSS, JasperReports и другие.

По умолчанию реализацией интерфейса ViewResolver является класс InternalResourceViewResolver. Также могут использоваться FreeMarkerViewResolver, BeanNameViewResolver, ResourceBundleViewResolver, TilesViewResolver и многие другие.

@Configuration
public class WebConfiguration {
    @Bean
    public InternalResourceViewResolver internalResourceViewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
}

prefix suffix

public class Main{
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public ModelAndView main() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("userJSP", new User());
        modelAndView.setViewName("index");
        return modelAndView;
    }
}

После того как в модель modelAndView было записано имя представления "index" и произошел выход из метода, то в действие включается ViewResolver. Для этого примера согласно настройкам в класс InternalResourceViewResolver будет искать представление с именем index, у которого префикс /WEB-INF/views/, а суффикс .jsp. Другими словами он должен найти представление с именем /WEB-INF/views/index.jsp.

<html lang="">
   <head>
      <title>Hello Spring MVC</title>
   </head>

   <body>
      <h2>${userJSP}</h2>
   </body>
</html>

В данном случае, переменная ${userJSP} выводит тот самый атрибут, установленный в Controller. Внутри View можно отобразить любое количество атрибутов.

Если представление найдено, то произойдет переход на эту страницу. В противном случае результат зависит от настроек реализации интерфейса ViewResolver. По умолчанию возвращается null, но можно возвращать имя или исключение, если вам это необходимо.

2.5. ExceptionHandler

Для обработки ошибки существует три варианта обработки:

  • для каждого контроллера

  • для каждого исключения

  • глобально

2.5.1. Уровень контроллера

Изначально основными способами обработки исключений в приложении были HandlerExceptionResolver и аннотация @ExceptionHandler, которая позволяла обрабатывать исключения на уровне отдельного контроллера. Для этого достаточно было объявить метод, в котором будет содержаться вся логика обработки нужного исключения, и проаннотировать его.

@RestController
public class ExampleController {
    @GetMapping(value = "/testExceptionHandler", produces = APPLICATION_JSON_VALUE)
    public Response testExceptionHandler() throws BusinessException {
        throw new BusinessException("BusinessException in testExceptionHandler");
    }

    @ExceptionHandler(BusinessException.class)
    public Response handleException(BusinessException e) {
        return new Response(e.getMessage());
    }
}

Метод handleException() предназначен для обработки ошибок. У него есть аннотация @ExceptionHandler(BusinessException.class), которая говорит о том, что для последующей обработки будут перехвачены все исключения типа BusinessException. В аннотации @ExceptionHandler можно прописать сразу несколько типов исключений, например так: @ExceptionHandler({BusinessException.class, ServiceException.class}).

Основной недостаток @ExceptionHandler в том что он определяется для каждого контроллера отдельно, а не глобально для всего приложения.

Также, на уровне контроллера можно формировать ответ путём выброса исключения ResponseStatusException.

@RestController
public class ExampleController {
    @GetMapping(value = "/testResponseStatusException", produces = APPLICATION_JSON_VALUE)
    public Response testResponseStatusException() {
        throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "ResponseStatusException in testResponseStatusException");
    }
}

Выбрасывая ResponseStatusException можно также возвращать пользователю определённый код статуса, в зависимости от того, что произошло в логике приложения. При этом не нужно создавать собственное исключение и прописывать аннотацию @ResponseStatus

2.5.2. Уровень исключений

Для обработки ошибок на уровне исключений используется ResponseStatusExceptionResolver. Он позволяет настроить код ответа для любого исключения с помощью аннотации @ResponseStatus.

@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
public class ServiceException extends Exception {
    public ServiceException(String message) {
        super(message);
    }
}
@RestController
public class ExampleController {
    @GetMapping(value = "/testResponseStatusExceptionResolver", produces = APPLICATION_JSON_VALUE)
    public Response testResponseStatusExceptionResolver() throws ServiceException {
        throw new ServiceException("ServiceException in testResponseStatusExceptionResolver");
    }
}

Из недостатков такого подхода — как и в предыдущем случае отсутствует тело ответа.

2.5.3. Уровень глобальной обработки

Глобально и централизованно обрабатывать исключения с помощью классов с аннотацией @ControllerAdvice.

@ControllerAdvice
public class DefaultAdvice {
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<Response> handleException(BusinessException e) {
        Response response = new Response(e.getMessage());
        return new ResponseEntity<>(response, HttpStatus.OK);
    }
}

Любой класс с аннотацией @ControllerAdvice является глобальным обработчиком исключений, который очень гибко настраивается. Метод handleException() имеет аннотацию @ExceptionHandler, в которой можно определить список обрабатываемых исключений.

Так же можно в рамках @ControllerAdvice сделать сразу несколько методов с аннотациями @ExceptionHandler для обработки разных исключений.

3. Spring Security

Spring Security — это мощный и настраиваемый фреймворк для authentication (аутентификации) и access-control (AC/контроля доступа). Он де-факто является стандартом для безопасности приложений на основе фреймворка Spring.

Spring Security — это фреймворк, ориентированный на обеспечение как authentication (аутентификации), так и authorization (авторизации) приложений на Java. Как и во всех проектах Spring, реальная сила Spring Security заключается в том, что его можно легко расширить для удовлетворения любых требований.

Spring Security обеспечивает всестороннюю поддержку:

  • authentication (аутентификации)

  • authorization (авторизации)

  • защиты от распространенных exploits (эксплойтов), т.е. фактически предотвращает проникновение в приложение злоумышленников

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

3.1. Resources

4. Spring Boot

4.1. Введение в Spring Boot

Spring Boot — самый популярный фреймворк на основе Java, построенный на базе функций Spring Framework. Он используется для создания простых и понятных в понимании standalone (автономных) и web-based (веб) приложений.

4.1.1. Что такое Spring Boot?

Spring Boot — это проект с открытым исходным кодом, разработанный командой Pivotal (команда Spring). Он построен на основе Spring Framework и предоставляет собой RAD (Rapid Application Development/Быстрая разработка приложений) на основе Spring Framework. Он комбинирует Spring Framework и third-party libraries (сторонние библиотеки), которые упрощают создание приложений и уменьшения усилия по разработке. В отличие от Spring Framework, Spring Boot не требует конфигурации на основе XML или аннотаций, поскольку он автоматически настраивает Spring и сторонние библиотеки.

Целью платформы Spring Boot является полное удаление конфигураций на основе XML и сокращение времени разработки и интеграционного тестирования.

Цели Spring Boot перечислены ниже:

  • Предложить полный Opinionated Development Approach.

  • Обеспечить большую часть функционала неявно или по умолчанию.

  • Избегать написания множества строк кода.

4.1.2. Необходимость использования Spring Boot

Некоторые из основных факторов использования среды Spring Boot перечислены ниже:

  • Он обеспечивает гибкость и простоту при разработке приложений на основе Java.

  • Он позволяет создавать менее трудоемкие приложения, так как большинство вещей управляются им по умолчанию.

  • Он не требует какой-либо конфигурации на основе XML или Java, поскольку он автоматически настраивает Spring и сторонние библиотеки.

  • Он также обеспечивает мощную batch (пакетную) обработку и гибкие транзакции базы данных.

4.1.3. Компоненты Spring Boot

components

As we have discussed, the Spring Boot framework is an upgraded project of the Spring framework with some additional features and components. There are four major components of Spring Boot that are listed below:

Spring Boot — это обновленный проект среды Spring с некоторыми дополнительными функциями и компонентами. Ниже перечислены четыре основных компонента Spring Boot:

  • Spring Boot Starters

  • Spring Boot AutoConfiguration

  • Spring Boot CLI

  • Spring Boot Actuator

Наряду с перечисленными выше основными компонентами в Spring Boot доступны еще два дополнительных компонента:

  • Spring Initializr

  • Spring Boot IDEs

Spring Boot Starters

Spring Boot Starters — один из основных компонентов среды Spring Boot. Он связывает более одной зависимости в группе. Это также уменьшает количество зависимостей, добавляемых вручную, путем объединения нескольких зависимостей в одну. Таким образом, он добавляет стартер вместо указания множества зависимостей.

Например, когда создается приложение Spring MVC, требуется множество зависимостей, таких как:

  • Spring Core

  • Spring Web MVC

  • Spring Web

Наряду с приведенными выше зависимостями необходимы еще некоторые зависимости. Ручное добавление зависимостей загромождает код. Spring Boot предложил решение этой проблемы.

Spring Boot упрощает задачу, поскольку добавляет только root dependency (корневую зависимость) или starter dependency (начальную зависимость). Когда добавляется starter зависимость в приложение, Spring Boot автоматически добавляет в приложение все необходимые зависимости.

Spring Boot AutoConfiguration

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

Поэтому для решения проблемы возник Spring Boot AutoConfiguration. Он отвечает за сокращение конфигурации Spring. При создании Spring Boot приложения нет необходимости определять какую-либо конфигурацию (на основе XML) и сократить использование конфигурации на основе аннотаций. Использование Spring Boot AutoConfiguration делает разработку приложений простой и быстрой, поскольку ее настройка не отнимает много времени.

Например, если использовать стартер spring-boot-starter-web в приложении, Spring Boot автоматически настраивает все bean-компоненты или классы необходимые для web-приложения.

Spring Boot CLI

Spring Boot CLI (Command Line Interface) — это интерфейс командной строки для приложений на основе Spring Boot. Он позволяет запустить приложение Spring Boot с помощью CLI. Он также используется для тестирования приложений Spring Boot из командной строки. Используя интерфейс командной строки Spring Boot, также можно выполнять Groovy код, который имеет аналогичный синтаксис, подобный Java.

При запуске некоторых приложений Spring Boot через CLI он под капотом использует компоненты Spring Boot Starter и Spring Boot AutoConfiguration для решения всех зависимостей и запуску приложения.

Spring Boot Actuator

Spring Boot Actuator также является важным компонентом Spring Boot. Он также разрабатывается как подпроект (инструмент) Spring Boot. Он предоставляет множество функций для среды Spring Boot, но в основном отвечает за две его основные функции:

  • Он предоставляет (HTTP) EndPoints для управления (HTTP) для приложения на Spring Boot.

  • Он позволяет управлять работающим приложениям с помощью этих HTTP EndPoints.

Spring Boot Actuator автоматически предоставляет имя хоста как localhost и номер порта как 8080 всякий раз, когда развертывается приложение Spring Boot с помощью интерфейса командной строки Spring Boot. Здесь обычно используются HTTP-методы GET или POST для взаимодействия с HTTP EndPoints по средствам Spring Boot Actuator.

Spring Boot Actuator в основном используется для доступа к внутренней информации приложения, такой как metrics (метрики), dump (дамп), health (работоспособность) и т.д.

Spring Initializr

Spring Initializr — это веб-интерфейс для создания, настройки и создания приложений на базе Spring. Другими словами, это инструмент, который используется для быстрого создания проекта на основе JVM. Он может создавать проекты на различных языках, таких как Java, Kotlin и Groovy. Он также предоставляет скрипт (Maven или Gradle) для создания приложений.

Spring Boot IDEs

Spring Boot поддерживает множество IDE, таких, как Eclipse, IntelliJ IDEA, Spring Tool Suite (STS) и т.д., которые используются для создания приложений.

4.1.4. Преимущества Spring Boot

Основное преимущество Spring Boot заключается в том, что он состоит из фреймворка Spring и Embedded HTTP server. Но конфигурации на основе XML и аннотаций почти нет.

advantages

Другие преимущества среды Spring Boot приведены ниже:

  • С ним легко разрабатывать приложения на основе Spring с помощью Groovy и Java.

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

  • Он сводит к минимуму написание типичного длинного кода, такого как конфигурация на основе XML и аннотаций.

  • Он делает простой и плавной интеграцию Spring Boot с другими экосистемами, такими как Spring Security, Spring Data, Spring JDBC и ORM.

  • Он также предоставляет встроенные HTTP-серверы, такие, как Apache Tomcat, Apache Jetty, сервер приложений Undertow и многие другие, для развертывания и тестирования приложений на основе Spring.

  • Он также предлагает несколько плагинов для простой разработки и тестирования приложений Spring Boot с использованием инструментов сборки, таких как Maven.

4.1.5. Ограничения Spring Boot

Некоторые из ограничений Spring Boot перечислены ниже:

  • Он содержит некоторые дополнительные зависимости, которые могут быть бесполезны для конкретного приложения, поскольку используется Spring Boot Starters (root dependencies).

  • Ненужные зависимости, используемые в приложениях, приводят к огромному размеру приложения.

  • Преобразование приложений на Spring Framework в приложения на Spring Boot занимает немного времени.

4.2. Spring Boot Features

Spring Boot построена на основе Spring Framework. Фактически он является улучшенной версией проекта Spring, поэтому он способен делать то, что не может сделать Spring Framework.

Ключевые особенности среды Spring Boot перечислены ниже:

Features of Spring Boot

features

  • SpringApplication

  • Lazy Initialization

  • Admin Features

  • Security

  • Logging

  • Caching

  • Kotlin Support

  • Validation

  • JSON

  • Testing

  • Task Execution and Scheduling

4.2.1. SpringApplication

Класс SpringApplication в основном используется для начальной загрузки и запуска приложения Spring с использованием main() метода. В некоторых случаях можно использовать статический метод SpringApplication.run().

public class MyFirstSpringApp {
    public static void main(String[] args) {
           SpringApplication.run(MyFirstSpringApp.class, args);
    }
}

По умолчанию в logs отображаются информация о запуске Spring приложения. Эти logs о запуске можно отключить, установив для spring.main.log-startup-info значение false в application.properties.

4.2.2. Lazy Initialization

В Spring Boot SpringApplication помогает lazy (отложенной/ленивой) инициализации Spring приложений. После включения lazy (отложенной/ленивой) инициализации bean-компоненты создаются по мере необходимости, а не во время запуска приложения, что приводит к более быстрому старту приложения. При включении lazy (отложенной/ленивой) инициализации в веб-приложении некоторые веб-компоненты не инициализируются до тех пор, пока не будет получен HTTP-запрос.

Включить lazy (отложенной/ленивой) инициализацию тремя способами:

  1. С помощью метода lazyInitialization() класса SpringApplicationBuilder.

  2. С помощью метода setLazyInitialization() класса SpringApplication.

  3. С помощью свойства spring.main.lazy-initialization=true.

4.2.3. Admin Features

В Spring Boot можно включить функции, связанные с администрированием, указав свойство spring.application.admin.enabled=true. Это позволит использовать задействовать интерфейс SpringApplicationAdminMXBean на платформе MBeanServer . Он используется для реализации wrapper services (служб-оболочек), а также для администрирования Spring Boot приложений.

4.2.4. Security

Spring Boot приложения — это приложения на основе Spring. Поэтому Spring Boot приложения очень безопасны и основаны на стратегиях безопасности Spring. Аннотация @EnableGlobalMethodSecurity используется для добавления безопасности на уровне метода в веб-приложение.

4.2.5. Logging

Spring Boot использует Commons-logging для всех внутренних logs, который представляет собой Java-based programming model service для logging и других наборов инструментов. Некоторые конфигурации по умолчанию также предоставляются для Log4J2, Logback и Java Util Logging.

4.2.6. Caching

Кэширование поддерживается Spring Boot. Кэширование также применяется и к методам приложений, что приводит к уменьшению количества выполнений на основе информации, доступной в кеше. Spring Boot автоматически настраивает кэш, а поддержка кэширования включается с помощью аннотации @EnableCaching.

4.2.7. Kotlin Support

Kotlin — это язык программирования, используемый для Android, серверной, мобильной кроссплатформенной и веб-разработки. Он предназначен для JVM и других платформ, которые позволяют писать короткий и простой код, обеспечивая при этом взаимодействие с другими существующими библиотеками Java.

4.2.8. Validation

Validation (валидация) автоматически поддерживается Spring Boot. Spring Boot позволяет аннотировать методы bean-компонента ограничением javax.validation для их полей и возвращаемых значений. Целевые классы аннотируются аннотацией @Validated и просматриваются validator (валидатором) при validation (валидации).

4.2.9. JSON

Spring Boot предлагает интеграцию с тремя основными библиотеками для JSON mapping:

  • Jackson
    Jackson — это библиотека JSON по умолчанию и наиболее предпочтительная. Входит в стартер spring-boot-starter-json. Конфигурация Jackson предоставляется по умолчанию. Компонент ObjectMapper настраивается автоматически, когда Jackson находится в classpath. Он также предлагает несколько свойств конфигурации для настройки конфигурации ObjectMapper.

  • Gson
    Конфигурация Gson предоставляется по умолчанию. Поэтому он автоматически настраивается, когда Gson находится в classpath. Существует несколько свойств конфигурации spring.gson.* для изменения конфигураций. Так же для управления конфигурациями используется компонент GsonBuilderCustomizer.

  • JSON-B
    Автоматическая настройка для JSON-B также предоставляется по умолчанию. Компонент JSON-B настраивается автоматически, когда API для JSON-B и его реализация находятся в classpath.

4.2.10. Testing

Spring Boot предоставляет множество утилит и аннотаций, помогающих тестировать приложения. Есть два модуля, которые обеспечивают поддержку тестирования:

  • spring-boot-test - содержит все основные элементы,

  • spring-boot-test-autoconfigure - поддерживает автоматическую настройку для тестов.

4.2.11. Task Execution and Scheduling

Если компонент Executor отсутствует в контексте, Spring Boot автоматически настраивает ThreadPoolTaskExecutor. В зависимости от цели можно изменить bean-компонент Executor на ThreadPoolTaskExecutor или определить как ThreadPoolTaskExecutor, так и AsyncConfiguration.

4.3. Spring Boot Architecture

Spring Boot — это расширенная версия или проект Spring Framework. Наряду с Spring Framework он также состоит из third-party libraries (сторонних библиотек) и Embedded HTTP servers. Он легко создает готовые к работе, менее трудоемкие и автономные приложения на основе Spring Framework.

Цель Spring Boot — полностью отказаться от использования конфигурации на основе XML и аннотаций в приложениях. Используя Spring Boot, можно создать приложение с минимальными усилиями (меньше времени и усилий). По умолчанию он предлагает большинство вещей, необходимых для разработки.

Spring Boot следует многоуровневой архитектуре и состоит из четырех слоев, как показано ниже.

  • Presentation Layer

  • Business Layer

  • Persistence Layer

  • Database Layer

architecture 1
Spring Boot Architecture

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

Краткое описание слоев приведено ниже.

  • Presentation layer
    Это front layer или верхний слой архитектуры, так как он состоит из views (представлений). Он используется для преобразования полей JSON в объекты и наоборот, а также обрабатывает аутентификацию и HTTP запросы. После завершения аутентификации он передает ее на business layer (бизнес-уровень) для дальнейшей обработки.

  • Business Layer
    Обрабатывает всю бизнес-логику, а также выполняет validation и authorization, поскольку является частью бизнес-логики. Например, только администраторы могут изменять учетную запись пользователя.

  • Persistence Layer
    Содержит всю логику хранилища, например, запросы к базе данных приложения. Он также переводит бизнес-объекты из/в записи в базе данных.

  • Database Layer
    Уровень базы данных состоит из базы данных, такой как MariaDB, PostgreSQL, MongoDB и т.д. Он может содержать несколько баз данных. Все операции, связанные с базой данных, такие как CRUD (создание, чтение/извлечение, обновление и удаление), выполняются на этом уровне.

Реализация вышеописанной многоуровневой архитектуры выполняется таким образом:

HTTP-запросы или веб-запросы обрабатываются Controllers на presentation layer, services контролируют business logic, а repositories обрабатывают persistence (логику хранения). Controller может использовать несколько services, service может использовать несколько repositories, а репозиторий может использовать несколько баз данных.

4.3.1. Spring Boot Workflow

Архитектура Spring Boot основана на Spring Framework. Таким образом, он в основном использует все функции и модули Spring-подобных Spring MVC, Spring Core и т.д., за исключением того, что нет необходимости в классах DAO и DAOImpl.

На следующей диаграмме показан workflow Spring Boot.

architecture 2
Spring Boot Architecture
  • Клиент делает HTTP-запрос (GET или POST).

  • Запрос пересылается Controller, который сопоставляет запрос и обрабатывает его. При необходимости он также вызывает логику Service.

  • Бизнес-логика выполняется на уровне Service, а логика выполняется с данными из базы данных, которые сопоставляются с Model или Entity class по средствам JPA.

  • Страница JSP возвращается в качестве ответа клиенту, если не произошло ошибки.