Java -- Filter(过滤器)

一、过滤器简介

1. 什么是过滤器

Filter(过滤器)是依赖于 Servlet 容器运行的,开发人员通过该技术,可以实现用户在访问某个目标资源之前,用来过滤用户的请求和响应,修改用户的请求和响应的数据,对请求进行拦截。如果某个功能是很多Web资源都需要执行,我们就可以在过滤器中集中进行处理。

2. 过滤器应用场景

  • 统一解决 post 提交请求乱码
  • 登录权限检查
  • 资源访问权限控制
  • 过滤用户发表内容中的非法字符

二、创建 First Filter Demo

1. 使用 Filter步骤

  • 创建一个类实现过滤器接口
  • 注解配置过滤器拦截的请求路径
  • doFilter()中编写过滤操作
  • FilterChain.doFilter()放行

2. 代码
  使用注解配置Filter,也可把配置信息放在 web.xml。

package com.zz.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

//编写过滤的路径: urlPatterns过滤的路径,只有访问welcome的时候过滤器才会执行。
@WebFilter(filterName = "FilterDemo",urlPatterns = "/welcome")
public class FilterDemo implements Filter {

    //编写过滤任务的代码
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        
        System.out.println("过滤器执行了...");
        //如果您允许客户访问目标资源
        chain.doFilter(request,response);  //放行..
    }

    public void init(FilterConfig config) throws ServletException {
		System.out.println("过滤器执初始化");
    }

    public void destroy() {
    	System.out.println("过滤器销毁了");
    }
}

3. 工作原理
  当过滤器类被载入容器并实例化后,容器会运行其init()方法并传入 FilterConfig对象作为参数。FilterConfig 是实现Filter接口的类上使用标注或web.xml中过滤器设置信息的代表对象,如果在定义过滤器时设置了初始参数,则可以通过getInitParameter()方法来取得初始参数。
  Filter接口的 doFilter() 方法类似于Servlet接口的service方法,当请求来到容器,而在 Servlet的service方法 执行之前,就调用该过滤器的 doFilter() 方法。
  调用了FilterChain的 doFilter()方法,就会运行下一个过滤器,如果没有下一个过滤器,就会调用请求目标 Servlet的service方法。如果因为某个情况(如用户没有通过验证)而没有调用 FilterChain的doFilter方法,则请求就不会继续交给接下来的过滤器或目标Servlet,这时就是所谓的拦截请求


三、过滤器的生命周期

过滤器的生命周期包含三个方法:

1. init()

init方法是初始化方法,当过滤器被部署到web服务器时,服务器启动时执行一次。
Filter--init()

2. doFilter()

只要有一个请求符合Filter拦截路径,都会执行doFilter方法。
Filter--doFilter()

3. destroy()

destroy方法是过滤器的销毁方法,服务器停止或者将项目从服务器中移除时,执行destroy方法销毁过滤器。
Filter--destroy()

4. 生命周期总结

  • init():服务器启动时会执行一次
  • doFilter():每次有符合过滤路径的请求时,都会重复执行
  • destroy():服务器停止或者项目从服务器中移除时执行一次

四、映射路径

1. 过滤路径
配置过滤器不同的映射路径,从而让过滤器过滤希望过滤器的请求。

@WebFilter(filterName = "FilterDemo",urlPatterns = "/xxx")

2. 过滤方式

匹配方式示例含义
全局/*整个应用的配置,访问所有资源时都起作用
以指定资源匹配/index.html只有访问了index.html资源时过滤器才会起作用
以指定目录匹配/servlet/*只有访问了指定目录servlet下的资源时过滤器才会起作用
以后指定后缀名匹配*.jsp只有访问了指定后缀为.jsp的资源时过滤器才会起作用

3. 单个Filter过滤多种请求
  如果一个过滤器需要过滤多种文件,则可在web.xml中配置多个<filter-mapping>

   <filter>
      <filter-name>loginFilter</filter-name>
      <filter-class>com.zz.control.loginFilter</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>loginFilter</filter-name>
      <url-pattern>*.html</url-pattern>
  </filter-mapping>
  <filter-mapping>
      <filter-name>loginFilter</filter-name>
      <url-pattern>/login.jsp</url-pattern>
  </filter-mapping>

五、过滤器链

1. 什么是过滤器链
  过滤器链: 访问某个资源的时候会经过多个过滤器

2. 多个Filter的执行顺序
  在请求到达目标Servle之前是可以经过多个过滤器的。一般来说,建议Filter之间不要有关联,各自处理各自的逻辑即可,这样无需关心执行顺序问题。如果要考虑执行顺序,使用注解配置的话,Filter的执行顺序跟名称的字母顺序有关,例如 AFilter 会比 BFilter 先执行;使用配置文件 web.xml 时Filter的执行顺序跟 <filter-mapping> 的顺序有关,先声明的先执行。如下:BFilter比AFilter先执行。

    <!--配置BFilter的基本信息-->
    <filter>
        <!--filter的别名-->
        <filter-name>BFilter</filter-name>
        <!--filter的完整类名-->
        <filter-class>com.zz.filter.BFilter</filter-class>
    </filter>
    <filter-mapping>
        <!--filter的别名-->
        <filter-name>BFilter</filter-name>
        <!--过滤的路径-->
        <url-pattern>/login.jsp</url-pattern>
    </filter-mapping>

    <!--配置AFilter的基本信息-->
    <filter>
        <filter-name>AFilter</filter-name>
        <filter-class>com.zz.filter.AFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>AFilter</filter-name>
        <url-pattern>/index.html</url-pattern>
    </filter-mapping>

注意:在web.xml中配置过滤器时,监听器 > 过滤器 > servlet,也就是说web.xml中监听器配置在过滤器之前,过滤器配置在servlet之前,否则会出错。


六、拦截方式

1. 学习过滤器的拦截方式

Filter默认情况只会过滤 URL地址直接访问 的与 请求重定向 的资源,对于 请求转发 的资源过滤器默认是不拦截,如果需要拦截请求转发的资源,需要学习过滤器的拦截方式。

2. 两种拦截方式

  • request(默认的拦截方式):浏览器发出的请求都会进行拦截,1)直接从地址栏访问的资源; 2)请求重定向的资源;

  • forward: 拦截请求转发的资源。

代码如下:

/*
		dispatcherTypes : 用于配置拦截方式的。
        1.request    是默认的方式, 过滤 url地址直接访问的 与 请求重定向 的资源
        2.forward    过滤 请求转发 的资源
*/
@WebFilter(filterName = "DispatcherFilterDemo",urlPatterns = "/index.html",
					dispatcherTypes={DispatcherType.FORWARD,DispatcherType.REQUEST}  )
public class DispatcherFilterDemo implements Filter {

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("过滤器执行了..");
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException { }
    public void destroy() { }
}


七、登录验证案例

用过滤器实现登录验证,没登录则驳回访问请求并重定向到登录页面

public void doFilter(ServletRequest srequest, ServletResponse sresponse, FilterChain chain)
										throws IOException, ServletException {

		HttpServletRequest request = (HttpServletRequest) srequest;
		HttpServletResponse response = (HttpServletResponse) sresponse;
		HttpSession session = request.getSession();

		String path = request.getRequestURI();
		Integer uid = (Integer) session.getAttribute("userid");

		// 登录页面不过滤
		if (path.indexOf("/login.jsp") > -1) {
			// 递交给下一个过滤器
			chain.doFilter(srequest, sresponse);
			return;
		}
		// 注册页面不过滤
		if (path.indexOf("/register.jsp") > -1) {
			chain.doFilter(request, response);
			return;
		}
		
		// 已经登录
		if (uid != null) {
			// 放行,递交给下一个过滤器
			chain.doFilter(request, response);
		} else {
			response.sendRedirect("login.jsp");
		}
	}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值