代理模式技术终结蔡徐坤
------敏感词过滤
-
在开始进入正题之前,先来简述一下代理模式
比如买戴尔电脑,有俩个选项,1:从戴尔总部购买,2:从代理商处购买
现在把戴尔总部抽象为一个类,它实现了卖电脑的接口
package cm.boke; /** * @author long * @date 5/28/19 - 4:53 PM */ //定义卖电脑的接口 interface saleComputer{ public String sale(int money); } //戴尔实现卖电脑的接口 public class DaiEr implements saleComputer{ @Override public String sale(int money) { return "花了"+money+"元买了戴尔电脑"; } //写一个main方法测试 public static void main(String[] args) { System.out.println(new DaiEr().sale(6000)); } }
运行结果 : 花了6000元买了戴尔电脑
虽然现在可以正常的卖电脑,但所谓"天高皇帝远",仅仅在戴尔总部地区卖电脑市场有限,那么
戴尔想要在全世界卖电脑则需要代理商.
抽象的来看,代理商一方面使得戴尔能在世界各地销售,相当于加强了电脑的销售功能;另一方
面,代理商需要赚取差价,从代理商处买电脑需要消费者支付更高的价格,这就相当于加强了买电脑
方法的参数;再来看,如果直接从总部买电脑,可能得到的只是一台电脑,而从代理商处买电脑,会得到
一些配件或者赠品,相当于加强了方法的返回值.
package cm.boke; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @author long * @date 5/28/19 - 6:34 PM */ public class DaiLi { public static void main(String[] args) { //代理对象依赖于原对象,在使用代理对象之前要创建原对象 DaiEr dr = new DaiEr(); //获得代理对象 /** * 该方法有三个参数,类加载器,原对象接口 * 最后一个参数里写逻辑 * 需要强制转换为接口类型 */ saleComputer dl = (saleComputer) Proxy.newProxyInstance(dr.getClass().getClassLoader(), dr.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { /** * 上面的method就是当前的函数,args为参数列表 */ //下面俩行用来修改参数,即增强参数 int num = (int)args[0]; num*=0.85;//假定代理商克扣了百分之15的差价 return method.invoke(dr,num)+",并得到了赠品电脑配件"; } }); //使用代理 System.out.println(dl.sale(8000)); } }
运行结果 : 花了6800元买了戴尔电脑,并得到了赠品电脑配件
好,理解了上面的设计模式,我们就可以做一个拦截器,屏蔽蔡徐坤
基本原理是使用代理模式增强ServletRequest里的getParameter方法
注释标的很全,感兴趣可以复制下来看
下面是最后的效果图(图形化界面是我自己写的)
package cm; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.List; /** * @author long * @date 5/28/19 - 7:04 PM */ @WebFilter("/*") public class FilterCXK implements Filter { //创建一个List存放敏感词 List<String> list = new ArrayList<>(); @Override public void init(FilterConfig filterConfig) throws ServletException { //该方法只在服务器启动时执行一次 //加载文件,文件里存放敏感词 //没有request对象,只能通过filterConfig来获取 ServletContext servletContext = filterConfig.getServletContext(); String realPath = servletContext.getRealPath("/WEB-INF/classes/cm/mgs.txt"); BufferedReader br = null; try{ br = new BufferedReader(new FileReader(realPath)); String temp; while (null != (temp = br.readLine())){ list.add(temp); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ if(null!=br){ try { br.close(); } catch (IOException e) { e.printStackTrace(); } } } } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //这个方法在每次拦截时都会执行 ServletRequest proxyServlet = (ServletRequest) Proxy.newProxyInstance(servletRequest.getClass().getClassLoader(), servletRequest.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //如果是getParameter方法就验证,不放行,如果是其他的方法就放行 if(method.getName().equals("getParameter")){ String msg = (String) method.invoke(servletRequest,args); //遍历敏感词集合 for (String temp:list) { //如果找到敏感词就替换为*** if(msg.contains(temp)){ System.out.println("执行了"); msg = msg.replaceAll(temp,"***"); } } return msg; }else{ return method.invoke(servletRequest,args); } } }); //放行代理对象 filterChain.doFilter(proxyServlet,servletResponse); } @Override public void destroy() { //在服务器正常关闭时会执行 } }