5.10.4. Регистрация сервлетов и фильтров
Чтобы использовать сервлеты и фильтры Spring Security, настроенные в компоненте приложения, их нужно зарегистрировать из компонента так, чтобы регистрация динамически распространялась и на родительское приложение. По умолчанию, в рамках одного приложения сервлеты регистрируются в файле конфигурации web.xml, но в случае с подключением компонентов такой подход не работает.
Для динамической регистрации сервлетов и фильтров используется бин ServletRegistrationManager: он гарантирует, что при загрузке каждого сервлета будет использован корректный ClassLoader, и позволяет обращаться к статическим классам, таким как AppContext. Этот бин необходимо использовать для корректной работы компонентов независимо от варианта развёртывания приложения.
Бин ServletRegistrationManager имеет два метода:
-
createServlet()- создаёт сервлет указанного класса. Он загружает класс сервлета с нужным экземпляромClassLoader, который получает из контекста приложения. Таким образом, новый сервлет может использовать статические классы платформы, например,AppContextили бин Messages. -
createFilter()- создаёт фильтр аналогично созданию сервлетов.
Для использования этого бина мы рекомендуем создать в компоненте приложения отдельный бин-инициализатор. Этот бин должен представлять собой обычный класс с аннотацией @Component и содержать слушатели событий создания и уничтожения контекста приложения: ServletContextInitializedEvent и ServletContextDestroyedEvent.
Пример бина-инициализатора:
@Component
public class WebInitializer {
@Inject
private ServletRegistrationManager servletRegistrationManager;
@EventListener
public void initializeHttpServlet(ServletContextInitializedEvent e) {
Servlet myServlet = servletRegistrationManager.createServlet(e.getApplicationContext(), "com.demo.comp.MyHttpServlet");
e.getSource().addServlet("my_servlet", myServlet)
.addMapping("/myservlet/");
}
}
Здесь класс WebInitializer содержит только один слушатель, который используется для регистрации HTTP-сервлета из компонента приложения в родительском приложении.
Метод createServlet() принимает контекст приложения, полученный из события ServletContextInitializedEvent, и полное имя класса HTTP-сервлета. Далее мы регистрируем сервлет по его имени (my_servlet) и указываем URL, по которому будет доступен сервлет (/myservlet/). Теперь при подключении этого компонента к другому приложению сервлет MyHttpServlet будет зарегистрирован сразу после инициализации AppContext и ServletContext.
Более сложный пример использования бина ServletRegistrationManager приведён в разделе Регистрация DispatcherServlet из компонента приложения.
- Регистрация сервлетов для развертывания в единый WAR-файл
-
Для корректной загрузки сервлетов и фильтров при развертывании в единый WAR-файл следуйте инструкции ниже:
-
Создайте класс, расширяющий
javax.servlet.ServletContextListener, который будет выполнять создание сервлетов/фильтров:public class CustomWebListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent servletContextEvent) { ServletContext servletContext = servletContextEvent.getServletContext(); registerServlet(servletContext); } @Override public void contextDestroyed(ServletContextEvent sce) { } protected void registerServlet(ServletContext servletContext) { Servlet testServlet = new TestServlet(); ServletRegistration.Dynamic servletReg = servletContext.addServlet("test_servlet", cubaServlet); servletReg.setLoadOnStartup(0); servletReg.setAsyncSupported(true); servletReg.addMapping("/testServlet"); } } -
Добавьте новый параметр
context-paramсо ссылкой на созданный класс в файлsingle-war-web.xml:<context-param> <param-name>webServletContextListener</param-name> <param-value>com.company.CustomWebListener</param-value> </context-param>
-