https://www.cnblogs.com/pomer-huang/p/9639322.html
https://blog.csdn.net/qq_38709999/article/details/99986797
SpringBoot 配置 서블릿, 필터, 리스너
SpringBoot 애플리케이션에서 둘 이상의 인터페이스를 통해 서블릿 3.0 컨테이너와 직접적 ServletContainerInitializer WebApplicationInitializer을, 즉 매립 구현 서블릿, 필터, 수신기 구성은 외부 코드의 애플리케이션에 대한 손상을 방지하도록 설계되어, 잘못 다음과 같이 프로그램은 읽기
임베디드 서블릿 컨테이너는 직접 서블릿 3.0 javax.servlet.ServletContainerInitializer 인터페이스를 실행하거나 봄의 org.springframework.web.WebApplicationInitializer 인터페이스하지 않습니다. 이 제 3의 라이브러리는 봄 부팅 응용 프로그램을 중단하는 전쟁 내에서 실행하도록 설계 위험을 줄이기위한 의도적 인 디자인 결정이다.
당신이 봄 부팅 응용 프로그램에서 서블릿 컨텍스트 초기화를 수행해야하는 경우 org.springframework.boot.context.embedded.ServletContextInitializer 인터페이스를 구현하는 bean을 등록해야합니다. 단일 onStartup 방법은 ServletContext에 대한 액세스를 제공하고, 필요한 경우 쉽게 기존 WebApplicationInitializer에 어댑터로서 사용될 수있다.
요약하면, 다음과 같은 구성을 취할 수
구성 정책 : ServletContextInitializer
공식 텍스트로 우리가 대안을 사용할 수 있음을 보여줍니다 다음과 같이 ServletContextInitializer, 예입니다
@Configuration
public class GoServletContextInitializer implements ServletContextInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { //配置 Log4j Config Listener servletContext.setInitParameter("log4jConfigLocation", "classpath:config/properties/log4j.properties"); servletContext.addListener(Log4jConfigListener.class); //配置 CharacterEncodingFilter FilterRegistration.Dynamic characterEncodingFilter = servletContext.addFilter("characterEncodingFilter", CharacterEncodingFilter.class); characterEncodingFilter.setInitParameter("encoding", "UTF-8"); characterEncodingFilter.setInitParameter("forceEncoding", "true"); characterEncodingFilter.addMappingForUrlPatterns( EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE), false, "/*"); //配置 statViewServlet StatViewServlet statViewServlet = new StatViewServlet(); ServletRegistration.Dynamic dynamic = servletContext.addServlet( "statViewServlet", statViewServlet); dynamic.setLoadOnStartup(2); dynamic.addMapping("/druid/*"); } }
봄 부팅 WAR로 포장하고, 톰캣 8.5에 배포 프로 테스트, 경우에도,이 구성은 효과적이다
구성 전략 2 : ServletContextInitializer의 확장
클래스 상속 시스템을 참조하십시오
원리 : 맨 아래 세 개의 서브 클래스가 자동으로 실행 서블릿, 리스너, 필터에 등록한다 (확인은 콩 스프링 컨테이너로 정의 할 수 있습니다)
- ServletRegistrationBean : 서블릿 컨테이너를 초기화 할 때, ServletContext를 사용자 정의 서블릿을 등록
- ServletListenerRegistrationBean : 서블릿 컨테이너를 초기화 할 때, ServletContext를 사용자 정의 ServletContextListener를 등록
- AbstractFilterRegistrationBean :( 템플릿 방법)을 getFilter 템플릿 (방법), 공정 지연 필터의 서브 클래스를 구축하고, 서블릿 컨테이너를 초기화 할 때, ServletContext 내 필터를 등록 할 수 있습니다. 개발자는, 템플릿 메소드를 오버라이드 (override) 사용자 정의를 구성하는 필터하기 위해 서브 클래스를 정의 할 수 있습니다.
서블릿 구성 예
@Configuration
public class ServletConfig { //配置 StatViewServlet @Bean public ServletRegistrationBean servletRegistration0() { ServletRegistrationBean registration = new ServletRegistrationBean(new StatViewServlet()); registration.addUrlMappings("/druid/*"); registration.setLoadOnStartup(0); return registration; } }
구성 예제 필터
@Configuration
public class FilterConfig { //配置 CharacterEncodingFilter @Bean public FilterRegistrationBean filterRegistration1() { FilterRegistrationBean registration = new FilterRegistrationBean(new CharacterEncodingFilter()); registration.addUrlPatterns("/*"); Map<String, String> initParameters = Maps.newHashMap(); initParameters.put("encoding", "UTF-8"); initParameters.put("forceEncoding", "true"); registration.setInitParameters(initParameters); return registration; } }
리스너 구성 예
@Configuration
public class ListenerConfig { //配置 RequestContextListener @Bean public ServletListenerRegistrationBean<RequestContextListener> listenerRegistration3() { return new ServletListenerRegistrationBean<>( new RequestContextListener()); } }
수요 : 일부 springboot 시작 코드, 초기화 데이터의 servletContext에 데이터를 자동화 할 수 있습니다. 먼저, 즉, 사용되지 않을 수 ServletContextListener @WebListener가 초기화 서블릿 컨테이너 때문에, 스프링은 초기화되지 않은 개체 스프링 @Autowired 주입을 사용할 수 없다. 권장 만약 ApplicationListener는 : 단지 만약 ApplicationListener를 구현 한 후로드 된 프로젝트, 봄을 시작하고 리스너 봄의 컨텐츠를 사용할 수 있습니다. @Component 공용 클래스 SettingDataInitListener 유단 만약 ApplicationListener <ContextRefreshedEvent> { @Override 공개 공극 onApplicationEvent (ContextRefreshedEvent ContextRefreshedEvent) { // WebApplicationContext에서 내로의 ApplicationContext WebApplicationContext에서의 WebApplicationContext = (의 WebApplicationContext) contextRefreshedEvent.getApplicationContext (); // 从의 WebApplicationContext中获取의 servletContext 의 ServletContext의 servletContext = webApplicationContext.getServletContext (); // 의 servletContext设置值 servletContext.setAttribute ( "키", "값" ); }
수요 : 일부 springboot 시작 코드, 초기화 데이터의 servletContext에 데이터를 자동화 할 수 있습니다.
먼저, 즉, 사용되지 않을 수 ServletContextListener @WebListener가 초기화 서블릿 컨테이너 때문에, 스프링은 초기화되지 않은 개체 스프링 @Autowired 주입을 사용할 수 없다.
권장 만약 ApplicationListener는 : 단지 만약 ApplicationListener를 구현 한 후로드 된 프로젝트, 봄을 시작하고 리스너 봄의 컨텐츠를 사용할 수 있습니다.
在SpringBoot应用中,嵌入式的 Servlet 3.0+ 容器不会直接使用 ServletContainerInitializer 和 WebApplicationInitializer,即通过以上两个接口实现的 Servlet、Filter、Listener 配置都是无效的,这是为了防止第三方代码的设计损坏应用程序,原文如下
Embedded servlet containers will not directly execute the Servlet 3.0+ javax.servlet.ServletContainerInitializer interface, or Spring’s org.springframework.web.WebApplicationInitializer interface. This is an intentional design decision intended to reduce the risk that 3rd party libraries designed to run inside a war will break Spring Boot applications.
If you need to perform servlet context initialization in a Spring Boot application, you should register a bean that implements the org.springframework.boot.context.embedded.ServletContextInitializer interface. The single onStartup method provides access to the ServletContext, and can easily be used as an adapter to an existing WebApplicationInitializer if necessary.
综上,可以采取以下配置
配置策略一:ServletContextInitializer
由官方原文可知,我们可以使用替代方案:ServletContextInitializer,示例如下
@Configuration
public class GoServletContextInitializer implements ServletContextInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { //配置 Log4j Config Listener servletContext.setInitParameter("log4jConfigLocation", "classpath:config/properties/log4j.properties"); servletContext.addListener(Log4jConfigListener.class); //配置 CharacterEncodingFilter FilterRegistration.Dynamic characterEncodingFilter = servletContext.addFilter("characterEncodingFilter", CharacterEncodingFilter.class); characterEncodingFilter.setInitParameter("encoding", "UTF-8"); characterEncodingFilter.setInitParameter("forceEncoding", "true"); characterEncodingFilter.addMappingForUrlPatterns( EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.INCLUDE), false, "/*"); //配置 statViewServlet StatViewServlet statViewServlet = new StatViewServlet(); ServletRegistration.Dynamic dynamic = servletContext.addServlet( "statViewServlet", statViewServlet); dynamic.setLoadOnStartup(2); dynamic.addMapping("/druid/*"); } }
亲测,即使将 Spring Boot 打包成 war,并部署到 Tomcat 8.5,这份配置也是有效的
配置策略二:ServletContextInitializer 的延伸
请看类继承体系
原理:最下边的三个子类会自动在运行时注册 Servlet、Listener、Filter(一定要将其定义为 Spring 容器的 Bean)
- ServletRegistrationBean:在Servlet容器初始化时,向 ServletContext 注册一个自定义的 Servlet
- ServletListenerRegistrationBean:在Servlet容器初始化时,向 ServletContext 注册一个自定义的 ServletContextListener
- AbstractFilterRegistrationBean :( 템플릿 방법)을 getFilter 템플릿 (방법), 공정 지연 필터의 서브 클래스를 구축하고, 서블릿 컨테이너를 초기화 할 때, ServletContext 내 필터를 등록 할 수 있습니다. 개발자는, 템플릿 메소드를 오버라이드 (override) 사용자 정의를 구성하는 필터하기 위해 서브 클래스를 정의 할 수 있습니다.
서블릿 구성 예
@Configuration
public class ServletConfig { //配置 StatViewServlet @Bean public ServletRegistrationBean servletRegistration0() { ServletRegistrationBean registration = new ServletRegistrationBean(new StatViewServlet()); registration.addUrlMappings("/druid/*"); registration.setLoadOnStartup(0); return registration; } }
구성 예제 필터
@Configuration
public class FilterConfig { //配置 CharacterEncodingFilter @Bean public FilterRegistrationBean filterRegistration1() { FilterRegistrationBean registration = new FilterRegistrationBean(new CharacterEncodingFilter()); registration.addUrlPatterns("/*"); Map<String, String> initParameters = Maps.newHashMap(); initParameters.put("encoding", "UTF-8"); initParameters.put("forceEncoding", "true"); registration.setInitParameters(initParameters); return registration; } }
리스너 구성 예
@Configuration
public class ListenerConfig { //配置 RequestContextListener @Bean public ServletListenerRegistrationBean<RequestContextListener> listenerRegistration3() { return new ServletListenerRegistrationBean<>( new RequestContextListener()); } }