JavaWeb过滤器(Filter)和SpringMVC拦截器(interceptor)详解

文章目录

  • 1.Filter
    • 1.1 Filter是什么
    • 1.2 过滤器的生命周期方法
    • 1.3 编写一个过滤器
    • 1.4 Filter配置拦截路径
    • 1.5 Filter过滤器这里有一个设计模式
  • 2. 拦截器(interceptor)
    • 2.1 拦截器(interceptor)的作用
    • 2.2 拦截器和过滤器的区别
    • 2.3 HandlerInterceptor接口的方法
    • 2.4 拦截器的使用步骤

1.Filter

1.1 Filter是什么

(1)Filter是过滤器,当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能
一般用于完成通用的操作,如登录验证、统一编码处理、敏感字符过滤等等。
(2)Filter可以在servlet这个目标程序执行之前添加代码,也可以在目标servlet执行之后添加代码,之前和之后都可以添加过滤规则
(3)注意:
①Servlet对象默认情况下,在服务器启动的时候是不会创建对象的
②Filter对象默认情况下,在服务器启动的时候会创建对象
③Servlet和Filter都是单例的
④Filter的优先级,天生就比Servlet的优先级高
(4)Filter接口源码

public interface Filter {
    default void init(FilterConfig filterConfig) throws ServletException {
     }
    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
    default void destroy() {
    }
  }  

注意:通过查看源码我们发现,只有doFilter方法没有实现,我们可以只重写doFilter方法,其他两个方法可以不重写

1.2 过滤器的生命周期方法

Filter的生命周期和Servlet对象生命周期基本一致。唯一的区别是:Filter默认情况下,在服务器启动阶段就实例化。Servlet不会。

(1)init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次,用于加载资源
(2)doFilter:每一次请求被拦截资源时,会执行。执行多次
(3)destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法,只执行一次。用于释放资源

1.3 编写一个过滤器

(1)编写一个Java类实现一个接口:jarkata.servlet.Filter,并且实现这个接口当中的所有方法
(2)使用web.xml或者注解@WebFilter对其配置

@WebFilter("/*")//注解配置
public class FilterDemo implements Filter {    
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    	//在请求的时候添加过滤规则
        System.out.println("对request进行过滤");
        //执行下一个过滤器,如果下一个不是过滤器,则执行目标程序Servlet
        filterChain.doFilter(servletRequest,servletResponse); //放行
        //在响应的时候添加过滤规则
        System.out.println("对response进行过滤");
    }
}

(3)过滤的调用顺序,遵循栈数据结构

1.4 Filter配置拦截路径

(1)web.xml配置(在web.xml中进行配置的时候,Filter的执行顺序依靠filter-mapping标签的配置位置,越靠上优先级越高)

 <filter>
    <filter-name>写filter的名字</filter-name>
    <filter-class>写filter的全类名路径</filter-class>
</filter>
<filter-mapping>
    <filter-name>写filter的名字</filter-name>
    <url-pattern>写拦截路径</url-pattern>
</filter-mapping>

(2)注解配置:查看源码得以下配置项
filterName:该filter的名字
initParams:初始化参数
displayName:filter显示名称
servletNames:指定对哪些servlet进行过滤
asyncSupported:是否支持异步模式
urlPatterns:指定拦截路径
value:指定拦截路径
注意:urlPatterns和value是一样的。urlPatterns和value只能配置一个,不能两个都配置,两个都配置就会报错。
实例:

@WebFilter(filterName = "loginCheckFilter",urlPatterns = "/*")

在使用@WebFilter的时候,Filter的执行顺序是比较Filter这个类名
①比如:FilterA和FilterB,则先执行FilterA
②比如:Filter1和Filter2,则先执行Filter1

1.5 Filter过滤器这里有一个设计模式

○ 责任链设计模式。
○ 过滤器最大的优点:
■ 在程序编译阶段不会确定调用顺序。因为Filter的调用顺序是配置到web.xml文件中的,只要修改web.xml配置文件中filter-mapping的顺序就可以调整Filter的执行顺序。显然Filter的执行顺序是在程序运行阶段动态组合的。那么这种设计模式被称为责任链设计模式。
○ 责任链设计模式最大的核心思想:
■ 在程序运行阶段,动态的组合程序的调用顺序。

2. 拦截器(interceptor)

2.1 拦截器(interceptor)的作用

(1)SpringMVC的拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
(2)将拦截器按一定的顺序联结成一条链,这条链称为拦截器链(interceptor Chain)。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。拦截器也是AOP思想的具体体现。

2.2 拦截器和过滤器的区别

(1)使用范围:
①过滤器(Filter)是servlet规范中的一部分,任何JavaWeb工程都可以使用
②拦截器(interceptor)是SpringMVC框架自己的,只有使用了SpringMVC框架的工程才能使用
(2)拦截范围:
①过滤器(Filter)在url-pattern 中配置了 /* 之后,可以对所有要访问的资源进行拦截
②拦截器(interceptor)在中配置了 /** 之后,也可以对所有资源进行拦截,但是可以
通过标签排除不需要拦截的资源
(3)执行顺序:过滤器在Servlet容器中的请求处理链中的位置更靠前,而拦截器在Spring MVC框架中的请求处理链中的位置更靠后。换句话说,过滤器在请求到达Servlet之前执行,而拦截器在请求到达Controller之前或之后执行。

2.3 HandlerInterceptor接口的方法

(1) preHandle()方法
该方法将在请求处理之前被调用。SpringMVC中的Interceptor是链式的调用,在一个应用或一个请求中
可以同时存在多个Interceptor。每个Interceptor的调用会依据它的声明顺序依次执行,而且最先执行的
都是Interceptor中的preHandle()方法,所以可以在这个方法中进行一些前置初始化操作或者是对当前
请求的一个预处理,也可以在这个方法中进行一些判断来决定请求是否要继续进行下去。该方法的返回
值是布尔值类型,当返回false时,表示请求结束,后续的Interceptor和Controller都不会再执行;当返
回值true时,就会继续调用下一个Interceptor的preHandle方法,如果已经是最后一个Interceptor的
时,就会调用当前请求的Controller方法。
(2) postHandle()方法
该方法将在当前请求进行处理之后,也就是Controller方法调用之后执行,但是它会在
DispatcherServlet进行视图返回渲染之前被调用,所以我们可以在这个方法中对Controller处理之后的
ModelAndView对象进行操作。postHandle方法被调用的方向跟preHandle是相反的,也就是说先声明
的Interceptor的postHandle方法反而会后执行。如果当前Interceptor的preHandle()方法返回值为
false,则此方法不会被调用。
(3) afterCompletion()方法
该方法将在整个当前请求结束之后,也就是在DispatcherServlet渲染了对应的视图之后执行。这个方法
的主要作用是用于进行资源清理工作。如果当前Interceptor的preHandle()方法返回值为false,则此方
法不会被调用。

2.4 拦截器的使用步骤

(1)创建拦截器类实现HandlerInterceptor接口

//定义处理器拦截器
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (request.getSession().getAttribute("uid") == null) {
            response.sendRedirect("/web/login.html");
            return false; // 返回false代表不放行
        }
        return true; // 返回true代表放行
    }
}

(2)配置拦截器

//注册处理器拦截器
@Configuration
public class LoginInterceptorConfigurer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        创建拦截器对象
        HandlerInterceptor interceptor = new LoginInterceptor();
//        添加白名单
        List<String> patterns = new ArrayList<>();
        patterns.add("/bootstrap3/**");
        patterns.add("/css/**");
        patterns.add("/images/**");
        patterns.add("/js/**");
        patterns.add("/web/login.html");
        patterns.add("/web/register.html");
        patterns.add("/web/index.html");
        patterns.add("/web/product.html");
        patterns.add("/users/reg");
        patterns.add("/users/login");
        patterns.add("/districts/**");
        patterns.add("/products/**");
//        通过注册工具添加拦截器
        registry.addInterceptor(interceptor).addPathPatterns("/**").excludePathPatterns(patterns);
    }
}

①addInterceptor:需要一个实现HandlerInterceptor接口的拦截器实例
②addPathPatterns:用于设置拦截器的过滤路径规则;addPathPatterns(“/**”)对所有请求都拦截
③excludePathPatterns:用于设置不需要拦截的过滤规则

你可能感兴趣的:(servlet,java)