Filter 过滤器简述

2021-12-30 0 By admin

Filter 过滤器是sun公司中servlet2.3后增加的一个新功能。Servlet规范中三个技术 Servlet、Listener、Filter。
在javaEE中定义了一个接口 javax.servlet.Filter来描述过滤器;过滤器就是实现了Filter接口的一个java类;通过过滤器可以拦截访问web资源的请求与响应操作。
WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。
例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

一、Filter 基础知识

1.1、Filter 常用API介绍

public void init(FilterConfig filterConfig) throws ServletException { }
应用程序启动时,服务器实例化Filter对象,并调用其init方法,读取web.xml配置,完成对象的初始化加载。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) }
实际的过滤操作,请求达到服务器时,Servlet容器将先调用过滤器的doFilter方法。

public void destroy() { }
容器在销毁过滤器前调用该方法,释放过滤器占用的资源。

1.2、Filter 的生命周期

  1. 当服务器启动,会创建Filter对象,并调用init()方法,只调用一次。
  2. 当访问资源时,路径与Filter的拦截路径匹配,会执行Filter中的doFilter()方法,这个方法是真正拦截操作的方法。
  3. 当服务器关闭时,会调用Filter的destroy()方法来进行销毁操作。

二、Filter 过滤器代码示例

2.1、实现Filter接口,编写过滤器

// 注解配置(@WebFilter(filterName="FilterTest",urlPatterns="/*"))
// 但这里用xml配置
public class FilterTest implements Filter {
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
	throws IOException, ServletException {
	  //表示处理Request 请求 
	  System.out.println("Filter 过滤器放行前的操作");
	  //表示放行,将请求交给下一个过滤器或者交给资源
	  chain.doFilter(request, response);
      //表示处理Response 响应
      System.out.println("响应过程中,上一个Filter或资源处理完成后,执行自此的代码");
  }
}

2.2、web.xml配置,注册Filter,绑定路径

<filter>
	<filter-name>FilterTest</filter-name>
	<filter-class>filter.FilterTest</filter-class>
</filter>
<filter-mapping>
	<filter-name>FilterTest</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

url-pattern配置

  1. 完全匹配:要求必须以”/”开始。
  2. 目录匹配:要求必须以”/”开始,以*结束。
  3. 扩展名匹配:不能以”/”开始,以*.xxx结束.例如:*.jsp *.do。

三、Filter 过滤器总结

  1. xml配置的顺序就是Filter的执行顺序,而注解方式是通过匹配地址的自然顺序执行的,这是注解的一个遗憾。
  2. 其中chain.doFilter()表示放行,配置多个过滤器时会把这些过滤器放到FilterChain里,调用它就会带上request和response,自动执行下一个过滤器。
  3. 这样的调用属于链式调用,类似于递归,调用完后还会回到该函数继续执行下面的代码
  4. chain.doFilter()如果没有下一个过滤器就访问资源。
Filter 中数据流的流向过程
Filter 中数据流的流向过程

3.1、自动登录功能实现

publicvoid doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  //1.强转
  HttpServletRequest req=(HttpServletRequest) request;
  HttpServletResponse resp=(HttpServletResponse) response;
  //2.逻辑
  //首先判断session中是否有user 若没有再继续操作
  User user = (User) req.getSession().getAttribute("user");
  if(user==null){//session中没有用户 需要继续操作
    //获取请求路径 若是login和regist的不需要自动登录
    String uri = req.getRequestURI();
    String contextPath = req.getContextPath();
    String path=uri.substring(contextPath.length());
    //System.out.println(path);
    if(!("/login.jsp".equals(path)||"/login".equals(path)||"/regist.jsp".equals(path)||"/regist".equals(path))){
    //查找是否有自动登录的cookie
    Cookie c = CookieUtils.getCookieByName("autoLogin", req.getCookies());
    if(c!=null){
      //若有 调用service 自动登录
      //拿到用户名和密码
      String username=c.getValue().split("-")[0];
      String password=c.getValue().split("-")[1];
      //调用service登录
      user = new UserService().login(username, password);
      //若登录成功 将user放入session中
      if(user!=null){
        req.getSession().setAttribute("user", user);
        System.out.println("自动登录..........");
       }
      }
    }
  }
  //3.放行
  chain.doFilter(req, resp);
}

注意:cookie中不能存放中文,若出现中文还需编码解决