上文我们已经介绍过 Servlet 的使用,实际上过滤器(Filter)和 监听器(Listener)的使用与 Servlet 大同小异,不信?且听我娓娓道来。
@WebFilter(filterName="myFirstFilter",urlPatterns="/*")
public class myFirstFilter implements Filter {
@Override
public void init(FilterConfig config){
System.out.println("init()");
}
@Override
public void destroy() {
System.out.println("destroy()");
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
System.out.println("doFilter()");
arg2.doFilter(arg0, arg1);
}
}
@WebFilter 将一个实现了 javax.servlet.Filter 接口的类定义为过滤器,其中属性 filterName 是可选的,用于声明过滤器的名称,而属性 urlPatterns 是必选的,指定要过滤的URL模式。
当然 @ServletComponentScan 注解是必须加到 TestApplication.java 上的:
@ServletComponentScan
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
其中 TestApplication.java 与上面相同,我们的监听器举例就以 ServletContextListener 为例
@WebListener
public class MyFirstListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContex begin()");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContex destroy()");
}
}
@WebListener 表示注册一个监听器。我们直接运行 TestApplication.java ,可以观察到
证明我们的监听器发挥到作用。
在 Java Web 工程中,除了使用过滤器来过滤 web 请求外,我们还可以使用拦截器。他们两个的区别是,过滤器是 Servlet 的API,而拦截器是由 Spring 提供的。
其实,拦截器的功能与过滤器区别不大,但它的控制能力更强。注意,我们不能通过拦截器修改request 的内容,但我们可以暂停 request 的执行。
实现拦截器只需要三步:
下面我们进行代码的模拟
//拦截器1
public class MyFirstInterceptor implements HandlerInterceptor{
// 只有返回true才会继续向下执行,返回false取消当前请求
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("在请求处理之前进行调用 MyFirstInterceptor");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("请求处理之后,视图被渲染之前进行调用 MyFirstInterceptor");
}
//主要是用于进行资源清理工作
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("请求结束之后,渲染视图之后进行调用 MyFirstInterceptor");
}
}
//拦截器2
public class MySecondInterceptor implements HandlerInterceptor{
// 只有返回true才会继续向下执行,返回false取消当前请求
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("在请求处理之前进行调用 MySecondInterceptor");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("请求处理之后,视图被渲染之前进行调用 MySecondInterceptor");
}
//主要是用于进行资源清理工作
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("请求结束之后,渲染视图之后进行调用 MySecondInterceptor");
}
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//多个拦截器组成一个拦截器链,addPathPatterns 用于添加拦截规则,excludePathPatterns 用于排除拦截
registry.addInterceptor(new MyFirstInterceptor()).addPathPatterns("/**");
registry.addInterceptor(new MySecondInterceptor()).addPathPatterns("/**");
}
}
在浏览器输入 http://localhost:8080/hello , 控制台输出如下:
注意,拦截器与过滤器还有一个区别,只有经过 DispatcherServlet 的请求,才会走拦截器链,自定义的 Servlet 请求是不会被拦截的。而只要符合过滤器的过滤规则的 Servlet ,过滤器是来者不拒的。
参考:Spring Boot 过滤器、监听器
Spring Boot 拦截器