Filter是JavaEE的规范,是一个接口,用于拦截请求,过滤响应,在获取目标资源之前执行
作为一个拦截器,主要的核心目的就是拦截请求数据,对session中的数据进行判断和处理
如何自定义一个Filter
-
创建一个类,继承javax.servlet.Filter接口
public class MyFilter implements Filter { }
-
重写init、destory、doFilter方法
public class MyFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { Filter.super.init(filterConfig); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { } @Override public void destroy() { Filter.super.destroy(); } }
doFilter方法是用于拦截请求的核心方法
-
在doFilter方法中处理拦截逻辑
@Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; HttpSession session = httpServletRequest.getSession(); User user = (User)session.getAttribute("user"); //没有登录,则跳转到login.jsp if (user == null) { servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse); }else{ //这段代码表示让程序继续向下访问用户的目标资源 filterChain.doFilter(servletRequest, servletResponse); } }
-
在web.xml文件中配置filter映射
<filter> <!--filter别名--> <filter-name>MyFilter</filter-name> <filter-class>com.carl.filter.MyFilter</filter-class> </filter> <filter-mapping> <!--映射<filter-name>的value值,表示当前拦截路径给哪个filter使用--> <filter-name>MyFilter</filter-name> <!--配置拦截路径 /表示请求地址为:http://ip:port/工程路径/ 即项目的web目录下 /img/* 表示img目录下的所有文件--> <url-pattern>/</url-pattern> </filter-mapping>
Filter的生命周期
- 创建构造器
- int初始化方法
在web工程启动时执行构造器和init方法,表示创建了Filter拦截器 - doFilter
浏览器每次访问web.xml中的拦截路径,就会触发调用doFilter方法 - destory
停止web工程时就会销毁拦截器
FilterConfig类
Filter拦截器的配置文件类,Tomcat每次创建Filter的时候,也会同时创建一个FilterConfig类,该类包含了Filter的配置信息
FilterConfig类的作用:
- 获取Filter的名称filter-name的内容
String filterName = filterConfig.getFilterName();
- 获取Filter中配置的init-param初始化参数
String userName = filterConfig.getInitParameter("userName"); Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
- 获取ServletContext对象
ServletContext servletContext = filterConfig.getServletContext();
FilterChain过滤器链
多个过滤器如何一起工作?FilterChain.doFilter的作用就是将所有Filter串联起来
如果存在多个过滤器,执行流程如下:
- 浏览器发起请求,经过Filter过滤器
- Filter过滤器进行拦截,并开始执行,执行到filterChain.doFilter()方法
- 判断后面是否还有其他过滤器,如果有,则执行其他过滤器,如果没有则直接访问目标资源
- 其他过滤器执行流程与上面类似,直到访问到目标资源后,才可以执行filter中的后置代码(挨个向前执行)
注意事项:
- 没有fiterChain.doFilter()将不会访问到目标资源,直接返回
- 多个Filter执行的时候,执行的优先顺序是由它们在web.xml文件中从上到下的配置顺序决定的
- 所有filter和目标资源默认都执行在同一个线程中
- 多个filter共同执行的时候,它们都使用的是同一个Request对象
Filter的拦截路径
-
精确匹配
<url-pattern>/index.jsp</url-pattern>
拦截路径必须是:
http://ip:port/工程路径/index.jsp
-
目录匹配
<url-pattern>/admin/*</url-pattern>
拦截路径必须是:
http://ip:port/工程路径/admin/
admin目录下的所有资源 -
后缀名匹配(不要用/开头)
<url-pattern>*.html</url-pattern>
拦截路径必须以
.html
结尾才会被拦截<!--常用的拦截为*.do或*.action--> <url-pattern>*.do</url-pattern> <url-pattern>*.action</url-pattern>
filter只关心请求的地址是否匹配,不关心请求的资源是否存在