JAVAWEB学习(8) -过滤器

过滤器(Filter)

1. 什么是过滤器

过滤器是servlet规范当中定义的一种特殊的组件,用来拦截servlet容器的调用过程。

当servlet容器收到请求之后,如果有过滤器,会先调用过滤器

过滤器一般用于登录权限验证、资源访问权限控制、敏感词汇过滤、字符编码转换等等操作,便于代码重用,不必每个servlet中还要进行相应的操作。
在这里插入图片描述

2. 过滤器是如何实现拦截的

Filter接口中有一个doFilter方法,当我们编写好Filter,并配置对哪个web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下目的:

  1. 调用目标资源之前,让一段代码执行。
  2. 是否调用目标资源(即是否让用户访问web资源)。
  3. 调用目标资源之后,让一段代码执行。

web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中最重要的一个对 象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法,调用该方法,则web服务器就会调用web资源的service方 法,即web资源就会被访问,否则web资源不会被访问。

3. 如何写过滤器

3.1 写一个java类,实现Filter接口

public class CommentFilter implements Filter {

	/**
	 * 容器启动之后,会立即将过滤器实例化
	 * 只会创建一个实例
	 */
	public CommentFilter() {
		System.out.println("CommentFilter的构造器");
	}

	/**
	 * 容器在删除过滤器实例之前,会调用destroy方法
	 * 该方法只会执行一次
	 */
	public void destroy() {
		System.out.println("commentFilter的destroy方法");
	}

	/**
	 * 容器会调用doFilter放来来处理请求(类似于service方法)
	 * FilterChain(过滤器链):如果调用了该对象的doFilter方法,表示继续向后执行,
	 * 	否则中断请求,返回处理结果。
	 * 
	 * ServletRequest是HttpServletRequest的父接口
	 * ServletResponse是HttpServletResponse的父接口
	 * 这儿使用父接口是因为这是sun公司过度设计的产物
	 */
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("CommentFilter的doFilter方法开始执行...");
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) res;
		HttpSession session=request.getSession();
		
        String path=req.getRequestURI();
        Integer uid=(Integer)session.getAttribute("userid");
        if(path.indexOf("/login.jsp")>-1){//登录页面不过滤
            chain.doFilter(req, res);//递交给下一个过滤器
            return;
        }
        if(path.indexOf("/register.jsp")>-1){//注册页面不过滤
            chain.doFilter(req, res);
            return;
        }
        
        if(uid!=null){//已经登录
            chain.doFilter(req, res);//放行,递交给下一个过滤器
            
        }else{
            response.sendRedirect("login.jsp");
        }
        
		System.out.println("CommentFilter的doFilter方法执行完毕");
	}

	/**
	 * 容器在创建好过滤器实例之后会调用该实例的Init方法
	 * 该方法只会执行一次
	 * FilterConfig对象类似于ServletConfig,可以用来读取初始化参数
	 */
	public void init(FilterConfig arg0) throws ServletException {
		System.out.println("CommentFilter的Init方法");
	}
}

3.2 配置过滤器(web.xml)

<!--配置过滤器-->
<filter>
  	<filter-name>commentFilter</filter-name>
  	<filter-class>web.CommentFilter</filter-class>
</filter>
<!--映射过滤器-->
<filter-mapping>
  	<filter-name>commentFilter</filter-name>
  	<url-pattern>/comment</url-pattern>
</filter-mapping>

配置过滤器一般有以下规则:

  1. 作用与所有web资源:<url—pattern>/*</url-pattern>。则客户端请求访问任意资源文件时都要经过过滤器过滤,通过则访问文件,否则拦截

  2. 作用于某一文件夹下所有文件:<url—pattern>/dir/*</url-pattern>

  3. 作用于某一种类型的文件:<url—pattern>.扩展名</url-pattern>

    比如<url—pattern>.jsp</url-pattern>过滤所有对jsp文件的访问请求

  4. 作用于某一文件夹下某一类型文件:<url—pattern>/dir/*.扩展名</url-pattern>

    扫描二维码关注公众号,回复: 4204174 查看本文章

4. 过滤器的优先级(Filter链)

在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。

web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

在这里插入图片描述

如图,浏览器发出的请求先递交给第一个filter进行过滤,符合规则则放行,递交给filter链中的下一个过滤器进行过滤。过滤器在链中的顺序与它在web.xml中配置的顺序有关,配置在前的则位于链的前端。当请求通过了链中所有过滤器后就可以访问资源文件了,如果不能通过,则可能在中间某个过滤器中被处理掉。

**在doFilter()方法中,chain.doFilter()前的一般是对request执行的过滤操作,chain.doFilter后面的代码一般是对response执行的操作。**过滤链代码的执行顺序如下:

在这里插入图片描述

5. 过滤器的生命周期


实例化 --> 初始化 --> 处理拦截 --> 销毁

注意:init方法也只会执行一次,destroy方法也只会执行一次


5.1 Filter的创建(实例化)

/**
 * 容器启动之后,会立即将过滤器实例化
 * 只会创建一个实例
 */
public CommentFilter() {
	System.out.println("CommentFilter的构造器");
}

5.2 Filter调用Init()方法(初始化)

/**
 * 容器在创建好过滤器实例之后会调用该实例的Init方法
 * 该方法只会执行一次
 * FilterConfig对象类似于ServletConfig,可以用来读取初始化参数
 */
public void init(FilterConfig arg0) throws ServletException {
	System.out.println("CommentFilter的Init方法");
}

5.3 Filter方法执行(处理拦截)

/**
 * 容器会调用doFilter放来来处理请求(类似于service方法)
 * FilterChain(过滤器链):如果调用了该对象的doFilter方法,表示继续向后执行,
 * 	否则中断请求,返回处理结果。
 */
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("CommentFilter的doFilter方法开始执行...");
		...
		System.out.println("CommentFilter的doFilter方法执行完毕");
	}

5.4 Filter调用destroy()方法(销毁)

/**
 * 容器在删除过滤器实例之前,会调用destroy方法
 * 该方法只会执行一次
 */
 public void destroy() {
	 System.out.println("commentFilter的destroy方法");
 }

猜你喜欢

转载自blog.csdn.net/yisany_Q/article/details/83349406