java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Filter过滤器

JavaWeb中的Filter过滤器解读

作者:Neo丶

这篇文章主要介绍了JavaWeb中的Filter过滤器解读,Filter过滤器是JavaWeb的三大组件之一,Filter过滤器是JavaEE的规范也就是接口,Filter的作用是拦截请求,过滤响应,需要的朋友可以参考下

Filter过滤器

Filter过滤器是JavaWeb的三大组件之一,Filter过滤器是JavaEE的规范也就是接口,Filter的作用是拦截请求,过滤响应。

拦截请求常见的应用场景:权限检查、日志操作、事务管理等等。

Filter过滤器的基本使用

例如权限检查,若没有成功验证用户信息无法打开目标页面。

<%
    Object user = session.getAttribute("user");
    if (user == null){
        request.getRequestDispatcher("/login.jsp").forward(request,response);
        return;
    }
%>

用户登录后会将用户登陆信息保存到Session域中,所以要检查用户是否登录,判断Session中是否包含用户登录信息。

客户端(浏览器) -> Filter过滤器(进行权限检查,检查用户是否有登录,如果有权限则程序默认执行,如果没有权限控制程序流转,不允许其访问)

package com.pero.servlet;
 
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
 
import java.io.IOException;
 
public class AdminFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
 
    }
 
    @Override
    public void destroy() {
 
    }
 
    /**
     * 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对象,通过该对象获取Session
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpSession session = httpServletRequest.getSession();
        Object attribute = session.getAttribute("user");
        //表示还没有登陆
        if (attribute == null){
            servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
        }else {
            //程序继续向下执行
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0">
    <!-- Filter标签用于配置一个Filter过滤器 -->
    <filter>
        <!-- 配置Filter别名 -->
        <filter-name>AdminFilter</filter-name>
        <!-- 配置Filter全类名 -->
        <filter-class>com.pero.servlet.AdminFilter</filter-class>
    </filter>
    <!-- 配置Filter过滤器的拦截路径 -->
    <filter-mapping>
        <!-- 表示当前拦截路径给哪一个Filter -->
        <filter-name>AdminFilter</filter-name>
        <!-- 配置拦截路径
            /admin/*    表示http://ip:port/工程路径/     admin目录下的所有文件
        -->
        <url-pattern>/admin/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.pero.servlet.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/loginServlet</url-pattern>
    </servlet-mapping>
</web-app>
package com.pero.servlet;
 
import jakarta.servlet.*;
import jakarta.servlet.http.*;
 
import java.io.IOException;
 
public class LoginServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        if ("root".equals(username) && "root".equals(password)){
            request.getSession().setAttribute("user",username);
            response.getWriter().write("登陆成功");
        }else {
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }
    }
 
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
    }
}
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2023/3/16
  Time: 22:07
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陆页面</title>
</head>
<body>
  <form action="http://localhost:8080/Filter_Web/loginServlet" method="get">
      用户名:<input type="text" name="username"><br/>
      密码:<input type="password" name="password"><br/>
      <input type="submit" value="提交">
  </form>
</body>
</html>

Filter的生命周期

Filter的生命周期是指Filter从创建到销毁整个过程执行方法的顺序。包含以下方法:

1.构造器方法;

2.init初始化方法;

3.doFilter过滤方法;

4.destory销毁方法;

在Web工程启动的时候构造器方法和初始化方法会被执行(Filter对象已经创建),每次拦截到请求时会执行doFilter方法,停止Web工程的时候就会执行destory方法。

FilterConfig类

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

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

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

2.获取web.xml配置的init-param初始化参数

3.获取ServletContext对象

package com.pero.servlet;
 
import jakarta.servlet.*;
 
import java.io.IOException;
 
public class TestFilter implements Filter {
 
    public TestFilter() {
        System.out.println("构造方法");
    }
 
    public void init(FilterConfig config) throws ServletException {
        System.out.println("init初始化方法");
        //获取Filter的名称filter-name的内容
        String filterName = config.getFilterName();
        //获取web.xml配置的init-param初始化参数
        System.out.println("filter-name为:" + filterName);
        String username = config.getInitParameter("username");
        String url = config.getInitParameter("url");
        System.out.println("username:" + username + "url:" + url);
        //获取ServletContext对象
        ServletContext servletContext = config.getServletContext();
        System.out.println("servletContext:" + servletContext);
    }
 
    public void destroy() {
        System.out.println("destory销毁方法");
    }
 
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("doFilter方法");
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0">
    <!-- Filter标签用于配置一个Filter过滤器 -->
    <filter>
        <!-- 配置Filter别名 -->
        <filter-name>AdminFilter</filter-name>
        <!-- 配置Filter全类名 -->
        <filter-class>com.pero.servlet.AdminFilter</filter-class>
    </filter>
    <filter>
        <filter-name>TestFilter</filter-name>
        <filter-class>com.pero.servlet.TestFilter</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/test</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>TestFilter</filter-name>
        <url-pattern>/testFilter</url-pattern>
    </filter-mapping>
    <!-- 配置Filter过滤器的拦截路径 -->
    <filter-mapping>
        <!-- 表示当前拦截路径给哪一个Filter -->
        <filter-name>AdminFilter</filter-name>
        <!-- 配置拦截路径
            /admin/*    表示http://ip:port/工程路径/     admin目录下的所有文件
        -->
        <url-pattern>/admin/*</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.pero.servlet.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/loginServlet</url-pattern>
    </servlet-mapping>
</web-app>

FilterChain过滤器链

客户端(浏览器) -> 服务器(Filter①:执行doFilter()方法:前置代码1 ->chain.doFilter(request, response); -> Filter②:执行doFilter()方法 :前置代码1 -> chain.doFilter(request, response); -> 查询目标资源,找到并获取 -> 后置代码2 ->Filter①:执行doFilter()方法:后置代码2)

FilterChain.doFilter()方法的作用:①如果有其他的Filter过滤器,执行下一个Filter过滤器;②如果没有其他需要执行的过滤器,执行目标资源。

多个Filter过滤器执行的时候他们执行的优先顺序是由在web.xml中filter-mapping从上到下的配置顺序决定的。

多个Filter过滤器执行的特点:

①所有Filter和目标资源默认都执行在同一个线程中

②多个Filter共同执行的时候,他们都使用同一个Request对象。

package com.pero.servlet;
 
import jakarta.servlet.*;
 
import java.io.IOException;
import java.lang.Thread;
 
public class Filter1 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("Filter1前置代码");
        System.out.println("Filter1线程" + Thread.currentThread().getName());
        System.out.println("Filter1" + request.getParameter("username"));
        chain.doFilter(request, response);
        System.out.println("Filter1线程" + Thread.currentThread().getName());
        System.out.println("Filter1后置代码");
    }
}
package com.pero.servlet;
 
import jakarta.servlet.*;
 
import java.io.IOException;
 
public class Filter2 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("Filter2前置代码");
        System.out.println("Filter2线程"+Thread.currentThread().getName());
        System.out.println("Filter2" + request.getParameter("username"));
        chain.doFilter(request, response);
        System.out.println("Filter2线程"+Thread.currentThread().getName());
        System.out.println("Filter2后置代码");
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0">
   ...
    <filter>
        <filter-name>Filter1</filter-name>
        <filter-class>com.pero.servlet.Filter1</filter-class>
    </filter>
 
    <filter>
        <filter-name>Filter2</filter-name>
        <filter-class>com.pero.servlet.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>
    ...
</web-app>
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  Date: 2023/3/17
  Time: 10:30
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <%
        System.out.println("target页面执行");
        System.out.println("目标资源"+Thread.currentThread().getName());
        System.out.println("目标资源" + request.getParameter("username"));
    %>
</body>
</html>

Filter的拦截路径

精确匹配

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

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

目标匹配

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

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

后缀名匹配

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

以上配置路径,表示请求地址必须为:.html

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

到此这篇关于JavaWeb中的Filter过滤器解读的文章就介绍到这了,更多相关Filter过滤器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文