代理模式使用过滤器实现对敏感词汇的过滤
一.代理模式 概念:
代理模式 是作为二十三种设计模式之一,所谓的设计模式就是一些通用的解决固定问题的一些方式
- 真实对象 : 被代理的对象
- 代理对象
- 代理模式: 代理对象代理真实对象 , 达到增强真实对象功能的目的
二.实现方式
在内存中形成代理类
三.分析
1.代理对象和真实对象实现相同的接口
2.代理对象 = Proxy.newProxyInstance();
3.使用代理对象调用方法
4.增强方法
增强方式:
1)增强参数列表
2)增强返回值类型
3)增强方法体执行逻辑
四.实现
对于使用代理模式对过滤器的编写 需要了解的是:
Proxy.newProxyInstance()方法接受三个参数:
ClassLoader loader
:指定当前目标对象使用的类加载器,获取加载器的方法是固定的Class[] interfaces
:指定目标对象实现的接口的类型,使用泛型方式确认类型InvocationHandler:
指定``动态处理器,
执行目标对象的方法时,会触发事件处理器的方法
SensitiveWordsFilter文件内容:
/**
* 需求: 敏感词汇的过滤 ,在txt文件中读取敏感词汇, 对于出现的敏感词汇能够替换为***
* 分析: 对request对象进行增强 增强获取参数相关方法
* 放行, 传递代理对象
*/ //拦截路径设置为"/*"代表全局
@WebFilter(filterName = "SensitiveWordsFilter", urlPatterns = "/*")
public class SensitiveWordsFilter implements Filter {
//创建存放敏感词汇的list集合
private List<String> list = new ArrayList<>();
public void init(FilterConfig config) throws ServletException {
try {
//1.读取文件的真实路径
ServletContext servletContext = config.getServletContext();
// src下文件的真实路径获取 : /WEB-INF/classes/文件.文件后缀名
String realPath = servletContext.getRealPath("/WEB-INF/classes/sensitiveWords.txt");
System.out.println(realPath);
//2.创建缓冲流对象
BufferedReader br = new BufferedReader(new FileReader(realPath));
//3.读取流对象
String line =null;
while ((line=br.readLine())!=null){
//4.将读取到的每一行数据加入到list集合中
list.add(line);
}
System.out.println(list);
//释放资源
br.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//1.创建代理对象
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 {
//2.增强 getParameter方法
if (method.getName().equals("getParameter")){
//2.1获取返回值 增强 返回值
String value= (String) method.invoke(req,args);
//如果返回值不为空
if (value!=null){
//2.2 对敏感词汇进行遍历
for (String str : list) {
//3.如果request.getParameter()获得的值中包含 敏感词汇 则进行替换
if (value.contains(str)){
value = value.replaceAll(str,"***");
}
}
}
//返回 value
return value;
}
//invoke方法就是调用被代理接口的所有方法时需要调用的,返回的值是被代理接口的一个实现类。
return method.invoke(req,args);
}
});
//放行
chain.doFilter(proxy_req,resp);
}
public void destroy() {
}
}
在项目的src路径下, 有一个名为 sensitiveWords.txt文件 ,文件里存放的是敏感词汇 , 项目下新建的有一个TestServlet的测试Servlet
TestServlet内的文件内容:
/*用于测试的servlet*/
@WebServlet(name = "TestServlet", urlPatterns = "/testServlet")
public class TestServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
String msg = request.getParameter("msg");
System.out.println(name+"--"+msg);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
五.测试
在sensitiveWords.txt文件中存放两个敏感词汇:坏蛋,笨蛋, 注意两个词汇各占一行, 启动服务器 ,
在浏览器中输入 http://localhost/testServlet?name=大坏蛋&msg=大笨蛋
查看控制台输出 :
大***--大***
至此,说明敏感词汇过滤成功
六.总结
实现对于敏感词汇的过滤实现方式有很多种 , 本人的方法其实主要就是使用代理对象对request的方法进行增强 ,
注意: 代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理 动态代理是在程序运行时通过反射机制动态创建的。