需求:传到服务器之前就让过滤器将非法字符转成*
前端显示部分:
过滤效果:
过滤器:
将脏话字符放到文本里在过滤器init方法读取。
动态代理增强getParameter()方法
过滤链放行代理对象
package com.alibaba.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
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;
/**
* @Author:ZZZ
* @Date: 2020/12/27 10:02
* @Version 1.0
*/
//需求:读取文本时传到服务器之前就让非法字符成*
public class IllegalFilter implements Filter {
List<String> wordsLits=new ArrayList<>();
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 读取脏话文本//不用加classpath
InputStream is = this.getClass().getClassLoader().getResourceAsStream("IllegalWords.txt");
// 字节缓冲流可以一行一行读
BufferedReader br= null;
try {
br = new BufferedReader(new InputStreamReader(is,"utf-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
String s="";
try {
//!!!这里是while 不断读取 不是if
while ((s=br.readLine())!=null) {
wordsLits.add(s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 强转 , 添加servlet依赖
HttpServletRequest httpServletRequest=(HttpServletRequest)servletRequest;
HttpServletResponse httpServletResponse =(HttpServletResponse)servletResponse;
// 导包 java.lang.reflect.Proxy;
//ClassLoader loader, 被代理类类加载器
ClassLoader classLoader = httpServletRequest.getClass().getClassLoader();
//Class<?>[] interfaces, 被代理类接口的Class对象,是接口不是类
Class<HttpServletRequest> aClass = HttpServletRequest.class;
//httpServletRequest的动态代理 接口=实现类
HttpServletRequest httpServletRequest_Proxy = (HttpServletRequest) Proxy.newProxyInstance(classLoader, new Class[]{aClass}, new InvocationHandler() {
private String params;
@Override //代理类对象 被代理类执行的方法 被代理类执行的方法的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (method.getName().equals("getParameter")) {
// 被代理对象执行方法getParameter获取参数
params = (String) method.invoke(httpServletRequest, args);
// 遍历脏话list
for (String words : wordsLits) {
if (params.contains(words)) {
// 用*取代脏话
// 创建字符串*的长度 *的个数=脏话字数
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < words.length(); i++) {
stringBuilder.append("*");
}
// !!!记得赋值
params= params.replace(words, stringBuilder.toString());
}
}
// 代理类执行getParameter的返回值
return params;
}
// !!!是被代理类执行其他方法的返回值
return method.invoke(httpServletRequest,args);
// 为什么执行代理对象invoke(proxy,args)会不断循环呢?
// 代理对象执行方法->结果返回代理对象执行方法的返回值(代理对象没有自己的方法,本来要去调用被代理的方法,
// 结果代理对象调用自己的方法,自己调用自己调用自己...
//
}
});
// !!! 放行增强的代理类
filterChain.doFilter(httpServletRequest_Proxy, servletResponse);
}
@Override
public void destroy() {
}
}
顺便过滤请求和响应字符编码
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html; charset=UTF-8");
filterChain.doFilter(servletRequest, servletResponse);
配置过滤器可以用配置文件
<filter>
<filter-name>IllegalFilter</filter-name>
<filter-class>com.alibaba.filter.IllegalFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>IllegalFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
也可以用注解配置