Filter过滤器(Java学习笔记)

概述

Filter过滤器是JavaWeb三大组件之一。三大组件分别是:Servlet、Listener、Filter
Filter过滤器它是javaEE的规范,也就是接口
Filter过滤器的作用:拦截请求,过滤响应

拦截请求常见的应用场景:

权限检查
日记操作
事务管理
处理中文乱码
登录验证….

Filter的生命周期

Filter的生命周期包含几个方法:

构造器方法:Web工程启动时候执行
init初始化方法:Web工程启动时候执行
doFilter过滤方法:每次拦截到请求就会执行
destroy销毁方法:停止Web工程时候就会执行(停止Web工程,也会销毁Web过滤器)

配置过滤器(Filter)拦截路径

    配置Filter的拦截路径有2种方式,一种是注解,一种是xml方式,我们分别进行讲解。

注解方式
我们如果使用注解来进行配置,那么我们就需要使用@WebFilter

filterName:该filter的名字
initParams:初始化参数
displayName:filter显示名称
servletNames:指定对哪些servlet进行过滤
 asyncSupported:是否支持异步模式
urlPatterns:指定拦截路径
value:指定拦截路径

Filter的拦截路径

精确匹配

<url-pattern>/target.jsp</url-pattern>

以上配置的路径,表示请求地址为:http://ip:port/工程路径/target.jsp

目录匹配

<url-pattern>/admin/*</url-pattern>

以上配置的路径,表示请求地址为:http://ip:port/工程路径/admin/*

后缀名匹配

<url-pattern>*.html</url-pattern>

以上配置的路径,表示请求地址必须以.html结尾才可拦截到

<url-pattern>*.do</url-pattern>

以上配置的路径,表示请求地址必须以.do结尾才可拦截到(.abc)

注:Filter过滤器只关心请求的地址是否匹配,不关心请求的资源是否存在!!!!
注意:urlPatterns和value是一样的。urlPatterns和value只能配置一个,不能两个都配置,两个都配置就会报错。
对于使用@WebFilter,里面的多个参数用 , 进行分隔。

说明:如果我们仅仅需要配置一个拦截路径,那么我们可以直接简写@WebLister(“拦截路径”),如@WebFilter(“/*”)就是拦截所有请求。

javapackage com.test01.javaweb01.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter("/filter")
public class FiltetrConfigTest01 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}


FilterConfig类

方法名作用
getFilterName():获取filter的名称
getServletContext():获取ServletContext
getInitparamter(String var1):获取配置的初始参数的值
getInitParamterNames():获取配置的所有参数名称

测试获取配置信息


package com.test01.javaweb01.filter;

import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;

public class FilterConfigTest01 implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("-----------获取全部key:value------------");
        //得到所有配置参数的名字
        Enumeration<String> names = filterConfig.getInitParameterNames();
        while (names.hasMoreElements()) {
            //得到每一个名字
            String name = names.nextElement();
            System.out.println(name+" = "+filterConfig.getInitParameter(name));
        }
        System.out.println("-----------end.....------------");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    }

    @Override
    public void destroy() {
    }
}

web,xml配置参数

   <filter>
        <filter-name>myFilterConfig</filter-name>
        <filter-class>com.test01.javaweb01.filter.FilterConfigTest01</filter-class>
        <init-param>
            <param-name>driver</param-name>
            <param-value>com.mysql.cj.jdbc.Driver</param-value>
        </init-param>
        <init-param>
            <param-name>url</param-name>
            <param-value>jdbc:mysql://localhost:3306/datasource</param-value>
        </init-param>
        <init-param>
            <param-name>username</param-name>
            <param-value>root</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>123456</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>myFilterConfig</filter-name>
        <url-pattern>/admin</url-pattern>
    </filter-mapping>

验证获取
在这里插入图片描述

FilterChain

我们查看类图,可以发现FilterChain就只有一个方法,其实这个方法就是用来对拦截进行放行的,如果有多个拦截器,那么就会继续调用下一个Filter进行拦截。doFilter方法需要传入个参数,一个是ServletRequest,一个是ServletResponse参数,这个直接传入进行。

    Tomcat在调用过滤器时,默认就会传入Request和Response,这个参数封装了请求和响应,我们直接使用就行。ServletResquest和ServletResponse可以直接强转成HttpServletRequest和HttpServletResponse,然后使用相应的方法。

filter01

package com.test01.javaweb01.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
 
@WebFilter("/admin/*")
public class Filter01 implements Filter {
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("调用过滤器01对请求进行过滤~~~~");
        //放行,如果还有过滤器,那么就执行下一个过滤器
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("调用过滤器01对响应进行过滤~~~~");
    }
 
    @Override
    public void destroy() {
    }
}

filetr02

package com.test01.javaweb01.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
 
@WebFilter("/admin/*")
public class Filter02 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("调用过滤器02对请求进行过滤~~~~");
        //放行,如果还有过滤器,那么就执行下一个过滤器
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("调用过滤器02对响应进行过滤~~~~");
    }
 
    @Override
    public void destroy() {
    }
}

多个Filter的执行顺序

    上面我们配置了2个过滤器,那么我们怎么知道那个过滤器先执行呢?其实大家可以直接使用代码进行验证,培养独立思考的习惯,这里我就直接给出答案了。

如果我们是在web.xml中配置的过滤器,那么过滤器的执行顺序就是在web配置的顺序,配置在上面那么就会先执行。
如果我们是使用@WebFilter进行配置的,那么执行顺序就是字符比较顺序来执行,例如有2个过滤器,一个是AFilter,一个是BFilter,那么AFilter就会先执行。
如果注解和xml混用,那么在web.xml中配置的会先执行。

实现Filet接口,重写对应的方法即可。

实例:登录验证
LoginFiler过滤器

package com.test01.javaweb01.filter;


import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;

public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("LoginFilter过滤器开始初始化");
    }
//    Chain 链
//    1.过滤中链中的所有代码,在过滤特定请求的时候都会执行
//    2.必须要让过滤器继续同行
//    chain.doFilter(request,response);
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpSession session = httpServletRequest.getSession();
        Object user =session.getAttribute("people01");
        if (user ==null){
            servletRequest.getRequestDispatcher("/login.html").forward(servletRequest,servletResponse);
            return;
        }else {
//            让程序继续往下访问用户的目标资源文件,不写的话就会在这块拦截停止掉了
            filterChain.doFilter(servletRequest,servletResponse);
        }
        System.out.println(user);

        System.out.println("LoginFilter过滤器继续执行");

    }

    @Override
    public void destroy() {
        System.out.println("LoginFilter销毁");
    }
//    初始化:web服务器启动,就已经初始化了,随时等待过滤对象出现

}


登录用的Servlet程序

package com.test01.javaweb01.filter;

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 javax.servlet.http.HttpSession;
import javax.websocket.Session;
import java.io.IOException;
import java.io.UnsupportedEncodingException;

@WebServlet(value = "/loginTest")
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //      解决乱码问题
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        resp.setCharacterEncoding("utf-8");

        String username = req.getParameter("username");
        String password = req.getParameter("password");

        if ("people01".equals(username) && "123456".equals(password)){
            req.getSession().setAttribute("people01",new People(username,password));
            resp.getWriter().write("验证成功!");
            HttpSession session = req.getSession();
            People people01 = (People) session.getAttribute("people01");
            System.out.println(people01);
        }else {
            System.out.println("验证失败!!");
            req.getRequestDispatcher("/login.html").forward(req,resp);

        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
    protected void removeSession(HttpServletRequest req,HttpServletResponse resp) throws UnsupportedEncodingException {
        //        解决乱码问题
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=utf-8");

        HttpSession session = req.getSession();
        session.removeAttribute("person01");

//        手动注销session
//        session.invalidate();
    }
}


html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
<form action="http://localhost:8080/JavaWeb01/loginTest" method="get">
  <label>用户名:<input  type="text" name="username"></label>
  <label>密码:<input type="text" name="password"></label>
    <input type="submit">
</form>
</body>
</html>

配置filter过滤器的路径

    <filter>
        <filter-name>loginFilter</filter-name>
        <filter-class>com.test01.javaweb01.filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>loginFilter</filter-name>
<!--        过滤该路径下的所有请求-->
        <url-pattern>/admin/*</url-pattern>
    </filter-mapping>

在webapps目录下创建admin/private.html页面,当外界想要访问到该文件目录下的资源时,我们的过滤器就会去session里面获取person01对象,如果有就让客户端继续访问资源进行相关的操作,否则就拦截并重定向到login.html页面。

参考文献

文献1
文献2
文献3

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值