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>
-