Spring MVC приложение за 15 минут

2 minute read

Введение

Spring web фреймворк разработан, чтобы облегчить жизнь современному enterprise разработчику создающему web-приложения. Он базируется на популярном архитектурном шаблоне: MVC(Model-View-Controller). Приложения получается слабо связными и гибкими в настройке как и сам Spring фреймворк.

Жизненный цикл запроса

Каждый раз когда пользователь нажимает ссылку или отправляет форму в web-браузере запрос отправляется на сервер. Давайте посмотрим на схему обработки запроса в Spring MVC(ссылка кликабельна и ведет на документацию на spring.io):

image-left

Spring MVC использует подход называемый wiki/Front_controller. В роли главного сервлета или front controller, принимающего все входящие запросы выступает DispatcherServlet. Работа DispatcherServlet состоит в том, чтобы послать запрос на соответствующий Spring MVC контроллер. Он пользуется помощью так называемых handler mappings которые помогают ему определить какой именно контроллер нужно вызвать.

После этого контроллер начинает отрабатывать.

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

Обычно после выполнения бизнес-логики пользователю нужно показать какую то информацю как результат. Эта информация обычно храниться в модели. Однако информация пеед показом должна пройти обработку, чтобы принять удобоваримый вид, например HTML. Для этого контроллер посылает модель и название view обратно в DispatcherServlet. Таким образом контролеер отвязан от конкретной реализации view. DispatcherServlet посылает запрос в view resolver чтобы понять какую действительно HTML-страницу нужно показать пользователю.

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

Начиная с версии Servlet 3.0 мы можем использовать не web.xml а Java-конфигурацию. Рекомендуется наследоваться от AbstractAnnotationConfigDispatcherServletInitializer который предоставляет возможность настроить 2 контекста: AppConfig и WebConfig

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        // AppConfig defines beans that would be in root-context.xml
        return new Class[] { AppConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        // WebConfig defines beans that would be in servlet.xml
        return new Class[] { WebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

}

Важно понимать разницу между корневым ApplicationContext и WebServletApplicationContext. Первый обычно содержит все сервисные и инфрастуктурные бины вашего приложения. Второй обычно содержит контекст относящийся к отдельному DispatcherServlet.

Как вы уже догадались, в отдельном приложении может быть несколько DispatcherServlet.

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

Рекомендую почитать информацию по этой теме тут: what-is-the-difference-between-applicationcontext-and-webapplicationcontext

image-left

В простейшем случае настройка WebAppContext сведется к такому Java-config:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "ru.smartcoder.spring_mvc_example.controller")
public class WebConfig extends WebMvcConfigurerAdapter {

    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setViewClass(JstlView.class);
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }

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

}
  • @EnableWebMvc поможет включить Spring MVC без дополнительных xml настроек
  • viewResolever метод создаст бин типа ViewResolver который поможет DispatcherServlet определить нужную JSP для отображения.
  • метод configureDefaultServletHandling перенаправит все запросы на статические ресурсы с DispatcherServlet на сервлет вашего контейнера для лучшей производительности what-does-configuredefaultservlethandling-means

Таким может быть настройка корневого контекста:

@Configuration
@ComponentScan(basePackages={"ru.smartcoder.spring_mvc_example.service"},
        excludeFilters={
                @ComponentScan.Filter(type= FilterType.ANNOTATION, value=EnableWebMvc.class)
        })
public class AppConfig {
}

Заметьте, что для того, чтобы исключить из @ComponentScan конфигурацию с аннотацией @EnableWebMvc мы использовали параметр excludeFilters. В данном приложении это необязательно, однако стоит иметь ввиду имеющиеся возможности у component scan preventing-a-enablewebmvc-annotated-class

Запуск

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

tomcat7:run

Зайдя по ссылке http://localhost:9090/hello вы увидите что наш контроллер отработал успешно.

Заключение

Рабочий код можно скачать по ссылке: https://github.com/levrun/spring-mvc-example

Leave a Comment