Главная страница
Навигация по странице:

  • Модели (например, набор данных из БД) и возвращает их в DispatcherServlet вместе с именем Представления (View)

  • 25. Что такое ViewResolver

  • 26. Расскажите про шаблон проектирования Front Controller, как он реализован в Spring

  • ContextLoaderListener vs DispatcherServlet

  • 27. Чем отличаются Model, ModelMap и ModelAndView

  • 28. Расскажите про аннотации @Controller и @RestController. Чем они отличаются Как вернуть ответ со своим статусом (например 213)

  • 29. В чем разница между Filters, Listeners и Interceptors

  • HandlerInterceptor или наследоваться от готового класса HandlerInterceptorAdapter

  • ModelAndView modelAndView

  • DefaultAnnotationHandlerMapping

  • Ызкштп. Оглавление Введение 61. Что такое инверсия контроля (IoC) и внедрение зависимостей (DI) Как они реализованы в


    Скачать 1.17 Mb.
    НазваниеОглавление Введение 61. Что такое инверсия контроля (IoC) и внедрение зависимостей (DI) Как они реализованы в
    АнкорЫзкштп
    Дата01.11.2021
    Размер1.17 Mb.
    Формат файлаpdf
    Имя файлаmetodichka_06_Spring (3).pdf
    ТипДокументы
    #260853
    страница4 из 5
    1   2   3   4   5
    HandlerMapping, который определяет, какой Контроллер (Controller) должен быть вызван, после чего HandlerAdapter, отправляет запрос в нужный метод Контроллера.
    ❖ Контроллер принимает запрос и вызывает соответствующий служебный метод, основанный на GET, POST и т.д. Вызванный метод формирует данные Модели
    (например, набор данных из БД) и возвращает их в DispatcherServlet вместе с именем
    Представления (View) (как правило имя html-файла).
    ❖ При помощи интерфейса ViewResolver DispatcherServlet определяет, какое
    Представление нужно использовать на основании полученного имени и получает в ответе имя представления View.
    ➢ если это REST-запрос на сырые данные (JSON/XML), то DispatcherServlet сам его отправляет;
    ➢ если обычный запрос, то DispatcherServlet отправляет данные Модели в виде атрибутов в Представление (View) - шаблонизаторы Thymeleaf, FreeMarker и т.д., которые сами отправляют ответ.

    Как мы видим все действия происходят через один единственный DispatcherServlet.
    Сконфигурировать наше Spring MVC-приложение мы можем с помощью Java-config, добавив зависимость spring-webmvc и установив над классом конфигурации
    @EnableWebMvc
    , которая применит дефолтные настройки - зарегистрирует некоторые специальные бины из
    Spring MVC и адаптирует их к нашим бинам. Но, если требуется тонкая настройка, то мы можем имплементировать интерфейс WebMvcConfigurer и переопределить необходимые методы.
    Теперь нужно зарегистрировать конфигурацию в Spring Context это позволит сделать созданный нами класс
    MyWebAppInitializer, который нужно унаследовать от
    AbstractAnnotationConfigDispatcherServletInitializer, и передать в его методы классы нашей конфигурации RootConfig.class и App1Config.class: public class
    MyWebAppInitializer extends
    AbstractAnnotationConfigDispatcherServletInitializer
    {
    @Override protected
    Class[] getRootConfigClasses() { return new
    Class[] { RootConfig.class };
    }
    @Override protected
    Class[] getServletConfigClasses() { return new
    Class[] { App1Config.class };
    }
    @Override protected
    String[] getServletMappings() { return new
    String[] {
    "/*"
    };
    }
    }
    Своими внутренними методами он создает два экземпляра WebApplicationContext в виде объектов класса AnnotationConfigWebApplicationContext.
    Если же у нас только один класс конфигурации, то его нужно передать в метод getRootConfigClasses(), а getServletConfigClasses() должен возвращать null.

    25. Что такое ViewResolver?
    Источники:
    Spring - View Resolution
    Javastudy - Spring MVC – описание интерфейса ViewResolver
    Baeldung - A Guide to the ViewResolver in Spring MVC
    Все платформы MVC предоставляют способ работы с представлениями. Spring делает это с помощью ViewResolver, который позволяет отображать модели в браузере, не привязывая реализацию к определенной технологии представления.
    ViewResolver сопоставляет имена представлений, возвращаемых методами контроллеров, с фактическими представлениями (html-файлами). Spring Framework поставляется с довольно большим количеством
    ViewResolver, например
    InternalResourceViewResolver, XmlViewResolver, ResourceBundleViewResolver и несколькими другими.
    По умолчанию реализацией интерфейса
    ViewResolver является класс
    InternalResourceViewResolver.
    Любым реализациям ViewResolver желательно поддерживать интернационализацию, то есть множество языков.

    26. Расскажите про шаблон проектирования Front Controller, как он
    реализован в Spring?
    Источники:
    Baeldung - A Guide to the Front Controller Pattern in Java
    Howtodoinjava - ContextLoaderListener vs DispatcherServlet
    Spring - DispatcherServlet
    Spring - The DispatcherServlet
    Паттерн Front Controller обеспечивает единую точку входа для всех входящих запросов.
    Все запросы обрабатываются одним фрагментом кода, который затем может делегировать ответственность за обработку запроса другим объектам приложения. Он также обеспечивает интерфейс для общего поведения, такого как безопасность, интернационализация и передача определенных представлений определенным пользователям.
    В Spring в качестве Front Controller выступает
    DispatcherServlet
    , все действия проходят через него. Как правило в приложении задаётся только один DispatcherServlet с маппингом “/”, который перехватывает все запросы. Это и есть реализация паттерна Front Controller.
    Однако иногда необходимо определить два и более DispatcherServlet-а, которые будут отвечать за свой собственный функционал. Например, чтобы один обрабатывал REST-запросы с маппингом “/api”, а другой обычные запросы с маппингом “/default”. Spring предоставляет нам такую возможность, и для начала нужно понять, что:
    ❖ Spring может иметь несколько контекстов одновременно. Одним из них будет корневой контекст, а все остальные контексты будут дочерними.
    ❖ Все дочерние контексты могут получить доступ к бинам, определенным в корневом контексте, но не наоборот. Корневой контекст не может получить доступ к бинам дочерних контекстов.
    ❖ Каждый дочерний контекст внутри себя может переопределить бины из корневого контекста.
    Каждый DispatcherServlet имеет свой дочерний контекст приложения.
    DispatcherServlet по сути является сервлетом
    (он расширяет HttpServlet), основной целью которого является обработка входящих веб- запросов, соответствующих настроенному шаблону URL. Он принимает входящий URI и находит правильную комбинацию контроллера и вида. Веб-приложение может определять любое количество
    DispatcherServlet-ов. Каждый из них будет работать в своем собственном пространстве имен, загружая свой собственный дочерний
    WebApplicationContext
    (на рисунке - Servlet
    WebApplicationContext) с вьюшками, контроллерами и т.д. Например, когда нам нужно в одном Servlet WebApplicationContext определить обычные контроллеры, а в другом
    REST-контроллеры.

    WebApplicationContext расширяет ApplicationContext (создаёт и управляет бинами и т.д.), но помимо этого он имеет дополнительный метод getServletContext(), через который у него есть возможность получать доступ к ServletContext-у.
    ContextLoaderListener создает корневой контекст приложения (на рисунке - Root
    WebApplicationContext) и будет использоваться всеми дочерними контекстами, созданными всеми DispatcherServlet. Напомню, что корневой контекст приложения будет общим и может быть только один. Root WebApplicationContext содержит компоненты, которые видны всем дочерним контекстам, такие как сервисы, репозитории, компоненты инфраструктуры и т.д.
    После создания корневого контекста приложения он сохраняется в ServletContext как атрибут, имя которого:
    WebApplicationContext.class.getName() +
    ".ROOT"
    Чтобы из контроллера любого дочернего контекста обратиться к корневому контексту приложения, мы можем использовать класс WebApplicationContextUtils, содержащий статические методы:
    @Autowired
    ServletContext context;
    ApplicationContext ac =
    WebApplicationContextUtils.getWebApplicationContext(context); if
    (ac == null
    ){ return
    "root application context is null"
    ;
    }
    ContextLoaderListener vs DispatcherServlet
    1. ContextLoaderListener создает корневой контекст приложения.
    2. Каждый DispatcherServlet создаёт себе один дочерний контекст.
    3. Дочерние контексты могут обращаться к бинам, определенным в корневом контексте.
    4. Бины в корневом контексте не могут получить доступ к бинам в дочерних контекстах (напрямую).
    5. Все контексты добавляются в
    ServletContext.
    6. Мы можем получить доступ к корневому контексту, используя класс
    WebApplicationContextUtils.

    27. Чем отличаются Model, ModelMap и ModelAndView?
    Источники:
    Baeldung - Model, ModelMap, and ModelView in Spring MVC
    Spring - Interface Model
    Spring - Class ModelMap
    Spring - Class ModelAndView
    Model
    Интерфейс, лежит в пакете spring-context. В методах контроллера мы можем использовать объекты Model для того, чтобы складывать туда данные, предназначенные для формирования представлений. Кроме того, в Model мы можем передать даже Map с атрибутами:
    @GetMapping
    (
    "/showViewPage"
    ) public
    String passParametersWithModel
    (Model model)
    {
    Map map = new
    HashMap<>(); map.put(
    "spring"
    ,
    "mvc"
    ); model.addAttribute(
    "message"
    ,
    "Baeldung"
    ); model.mergeAttributes(map); return
    "viewPage"
    ;
    }
    ModelMap
    Этот класс наследуется от LinkedHashMap и по сути служит общим контейнером модели для Servlet MVC, но не привязан к нему, и лежит в пакете spring-context.
    Имеет все преимущества LinkedHashMap плюс несколько удобных методов:
    @GetMapping
    (
    "/printViewPage"
    ) public
    String passParametersWithModelMap
    (ModelMap map)
    { map.addAttribute(
    "welcomeMessage"
    ,
    "welcome"
    ); map.addAttribute(
    "message"
    ,
    "Baeldung"
    ); return
    "viewPage"
    ;
    }
    ModelAndView
    Этот класс лежит в пакете spring-webmvc и может одновременно хранить модели и представление, чтобы контроллер мог отдавать их в одном возвращаемом значении. Внутри содержит поле private Object view, куда записывает нужное представление, а также поле private
    ModelMap model, куда и складывает все атрибуты модели:
    @GetMapping
    (
    "/goToViewPage"
    ) public
    ModelAndView passParametersWithModelAndView
    ()
    {
    ModelAndView modelAndView = new
    ModelAndView(
    "viewPage"
    ); modelAndView.addObject(
    "message"
    ,
    "Baeldung"
    ); return modelAndView;
    }

    28. Расскажите про аннотации @Controller и @RestController. Чем они
    отличаются? Как вернуть ответ со своим статусом (например 213)?
    Источники:
    Baeldung - @Controller and @RestController
    Baeldung - Using Spring ResponseEntity
    @Controller
    @Controller помечает класс как контроллер HTTP-запросов. @Controller обычно используется в сочетании с аннотацией @RequestMapping, используемой в методах обработки запросов. Это просто дочерняя аннотация аннотации @Component и позволяет автоматически определять классы при сканировании пакетов.
    @RestController
    Аннотация @RestController была введена в Spring 4.0 для упрощения создания RESTful веб-сервисов. Это удобная аннотация, которая объединяет @Controller и @ResponseBody, что устраняет необходимость аннотировать каждый метод обработки запросов аннотацией
    @ResponseBody.
    @ResponseBody сообщает контроллеру, что возвращаемый объект автоматически сериализуется в json или xml и передается обратно в объект HttpResponse. Контроллер использует Jackson message converter для конвертации входящих/исходящих данных. Как правило целевые данные представлены в json или xml.
    ResponseEntity
    Данный класс используется для формирования ответа HTTP с пользовательскими параметрами (заголовки, код статуса и тело ответа). ResponseEntity необходим, только если мы хотим кастомизировать ответ. Во всех остальных случаях достаточно использовать
    @ResponseBody.
    Если мы хотим использовать ResponseEntity, то просто должны вернуть его из метода,
    Spring позаботится обо всем остальном.
    @GetMapping
    (
    "/customHeader"
    )
    ResponseEntity customHeader
    ()
    {
    HttpHeaders headers = new
    HttpHeaders(); headers.add(
    "Custom-Header"
    ,
    "foo"
    ); return new
    ResponseEntity<>(
    "Custom header set"
    , headers, HttpStatus.OK);
    }
    Если клиент ждет от нас JSON/XML, мы можем параметризовать ResponseEntity конкретным классом и добавить к ответу заголовки и Http статус:
    @RequestMapping
    (value =
    "/employees/{id}"
    ) public
    ResponseEntity getEmployeeById
    (@PathVariable(
    "id"
    )
    int id){ if
    (id <=
    3
    ) {

    EmployeeVO employee = new
    EmployeeVO(
    1
    ,
    "Lokesh"
    ,
    "Gupta"
    ,
    "howtodoinjava@gmail.com"
    ); return new
    ResponseEntity(employee, HttpStatus.OK);
    } return new
    ResponseEntity(HttpStatus.NOT_FOUND);
    }
    }

    29. В чем разница между Filters, Listeners и Interceptors?
    Источники:
    Javadoc - Interface Filter
    Javadoc - Interface ServletContextListener
    Spring API - Interface Interceptor
    Spring API - Interface HandlerInterceptor
    O7planning - Руководство Spring MVC Interceptor
    Baeldung - Introduction to Spring MVC HandlerInterceptor
    Programmer - Filters, Interceptors, Listeners
    Mkjava - Filter vs. Interceptor
    Oracle - Servlet Filters and Event Listeners
    Mkyong - ServletContextListener Example
    Filter
    Это интерфейс из пакета javax.servlet, имплементации которого выполняют задачи фильтрации либо по пути запроса к ресурсу (сервлету, либо по статическому контенту), либо по пути ответа от ресурса, либо в обоих направлениях.
    Фильтры выполняют фильтрацию в методе doFilter. Каждый фильтр имеет доступ к объекту FilterConfig, из которого он может получить параметры инициализации, и ссылку на
    ServletContext, который он может использовать, например, для загрузки ресурсов, необходимых для задач фильтрации. Фильтры настраиваются в дескрипторе развертывания веб-приложения.
    В веб-приложении мы можем написать несколько фильтров, которые вместе называются цепочкой фильтров. Веб-сервер решает, какой фильтр вызывать первым, в соответствии с порядком регистрации фильтров.
    Когда вызывается метод doFilter(ServletRequest request, ServletResponse response,
    FilterChain chain) первого фильтра, веб-сервер создает объект FilterChain, представляющий цепочку фильтров, и передаёт её в метод.
    Interceptor
    Это интерфейс из пакета org.aopalliance.intercept, предназначенный для аспектно- ориентированного программирования.
    В Spring, когда запрос отправляется в Controller, перед тем как он в него попадёт, он может пройти через перехватчики Interceptor (0 или более). Это одна из реализаций АОП в
    Spring. Вы можете использовать Interceptor для выполнения таких задач, как запись в Log, добавление или обновление конфигурации перед тем, как запрос обработается Controller-ом.

    Стек перехватчиков: он предназначен для связывания перехватчиков в цепочку в определенном порядке. При доступе к перехваченному методу или полю перехватчик в цепочке перехватчиков вызывается в том порядке, в котором он был определен.
    Мы можем использовать Interceptor-ы для выполнения логики до попадания в контроллер, после обработки в контроллере, а также после формирования представления.
    Также можем запретить выполнение метода контроллера. Мы можем указать любое количество перехватчиков.
    Перехватчики работают с HandlerMapping и поэтому должны реализовывать интерфейс
    HandlerInterceptor
    или наследоваться от готового класса HandlerInterceptorAdapter. В случае реализации HandlerInterceptor нам нужно переопределить 3 метода, а в случае
    HandlerInterceptor, только необходимые нам:
    ❖ public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
    Object handler) - вызывается после того, как HandlerMapping определил соответствующий контроллер, но до того, как HandlerAdapter вызовет метод контроллера. С помощью этого метода каждый перехватчик может решить, прервать цепочку выполнения или направить запрос на испольнение дальше по цепочке перехватчиков до метода контроллера. Если этот метод возвращает true, то запрос отправляется следующему перехватчику или в контроллер. Если метод возвращает false, то исполнение запроса прекращается, обычно отправляя ошибку HTTP или записывая собственный ответ в response.
    ❖ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) - отработает после контроллера, но перед формированием представления. Мы можем использовать этот метод для добавления дополнительных атрибутов в ModelAndView или для определения времени, затрачиваемого методом-обработчиком на обработку запроса клиента. Вы можете добавить больше объектов модели в представление, но вы не можете изменить
    HttpServletResponse, так как он уже зафиксирован.
    ❖ public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
    Object handler, Exception ex) - отработает после формирования представления.
    Вызывается только в том случае, если метод preHandle этого перехватчика успешно завершен и вернул true!

    Следует знать, что HandlerInterceptor связан с бином DefaultAnnotationHandlerMapping, который отвечает за применение перехватчиков к любому классу, помеченному аннотацией
    @Controller.
    Чтобы добавить наши перехватчики в конфигурацию Spring, нам нужно переопределить метод addInterceptors () внутри класса, который реализует WebMvcConfigurer:
    @Override public void addInterceptors
    (InterceptorRegistry registry)
    {
    // LogInterceptor applies to all URLs.
    registry.addInterceptor(
    new
    LogInterceptor());
    // This interceptor applies to URL /admin/oldLogin.
    // Using OldURLInterceptor to redirect to new URL.
    registry.addInterceptor(
    new
    OldLoginInterceptor())
    .addPathPatterns(
    "/admin/oldLogin"
    );
    // This interceptor applies to URLs like /admin/*
    // Exclude /admin/oldLogin registry.addInterceptor(
    new
    AdminInterceptor())
    .addPathPatterns(
    "/admin/*"
    )
    //
    .excludePathPatterns(
    "/admin/oldLogin"
    );
    }
    Filter vs. Interceptor
    ❖ Перехватчик основан на механизме Reflection, а фильтр основан на обратном вызове функции.
    ❖ Фильтр зависит от контейнера сервлета, тогда как перехватчик не зависит от него.
    ❖ Перехватчики могут работать только с запросами к контроллерам, в то время как фильтры могут работать почти со всеми запросами (например, js, .css и т.д.).

    ❖ Перехватчики в отличии от фильтров могут обращаться к объектам в контейнере Spring, что даёт им более изощренный функционал.
    Порядок работы:
    1. Фильтры до;
    2. Перехватчики до;
    3. Метод контроллера;
    4. Перехватчики после;
    5. Фильтры после.
    HandlerInterceptor в основном похож на
    1   2   3   4   5


    написать администратору сайта