一、过滤器(Filter)和拦截器(Interceptor)的区别:
- 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
- 拦截器是在Spring容器内的,是Spring框架支持的;
过滤器是Servlet容器支持的。 - Interceptor 需要在SpringMVC中配置,Filter 需要在web.xml中配置。
- 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
- 拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
- action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
- 拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
二、过滤器(Filter)【登录过滤】
- 在HttpServletRequest到达 Servlet 之前,拦截客户的HttpServletRequest。
- 根据需要检查HttpServletRequest,也可以修改HttpServletRequest 头和数据。
- 在HttpServletResponse到达客户端之前,拦截HttpServletResponse 。
- 根据需要检查HttpServletResponse,也可以修改HttpServletResponse头和数据。
- 新建过滤类,实现Filter接口
public class LoginFilter implements Filter {
//初始化,容器中过滤器生成的时候调用;
@Override
public void init(FilterConfig arg0) throws ServletException {}
//拦截请求,过滤器主要代码(这个方法完成实际的过滤操作)
//当用户请求访问与过滤器关联的URL的时候,Servlet过滤器将先执行doFilter方法。FilterChain参数用于访问后续过滤器。
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)request;
HttpServletResponse response = (HttpServletResponse)response;
HttpSession session = request.getSession();
// 获得用户请求的URI
String path = request.getRequestURI();
//登录相关的不拦截
if (path.contains("login")) {
chain.doFilter(servletRequest, servletResponse);
return;
}
//判断用户是否已经登录
if(session.getAttribute("LOGIN_USER")==null){
//用户未登录,重定向
response.sendRedirect(request.getContextPath()+"/login");
}else{
//放行,通过了当前过滤器,递交给下一个filter进行过滤
chain.doFilter(request, response);
}
}
//销毁,容器中过滤器销毁的时候调用
@Override
public void destroy() {}
}
- 在
web.xml
中进行配置:(多个过滤器的执行顺序跟xml文件中定义的先后关系有关)
<filter>
<filter-name>loginFIlter</filter-name>
<filter-class>com.yt.bookstore.util.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFIlter</filter-name>
<!--对所有的url使用自己写的过滤器-->
<url-pattern>/*</url-pattern>
</filter-mapping>
三、拦截器(Interceptor)【登录拦截】
- 新建拦截类,实现HandlerInterceptor接口
public class LoginInterceptor implements HandlerInterceptor {
//在请求处理的方法之前执行
//如果返回true执行下一个拦截器
//如果返回false就不执行下一个拦截器
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o)
throws Exception {
HttpSession session = request.getSession();
if(session.getAttribute("LOGIN_USER")!=null) {
// 登录成功不拦截
return true;
}else {
// 拦截后进入登录页面
response.sendRedirect(request.getContextPath()+"/login");
return false;
}
//System.out.println("------------处理前------------");
return true;
}
//在请求处理方法执行之后,返回modelAndView之前执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o, ModelAndView modelAndView) throws Exception {
//System.out.println("------------处理后------------");
}
//在dispatcherServlet处理后执行,做清理工作.
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) throws Exception {
//System.out.println("------------清理------------");
}
}
- 在
spring-mvc.xml
的配置文件中进行配置
<!-- 配置拦截器 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- 拦截所有mvc控制器 -->
<mvc:mapping path="/**"/>
<!-- mvc:exclude-mapping是另外一种拦截,它可以在你后来的测试中对某个页面进行不拦截,这样就不用在 LoginInterceptor的preHandler方法里面获取不拦截的请求uri地址了(优选) -->
<mvc:exclude-mapping path="/login"/>
<bean class="com.yt.bookstore.util.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
过滤器、拦截器的各方法执行顺序感谢!