Filter过滤器02

5.Filter过滤器生命周期

  • Filter生命周期图解

  • 验证-Tomcat来创建Filter实例,只会创建一个实例

    package com.filter;
    
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    import java.io.IOException; /**
    * 1.filter在web项目启动时,由Tomcat来创建Filter实例,只会创建一个实例
    * 2.会调用filter的默认无参构造器,同时会调用init()方法,只会调用一次
    * 3.在创建filter实例时,同时会创建FilterConfig对象,并通过init()方法传入
    * 4.通过FilterConfig对象,程序员可以获取该filter的相关配置信息
    * 5.当一个http请求和该filter的url-pattern匹配时,就会调用doFilter()方法
    * 6.在调用doFilter()方法时,Tomcat会同时创建ServletRequest,ServletResponse和FilterChain三个对象
    * 并通过doFilter方法传入
    * 7.如果后面的请求目标资源(jsp,servlet..)会使用到request,response,那么会继续传递,
    * 即request和后面的request是同一个,response和后面的也是同一个
    */
    public class ManageFilter implements Filter { private int count = 0; @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    //当Tomcat创建filter后,会调用该方法,进行初始化
    System.out.println("ManageFilter init方法被调用...");
    } @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,FilterChain filterChain) throws IOException, ServletException {
    System.out.println("doFilter被调用的次数=" + (++count));
    } @Override
    public void destroy() {
    //当filter对像被销毁时,就会调用该方法
    System.out.println("ManageFilter destroy被调用...");
    }
    }

    redeployTomcat,在浏览器访问资源,触发过滤器,后台输出如下:

6.FilterConfig

6.1FilterConfig基本使用

  • FilterConfig接口图

  • FilterConfig说明

    1. FilterConfig是Filter过滤器的配置类
    2. Tomcat每次创建Filter的时候,也会创建一个FilterConfig对象,这里包含了Filter配置文件的配置信息。
    3. FilterConfig对象的作用是获取filter过滤器的配置内容

FilterConfig的简单使用:

DemoFilterConfig:

package com.filter;

import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration; /**
* 演示FilterConfig使用
*/
public class DemoFilterConfig implements Filter { @Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("DemoFilterConfig init方法被调用...");
//演示通过FilterConfig获取相关的参数 //获取filter在xml中配置的名字<filter-name>
String filterName = filterConfig.getFilterName();
//获取指定参数
String ip = filterConfig.getInitParameter("ip");
//filterConfig可以获取到ServletContext,
// 这意味着filter过滤器可以和任何Servlet进行通信
ServletContext servletContext = filterConfig.getServletContext();
//这里可以获取该filter所有的配置的参数名
// (也可以进一步使用getInitParameter获取指定参数)
Enumeration<String> initParameterNames =
filterConfig.getInitParameterNames();
//遍历枚举
while (initParameterNames.hasMoreElements()) {
System.out.println("名字= " + initParameterNames.nextElement());
} System.out.println("filterName= " + filterName);
System.out.println("ip= " + ip);
System.out.println("servletContext= " + servletContext);
} @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException { } @Override
public void destroy() { }
}

在web.xml文件中配置filter:

<!--配置DemoFilterConfig-->
<filter>
<filter-name>DemoFilterConfig</filter-name>
<filter-class>com.filter.DemoFilterConfig</filter-class>
<!--这里就是给filter配置的参数-由程序员根据业务逻辑来设置-->
<init-param>
<param-name>ip</param-name>
<param-value>166.66.66.66</param-value>
</init-param>
<init-param>
<param-name>port</param-name>
<param-value>8888</param-value>
</init-param>
<init-param>
<param-name>email</param-name>
<param-value>jack@qq.com</param-value>
</init-param>
<!---->
</filter>
<filter-mapping>
<filter-name>DemoFilterConfig</filter-name>
<url-pattern>/abc/*</url-pattern>
</filter-mapping>

redeployTomcat,后台输出如下:

可以看到FilterConfig对象可以获取filter过滤器的配置内容。

6.2简单应用-封杀ip

需求:只要某个网段(如以127.0开头的ip)访问我们的web应用,就将其返回登录页面,不允许访问网站。

思路:在web.xml文件中,将要封杀的网段作为初始配置信息。filter实例创建的时候,在init方法中读取配置的要封杀的网段信息,在filter使用的过程中,如果发现用户的请求ip包含了配置的ip网段,就认为是被封杀的ip,进行处理。

细节补充:filter配置的初始化信息只能在init方法中通过FilterConfig对象来获取。为了让doFilter方法中也能使用到,我们在filter类中创建一个属性,在init方法中将获取的配置ip赋给属性,让其在doFilter方法中也能使用。

例子

DemoFilterConfig:

package com.filter;

import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration; /**
* 演示FilterConfig使用
*/
public class DemoFilterConfig implements Filter { private String ip;//从配置中获取的ip @Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("DemoFilterConfig init方法被调用...");
//获取指定参数
ip = filterConfig.getInitParameter("ip");
} @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
//通过forbidden ip来控制
//先获取访问ip
String remoteAddr = servletRequest.getRemoteAddr();
if (remoteAddr.contains(ip)) {//如果访问ip包含了配置ip
//封杀该网段
System.out.println("当前访问的ip为" + remoteAddr + "-封杀该网段...");
servletRequest.getRequestDispatcher("/login.jsp")
.forward(servletRequest, servletResponse);
return;//直接返回
}
//否则就继续访问目标资源
filterChain.doFilter(servletRequest, servletResponse);
} @Override
public void destroy() { }
}

在web.xml中配置filter:

<!--配置DemoFilterConfig-->
<filter>
<filter-name>DemoFilterConfig</filter-name>
<filter-class>com.filter.DemoFilterConfig</filter-class>
<!--配置封杀网段-->
<init-param>
<param-name>ip</param-name>
<param-value>127.0</param-value>
</init-param>
<!---->
</filter>
<filter-mapping>
<filter-name>DemoFilterConfig</filter-name>
<url-pattern>/abc/*</url-pattern>
</filter-mapping>

redeployTomcat,在浏览器直接访问web应用abc目录下的资源,以触发filter。

可以看到浏览器直接返回登录页面。因为当前访问的ip为127.0.0.1,filter检测到当前地址为封杀网段,将页面直接转发回登录页面。

后台输出:

7.FilterChain过滤器链

一句话FilterChain:在处理某些复杂业务时,一个过滤器不够,可以设计多个过滤器共同完成过滤任务,形成过滤器链。

7.1基本原理示意图

如上,服务器接收请求,将请求中的url和过滤器的配置的url-pattern匹配,如果匹配成功,就会触发过滤器。如果匹配多个过滤器的url-pattern,则执行多个过滤器。

  1. 第一个过滤器调用doFilter方法,走前置代码(业务代码),运行到chain.doFilter()时,若请求的url符合其他过滤器配置的url-pattern,就会在doFilter方法中执行下一个filter过滤器的doFilter方法。

    多个filter过滤器的执行顺序与web.xml文件中配置的顺序一致。

  2. 下一个filter过滤器执行完前置代码后,也在chain.doFilter()继续判断...依次类推,最后调用目标资源。

  3. 当目标资源调用完毕后,返回执行倒数第一个filter的后置代码(业务代码),然后返回执行倒数第二个filter后置代码,依次类推....直到第一个filter的后置代码执行完毕,然后服务器向浏览器返回响应。

这个返回调用的机制在事务提交上很有用

7.2过滤器链实例演示

需求:演示过滤器链的使用

AFilter:

package com.filter;

import javax.servlet.*;
import java.io.IOException; public class AFilter 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("AFilter doFilter 的前置代码... ");
System.out.println("执行AFilter filterChain.doFilter()...");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("AFilter doFilter 的后置代码... ");
} @Override
public void destroy() { }
}

BFilter:

package com.filter;

import javax.servlet.*;
import java.io.IOException; public class BFilter 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("BFilter doFilter 的前置代码... ");
System.out.println("执行BFilter filterChain.doFilter()...");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("BFilter doFilter 的后置代码... ");
} @Override
public void destroy() { }
}

在admin目录下的hi.jsp:

<%--
Created by IntelliJ IDEA.
User: li
Date: 2022/11/29
Time: 17:55
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>admin 目录下的 hi.jsp</title>
</head>
<body>
<h1>admin 目录下的 hi.jsp</h1>
<h1>后台管理</h1>
<a href="#">用户列表</a>||<a href="#">添加用户</a>||<a href="#">删除用户</a>
<hr/>
</body>
</html>

在web.xml中配置filter:

<!--配置AFilter和BFilter-->
<filter>
<filter-name>AFilter</filter-name>
<filter-class>com.filter.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>BFilter</filter-name>
<filter-class>com.filter.BFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>BFilter</filter-name>
<url-pattern>/admin/*</url-pattern>
</filter-mapping>

redeployTomcat,在浏览器访问http://localhost:8080/filter/admin/hi.jsp

后台输出如下:

7.3FilterChain注意事项和细节

  1. 多个filter和目标资源在一次http请求中,在同一线程中

  2. 当一个请求url和filter的url-pattern匹配时,才会被执行,如果有多个匹配上,就会顺序执行,形成一个filter调用链

  3. 多个filter共同执行时,因为是一次http请求,使用的是同一个request对象

  4. 多个filter执行的顺序和web.xml配置顺序一致

  5. chain.doFilter(req,resp)方法,将执行下一个过滤器的doFilter方法,如果后面没有过滤器,则执行目标资源

  6. 小结:注意执行过滤器链时,顺序是(以7.2的例子演示):

    HTTP请求->A过滤器doFilter()->A过滤器前置代码->A过滤器chain.doFilter()->B过滤器doFilter()->B过滤器前置代码—>B过滤器chain.doFilter()->目标文件->B过滤器后置代码->A过滤器后置代码->返回给浏览器页面/数据

8.Filter练习

需求:使用过滤器,完成如下要求

  1. 点击发表评论页面topic.jsp,可以在showTopic.jsp显示评论内容
  2. 如果发表的评论内容中,有关键字比如“苹果”,“香蕉”,就返回topic.jsp,并提示有禁用词
  3. 要求发表评论到showTopic.jsp时,要经过过滤器的处理
  4. 禁用词配置在过滤器,在启动项目时动态获取,注意中文的处理

练习


topic.jsp:

<%--
Created by IntelliJ IDEA.
User: li
Date: 2022/11/29
Time: 22:17
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>topic</title>
</head>
<body>
<form action="<%=request.getContextPath()%>/hw/showTopic.jsp" method="post">
<h1>发表对阿凡达电影的评论</h1>
过滤词:苹果,香蕉
<div style="color: red">${notice}</div>
用户:<input type="text" name="username"/><br/>
评论:<textarea cols="15" rows="5" name="topic"></textarea><br/>
<input type="submit" value="发表评论">
</form>
</body>
</html>

showTopic.jsp:

<%--
Created by IntelliJ IDEA.
User: li
Date: 2022/11/29
Time: 22:18
Version: 1.0
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h3>用户:<span style="color: #6799f3">
<%=request.getParameter("username")%></span></h3>
<h3>发表的评论是:<%=request.getParameter("topic")%>
</h3>
</body>
</html>

TopicFilter:

package com.filter.hw;

import javax.servlet.*;
import java.io.IOException; public class TopicFilter implements Filter {
private String[] forbiddenWords; @Override
public void init(FilterConfig filterConfig) throws ServletException {
//获取配置信息(禁用词)
String forbiddenWord = filterConfig.getInitParameter("forbiddenWord");
forbiddenWords = forbiddenWord.split(",");
} @Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException { //注意中文乱码问题!!!
servletRequest.setCharacterEncoding("utf-8");
//获取用户评论
String username = servletRequest.getParameter("username");
String topic = servletRequest.getParameter("topic");
//评论不能为空
if (topic == null || "".equals(topic)) {
servletRequest.setAttribute("notice", "评论不能为空!");
servletRequest.getRequestDispatcher("/hw/topic.jsp")
.forward(servletRequest, servletResponse);
return;
}
//判断评论是否有禁用词
for (String forbiddenWord : forbiddenWords) {
if (topic.contains(forbiddenWord)) {
servletRequest.setAttribute("notice", "含有敏感词...");
servletRequest.getRequestDispatcher("/hw/topic.jsp")
.forward(servletRequest, servletResponse);
return;
}
}
//如果没有禁用词,且评论不为空
servletRequest.getRequestDispatcher("/hw/showTopic.jsp")
.forward(servletRequest, servletResponse);
} @Override
public void destroy() { }
}

在web.xml中配置filter:

<!--配置TopicFilter-->
<filter>
<filter-name>TopicFilter</filter-name>
<filter-class>com.filter.hw.TopicFilter</filter-class>
<!--配置禁用词-->
<init-param>
<param-name>forbiddenWord</param-name>
<param-value>香蕉,苹果</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>TopicFilter</filter-name>
<!--精准匹配-->
<url-pattern>/hw/showTopic.jsp</url-pattern>
</filter-mapping>

redeployTomcat,在浏览器访问http://localhost:8080/filter/hw/topic.jsp

  1. 输入不含敏感词的评论:

  2. 输入含敏感词的评论:

day27-过滤器Filter02的更多相关文章

  1. django中模板变量与内置标签以及过滤器

    本文参考 官方文档 . 一  模板变量 格式: {{ variable_name }} variable_name   命名规则与变量命名规则类似,允许字符数字下划线,不允许标点. variable_ ...

  2. Filter过滤器,xml配置与页面不乱码整理

    1.xml配置 <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi=" ...

  3. SpringBoot第五集:整合监听器/过滤器和拦截器(2020最新最易懂)

    SpringBoot第五集:整合监听器/过滤器和拦截器(2020最新最易懂) 在实际开发过程中,经常会碰见一些比如系统启动初始化信息.统计在线人数.在线用户数.过滤敏/高词汇.访问权限控制(URL级别 ...

  4. ASP.NET Core 中文文档 第四章 MVC(4.3)过滤器

    原文:Filters 作者:Steve Smith 翻译:刘怡(AlexLEWIS) 校对:何镇汐 ASP.NET MVC 过滤器 可在执行管道的前后特定阶段执行代码.过滤器可以配置为全局有效.仅对控 ...

  5. ASP.NET Web API 过滤器创建、执行过程(二)

    ASP.NET Web API 过滤器创建.执行过程(二) 前言 前面一篇中讲解了过滤器执行之前的创建,通过实现IFilterProvider注册到当前的HttpConfiguration里的服务容器 ...

  6. ASP.NET Web API 过滤器创建、执行过程(一)

    ASP.NET Web API 过滤器创建.执行过程(一) 前言 在上一篇中我们讲到控制器的执行过程系列,这个系列要搁置一段时间了,因为在控制器执行的过程中包含的信息都是要单独的用一个系列来描述的,就 ...

  7. ABP(现代ASP.NET样板开发框架)系列之13、ABP领域层——数据过滤器(Data filters)

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之13.ABP领域层——数据过滤器(Data filters) ABP是“ASP.NET Boilerplate P ...

  8. AngularJS过滤器filter-时间日期格式-渲染日期格式-$filter

    今天遇到了这些问题索性就 写篇文章吧 话不多说直接上栗子 不管任何是HTML格式还是JS格式必须要在  controller 里面写 // new Date() 获取当前时间 yyyy-MM-ddd ...

  9. ASP.NET MVC5+EF6+EasyUI 后台管理系统(40)-精准在线人数统计实现-【过滤器+Cache】

    系列目录 上次的探讨没有任何结果,我浏览了大量的文章和个别系统的参考!决定用Cache来做,这可能有点难以接受但是配合mvc过滤器来做效果非常好! 由于之前的过滤器我们用过了OnActionExecu ...

  10. Hawk 4.2 过滤器

    过滤器可以在流中,过滤掉不符合条件的文档.当然也可勾选反向,此时只会留下不符合条件的文档. 空对象过滤器 最为常用,需要列名,可以过滤掉所有内容为Null,或字符串全部都是空字符的情况 数值范围过滤 ...

随机推荐

  1. 对比es6class类和构造函数

    构造函数 在原来class 类这个语法糖没有出来之前 我们一般会把方法挂在prototype 上 为了防止过多的开辟内存 1 // 构造函数------------------------------ ...

  2. Fielddata is disabled on text fields by default Set fielddata=true on [service.address]

    2个字段的: PUT metricbeat-7.3.0/_mapping { "properties": { "service": { "proper ...

  3. 清理rook-ceph

    官方步骤文档:https://rook.io/docs/rook/v1.8/ceph-teardown.html 请注意需要清理的以下资源: rook-ceph namespace: The Rook ...

  4. 请推荐下比较适合中小企业的ERP系统,如odoo,除前期开发和不定期完善,有没有其他固定月费或年费?

    odoo的话你自己就可以下载开源的安装使用的啊,如果你要别人帮你开发和完善做技术服务的话一般都还是要年费的,主要是因为要帮你做维护或修bug什么的,自己能搞定的话自然不需要的哦.只是odoo使用的是p ...

  5. nsis利用ButtonEvent插件移动无标题窗口

    众所周知,普通win窗口是带有标题栏的,标题栏的主要功用之一,就是可以方便的拖动窗体,但为了各式各样的目的,有时候我们不得不想办法将其消除,在nsis中主要是靠system插件调用系统函数改变窗体风格 ...

  6. python+request+pymysql+pytest数据驱动

    一.pymysql简单使用 1.安装mysql 下载地址:https://www.mysql.com/,安装教程这里不做介绍了,网上一大推. 2.安装pymysql库 在Terminal终端输入:pi ...

  7. POJ1094 Sorting It All Out (floyd传递闭包)

    关系具有传递性,可以用floyd解决. 将关系都看做i<j的形式,令d[i][j]=1,如果d[i][j]=d[j][i]=1,说明矛盾:d[i][j]=d[j][i]=0,说明i与j的关系无法 ...

  8. POJ3311 Hie with the Pie(状压DP,Tsp)

    本题是经典的Tsp问题的变形,Tsp问题就是要求从起点出发经过每个节点一次再回到起点的距离最小值,本题的区别就是可以经过一个节点不止一次,那么先预处理出任意两点之间的最短距离就行了,因为再多走只会浪费 ...

  9. 4.ElasticSearch系列之基本概念

    1. 文档 ElasticSearch是面向文档的,文档是所有可搜索数据的最小单位 文档会被序列化成JSON格式,保存在ES中 每个文档都有一个unique ID #查看前10条文档,了解文档格式 P ...

  10. 前端框架Vue------>第一天学习、Vue学习的路径、Vue官网(1)

    文章目录 1.学习目标 2.前端知识体系 2.1 前端三要素 2.2.MVVM 3.第一个Vue程序 4.Vue实例的生命周期 vue的官方文档:https://cn.vuejs.org/ 1.学习目 ...