Interceptor和Filter

一.Interceptor
Interceptor是Spring拦截器,要实现一个拦截器功能可以继承Spring的HandlerInterceptor接口:

package com.hpx.xiyou.wuKong.aop;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@Component
public class sanZangInterceptor implements HandlerInterceptor{
    static public final Logger logger = LoggerFactory.getLogger(sanZangInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        //System.out.println("interceptortest pre");
        logger.info("interceptortest pre");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        //System.out.println("interceptortest post");
        logger.info("interceptortest post");
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        //System.out.println("interceptortest after");
        logger.info("interceptortest after");
    }
}

HandlerInterceptor接口有三个需要实现的方法:preHandle(),postHandle()和afterCompletion()。
preHandle方法将在请求处理之前调用,SpringMVC中的Interceptor是链式调用的,每个Interceptor的调用都根据它的声明顺序依次执行,且最先执行其preHandle方法,所以可以在该方法中进行一些前置初始化操作或是预处理。该方法的返回值是布尔类型,如果返回false,表示请求结束,后续的Interceptor和Controller都不会再执行了,如果返回true就执行下一个拦截器的preHandle方法,一直到最后一个拦截器preHandle方法执行完成后调用当前请求的Controller方法。

postHandle方法是在当前请求进行处理之后,也就是Controller方法调用结束之后执行,但是它会在DispatcherServlet进行视图渲染之前被调用,所以可以在这个方法中可以对Controller处理之后的ModelAndView对象进行操作。postHandle方法被调用的方向跟preHandle是相反的,也就是说先声明的Interceptor的postHandle方法反而后执行。

afterCompletion方法需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行。该方法会在整个请求结束之后,也就是在DispatcherServlet渲染了对应的视图之后执行,这个方法的主要作用是用于资源清理工作。

实现一个interceptor拦截器类后,需要在配置中配置使它生效:实现 WebMvcConfigurerAdapter并重写 addInterceptors,同时在这个方法里设置要过滤的URL。

package com.hpx.xiyou.wuKong.Adapter;

import com.hpx.xiyou.wuKong.aop.sanZangInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;


@Configuration
public class WebConfigurerAdapter extends WebMvcConfigurerAdapter {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new sanZangInterceptor()).addPathPatterns("/wukong/**");

    }
}

以上配置生效后,当访问/wukong/**类型url时,控制台输出如下,其中controller为controller方法中的打印信息:

interceptortest pre
controller
interceptortest post
interceptortest after

二.Filter
Filter是Spring过滤器,要定义一个Filter类有以下步骤:

首先定义一个Filter类,继承javax.servlet.Filter类,重写其init、doFilter、destroy方法。init()方法会在Filter初始化后进行调用,在init()方法里面我们可以通过FilterConfig访问到初始化参数( getInitParameter()或getInitParameters() )、ServletContext (getServletContext)和当前Filter部署的名称( getFilterName() )等信息。destroy()方法将在Filter被销毁之前调用。而doFilter()方法则是真正进行过滤处理的方法,在doFilter()方法内部,我们可以过滤请求的request和返回的response,同时我们还可以利用FilterChain把当前的request和response传递给下一个过滤器或Servlet进行处理。

public class FilterTest implements Filter {
    @Autowired
    private PointService pointService;
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init yes");
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter test");
        filterChain.doFilter(servletRequest, servletResponse);  // 传递给下一个Filter进行处理
        return;
    }
 
    @Override
    public void destroy() {
        System.out.println("destroy yes");
    }
}


然后在配置中使该Filter生效:

<filter>
    <filter-name>filtertest</filter-name>
    <filter-class>FilterTest</filter-class>
</filter>
<filter-mapping>
    <filter-name>filtertest</filter-name>
    <url-pattern>/point/*</url-pattern>
</filter-mapping>
这样,当我们访问/point/*类型的url,控制台输出如下:

init yes
filter test
controller

三.比较
同时配置过滤器和拦截器然后请求,结果如下:

init yes
filter test
interceptortest pre
controller
interceptortest post
interceptortest after

可以看到filter优先于interceptor被调用。

过滤器和拦截器主要区别如下:

1.二者适用范围不同。Filter是Servlet规范规定的,只能用于Web程序中,而拦截器既可以用于Web程序,也可以用于Application、Swing程序中。
2.规范不同。Filter是在Servlet规范定义的,是Servlet容器支持的,而拦截器是在Spring容器内的,是Spring框架支持的。
3.使用的资源不同。同其他代码块一样,拦截器也是一个Spring的组件,归Spring管理,配置在Spring文件中,因此能使用Spring里的任何资源、对象(各种bean),而Filter不行。
4.深度不同。Filter只在Servlet前后起作用,而拦截器能够深入到方法前后、异常跑出前后等,拦截器的使用有更大的弹性。

5.filter、监听器是生存在web容器里的,Spring MVC容器也是存活在web容器里的,他们是平级关系,所以filter不能由Spring管理

猜你喜欢

转载自blog.csdn.net/asdfsadfasdfsa/article/details/85252361
今日推荐