前言
过滤器和拦截器,说到他俩,不得不对比一下,先来说说他俩的区别以及执行的先后顺序问题。
区别
- 适用范围不同:Filter是Servlet规范规定的,只能用于Web程序中。而拦截器既可以用于Web程序,也可以用于Application、Swing程序中。
- 规范不同:Filter是在Servlet规范中定义的,是Servlet容器支持的。而拦截器是在Spring容器内的,是Spring框架支持的。
- 使用的资源不同:同其他的代码块一样,拦截器也是一个Spring的组件,归Spring管理,配置在Spring文件中,因此能使用Spring里的任何资源、对象,例如Service对象、数据源、事务管理等,通过IOC注入到拦截器即可;而Filter不能。
- 深度不同:Filter旨在Servlet前后起作用。而拦截器能够深入到方法前后、异常抛出前后能,因此拦截器的使用具有更大的弹性。所以在Spring架构的程序中,要优先使用拦截器。
- 触发时间不同:请求通过Tomcat > Filter > Servlet > Interceptor >Controller,由此可见,过滤器先触发,拦截器后触发
流程图
使用情况
过滤器的实现基于回调函数。 而拦截器(代理模式)的实现基于反射,代理分静态代理和动态代理,动态代理是拦截器的简单实现。
何时使用拦截器?何时使用过滤器?
- 如果是非spring项目,那么拦截器不能用,只能用过滤器。
- 如果是处理controller前后,既可以使用拦截器也可以使用过滤器。
- 如果是处理dispatcherServlet前后,只能使用过滤器。
过滤器的基本使用方法
方法一:
1、 创建FirstFilter类并实现Filter接口
注意:该接口是javax.servlet包下的
2、 重写方法
注意:Filter属于Servlet的子技术,所以启动类@ServletComponentScan注解可以扫描到此@WebFilter的类。
package com.example.demo.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
//配置拦截信息
@WebFilter(filterName = "ControlFilter",urlPatterns = {"/*"})
public class ControlFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//...逻辑操作
//放行
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
在启动器类中添加扫描Filter类的注解@ServletComponentScan
package com.example.demo;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
@SpringBootApplication
@MapperScan("com.example.demo.mapper")
//扫描WebFilter注解
@ServletComponentScan
public class RaiseApplication {
public static void main(String[] args) {
SpringApplication.run(RaiseApplication.class, args);
}
}
拦截器的基本使用方法
创建MyHandlerInterceptor类,然后实现HandlerInterceptor接口,重写 preHandle()方法
package com.example.demo.Interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class MyHanderInterceotor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//简单判断用户是否登录
HttpSession session=request.getSession();
Object ob=session.getAttribute("userIsNull");
if(ob==null){
return false;
}
System.out.println(3);
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
到这儿还没完,Springboot不知道这里是拦截器,接下来还需要Springboot和MyHandlerInterceptor的关系。创建InterceptorConfig类,内容如下:
package com.example.demo.config;
import com.core.raise.Interceptor.MyHanderInterceotor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.ArrayList;
import java.util.List;
//添加Springboot配置扫描注解,该注解会在Springboot项目启动的时候被加载
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加拦截路径
List<String> list=new ArrayList<>();
list.add("/*");
List<String> list2=new ArrayList<>();
list2.add("/toLogin");
list2.add("/toAddUser");
registry.addInterceptor(new MyHanderInterceotor())
.addPathPatterns(list)//指定黑名单,只要匹配到路径就运行拦截器的方法
.excludePathPatterns(list2);//指定白名单,直接绕过拦截器
}
}