过滤器

1、什么是过滤器

Filter:一个实现了特殊接口(Filter)的Java类. 实现对请求资源(jsp,servlet,html,)的过滤的功能.  

过滤器是一个运行在服务器的程序, **优先于**请求资源(Servlet或者jsp,html)之前执行. 过滤器是javaweb技术中**最为实用**的技术. 

我们可以理解成这是客户端请求经历过的第一个关卡,之后才是servlet或者html等静态资源;

2、filter作用

对目标资源(Servlet,jsp)进行过滤.  

应用场景:登录权限检查,解决网站乱码,过滤敏感字符 ...   

3、Filter

跟servlet一样,有注解方式,也有xml配置方式,但是更加通用的是使用注解方式。

但是因为filter存在着调用链条方式

3.1、过滤器链

过滤器链作用:当一个filter收到请求的时候,调用chain.doFilter才可以访问下一个匹配的filter,若当前的filter是最后一个filter,调用chain.doFilter才能访问目标资源

过滤器链执行顺序

  • 配置文件: 谁先配置filter-mapping 谁先执行
  • 注解方式: 按照Filter的首字母顺序 eg: AFilter BFilter A在B的前面, AFilter先执行

那么首先写一个filter先来测试一下:

filter:

@WebFilter(filterName = "HelloFilter",urlPatterns="/*")
public class HelloFilter implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("请求来了filter...........");
        chain.doFilter(request, response);
    }
}

servlet:

@WebServlet(name = "HelloServlet", value = "/HelloServlet")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("请求来了request...........");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

直接在浏览器请求:http://localhost:8080/filter_war_exploded/HelloServlet

可以看到控制台输出:

��������filter...........
��������request...........

存在乱码问题,那么首先在过滤器中来进行解决处理。

直接修改filter中的方法

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1.强转两个参数
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        //2.处理乱码
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        //3.放行
        chain.doFilter(request, response);
    }

4、生命周期方法

public interface Filter {
    void init(FilterConfig var1) throws ServletException;

    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

    void destroy();
}

init方法在容器启动的时候进行加载;(与servlet类似,但是servlet需要修改启动的顺序,而filter是默认的)

doFilter方法,每次在访问路径被拦截的时候,都会在来执行这个方法;

destroy方法:在容器销毁的时候执行代码;

5、映射路径

  1. 完全路径匹配
  2. 目录匹配
  3. 扩展名匹配
  4. 缺省匹配

假设有一个管理员权限的过滤器,它应该对用户发出的管理员功能的请求进行条件的过滤。但是当用户发出登录、注册等请求的时候,不应该进行过滤。所以我们过滤器,应该有选择的过滤器请求。这就需要学习配置过滤器不同的映射路径,从而让过滤器过滤希望过滤器的请求。

5.1完全路径匹配

以"/"开始

/demo01 ---> 过滤器只能拦截路径/demo01; 

5.2目录匹配

以"/"开始 以 *结束 .

/* --->当前项目下的所有的路径都可以拦截;   /aa/*  ---> 可以拦截 /aa/bb, /aa/bb/cc

5.3扩展名匹配

以"*"开始 例如: *.jsp *.do

*.do--->可以拦截路径的后缀是 do的 ;  *.jsp--->拦截所有JSP

5.4缺省匹配

/ 除了jsp以外的资源都匹配

当前Filter里面不支持, Servlet里面可行的. 后面在Servlet里面遇到

6、拦截方式

有了上面学习的映射路径,我们可以控制过滤器过滤指定的内容,但是我们在访问资源的时候,并不是每次都是直接访问,有时是以转发的方式访问的,这就需要我们要让过滤器可以区分不同的访问资源的方式,有不同的拦截方式。 是通过 DispatcherType 来指定的.

  • DispatcherType.REQUEST

    默认值,过滤从浏览器发送过来的请求和重定向 不过滤转发

  • DispatcherType.FORWARD

    只过滤转发过来的请求

/*只拦截转发*/
/*@WebFilter(urlPatterns = "/demo05",dispatcherTypes={DispatcherType.FORWARD})*/

/*转发,重定向,浏览器的直接请求都会拦截了*/
@WebFilter(urlPatterns = "/demo05",dispatcherTypes={DispatcherType.FORWARD,DispatcherType.REQUEST})
public class FilterDemo05 implements Filter {

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println("FilterDemo05()  收到了请求...");
        chain.doFilter(req, resp);
    }
    public void destroy() {

    }
    public void init(FilterConfig config) throws ServletException {

    }
}

7、综合案例

7.1、非法字符过滤

在web文件夹下面建立一个a.txt文件,然后写上对应的违法的字符

@WebFilter(filterName = "IlleaglFilter",urlPatterns = "/*")
public class IlleaglFilter implements Filter {

    private  static List<String> wordList = new ArrayList<String>();

    public void init(FilterConfig config) throws ServletException {
        InputStream is = null;
        try {
            //1.读取文件到集合List<String> list (方式一:根据is获得字符串 存到List 方式二:包装)
            //a.根据aa.txt获得InputStream
            is = config.getServletContext().getResourceAsStream("aa.txt");
            //b包装
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"));
            String line = null;
            while ((line = reader.readLine()) != null) {
                wordList.add(line);
            }
            System.out.println(wordList);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        // 1.强转两个参数
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        // 2.获得用户发布的言论(请求参数)
        String message = request.getParameter("message");
        System.out.println("对应的信息是:"+message);
        // 3.遍历List集合, 判断用户发布的言论是否包含非法字符
        if(message != null){
            for (String word : wordList) {
                if(message.contains(word)){
                    // 3.1 包含, 拦截, 响应 "重新发布"
                    //response.getWriter().print("发布的言论包含非法字符,重新发布");

                    message = message.replace(word,"***");
                    response.getWriter().print("您发布的言论是:"+message);

                    return;
                }
            }
        }

        // 3.2 不包含, 放行
        chain.doFilter(request,response);
    }
}

然后上面的IlleaglFilter的fileName=IlleaglFilter,而HelloFilter的HelloFilter,根据字母H在I之前,所以H先执行,所以乱码问题已经处理过了

posted @ 2022-02-14 00:20  写的代码很烂  阅读(55)  评论(0编辑  收藏  举报