过滤器Filter案例-实现敏感词汇过滤
Filter概念: web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。
过滤器的作用:
- 一般用于完成通用的操作,如:登陆验证,统一编码处理、敏感字符过滤…等。
- Filter过滤器能够在Servlet被调用之前检查Request对象,并修改Request Header和Request内容;在Servlet被调用之后检查Response对象,修改Response Header和Response的内容,实现多次过滤。
- Filter可以过滤的web组件包括Servlet,JSP和HTML等文件。
Filter的过滤原理
当浏览器向服务器发出资源的请求时,当浏览器满足过滤条件时,Web服务器根据应用程序配置文件设置的过滤规则进行检查。是一次双向过滤的过程
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHLx0ERPRTQ65keRpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnLzMjM3UzM1kTMwMDOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
过滤器生命周期方法
init()方法:在服务器启动后,会创建filter对象,然后调用init方法。只执行一次,用于加载资源。
doFilter()方法:每一次请求被拦截资源时,会执行,执行多次。
destroy()方法:在服务器关闭后,filter对象会被销毁,如果服务器时正常关闭,则会执行destroy方法,只执行一次,用于释放资源。
过滤器链(配置多个过滤器)
执行顺序:如果有两个过滤器:过滤器1,过滤器2
过滤器1–>过滤器2–>资源执行–>(返回)–>过滤器2–>过滤1
过滤器先后顺序问题:
注解配置:按照类名的字符串比较规则比较,值小的先执行。
如:Afilter 和 Bfilter,A<B A先执行
过滤器配置
拦截方式配置:dispatcherTypes 资源访问的方式:
//假如时浏览器直接请求index.jsp路径,那么将直接拦截,转发到该路径则不予阻拦
@WebFilter(value = "/index.jsp", dispatcherTypes = DispatcherType.REQUEST)
//释放代码
chain.doFilter(req, resp);
案例敏感词的过滤:
代理模式详解图:(灵魂画手)、反正意思就似乎用上代理类,效率高,还能过滤掉敏感词汇
为什么要用代理模式?
中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口。
接下来就是实现代理模式
** public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
String name = req.getParameter("name");
//动态代理增强,增强getParameter方法
/* 三个参数:
1. 类加载器:真实对象.getClass().getClassLoader()
2. 接口数组:真实对象.getClass().getInterfaces()
3. 处理器:new InvocationHandler()
这边的真实对象就是ServletRequest req的参数;
*/
ServletRequest ser = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/* 代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法执行
参数:1. proxy:代理对象
2. method:代理对象调用的方法,被封装为的对象
3. args:代理对象调用的方法时,传递的实际参数
*/
//判断是不是getParameter方法
if (method.getName().equals("getParameter")){
//使用真实对象调用该方法
String invoke = (String) method.invoke(req, args);
//假如返回的值不为空,则进行敏感字符过滤
if (invoke != null ){
for (String s : list) {
if (invoke.contains(s)){
invoke = invoke.replaceAll(s,"***");
}
}
}
return invoke;
}
return method.invoke(req,args);
}
});
String name1 = ser.getParameter("name");
String rows = ser.getParameter("rows");
System.out.println(rows);
chain.doFilter(ser, resp);
}
//init方法在第一时间进行执行,并且只会执行一次。把每对敏感字符存入到list集合中
private List<String> list = new ArrayList<>();
@Override
public void init(FilterConfig config) throws ServletException {
//获取路径
try {
ServletContext servletContext = config.getServletContext();
String realPath = servletContext.getRealPath("//WEB-INF//classes//敏感词汇.txt");
//防止乱码 用InputStreamReade是从字节流到字符流的桥梁。
BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream(realPath),"gbk"));
String len = null;
while ((len = bufr.readLine()) != null){
list.add(len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}**
效果展示:
你是坏蛋,王八蛋
你是***,***
你是***,***