Filter过滤器

什么是filter过滤器

  1. Filter 过滤器它是 JavaWeb 的三大组件之一。三大组件分别是:Servlet 程序、Listener 监听器、Filter 过滤器

  2. Filter 过滤器它是 JavaEE 的规范。也就是接口

  3. Filter 过滤器它的作用是:拦截请求,过滤响应。

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

1、权限检查

2、日记操作

3、事务管理

……等等



Filter 的初体验

要求:在你的 web 工程下,有一个 admin 目录。这个 admin 目录下的所有资源(html 页面、jpg 图片、jsp 文件、等等)都必须是用户登录之后才允许访问。

在这里插入图片描述


那么如何知道用户是否登录呢?
我们知道,用户登录之后都会把用户登录的信息保存到 Session 域中。所以要检查用户是否登录,可以判断 Session 中否包含有用户登录的信息即可!


filter过滤流程
在这里插入图片描述
Filter 过滤器的使用步骤:

  1. 编写一个类去实现 Filter 接口

  2. 实现过滤方法 doFilter()

这里在filter过滤器中通过session获取登录信息,如果session中有username的信息,则继续访问,否则跳回登录页面

package com.xrj.filter;


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

/**
 * @auther xuruijie
 * @date 2021/12/13 14:42
 */
public class AdminFilter implements Filter {

    public AdminFilter() {
        System.out.println("1.Filter构造器方法AdminFilter()");
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("2.Filter初始化方法init");
    }

    @Override
    /*
     * doFilter 方法,专门用于拦截请求,可以做权限检查
     * @param
     * @return   
     */
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("3.Filter的doFilter方法");
        HttpServletRequest httpServletRequest=(HttpServletRequest) servletRequest;
        HttpSession session=httpServletRequest.getSession();
        Object user=session.getAttribute("user");
        //如果等于null,说明还没有登录
        if(user==null){
            servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
            return;
        }else{
            //让程序继续往下访问用户的目标资源
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }

    @Override
    public void destroy() {
        System.out.println("4.Filter的destroy销毁方法");
    }
}


3. 到 web.xml 中去配置 Filter 的拦截路径

    <!--filter标签用于配置一个filter过滤器-->
    <filter>
        <!--给filter起一个名称-->
        <filter-name>AdminFilter</filter-name>
        <!--配置全类名-->
        <filter-class>com.xrj.filter.AdminFilter</filter-class>
    </filter>
    
    <!--filter-mapping配置filter过滤器拦截路径-->
    <filter-mapping>
        <!--filter-name表示当前的拦截路径给那个filter使用 -->
        <filter-name>AdminFilter</filter-name>
        <!--url-pattern配置拦截路径
            / 表示请求地址是: http://ip:port/工程路径/     映射到IDEA的web目录
            / admin/* 表示请求地址为http://ip:port/工程路径/admin/*
            -->
        <url-pattern>/admin/*</url-pattern>
    </filter-mapping>


login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    这是登录页面。login.jsp<br>
    <form action="http://localhost:8080/15_filter/loginServlet" method="get">
        用户名:<input type="text" name="username"/><br>
        密码:<input type="password" name="password"/><br>
        <input type="submit" />
    </form>
</body>
</html>



servlet程序

这里为了方便将用户名和密码写为固定值,获取login.jsp页面传来的数据,如果username和password都正确,那么就将username存入session中,这样session中username不为null,就可以访问admin中的数据了。如果不正确,就跳回login.jsp重新登陆

package com.xrj.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.Charset;

public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        String username=req.getParameter("username");
        String password=req.getParameter("password");

        if("xrj123".equals(username)&&"123456".equals(password)){
            req.getSession().setAttribute("user",username);
            resp.getWriter().write("登陆成功");
        }else{
            req.getRequestDispatcher("/login.jsp").forward(req,resp);
        }
    }
}



Filter 的生命周期

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

  1. 构造器方法
  2. init 初始化方法 ​
  3. doFilter 过滤方法
  4. destroy 销毁
  • 第 1,2 步,在 web 工程启动的时候执行(Filter 已经创建)
  • 第 3 步,每次拦截到请求,就会执行
  • 第 4 步,停止 web 工程的时候,就会执行(停止 web 工程,也会销毁 Filter 过滤器)


FilterConfig 类

FilterConfig 类见名知义,它是 Filter 过滤器的配置文件类。
Tomcat 每次创建 Filter 的时候,也会同时创建一个 FilterConfig 类,这里包含了 Filter 配置文件的配置信息。

FilterConfig 类的作用是获取 filter 过滤器的配置内容

1、 获取 Filter 的名称 filter-name 的内容

2、获取在 Filter 中配置的 init-param 初始化参数

init-param参数在web.xml文件中配置

<filter>
        <filter-name>AdminFilter</filter-name>
        <filter-class>com.xrj.filter.AdminFilter</filter-class>
        <init-param>
            <param-name>username</param-name>
            <param-value>root</param-value>
        </init-param>

        <init-param>
            <param-name>url</param-name>
            <param-value>jdbc:mysql://localhost:3306</param-value>
        </init-param>
    </filter>

3.、获取 ServletContext 对象



下面代码为获取filter-name、init-param以及ServletContext 对象

 @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("2.Filter初始化方法init");

//        1、获取 Filter 的名称 filter-name 的内容
        System.out.println("filter-name的值是:"+filterConfig.getFilterName());
//        2、获取在 Filter 中配置的 init-param 初始化参数
        System.out.println("初始化参数username的值是:"+filterConfig.getInitParameter("username"));
        System.out.println("初始化参数url的值是:"+filterConfig.getInitParameter("url"));
//        3、获取 ServletContext 对象
        System.out.println(filterConfig.getServletContext());

    }


FilterChain 过滤器链

FilterChain 就是过滤器链(多个过滤器如何一起工作)

工作流程:


多个Fliter过滤器执行时,都会先执行FilterChain.doFilter()之前的代码,FilterChain.doFilter()的作用是如果还有filter就执行下一个Filter,否则执行目标资源,在Filter执行完后执行目标资源,然后反过来以此执行FilterChain.doFilter()之后的代码,如图所示

在这里插入图片描述

Filter1:

package com.xrj.filter;

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

public class Filter1 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("filter1前置代码");
        System.out.println("filter1线程"+Thread.currentThread().getName());
        System.out.println("Filter1"+servletRequest.getParameter("username"));
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("filter1后置代码");
    }

    @Override
    public void destroy() {

    }
}


Filter2:

package com.xrj.filter;

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

public class Filter2 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("filter2前置代码");
        System.out.println("filter2线程"+Thread.currentThread().getName());
        System.out.println("Filter2"+servletRequest.getParameter("username"));
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("filter2后置代码");
    }

    @Override
    public void destroy() {

    }
}


目标资源target.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    System.out.println("target"+request.getParameter("username"));
    System.out.println("目标资源线程"+Thread.currentThread().getName());
    System.out.println("target.jsp页面执行了");
%>
</body>
</html>

运行结果:

在这里插入图片描述



Filter 的拦截路径

1、精确匹配

/target.jsp

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



2、目录匹配

/admin/*

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



3、后缀名匹配

*.html

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

*.do

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

*.action

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



Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值