刚刚做了一个关于Filter的应用,趁着脑热赶紧记录下来,此篇一共是有两个小应用一个是关于权限管理,*什么是权限管理呢?*就是当你没有登录的时候你不能做任何事情,这个操作很眼熟,例如天猫的下单系统,当你没有登录的时候只能浏览,并不能提交订单和付款,当你提交订单的时候会提醒你先登录。还有一个常见的例子就是一些网站的登录查询系统,当你没有登录的时候是不能查看任何信息的,这就是权限管理,这样做的好处就是很安全,过滤掉了一些不安全的因素,一般现在只要是涉及到登陆的网站基本都是用了过滤器来实现这个权限管理操作的。另一个小应用就是过滤敏感词汇,这个应用就更常见了,这个例子随处可见,例如在王者峡谷,你是祖安人,然后对面很菜,或者是说你也很菜,对面在喷你,然后你发挥祖安人的良好血统,开始对喷,这时候你会发现聊天框里就会出现"我 **你 * **" 大量的我,你,还有星号,这就是做了敏感词汇过滤操作,接下来我们重点实现以下敏感词汇过滤。
关于权限管理,其实实现起来很简单,大体思想就是先看你要访问的资源是否是与登录有关的例如login.jsp这样的资源就不会过滤掉,然后咱判断你是否已经登陆了,是否已经登录是通过session来判断的,当你登陆成功之后你会在session里面存一个参数,在过滤器里面验证这个参数是否存在就可以了,当你当打开浏览器还没有登录的时候这个参数肯定是空的,这时节如果你要访问别的资源就会被拦截,过滤器的代码如下:
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//强制转换
HttpServletRequest request = (HttpServletRequest) req;
//获取请求的资源路径 看是否是登录相关的资源
String uri = request.getRequestURI();
//判断
if (uri.contains("/index.jsp") || uri.contains("/UserLoginServlet") ||uri.contains("/JSP/css/") || uri.contains("/JSP/js/")){
//包含 证明用户就是想登陆 放行
chain.doFilter(req, resp);
}else{
//不包含 验证用户是否已经登录
if (request.getSession().getAttribute("user") != null){
//已经登陆 放行
chain.doFilter(req, resp);
}else {
System.out.println("您被拦截了,您需要先登录" );
request.setAttribute("longinmessage","您尚未登录,请先登录!");
request.getRequestDispatcher("/index.jsp").forward(request, resp);
}
}
}
然后我们重点来说一下实现敏感词汇屏蔽的操作,这个操作思路上很简单,就是有一个txt文件,里面放着各种敏感词汇,一行一个敏感词。当你调用方法输入带有敏感词的语句的时候就会把敏感词来替换成星号,这个替换的操作在request的方法里面没有可以实现这个功能的,所以我们需要用到一个代理模式,这个才是麻烦的地方,*为什么要用代理模式呢?*比如我们调用request.getParameter("name");
这条语句,我们给name赋值,但是这个方法本身并不支持替换敏感字符,需要我们增强一个这个方法的功能,让他调用的时候可以实现替换掉敏感词。
那我们先来说什么是代理模式?
代理模式可以做到增强一些方法的功能,就像是刚才上面说的给某个方法增强过滤功能,以后调用这个方法的时候就会过滤掉一些敏感词,增强方法功能的设计模式呢还有一个叫装饰者模式,这两个都可以实现增强方法的功能。代理模式顾名思义,具有代理商的一种模式,有代理肯定就有真实的大老板,代理商从大老板那里拿货,就像是我们日常生活中的例子,很多卖鞋的,莆田货居多,在莆田有很多大牛,然后他们手下有很多代理商,我们买鞋都是通过代理商,而不是直接找大老板。比如大老板卖这双鞋子是八百,通过代理商我成功入手价格是900,代理商增强了价格,含泪赚了我一百块钱。那我们为什么不直接找大老板呢?因为代价太大,或者是找不到大老板,所以我们只能通过代理商来拿货。这样来讲代理模式就明白许多了吧,代理商代理大老板,我们从代理商那里拿货,并达到从大老板那里拿货的目的。
我们通过一个简单的例子来说明一下,我们先新建一个接口,不管是代理商还是大老板都是卖鞋的,我们需要有一个接口来说明相关的方法:
package proxy;
/**
* @author Shi Jun Yi
* @version 1.0
* @date 2021/1/25 12:32
*/
public interface SaleComputer {
public String sale(double money);
public void show();
}
有了这个接口之后我们就要有一个真实的大老板对象
package proxy;
/**
* @author Shi Jun Yi
* @version 1.0
* @date 2021/1/25 12:34
*/
public class Lenovo implements SaleComputer {
@Override
public String sale(double money) {
System.out.println("花了"+money+"元买了一双回到未来....");
return "耐克鞋子";
}
@Override
public void show() {
System.out.println("展示鞋子.....");
}
}
接下里我们写一个测试类:
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @author Shi Jun Yi
* @version 1.0
* @date 2021/1/25 12:35
*/
public class ProxyTest {
public static void main(String[] args ){
//创建真实对象
Lenovo lenovo = new Lenovo();
//动态代理 增强lenovo对象
/*
三个参数
类加载器 真实对象
接口数组 真实对象
处理器 很重要 核心业务逻辑
*/
SaleComputer proxy_lenovo = (SaleComputer) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(), lenovo.getClass().getInterfaces(), new InvocationHandler() {
/*
代理逻辑 代理对象调用的所有的方法都会触发该方法
参数
1 代理对象
2 代理对象调用的方法
3 调用对象的时候传递的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/* System.out.println("该方法被执行了......");
System.out.println(method.getName());
System.out.println(args[0]);*/
//使用真实对象的方法调用该方法
if(method.getName().equals("sale")){
//增强参数
double money = (double)args[0];
money = money*0.85;
System.out.println("专车接....");
String obj = (String) method.invoke(lenovo, money);
System.out.println("专车送....");
//增强返回值
return obj+"_鞋垫";
}else{
Object obj = method.invoke(lenovo,args);
return obj;
}
}
});
//调用方法
String computer = proxy_lenovo.sale(80000);
System.out.println(computer);
}
}
然后我们来说一下大致的实现步骤:
- 既然是代理模式 那我们肯定是要对真实对象进行代理 所以我们new一个真实对象。
- 通过固定的格式
Proxy.newProxyInstance(....)
格式来实现对真实对象的代理,在这个方法里面有一个重写过的invoke方法,这里面放的是核心的增强逻辑,代理逻辑 代理对象调用的所有的方法都会触发该方法。 - 这个invoke方法里面有三个参数,第一个参数是代理对象,第二个参数是代理对象调用的方法,代理对象调用方法时传的参数。
String computer = proxy_lenovo.sale(80000);
由于我们调用的是sale方法,所以我们就需要判断方法名是不是sale,如果是的话就会增强返回值,如果不是就默认执行方法。这个增强方法的实现,其实就是把原先没有增强的方法先执行一下,然后对没有增强的返回值加上一些内容,将新的返回值返回,以达到增强方法的效果。- 当我们代理对象调用的方法是sale的时候会把参数先传过来,然后将这个参数乘0.85,在执行真实对象的该方法并返回一个值,
String obj = (String) method.invoke(lenovo, money);
这句话就是调用真实对象方法的语句。得到了返回值,对返回值加上一些内容返回输出就可以了。
这就是一个简单的实现。接下来我们再说回敏感词汇的问题。
首先我们先创建一个名为“敏感词汇.txt”的文件,内容如下:
一些极度祖安的话我就不说了,太敏感了,你们自行添加~
首先我们新建一个过滤器名字就叫sesitivewordsfilter,我们自然是要在doFlter方法里面进行字符过滤操作,一开始我们就创建一个代理对象,模式与上一样,在做增强方法之前我们先要将敏感词汇.txt文件进行加载,初始化记载文件应该放到init方法内,首先我们先要有一个存放敏感词汇的集合private List<String> list = new ArrayList<>();
在inti方法中有一个参数叫config,我们可以用config自带的config.getServletContext().getRealPath("敏感词汇.txt");
方法加载文件,加载好之后进行读取,我们用到了IO流的知识,用一个带缓冲区的文件读取文件BufferedReader br = new BufferedReader(new FileReader(contextPath));
,然后将文件的每一行加入到集合当中,当文件读完了就关闭该流,这样一来我们的所有敏感词就全部存到了list集合当中了,到时候我们只需要对比是否包含就可以了。我们先对request的getParameter方法进行增强,第一步我们要做的肯定是要判断是否是该方法,通过参数列表里面自带的method.getName();
来返回方法名,然后先执行原先的getPramenter方法,将其值返回,返回之后如果返回值不为空,那么遍历list结合,查看返回值是否包含list集合当中的敏感词,如果包含替换成星号。如果不是调用的getParamenter方法,就返回原先的参数return method.invoke(req,args);
,最后通过chain.doFilter(proxy_req, resp);
返回增强之后的request。
过滤器代码:
package filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.BufferedReader;
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 Shi Jun Yi
* @version 1.0
* @date 2021/1/25 15:03
* 敏感词汇过滤器
*/
@WebFilter(filterName = "SensitiveWordsFilter", value = "/TestServlet")
public class SensitiveWordsFilter implements Filter {
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//创建代理对象 增强getParameter方法
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 (method.getName().equals("getParameter")){
//增强返回值
String value = (String)method.invoke(req, args);
if (value != null){
for (String str:list) {
if (value.contains(str)){
value = value.replaceAll(str,"***");
}
}
}
return value;
}
//增强getAttribute方法
if (method.getName().equals("getAttribute")){
//增强返回值
String value = (String) method.invoke(req, args);
if (value != null){
for (String str:list) {
if (value.contains(str)){
value = value.replaceAll(str,"**");
}
}
}
return value;
}
return method.invoke(req,args);
}
});
//放行增强后的request方法
chain.doFilter(proxy_req, resp);
}
//放敏感词汇集合
private List<String> list = new ArrayList<>();
@Override
public void init(FilterConfig config) throws ServletException {
try{
//加载文件
String contextPath = config.getServletContext().getRealPath("敏感词汇.txt");
//读取文件
BufferedReader br = new BufferedReader(new FileReader(contextPath));
//将文件的每一行添加到list当中
String line = null;
while ((line = br.readLine()) != null){
list.add(line);
}
br.close();
System.out.println(list);
}catch (Exception e){
e.printStackTrace();
}
}
}
我们新建一个servlet来调用一下增强后的方法,
package control;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author Shi Jun Yi
* @version 1.0
* @date 2021/1/25 15:33
*/
@WebServlet(name = "TestServlet", value = "/TestServlet")
public class TestServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name");
String msg = request.getParameter("msg");
request.setAttribute("name2", "我diu,你这个大笨蛋,大SB...");
System.out.println(request.getAttribute("name2"));
System.out.println(name+":"+msg);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
接下来我们查看效果:
效果还不错,hhh~~,以上就是这篇博客所要展示的内容,如有不足之处,还请指出,谢谢。