JavaWeb Filter 过滤器

news2024/9/23 1:28:03

参考:JavaWeb过滤器(Filter)详解

1、简介

顾名思义就是对事物进行过滤的,在Web中的过滤器,当然就是对请求进行过滤,我们使用过滤器,就可以对请求进行拦截,然后做相应的处理,实现许多特殊功能。如登录控制权限管理过滤敏感词汇等。

只要请求或者响应符合配置的路径,不管路径对应的资源是否存在,都会进行过滤。

1.1、原理:

过滤器会对游览器的请求(和服务器返回的响应)进行过滤,过滤器可以动态的分为3个部分:

  • 1.放行之前的代码:对游览器请求进行第一次过滤,然后继续执行
  • 2.放行(filterChain.doFilter(servletRequest,servletResponse)):将游览器请求放行,如果还有过滤器,那么就继续交给下一个过滤器
  • 3.放行后的代码:对返回的Web资源再次进行过滤处理

这3个部分分别会发挥不同作用。
在这里插入图片描述

1.2、包:

servlet-api.jar

2、生命周期

Filter有3个阶段,分别是初始化,过滤,销毁。

  1. 初始化阶段:当服务器启动时,我们的服务器(Tomcat)就会读取配置文件,扫描注解,然后来创建我们的Filter。
  2. 过滤阶段:只要请求资源的路径和拦截的路径相同,那么过滤器就会对请求进行过滤,这个阶段在服务器运行过程中会一直循环。
  3. 销毁阶段:当服务器(Tomcat)关闭时,服务器创建的Filter也会随之销毁

它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新部署的时候才销毁。

过滤器生命周期:初始化init() → 过滤doFilter() → 析构(销毁)destroy()

3、使用

我们创建Filter,只需要继承Filter接口就行。

import javax.servlet.*;
import java.io.IOException;
 
public class MyFilter implements Filter {
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
 
    }
}

3.1、接口、参数

3.1.1、接口

package javax.servlet;

public interface Filter {
    default void init(javax.servlet.FilterConfig filterConfig) throws javax.servlet.ServletException { /* compiled code */ }

    void doFilter(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse, javax.servlet.FilterChain filterChain) throws java.io.IOException, javax.servlet.ServletException;

    default void destroy() { /* compiled code */ }
}

3.1.2、参数

FilterConfig和FilterConfig这2个对象是由服务器(Tomcat)在创建和调用Filter对象时所传入的,这2个对象十分有用。

  • FilterConfig对象可以读取我们配置的初始参数;
  • FilterChain可以实现多个Filter之间的连接。
public interface FilterConfig {
	// 获取filter的名称
    java.lang.String getFilterName();
	// 获取ServletContext
    javax.servlet.ServletContext getServletContext();
	// 获取配置的初始参数的值
    java.lang.String getInitParameter(java.lang.String s);
	// 获取配置的所有参数名称
    java.util.Enumeration<java.lang.String> getInitParameterNames();
}

/*
FilterChain就只有一个方法,其实这个方法就是用来对拦截进行放行的;
如果有多个拦截器,那么就会继续调用下一个Filter进行拦截。
doFilter方法需要传入个参数,一个是ServletRequest,一个是ServletResponse参数,这个直接传入进行。

Tomcat在调用过滤器时,默认就会传入Request和Response,
这个参数封装了请求和响应,我们直接使用就行。
ServletResquest和ServletResponse可以直接
强转成HttpServletRequest和HttpServletResponse,然后使用相应的方法
*/
public interface FilterChain {
    void doFilter(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws java.io.IOException, javax.servlet.ServletException;
}

①、FilterConfig
运用:在init方法中使用FilterConfig来读取配置的数据库的信息,然后输出。

<web-app>
	<filter>
	    <filter-name>myFilterConfig</filter-name>
	    <!-- 过滤器对应的java类 -->
	    <filter-class>com.clucky.filter.MyFilterConfig</filter-class>
	    <!-- 初始化参数 -->
	    <init-param>
	        <param-name>driver</param-name>
	        <param-value>com.mysql.jdbc.Driver</param-value>
	    </init-param>
	    <init-param>
	        <param-name>url</param-name>
	        <param-value>jdbc:mysql://localhost:3306/equip_employ_manage?serverTimezone=GMT</param-value>
	    </init-param>
	    <init-param>
	        <param-name>username</param-name>
	        <param-value>root</param-value>
	    </init-param>
	    <init-param>
	        <param-name>password</param-name>
	        <param-value>root</param-value>
	    </init-param>
	</filter>
	<filter-mapping><!-- 映射 -->
	    <filter-name>myFilterConfig</filter-name>
	    <!-- 拦截路径:拦截所有请求 -->
	    <url-pattern>/*</url-pattern>
	</filter-mapping>
</web-ap>
import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;
 
public class MyFilterConfig implements Filter {
 
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("-----------获取全部key:value------------");
        //得到所有配置参数的名字
        Enumeration<String> names = filterConfig.getInitParameterNames();
        while (names.hasMoreElements()) {
            //得到每一个名字
            String name = names.nextElement();
            System.out.println(name+" = "+filterConfig.getInitParameter(name));
        }
        System.out.println("-----------end.....------------");
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    }
 
    @Override
    public void destroy() {
    }
}

在这里插入图片描述

②、FilterConfig
配置2个Filter,通过FilterChain来进行多个过滤。
第一个过滤器

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
//注解方式配置Filter
@WebFilter("/*")
public class Filter01 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("调用过滤器01对请求进行过滤~~~~");
        //放行,如果还有过滤器,那么就执行下一个过滤器
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("调用过滤器01对响应进行过滤~~~~");
    }
 
    @Override
    public void destroy() {
    }
}

第二个过滤器

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
 
@WebFilter("/*")
public class Filter02 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("调用过滤器02对请求进行过滤~~~~");
        //放行,如果还有过滤器,那么就执行下一个过滤器
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("调用过滤器02对响应进行过滤~~~~");
    }
 
    @Override
    public void destroy() {
    }
}

Filter01先进行过滤,然后交给Filter02,然后访问资源,然后Filter02对响应进行过滤,然后Filter01对响应进行过滤。图示如下:
在这里插入图片描述
在这里插入图片描述

3.2、配置

  • Filter 的 url-pattern 中配置的路径是访问已经存在的网络资源,如静态页面、jsp、servlet等。
  • filter 和 url-pattern 之间的关系是 多对多的关系。即,Filter可负责拦截多个请求或响应;一个请求或响应也可被多个Filter拦截。(多个 filter 会根据 web.xml 中配置的顺序组成 filter 链)。

3.2.1、注解方式

@WebFilter(value = {"/*"},filterName = "myFilter")
public class test implements Filter {
}

@WebFilter源码

urlPatterns和value是一样的。urlPatterns和value只能配置一个,不能两个都配置,两个都配置就会报错。

public @interface WebFilter {
    java.lang.String description() default "";
	// filter显示名称
    java.lang.String displayName() default "";
	// 初始化参数
    javax.servlet.annotation.WebInitParam[] initParams() default {};
	// 该filter的名字
    java.lang.String filterName() default "";

    java.lang.String smallIcon() default "";

    java.lang.String largeIcon() default "";
	// 指定对哪些servlet进行过滤
    java.lang.String[] servletNames() default {};
	// 指定拦截路径
    java.lang.String[] value() default {};
	// 指定拦截路径
    java.lang.String[] urlPatterns() default {};

    javax.servlet.DispatcherType[] dispatcherTypes() default {javax.servlet.DispatcherType.REQUEST};
	// 是否支持异步模式
    boolean asyncSupported() default false;
}

3.2.2、xml方式

<web-app>
    <filter>
        <filter-name>myFilter</filter-name>
        <filter-class>com.clucky.filter.MyFilter</filter-class>
    </filter>
    <!-- 一个过滤器需要过滤多种文件,则可以配置多个<filter-mapping>,
    一个mapping定义一个url-pattern来定义过滤规则 -->
    <filter-mapping>
        <filter-name>myFilter</filter-name>
        <!-- 所有外部访问都需要先经过该过滤器。 -->
		<url—pattern>/*</url-pattern>
		<!-- 作用于某一文件夹下所有文件 -->
		<!-- <url—pattern>/dir/*</url-pattern> -->
		<!-- 作用于某一种类型的文件 -->
		<!-- <url—pattern>*.扩展名</url-pattern> -->
		<!-- 作用于某一文件夹下某一类型文件 -->
		<!-- <url—pattern>/dir/*.扩展名</url-pattern> -->
    </filter-mapping>
</web-app>

3.3、执行顺序

多个Filter的执行顺序

如果配置了2个过滤器,怎么知道那个过滤器先执行呢?

  • 如果我们是在web.xml中配置的过滤器,那么过滤器的执行顺序就是<filter-mapping>在web配置的顺序,配置在上面那么就会先执行。
  • 如果我们是使用@WebFilter进行配置的,那么执行顺序就是字符比较顺序来执行,例如有2个过滤器,一个是AFilter,一个是BFilter,那么AFilter就会先执行。
  • 如果注解和xml混用,那么在web.xml中配置的会先执行。

3.4、具体应用(过滤敏感词)

如果评论中含有我们定义的敏感词汇,那么我们就进行过滤,使用**来进行代替。

jsp页面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>评论</title>
</head>
<body>
<h1>输入评论内容</h1>
<form action="${pageContext.request.contextPath}/comment" method="post">
    <textarea name="message" cols="30" rows="10"></textarea>
    <input type="submit" value="提交">
</form>
<p >${requestScope.get("name")}<span style="color: red">${requestScope.get("comment")}</span></p>
</body>
</html>

requestScope介绍

Filter java

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
 // 这里使用注解配置,也可以用xml配置
@WebFilter(servletNames = {"comment"},initParams = {@WebInitParam(name = "sensitiveWord", value = "zz")})
public class CommentFilter implements Filter {
 
    private List<String> sensitiveWords = new ArrayList<>();
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //得到敏感词汇
        String word = filterConfig.getInitParameter("sensitiveWord");
        //加入集合
        sensitiveWords.add(word);
    }
 
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //设置编码
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");
        //得到评论
        String message = servletRequest.getParameter("message");
        for (String sensitiveWord : sensitiveWords) {
            //对所有敏感词汇进行过滤
            if (message.contains(sensitiveWord)){
                //替换敏感词汇
                message = message.replace(sensitiveWord, "**");
            }
        }
        //存入request域
        servletRequest.setAttribute("comment",message);
        //放行
        filterChain.doFilter(servletRequest,servletResponse);
    }
 
    @Override
    public void destroy() {
    }
}

Servlet java

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.HashSet;
 
@WebServlet(name = "comment",value = "/comment")
public class CommentServlet extends HttpServlet {
 
    //记录评论敏感词汇的ip
    private HashSet<String> hashSet = new HashSet<>();
 
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String message = request.getParameter("message");
        String comment = (String) request.getAttribute("comment");
        if (message.equals(comment)){
            System.out.println("没有敏感词汇.....");
            //设置名字
            request.setAttribute("name","good boy:");
        }else {
            //有敏感词汇,记录IP
            String localAddr = request.getLocalAddr();
            System.out.println(localAddr);
            hashSet.add(localAddr);
            //设置名字
            request.setAttribute("name","bad boy:");
        }
        //转发到comment.jsp页面
        request.getRequestDispatcher("/comment.jsp").forward(request,response);
    }
 
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request, response);
    }
}

输入:你真是个zz
在这里插入图片描述

3.5、具体应用(解决乱码)

web.xml配置

<web-app>
 <filter>
    <filter-name>encoding</filter-name>
    <filter-class>com.yyl.utils.EncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>  
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>encoding</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

java

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class EncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        // 强转
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        request.setCharacterEncoding("UTF-8") ;
        // 网页编码编译的格式
        response.setContentType ("text/html; charset=UTF-8") ;
        filterChain.doFilter(request, response) ;

    }

    @Override
    public void destroy() {

    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/61185.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

阿里云部署应用

安装jdk 查看已安装版本 rpm -qa | grep java yum命令查找JDK1.8软件包 yum -y list java-1.8* 安装列表中的JDK1.8软件包 yum -y install java-1.8.0-openjdk-devel.x86_64 java -version 配置环境变量 vim /etc/profile JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk-1.8.…

三、内存管理 (二)虚拟存储器

目录 2.1虚拟内存的基本概念 2.2内存分配策略 2.2.1驻留集大小 2.2.2固定分配局部置换 2.2.3可变分配全局置换 2.2.4可变分配局部置换 2.3地址变换机构 2.3.1页表机制 2.3.2预调页策略和请求调页策略 2.3.3缺页中断机构 2.3.4对换区与文件区 2.3.5页面置换算法 …

搭建springWeb保姆级教程

经过我们对mybatis和spring框架的学习&#xff0c;我们即将要用框架进行前后端数据交互&#xff0c;已经脱离了那种用servlet的方式进行数据传输&#xff0c;今天让我们来搭建最基本的springweb框架&#xff01;&#xff01;&#xff01; 1.创建一个web项目 1. 2. 选择一个we…

自定义线程实现c++代码回调run方法

目录 pthread_create函数介绍 前面写过一篇文章《Thread类的start()方法创建线程的底层分析》&#xff0c;这次来自定义一个线程&#xff0c;并实现在底层创建内核线程来执行用户代码。 pthread_create函数介绍 在这之前&#xff0c;先熟悉下Linux中创建内核线程函数pthread…

【计算机视觉】 摄像机标定

摄像机标定 齐次坐标 齐次坐标&#xff0c;将欧氏空间的无穷远点&#xff0c;与投影空间中有实际意义的消失点&#xff0c;建立起映射关系。 把齐次坐标转化为笛卡尔坐标的方法&#xff1a;是前面n-1个坐标分量分别除以最后一个分量即可 一些解释和性质&#xff1a; 比较好的…

Linux最常用命令用法总结(精选)

1. su 普通用户切换root用户 ubuntuubuntu20:~$ su Password: rootubuntu20:/home/ubuntu# exit exit ubuntuubuntu20:~$ 2. clear 清除当前终端显示的输出快捷键ctrlL键 3. cd 改变目录 ubuntuubuntu20:~/workspace$ cd .. ubuntuubuntu20:~$ cd / ubuntuubuntu20:/$ c…

docker下搭建redis集群

1. 环境准备 准备好Linux系统机器&#xff0c;并安装好docker&#xff0c;阅读这篇文章前请先了解清楚docker的基本知识并且会熟悉运用docker的常用命令。学习docker基础知识可以参考这篇博文 安装好并启动docker后就可以开始搭建redis了 2. docker容器下安装redis 本篇文章…

数据链路层(必备知识)

文章目录1、数据链路层的作用2、认识以太网<1>以太网帧格式<2>认识MAC地址<3>认识MTU<4>查看硬件地址和MTU3、ARP协议<1>什么是ARP协议<2>ARP数据报格式<3>ARP协议的工作机制4、其他重要协议或技术<1> DNS<2>NAT技术1、…

《MySQL实战45讲》——学习笔记19 “SQL查一行执行慢的排查、锁等待/一致性读“【建议收藏】

由于SQL本身的写法问题&#xff08;如join太多表、未走索引/索引失效、一次查太多数据等&#xff09;&#xff0c;或是MySQL节点CPU占用率很高或IO利用率很高&#xff0c;都会导致一条SQL执行的比较慢&#xff1b;但是有时候&#xff0c;"只查一行数据"&#xff0c;也…

内存优化之重新认识内存

我们知道&#xff0c;手机的内存是有限的&#xff0c;如果应用内存占用过大&#xff0c;轻则引起卡顿&#xff0c;重则导致应用崩溃或被系统强制杀掉&#xff0c;更严重的情况下会影响应用的留存率。因此&#xff0c;内存优化是性能优化中非常重要的一部分。但是&#xff0c;很…

深入体会线程状态的切换

✨✨hello&#xff0c;愿意点进来的小伙伴们&#xff0c;你们好呐&#xff01; &#x1f43b;&#x1f43b;系列专栏&#xff1a;【JavaEE初阶】 &#x1f432;&#x1f432;本篇内容&#xff1a;线程状态详解 &#x1f42f;&#x1f42f;作者简介:一名现大二的三非编程小白&am…

微机-------CPU与外设之间的数据传送方式

目录 一、无条件方式二、查询方式三、中断方式四、DMA方式一、无条件方式 外设要求:简单、数据变化缓慢。 外设被认为始终处于就绪状态。始终准备好数据或者始终准备好接收数据。 IN AL,数据端口 数据端口的地址通过CPU的地址总线送到地址译码器进行译码,同时该指令进行的是…

JAVASE(复习)——异常

所有的异常都是在java.lang包中的Throwable类中 一、Exception 和 Error 的区别 exception&#xff1a;程序本身发生的异常&#xff0c;可以捕获抛出异常&#xff0c;一般用try—catch—finally捕获。 error&#xff1a;发生在jvm层面的错误&#xff0c;程序无法处理。 二…

Git 如何调整 commit 的顺序

title: Git 如何调整 commit 的顺序 date: 2022-12-02 23:11 tags: [git] 〇、问题 使用哪条命令调整commit的顺序&#xff1f; git rebase -i 一、前言 今天测试了git hooks&#xff0c;产生了大量的commit&#xff0c;而后又进行了正常的commit&#xff0c;因此在这里是想要…

java——mybatis——Mybatis注解开发——@Update——修改数据

DAO接口&#xff1a; package com.sunxl.dao;import com.sunxl.pojo.User; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.SelectKey; import org.apache.ibatis.annotations.Update;impo…

SpringBoot+Thymeleaf上传头像并回显【表单提交】

参考文章&#xff1a;springbootthymeleaf实现图片上传并回显https://www.wanmait.com/note/shaowei/javaee/b3717a24fde24d3e89c47765a1a63214.html 一、新建SpringBoot项目 添加 spring web和 thymeleaf 的依赖 二、在templates新建页面 在页面中添加一个表单和一个文件上传…

8086,8088CPU管脚,奇偶地址体, ready信号,reset复位信号。规则字和非规则字

8086/8088均为40条引线&#xff0c;双列直插式封装&#xff0c;某些引线有多重功能&#xff0c;其功能转换有两种情况&#xff1a;一种是分时复用&#xff0c;一种是按组态定义。 用8088微处理器构成系统时&#xff0c;有两种不同的组态&#xff1a; 最小组态&#xff1a;808…

@AutoWired与@Resource

参考 : Qualifier - 搜索结果 - 知乎 Autowired和Resource的区别是什么&#xff1f; - 知乎 面试突击78&#xff1a;Autowired 和 Resource 有什么区别&#xff1f; - 掘金 目录 同一类型多个Bean报错问题 Resource注解 Resource的查找顺序 Resource注解实现依赖注入 Reso…

网课题库接口调用方法

网课题库接口调用方法 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#xff08;点…

QT对象树机制

Qt提供了对象树机制&#xff0c;能够自动、有效的组织和管理继承自QObject的Qt对象。 每个继承自QObject类的对象通过它的对象链表&#xff08;QObjectList&#xff09;来管理子类对象&#xff0c;当用户创建一个子对象时&#xff0c;其对象链表相应更新子类对象信息&#xff0…