@WebServlet
,@WebFilter
和@WebListener
使用问题
昨天发现一个问题。在Springboot ,使用 @WebFilter
配置过滤器时。发现jar包和war部署的效果不一样。
使用 war 包部署到 外部的Tomcat 容器, 我们配置的过滤器,会有效果。
但是使用 jar 包,使用 java -jar
命令部署,结果过滤器没有效果。
经过查阅,了解到:
@WebServlet
,@WebFilter
和@WebListener
是Servlet 3.0 出现的新规范。
当一个类由 @WebServlet
,@WebFilter
和@WebListener
声明时,会被容器能进行处理。
但是,在SpringBoot中,使用 @WebServlet
,@WebFilter
和@WebListener
注解时,
我们需要注意:
在 Springboot 内置的容器时,该类注解,需要通过@ServletComponentScan
注释,才能被使用。
这是因为 Springboot 不直接执行Servlet 3.0+ javax.servlet.ServletContainerInitializer
接口或Springorg.springframework.web.WebApplicationInitializer
接口。为了降低第三方库对Spring Boot应用程序破坏的风险。
官方文档如下:
29.4.2 Servlet Context Initialization
Embedded servlet containers do 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 third party libraries designed to run inside a war may 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.web.servlet.ServletContextInitializer interface. The single onStartup method provides access to the ServletContext and, if necessary, can easily be used as an adapter to an existing WebApplicationInitializer.
Scanning for Servlets, Filters, and listeners
When using an embedded container, automatic registration of classes annotated with @WebServlet, @WebFilter, and @WebListener can be enabled by using @ServletComponentScan.
代码使用如下:以@WebFilter
为例
@WebFilter(filterName="myFilter",urlPatterns="/*")
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("开始进行过滤处理");
//调用该方法后,表示过滤器经过原来的url请求处理方法
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void destroy() {
}
}
如果部署时,使用的是springboot 内置容器。需要使用@ServletComponentScan
@SpringBootApplication
@ServletComponentScan
public class DemoApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
如果使用外部容器时
@SpringBootApplication
public class DemoApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
/**
* 实现SpringBootServletInitializer可以让spring-boot项目在web容器中运行
*/
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(DemoApplication.class);
}
}