大家好,我是一只学弱狗,记录学习的点点滴滴!
优质文章
优质专栏
从没有白费的努力,也没有碰巧的成功。只要认真对待生活,终有一天,你的每一份努力,都将绚烂成花。
通过本文,你可以学到
- 什么是Filter?有什么作用?如何使用?
- 什么是代理模式?其作用是什么?
- 案例演示:登陆验证功能实现
- 案例演示:敏感词汇过滤
- 什么是Listener及其如何使用?
Filter
概念
Filter,即过滤器,其功能是当客户端浏览器向服务器发送资源请求时,过滤器可以将请求拦截下来,完成一些特殊的功能,我们来看下百度百科上面的介绍:Filter可以使用户改变一个request和修改一个response,它不是一个Servlet,不能产生一个response,它能够在一个request到达Servlet之前预处理request,也可以在response离开Servlet后处理response。
使用方法
Servlet、Filter和Listener是Java Web的三大组件,它们在使用方面及其相似,小伙伴们可以先回顾一下Servlet的使用,也要两种方式,其一:配置web.xml文件,其二:使用注解。
配置文件
首先,我们需要在声明一个类,使得这个类呢实现Filter接口,实现其方法。
还没完,我们需要在web.xml文件中配置一下
记住:Filter中的url-pattern需要配置的是拦截路径,而Servlet中的yrl-pattern配置的是访问资源路径
注意代码执行的顺序,下面我们将具体的阐述
注解
执行流程
通过上面的代码演示,不难发现,过滤器的执行顺序是这样的
- 执行过滤器中放行代码之前的代码
- 执行需要访问的资源
- 回来继续执行放行代码下边的代码
深度剖析
生命周期方法
和Servlet一样,Filter的init方法是在服务器启动后,会创建Filter对象,然后调用其init方法,只执行一次,一般用于加载资源;destroy是在服务器正常关闭后,会调用destroy方法,只执行一次,用于释放资源;而doFilter方法,在每一次请求被拦截时,会执行,故会执行多次。
拦截路径配置
-
具体资源路径
-
拦截目录
-
后缀名拦截
-
拦截所有资源
在拦截路径中填写“/*”即可。
拦截方式配置
拦截方式:指资源被访问的方式。什么意思呢?举个例子,一个资源,我们可以使用URL路径直接访问,也可以通过请求转发去访问,同样都可以访问到这个资源,但是其方式是不一样的,明白了这一点,我们就可以继续往下聊了。
首先拦截方式有以下几个取值:
拦截方式 | 描述 |
---|---|
REQUEST | 默认值,浏览器直接请求资源 |
FORWARD | 转发访问资源 |
INCLUDE | 包含访问资源 |
ERROR | 错误跳转资源 |
ASYNC | 异步访问资源 |
下面,我们先来演示下最基本的REQUEST拦截方式。
直接访问ServletDemo3,会触发拦截
下同通过转发来访问ServetDemo3,并没有触发过滤器
那我们该如何去设置拦截方式呢?同样的,通过注解,获取配置文件
先说注解配置
我们再通过转发的方式访问ServletDemo3的资源时,也可以触发过滤器了
再着,就是通过配置文件,在< filter-mapper >标签下设置< dispatcher >标签即可。
过滤器链
大家有没有考虑过这么一种情况,当访问某个资源时,我们有时候需要多个过滤器,那么这样的话就又会产生两个问题,第一个:假设现在有两个过滤器,那么他们谁先执行?谁后执行呢?第二个,如果我们规定了他们的顺序,那么他们的执行顺序又是怎样的呢?就上面两个问题,我们展开如下的探讨。
过滤器先后顺序问题
- 注解配置:按照类名的字符串比较规则,值小的先执行
- web.xml配置:< filter-mapping >谁定义在上边,谁先执行
执行顺序
从上面也可以看到,两个过滤器的执行顺序向一个栈,即
- 过滤器1
- 过滤器2
- 资源
- 过滤器2
- 过滤器1
代理模式
这里我就不做多余的解释了,给你个糖果
验证验证功能
敏感词汇过滤
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.*;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.List;
@WebFilter("/servletDemo")
public class FilterDemo implements Filter {
private List<String> list = new ArrayList<>();
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//解决中文乱码问题
req.setCharacterEncoding("utf-8");
ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("getParameter".equals(method.getName())) {
String value = (String) method.invoke(req, args);
if (null != value) {
for (String str : list) {
if(value.contains(str)){
value = value.replaceAll(str,"***");
}
}
}
return value;
}
return method.invoke(req, args);
}
});
chain.doFilter(proxy_req, resp);
}
public void init(FilterConfig config) throws ServletException {
/* String path = FilterDemo.class.getClassLoader().getResource("敏感词汇.txt").getPath();
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(path));
String str = null;
while ((str = br.readLine()) != null) {
list.add(str);
}
System.out.println(list);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}*/
ServletContext servletContext = config.getServletContext();
String path = servletContext.getRealPath("/WEB-INF/classes/敏感词汇.txt");
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader(path));
String str = null;
while ((str = br.readLine()) != null) {
list.add(str);
}
System.out.println(list);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}