admin管理员组

文章数量:1574508

文章目录

  • 什么是过滤器
  • 写过滤器的步骤
  • 配置初始化参数
  • 过滤器的优先级
  • 过滤器的优点
  • 过滤器执行过程图解
  • 过滤敏感词的示例代码
    • 使用 Servlet 来过滤敏感词
    • 使用过滤器来过滤敏感词
    • 通过配置初始化参数来设置敏感词
  • 关于 web.xml 的配置

什么是过滤器

Servlet 规范当中定义的一种特殊的类,用于对 Servlet 容器的调用过程进行拦截。

写过滤器的步骤

step1
写一个 java 类,实现一个 Filter 接口。
step2
在 doFilter 方法里,实现过滤的逻辑。
step3
配置(web.xml)。

配置初始化参数

step1
web.xml 中,使用 <init-para> 元素来配置初始化参数
step2
在 Filter 类中,使用 FilterConfig.getInitParameter(String paraName); 获得初始化参数。

过滤器的优先级

当有多个过滤器都满足过滤的条件时,依据 <filter-mapping> 的先后顺序依次执行。

过滤器的优点

a. 可以将多个 web 组件相同的逻辑写在一个过滤器当中,方便代码的维护
b. 可实现代码的“可插拔性"。
给一个软件增加戒者减少某个功能不会影响已经存在的功能。

过滤器执行过程图解

  1. 浏览器发送请求给服务器
  2. 服务器的 Servlet 引擎创建 Request 对象&&Response 对象
  3. Servlet 引擎先调用过滤器的 doFilter 方法,该方法有两个参数 request 和 response,
    (在过滤器中可以访问到 Request 对象&&Response 对象)
  4. 过滤器对拦截的内容迚行处理
  5. 之后调用 SomeServlet 的 service 方法
  6. service 方法执行
  7. service 方法执行结束后,将结果返回到过滤器
  8. 过滤器将 service 方法返回的结果再次进行过滤
  9. 最后,Servlet 引擎将结果返回给浏览器

过滤敏感词的示例代码

使用 Servlet 来过滤敏感词

实现敏感词过滤功能,如果没有使用过滤器,我们使用 Servlet 来实现。

JSP 页面代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body style="font-size: 30px;">
<form action="process" method="post">
    input your comment:<input type="text" name="comment"/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>

Servlet 代码:

package priv.lwx.servlet.filter.web;

import org.junit.jupiter.api.Test;

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 java.io.IOException;
import java.io.PrintWriter;

/**
 * description
 *
 * @author liaowenxiong
 * @date 2022/2/23 22:40
 */
@WebServlet("/process")
public class ProcessServlet extends HttpServlet {
  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    req.setCharacterEncoding("utf-8");
    resp.setContentType("text/html;charset=utf-8");
    PrintWriter out = resp.getWriter();
    String comment = req.getParameter("comment");
    if (comment.indexOf("dog") >= 0) {
      out.println("含有违禁关键字");
    } else {
      out.println("你的评论是:" + comment);
    }
    out.close();
  }

  @Test
  public void test() {
    System.out.println("dog".indexOf("dog"));
  }
}

使用过滤器来过滤敏感词

Filter 的代码如下:

package priv.lwx.servlet.filter;
/**
 * 评论敏感词过滤器
 *
 * @author liaowenxiong
 * @date 2022/2/23 23:14
 */


import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
import java.io.PrintWriter;

@WebFilter("/process")
public class CommentFilter implements Filter {

  /**
   * Servlet 容器在创建好 Filter 实例之后,会立即创建
   * FilterConfig 实例并调用 init()方法,将 FilterConfig
   * 实例作为参数传递过去。通过该实例,可以访问 Filter 的初始化参数。
   * String FilterConfig.getInitParameter(String paraName);
   * init()方法只会执行一次。
   *
   * @param config
   * @throws ServletException
   */
  public void init(FilterConfig config) throws ServletException {
    System.out.println("init...");
  }

  /**
   * 在容器删除Filter实例之前,调用该方法。
   * 只会执行一次。
   */
  public void destroy() {
    System.out.println("destroy...");
  }

  /**
   * 当请求到达容器,容器会调用 doFilter 方法。
   * 容器会将事先创建好的 request,response 对象作为
   * 参数传递过去。
   * FilterChain:过滤器链。
   * 如果调用了 FilterChain.doFilter 方法,表示调用
   * 后续的过滤器。如果没有过滤器了,则调用对应的 web 组件。
   *
   * @param request
   * @param response
   * @param chain
   * @throws ServletException
   * @throws IOException
   */
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
    request.setCharacterEncoding("utf8");
    response.setContentType("text/html;charset=utf-8");
    PrintWriter out = response.getWriter();
    String comment = request.getParameter("comment");
    if (comment.indexOf("dog") >= 0) {
      out.println("评论中含有敏感词!");
    } else {
      // 调用后续的过滤器,如果没有了,则调用Web组件
      chain.doFilter(request, response);
    }
  }

}

注意点:过滤器的请求路径(即url-pattern)必须与web组件(Servlet)的url-pattern相同。

Servlet 的代码如下:

package priv.lwx.servlet.filter.web;

import org.junit.jupiter.api.Test;

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 java.io.IOException;
import java.io.PrintWriter;

/**
 * description
 *
 * @author liaowenxiong
 * @date 2022/2/23 22:40
 */
@WebServlet("/process")
public class ProcessServlet extends HttpServlet {
  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    req.setCharacterEncoding("utf-8");
    resp.setContentType("text/html;charset=utf-8");
    PrintWriter out = resp.getWriter();
    String comment = req.getParameter("comment");
    out.println("你的评论是:" + comment);
    out.close();
  }

  @Test
  public void test() {
    System.out.println("dog".indexOf("dog"));
  }
}

通过配置初始化参数来设置敏感词

Filter 的示例代码:

package priv.lwx.servlet.filter;
/**
 * 评论敏感词过滤器
 *
 * @author liaowenxiong
 * @date 2022/2/23 23:14
 */


import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

@WebFilter(value = "/process", initParams = {@WebInitParam(name = "illegalStr0",
        value = "dog"), @WebInitParam(name = "illegalStr1", value = "pig")})
public class CommentFilter implements Filter {
  private FilterConfig config;

  /**
   * Servlet 容器在创建好 Filter 实例之后,会立即创建
   * FilterConfig 实例并调用 init()方法,将 FilterConfig
   * 实例作为参数传递过去。通过该实例,可以访问 Filter 的初始化参数。
   * String FilterConfig.getInitParameter(String paraName);
   * init()方法只会执行一次。
   *
   * @param config
   * @throws ServletException
   */
  public void init(FilterConfig config) throws ServletException {
    System.out.println("init...");
    config = config;
  }

  /**
   * 在容器删除Filter实例之前,调用该方法。
   * 只会执行一次。
   */
  public void destroy() {
    System.out.println("destroy...");
  }

  /**
   * 当请求到达容器,容器会调用 doFilter 方法。
   * 容器会将事先创建好的 request,response 对象作为
   * 参数传递过去。
   * FilterChain:过滤器链。
   * 如果调用了 FilterChain.doFilter 方法,表示调用
   * 后续的过滤器。如果没有过滤器了,则调用对应的 web 组件。
   *
   * @param request
   * @param response
   * @param chain
   * @throws ServletException
   * @throws IOException
   */
  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
    request.setCharacterEncoding("utf8");
    response.setContentType("text/html;charset=utf-8");
    PrintWriter out = response.getWriter();
    String comment = request.getParameter("comment");
    Enumeration<String> initParameterNames = config.getInitParameterNames();
    // 是否含有敏感词,默认无
    boolean isIllegal = false;
    while (initParameterNames.hasMoreElements()) {
      String initParameterName = initParameterNames.nextElement();
      String initParameter = config.getInitParameter(initParameterName);
      if (comment.indexOf(initParameter) >= 0) {
        // 含有敏感词
        isIllegal = true;
        out.println("评论中含有敏感词:" + initParameter);
        break;
      }
    }
    if (!isIllegal) {
      // 没有敏感词,则调用后续的过滤器,如果没有过滤器,则调用Web组件
      chain.doFilter(request, response);
    }
  }

}

注意点:注解 WebFilter 的 属性 initParams,其值是一个注解数组,即数组元素的类型就是 @WebInitParam,或者说数组元素是 @WebInitParam 的实例对象。

赋值示例代码如下:

initParams = {@WebInitParam(name = "illegalStr0",value = "dog"), @WebInitParam(name = "illegalStr1", value = "pig")}

解读:
注解 WebInitParam 用来封装参数,方法 initParams 用来从 WebInitParam 对象获取参数,再将参数封装到 Request 对象中。

Servlet 的示例代码:

package priv.lwx.servlet.filter.web;

import org.junit.jupiter.api.Test;

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 java.io.IOException;
import java.io.PrintWriter;

/**
 * description
 *
 * @author liaowenxiong
 * @date 2022/2/23 22:40
 */
@WebServlet("/process")
public class ProcessServlet extends HttpServlet {
  @Override
  protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    req.setCharacterEncoding("utf-8");
    resp.setContentType("text/html;charset=utf-8");
    PrintWriter out = resp.getWriter();
    String comment = req.getParameter("comment");
    out.println("你的评论是:" + comment);
    out.close();
  }

  @Test
  public void test() {
    System.out.println("dog".indexOf("dog"));
  }
}

关于 web.xml 的配置

上面的示例并没有在 web.xml 文件中对 Servlet、Filter 进行配置,采用的都是注解配置。如果要在 web.xml 配置 Servlet、Filter 请参考下面的配置内容:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp/xml/ns/javaee"
         xmlns:xsi="http://www.w3/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp/xml/ns/javaee http://xmlns.jcp/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <filter>
        <filter-name>filter1</filter-name>
        <filter-class>priv.lwx.servlet.filter.CommentFilter</filter-class>
        <init-param>
            <param-name>illegalStr0</param-name>
            <param-value>dog</param-value>
        </init-param>
        <init-param>
            <param-name>illegalStr1</param-name>
            <param-value>pig</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>filter1</filter-name>
        <url-pattern>/process</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>process</servlet-name>
        <servlet-class>priv.lwx.servlet.filter.web.ProcessServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>process</servlet-name>
        <url-pattern>/process</url-pattern>
    </servlet-mapping>
</web-app>

本文标签: 过滤器定义servlet