Filter实战——实现非法字符的过滤

使用Filter实现非法字符过滤
需求:用户在评论页面输入非法字符以后,需要将非法字符替换为*
需要考虑的问题
1.用户输入的非法字符可能会有很多种,如果想要校验用户输入的字符是否是非法字符,首先需要将非法字符存储起来,而不是写死,那么存储非法字符的存储位置

  • 文件如果文件的内容有变更,需要重启服务器才生效,
  • 数据库(开发项目的时候)如果数据库有变更,不需要重启服务器,因为是实时查询数据库看到的都是最新的数据,Ctrip Apollo。

将非法字符存储到文件中,服务器启动之后就应该读取文件中的内容并且存储到集合中,而不是等到请求过来之后再读,因为这样会影响体验,

2.由于可能会有很多的页面存在用户输入的数据(订单评价,商品搜索等等),因此这个事情应该交给Filter去做,而不是servlet,因为servlet是负责处理没有非法字符的请求,有非法字符的请求统一交给Filter去做,这样就是实现了非法字符的过滤。

模拟评论页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>评论页面</title>
</head>
<body>
<h1>评论页面处理非法字符</h1>
<form action="${pageContext.request.contentType}/comments" method="post">

 评论内容:<input type="text" name="comments"><br>
    <input type="submit">

</form>
</body>
</html>

在src下创建非法字符的文件
Filter实战——实现非法字符的过滤
过滤器处理非法字符

package 过滤器;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
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;

@WebFilter("/comments")
public class illegalCharcaterFilter implements Filter {
    List<String> list;


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
     //获取非法的字节输入流
        InputStream resourceAsStream = illegalCharcaterFilter.class.getClassLoader().getResourceAsStream("illegal.txt");
        InputStreamReader inputStreamReader = null;
        try {
            inputStreamReader = new InputStreamReader(resourceAsStream,"UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String line =null;
        list = new ArrayList<>();
        while(true){
            try {
                if (!((line=bufferedReader.readLine())!=null)) break;
            } catch (IOException e) {
                e.printStackTrace();
            }
            list.add(line);
        }

        System.out.println("当前的非法字符");
        for (String s:list){
            System.out.println(s);
        }


    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
  //进行非法字符的替换
        //使用动态代理增强HttpServletRequest的getparameter()方法
        HttpServletRequest req =(HttpServletRequest)servletRequest;

        HttpServletRequest proxyHttpServletRequest=(HttpServletRequest)  Proxy.newProxyInstance(HttpServletRequest.class.getClassLoader(), new Class[]{HttpServletRequest.class}, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String returnValue=null;
                String proxyMethodName="getParameter";
                //增强getParameter的方法
                if(method.getName().equals(proxyMethodName)){
                    //目的是改变getParameter的返回值
                    //执行原本的方法获取返回值
                    returnValue=(String)method.invoke(req,args);
                    //将返回值的结果替换为非法字符**
                    if(returnValue!=null){
                        if(list!=null){
                            //遍历所有的非法字符
                            for (String illegalCharacter:list){
                                if(returnValue.contains(illegalCharacter)){
                                    String asterisk="";
                                    //用* 号代表一个字符
                                    for (int i=0;i<illegalCharacter.length();i++){
                                        asterisk+="*";
                                    }
                                    //将非法字符替换成星号
                                    returnValue=returnValue.replace(returnValue,asterisk);
                                    System.out.println("替换之后的为:"+returnValue);
                                }


                            }
                        }
                        return returnValue;
                    }
                }
                //如果不是getParameter方法,则执行原来的方法,不增强
                return method.invoke(req,args);
            }
        });
        filterChain.doFilter(proxyHttpServletRequest,servletResponse);
    }

    @Override
    public void destroy() {

    }
}

servlet处理请求

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;
@WebServlet("/comments")
public class illegalServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("UTF-8");

        resp.setContentType("text/html;character=utf-8");
        String comments = req.getParameter("comments");
        System.out.println("接收到了客户请求"+comments);

        resp.getWriter().write(comments);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

运行结果
Filter实战——实现非法字符的过滤
Filter实战——实现非法字符的过滤

上一篇:19. 删除链表的倒数第 N 个结点


下一篇:19 深入Plugin