过滤器和拦截器的区别

一、拦截器和过滤器的区别

  1. 拦截器(Interceptor)只对action请求起作用 即对外访问路径
    而过滤器(Filter)则可以对几乎所有的请求都能起作用 包括css js等资源文件

  2. 拦截器(Interceptor)是在Servlet和Controller控制器之间执行
    而过滤器(Filter)是在请求进入Tomcat容器之后 但是在请求进入Servlet之前执行

  3. 拦截器是基于java的反射机制的,而过滤器是基于函数回调。

  4. 拦截器不依赖与servlet容器,过滤器依赖与servlet容器。

  5. 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。

  6. 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。

  7. 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。

  8. 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。拦截器可以获取ioc中的service bean实现业务逻辑。

二、拦截器和过滤器的代码实现

1.拦截器

首先需要一个拦截器类 并且这个类要实现HandlerInterceptor接口,这个接口里面有三个方法:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
    // 在拦截点(Controller方法处理之前)执行拦截 若返回的是false则中断执行 反之亦然
    return false;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception{
    // 在处理过程中(Controller方法处理完之后 DispatcherServlet进行视图的渲染之前)执行拦截
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception{
    // 在DispatcherServlet进行视图的渲染后 返回前进行拦截
}

稍微写一下方法:

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
     // 在Controller方法处理之前执行拦截 若返回的是false则中断执行 反之亦然
 
     // 判断当前的User是否为空 若不为空则不拦截
     if (request.getSession().getAttribute("USERINFO")!=null){
         return true;
     }
     // 进行拦截 返回登录界面
     response.sendRedirect(request.getContextPath()+"/user/doLogin.do");
     return false;
 }

然后需要去SpringMVC的配置文件中配置拦截器:

<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 拦截所有的mvc控制器(Controller) -->
<mvc:mapping path="/**"/>
<!-- 放行机制 指定对某个页面不进行拦截 -->
<!-- 拦截器只对action起作用 因此填入的不是页面路径 而是方法 -->
<mvc:exclude-mapping path="/user/doLogin.do"/>
<!-- 指定使用哪个拦截器 -->
<bean class="net.zjitc.interceptor.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>

如此 当访问的请求不为/user/doLogin.do会被拦截然后重定向到/user/doLogin.do

但是访问其它的页面不会被拦截

想要让页面也被拦截则需要过滤器

2.过滤器

同理 需要一个过滤器类 然后实现javax.servlet.Filter接口

注意Filter的路径别导错了 因为有很多同名接口

public class LoginFilter implements Filter {
 
     @Override
     public void init(FilterConfig filterConfig) throws ServletException{
         // 过滤器初始化
     }
 
     @Override
     public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException{
 
     }
 
     @Override
     public void destroy(){
         // 过滤器销毁
     }
 }

稍微写一下方法:

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException{
     // ServletRequest是一个接口 而HttpServletRequest是接口的实现
     // 但有些方法是HttpServletRequest独有的 例如getSession()
     // HttpServletRequest接口继承自ServletRequest接口 增加了和Http相关的方法
     // 但是我们可以强制转换
     HttpServletRequest request=(HttpServletRequest)servletRequest;
     HttpServletResponse response=(HttpServletResponse)servletResponse;
 
     // 若用户没有登录
     if (request.getSession().getAttribute("USERINFO")==null && request.getRequestURI().indexOf("/user/doLogin.do")==-1){
         response.sendRedirect(request.getContextPath()+"/user/doLogin.do");
     }
     // 若用户已经登录 则继续下一个请求(继续访问)
     filterChain.doFilter(request,response);
 }

然后需去web.xml中配置过滤器:

<!-- 配置自定义的Filter 实现登录控制 -->
 <filter>
     <filter-name>sessionFilter</filter-name>
     <filter-class>net.zjitc.filter.LoginFilter</filter-class>
 </filter>
 <filter-mapping>
     <filter-name>sessionFilter</filter-name>
     <!-- 拦截所有的页面 /斜杠代表在webapp目录下 -->
     <url-pattern>/pages/*</url-pattern>
     <url-pattern>/css/*</url-pattern>
     <url-pattern>/img/*</url-pattern>
     <url-pattern>/failer.jsp</url-pattern>
 </filter-mapping>