一、概述
Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态html文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。
二、基本使用方法
2.1 步骤
- 创建Filter类对象
- 注解或者xml形式修改属性,设置拦截url
- 重写doFilter方法:chain.doFilter(request, response) 表示可以通行
2.2 注意的问题
- 注解和xml的配置,可以配置initParam参数,可以配置url,可以在init方法中获取初始参数,这些都和servlet一样,参考Servlet的具体使用方式以及http协议
- 多个过滤器存在的时候,先后顺序,在xml文件中是【mapping映射】属性先后顺序决定,在注解中是,类文件名称决定。
- servlet和filter的url的意义不一样,前者是用来被访问,后者是用于过滤拦截,比如【*.jsp】标示,凡是jsp文件都要走过滤器,如果【chain.doFilter(request, response) 】方法没有,表示所有jsp文件不通行。
- 两个过滤器可以拦截同一个路径,但是servlet不可以。
- 不能写【"/"】路径符号
- doFilter方法内,必须将req和resp强转为【HttpServletRequest request】和【HttpServletResponse response】
2.3 过滤流程【重点】
两个过滤器,如下:
过滤器2,依靠xml文件配置url
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<!--过滤器的xml配置方式-->
<!--1.添加filter节点-->
<filter>
<filter-name>myfilter2</filter-name>
<filter-class>MyFilter2</filter-class>
<!--可以设置属性-->
<init-param>
<param-name>name</param-name>
<param-value>张三</param-value>
</init-param>
</filter>
<!--添加映射-->
<!--该方式的配置优先级是按照filter-mapping顺序决定-->
<filter-mapping>
<filter-name>myfilter2</filter-name>
<url-pattern>*.html</url-pattern>
</filter-mapping>
</web-app>
//过滤器2
public class MyFilter2 implements Filter {
public void destroy() {
System.out.println("销毁了myfilter2");
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("处理前Myfilter2");
//chain.doFilter(req, resp);
System.out.println("处理后myfilter2");
}
public void init(FilterConfig config) throws ServletException {
System.out.println("初始化myfilter2");
/*可以在xml设置属性,并获取*/
String name = config.getInitParameter("name");
System.out.println(name);
}
}
//过滤器1,注解配置
@WebFilter(filterName = "MyFilter1",value = "/hello.jsp",initParams = {
@WebInitParam(name = "age", value = "40")})
public class MyFilter1 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化myFilter1");
/*可以在注解里面设置属性,并获取,优先级是xml最高*/
String age = filterConfig.getInitParameter("age");
System.out.println(age);
}
@Override
/**
* 过滤器链FilterChain
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("过滤前处理MyFilter1_before。。。。");
//chain.doFilter(request, response); //放行目标资源,允许执行,没有该方法,表示拦截
System.out.println("过滤后处理MyFilter1_after。。。。");
}
@Override
public void destroy() {
//销毁
System.out.println("销毁了myfilter1");
}
}
两个过滤器拦截不同,过滤器1是【"/hello.jsp"】,过滤器2是【"*.html"】
来回都可以过滤,资源1和资源2就是url部分,想要处理哪个资源就将其放入。可以双向过滤,如果要在来时过滤,则在过滤器中使用【request】方法,反之,使用【response】方法。
三、案例
3.1 自动登录案例
当前端页面,用户勾选了【记住帐号密码】,浏览器会将用户的登录信息放到【cookie】,加密保存,下次登录的时候,直接检查cookie,如果匹配则直接登录。
这里要注意还有一种情况:用户登录以后,没有关掉浏览器,会话还存在的情况下,属于已经登录状态,无须再次登录。这就需要用session进行本次会话的监视。
这里的自动登录,是不需要用户输入了,但其实还是需要将信息给到服务器,让服务器帮忙登录的。
关于cookie和session的使用方式,详见《Web的状态管理——Cookie和session技术的使用》
正常访问流程
这样的话,如果浏览器直接访问主页,也能进入主页,但是没有登录信息,就是登录失败。
自动登录,信息在cookie,过滤器通过cookie比对,成功后,将用户名放入session,这样,主页可以拿到用户名了,也就登录成功了
登录界面
<html>
<head>
<title>用户登录</title>
</head>
<body>
<h2>用户登录</h2>
<form action="${pageContext.request.contextPath}/login" method="post" enctype="application/x-www-form-urlencoded">
用户名<input type