JavaWeb--Filter

Filter过滤器

概述

1. 什么是Filter过滤器

Filter过滤器是JavaEE的一个接口,是JavaWeb的三大组件之一(三大组件分别是:Servlet程序、Listener监听器、Filter过滤器),它的作用就是拦截请求,过滤响应

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

  • 权限检查
  • 日志操作
  • 事务管理

...

2. 如何创建一个Filter过滤器

要求:在web工程下,有一个admin目录,这个目录下的资源必须要求用户登录之后才能访问

目前阶段用户登录之后信息会保存在Session域中,所以判断用户是否登录,只需检查Session域中有没有用户信息即可

Filter代码示例:

/**
 * doFilter():处理请求,拦截响应,可以做权限检查
 * @param servletRequest
 * @param servletResponse
 * @param filterChain
 * @throws IOException
 * @throws ServletException
 */
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) servletRequest;
    HttpSession session = request.getSession();

    Object user = session.getAttribute("user");

    if(user == null){
        servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
    }else{
        //使程序继续访问目标资源
        filterChain.doFilter(servletRequest,servletResponse);
    }
}

web.xml中的配置:

<filter>
    <filter-name>AdminFilter</filter-name>
    <filter-class>com.th1024.filter.AdminFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>AdminFilter</filter-name>
    <!--
    /  表示请求地址为:http://ip:port/工程路径/  映射到IDEA web目录
    /admin/*  表示拦截请求地址为:http://ip:port/工程路径/admin/*
    -->
    <url-pattern>/admin/*</url-pattern>
</filter-mapping>

Filter过滤器在请求到达服务器之后会先将请求拦截,并根据业务要求检查相应的权限,有权限即放行,无权限则不允许访问或跳转至某个页面

3. Filter过滤器的创建步骤

  1. 编写一个类实现Filter接口
  2. 实现执行过滤操作的方法doFilter()
  3. 在web.xml中配置Filter的拦截路径

完整的用户登录

登录表单:

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

Servlet程序:

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("th1024".equals(username) && "123456".equals(password)){
            req.getSession().setAttribute("user",username);
            resp.getWriter().write("登录成功");
        }else{
            resp.sendRedirect(req.getContextPath() + "/login.jsp");
        }
    }
}

4. Filter过滤器的生命周期

在Filter过滤器中包含几个方法

  1. 构造器方法

  2. init()初始化方法

    第1、2步在web工程启动的时候执行(创建Filter过滤器)

  3. doFilter()方法

    第3步每次拦截到请求都会执行

  4. destroy()方法

    第4步在web工程停止的时候执行(销毁FIlter过滤器)

FilterConfig类

FilterConfig类是Filter过滤器的配置文件类,服务器在创建Filter过滤器对象时,也会同时创建一个FilterConfig类的对象,包含了Filter配置文件的信息

Java代码:

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

web.xml的配置:

<!--filter 标签用于配置一个Filter 过滤器-->
<filter>
	<!--给filter 起一个别名-->
	<filter-name>AdminFilter</filter-name>
	<!--配置filter 的全类名-->
	<filter-class>com.atguigu.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://localhost3306/test</param-value>
	</init-param>
</filter>

FilterChain过滤器链

FilterChain过滤器链可以链式执行Filter过滤器的doFilter()方法

doFilter():

  1. 执行下一个Filter过滤器的doFilter()方法(有下一个Filter)
  2. 访问目标资源(没有下一个Filter)

执行顺序:按照在web.xml中配置Filter的先后顺序来执行

特点:

  1. 所有Filter过滤器和目标资源默认都执行在同一个线程中
  2. 多个Filter过滤器共同执行的时候,共用一个Request对象

Filter1:

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前置代码");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("Filter1后置代码");
    }

    @Override
    public void destroy() {

    }
}

Filter2:

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前置代码");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("Filter2后置代码");
    }

    @Override
    public void destroy() {

    }
}

web.xml中的配置:

<filter>
    <filter-name>filter1</filter-name>
    <filter-class>com.th1024.filter.Filter1</filter-class>
</filter>
<filter>
    <filter-name>filter2</filter-name>
    <filter-class>com.th1024.filter.Filter2</filter-class>
</filter>
<filter-mapping>
    <filter-name>filter1</filter-name>
    <url-pattern>/target.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>filter2</filter-name>
    <url-pattern>/target.jsp</url-pattern>
</filter-mapping>

输出结果:

Filter1前置代码
Filter2前置代码
Filter2后置代码
Filter1后置代码

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结尾才会被拦截

Filter过滤器拦截请求与请求访问的资源是否存在没有关系

posted on 2021-05-02 14:39  来点番茄酱  阅读(68)  评论(0)    收藏  举报