JavaWeb:过滤器与监听器

news2024/11/25 6:20:22

一、过滤器Filter

1.1 过滤器Filter概述

Filter表示过滤器,是JavaWeb三大组件(ServletFilterListener)之一。Servlet我们之前都已经介绍过了,FilterListener我们今天都会进行介绍。

过滤器可以把对资源的请求 拦截 下来,从而实现一些特殊的功能。

如下图所示,浏览器可以访问服务器上的所有的资源(servletjsphtml等)

在这里插入图片描述

而在访问到这些资源之前可以使过滤器拦截来下,也就是说在访问资源之前会先经过Filter,如下图

在这里插入图片描述

拦截器拦截到后可以做什么功能呢?

过滤器一般完成一些通用的操作。 比如每个资源都要写一些代码完成某个功能,我们总不能在每个资源中写这样的代码吧,而此时我们可以将这些代码写在过滤器中,因为请求每一个资源都要经过过滤器。

我们之前做的品牌数据管理的案例中就已经做了登陆的功能,而如果我们不登录能不能访问到数据呢?我们可以在浏览器直接访问首页 ,可以看到 查询所有 的超链接

在这里插入图片描述

当我点击该按钮,居然可以看到品牌的数据

在这里插入图片描述

这显然和我们的要求不符。我们希望实现的效果是用户如果登陆过了就跳转到品牌数据展示的页面;如果没有登陆就跳转到登陆页面让用户进行登陆,要实现这个效果需要在每一个资源中都写上这段逻辑,而像这种通用的操作,我们就可以放在过滤器中进行实现。这个就是 权限控制 ,以后我们还会进行细粒度权限控制。过滤器还可以做 统一编码处理敏感字符处理 等等…

1.2 Filter快速入门

1.2.1 开发步骤

进行 Filter 开发分成以下三步实现

  • 定义类,实现Filter接口,并重写其所有方法在这里插入图片描述

  • 配置Filter拦截资源的路径:在类上定义 @WebFilter 注解。而注解的 value 属性值 /* 表示拦截所有的资源在这里插入图片描述

  • doFilter方法中输出一句话,并放行在这里插入图片描述

    上述代码中的 chain.doFilter(request,response); 就是放行,也就是让其访问本该访问的资源。

1.2.2 代码演示

创建一个项目,项目下有一个 hello.jsp 页面,项目结构如下:在这里插入图片描述

pom.xml 配置文件内容如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.dcxuexi</groupId>
  <artifactId>filter-demo</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>

  <properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.1.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
</project>

hello.jsp 页面内容如下:

<%--
  Created by IntelliJ IDEA.
  User: DongChuang
  Date: 2023/2/2
  Time: 20:30
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>hello</title>
</head>
<body>
    <h1>hello JSP~</h1>
</body>
</html>

我们现在在浏览器输入 http://localhost/filter-demo/hello.jsp 访问 hello.jsp 页面,这里是可以访问到 hello.jsp 页面内容的。在这里插入图片描述

接下来编写过滤器。过滤器是Web三大组件之一,所以我们将 filter 创建在 com.itheima.web.filter 包下,起名为 FilterDemo

package com.dcxuexi.web.filter;

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

/***
 * @Title FilterDemo
 * @Description TOTD
 * @Auter DongChuang
 * @Date 2023/2/2 20:28
 * @Version 1.0.0
 */
@WebFilter("/*")
public class FilterDemo implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("FilterDemo  被执行了,,,");
    }

    @Override
    public void destroy() {

    }
}

重启启动服务器,再次重新访问 hello.jsp 页面,这次发现页面没有任何效果,但是在 idea 的控制台可以看到如下内容在这里插入图片描述

上述效果说明 FilterDemo 这个过滤器的 doFilter() 方法执行了,但是为什么在浏览器上看不到 hello.jsp 页面的内容呢?这是因为在 doFilter() 方法中添加放行的方法才能访问到 hello.jsp 页面。那就在 doFilter() 方法中添加放行的代码

//放行
 chain.doFilter(request,response);

再次重启服务器并访问 hello.jsp 页面,发现这次就可以在浏览器上看到页面效果。

FilterDemo 过滤器完整代码如下:

package com.dcxuexi.web.filter;

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

/***
 * @Title FilterDemo
 * @Description TOTD
 * @Auter DongChuang
 * @Date 2023/2/2 20:28
 * @Version 1.0.0
 */
@WebFilter("/*")
public class FilterDemo implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("FilterDemo  被执行了,,,");
        //放行
        chain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }
}

1.3 Filter执行流程

在这里插入图片描述

如上图是使用过滤器的流程,我们通过以下问题来研究过滤器的执行流程:

  • 放行后访问对应资源,资源访问完成后,还会回到Filter中吗?

    从上图就可以看出肯定 回到Filter

  • 如果回到Filter中,是重头执行还是执行放行后的逻辑呢?

    如果是重头执行的话,就意味着 放行前逻辑 会被执行两次,肯定不会这样设计了;所以访问完资源后,会回到 放行后逻辑,执行该部分代码。

通过上述的说明,我们就可以总结Filter的执行流程如下:在这里插入图片描述

接下来我们通过代码验证一下,在 doFilter() 方法前后都加上输出语句,如下

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("FilterDemo  被执行了,,,");
        //1. 放行前,对 request数据进行处理
        System.out.println("1.FilterDemo...");
        //放行
        chain.doFilter(request,response);

        //2. 放行后,对Response 数据进行处理
        System.out.println("3.FilterDemo...");
    }

同时在 hello.jsp 页面加上输出语句,如下

<%--
  Created by IntelliJ IDEA.
  User: DongChuang
  Date: 2023/2/2
  Time: 20:30
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>hello</title>
</head>
<body>
    <h1>hello JSP~</h1>
    <%
        System.out.println("2.hello jsp");
    %>
</body>
</html>

执行访问该资源打印的顺序是按照我们标记的标号进行打印的话,说明我们上边总结出来的流程是没有问题的。启动服务器访问 hello.jsp 页面,在控制台打印的内容如下:

在这里插入图片描述

以后我们可以将对请求进行处理的代码放在放行之前进行处理,而如果请求完资源后还要对响应的数据进行处理时可以在放行后进行逻辑处理。

1.4 Filter拦截路径配置

拦截路径表示Filter会对请求的哪些资源进行拦截,使用 @WebFilter 注解进行配置。如:@WebFilter("拦截路径")

拦截路径有如下四种配置方式:

  • 拦截具体的资源:/index.jsp:只有访问index.jsp时才会被拦截
  • 目录拦截:/user/*:访问/user下的所有资源,都会被拦截
  • 后缀名拦截:*.jsp:访问后缀名为jsp的资源,都会被拦截
  • 拦截所有:/*:访问所有资源,都会被拦截

通过上面拦截路径的介绍,大家会发现拦截路径的配置方式和 Servlet 的请求资源路径配置方式一样,但是表示的含义不同。

1.5 过滤器链

1.5.1 概述

过滤器链是指在一个Web应用,可以配置多个过滤器,这多个过滤器称为过滤器链。

如下图就是一个过滤器链,介绍过滤器链主要是介绍过滤器链执行的流程

在这里插入图片描述

上图中的过滤器链执行是按照以下流程执行:

  1. 执行 Filter1 的放行前逻辑代码
  2. 执行 Filter1 的放行代码
  3. 执行 Filter2 的放行前逻辑代码
  4. 执行 Filter2 的放行代码
  5. 访问到资源
  6. 执行 Filter2 的放行后逻辑代码
  7. 执行 Filter1 的放行后逻辑代码

以上流程串起来就像一条链子,故称之为过滤器链。

1.5.2 代码演示

  • 编写第一个过滤器 FilterDemo ,配置成拦截所有资源

    package com.dcxuexi.web.filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.IOException;
    
    /***
     * @Title FilterDemo
     * @Description TOTD
     * @Auter DongChuang
     * @Date 2023/2/2 20:28
     * @Version 1.0.0
     */
    @WebFilter("/*")
    public class FilterDemo implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            System.out.println("FilterDemo  被执行了,,,");
            //1. 放行前,对 request数据进行处理
            System.out.println("1.FilterDemo...");
            //放行
            chain.doFilter(request,response);
    
            //2. 放行后,对Response 数据进行处理
            System.out.println("5.FilterDemo...");
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
  • 编写第二个过滤器 FilterDemo2 ,配置拦截所有资源

    package com.dcxuexi.web.filter;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    /***
     * @Title FilterDemo2
     * @Description TOTD
     * @Auter DongChuang
     * @Date 2023/2/2 20:58
     * @Version 1.0.0
     */
    @WebFilter("/*")
    public class FilterDemo2 implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            System.out.println("FilterDemo2  被执行了,,,");
            //1. 放行前,对 request数据进行处理
            System.out.println("2.FilterDemo2...");
            //放行
            chain.doFilter(request,response);
    
            //2. 放行后,对Response 数据进行处理
            System.out.println("4.FilterDemo2...");
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
  • 修改 hello.jsp 页面中脚本的输出语句

    <%--
      Created by IntelliJ IDEA.
      User: DongChuang
      Date: 2023/2/2
      Time: 20:30
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>hello</title>
    </head>
    <body>
        <h1>hello JSP~</h1>
        <%
            System.out.println("3.hello jsp");
        %>
    </body>
    </html>
    
  • 启动服务器,在浏览器输入 http://localhost/filter-demo/hello.jsp 进行测试,在控制台打印内容如下在这里插入图片描述

    从结果可以看到确实是按照我们之前说的执行流程进行执行的。

1.5.3 问题

上面代码中为什么是先执行 FilterDemo ,后执行 FilterDemo2 呢?

我们现在使用的是注解配置Filter,而这种配置方式的优先级是按照过滤器类名(字符串)的自然排序。

比如有如下两个名称的过滤器 : BFilterDemoAFilterDemo 。那一定是 AFilterDemo 过滤器先执行。

二、监听器Listener

2.1 概述

  • Listener表示监听器,是JavaWeb三大组件(ServletFilterListener)之一。

  • 监听器可以监听就是在 applicationsessionrequest 三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件。

    requestsession我们介绍过。而 applicationServletContext 类型的对象。

    ServletContext 代表整个web应用,在服务器启动的时候,tomcat会自动创建该对象。在服务器关闭时会自动销毁该对象。

2.2 分类

JavaWeb提供了8个监听器:在这里插入图片描述

这里面只有 ServletContextListener 这个监听器后期我们会接触到,ServletContextListener 是用来监听 ServletContext 对象的创建和销毁。

ServletContextListener 接口中有以下两个方法

  • void contextInitialized(ServletContextEvent sce)ServletContext 对象被创建了会自动执行的方法
  • void contextDestroyed(ServletContextEvent sce)ServletContext 对象被销毁时会自动执行的方法

2.3 代码演示

我们演示一下 ServletContextListener 监听器

  • 定义一个类,实现ServletContextListener 接口
  • 重写所有的抽象方法
  • 使用 @WebListener 进行配置

代码如下:

@WebListener
public class ContextLoaderListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        //加载资源
        System.out.println("ContextLoaderListener...");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //释放资源
    }
}

启动服务器,就可以在启动的日志信息中看到 contextInitialized() 方法输出的内容,同时也说明了 ServletContext 对象在服务器启动的时候被创建了。

在这里插入图片描述

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

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

相关文章

Python的判断语句

进行逻辑判断&#xff0c;是生活中常见的行为。 同样&#xff0c;在程序中&#xff0c;进行逻辑判断也是最为基础的功能。 布尔类型和比较运算符 布尔类型的字面量&#xff1a; true 表示真&#xff08;是、肯定&#xff09;false 表示假&#xff08;否、否定&#xff09; …

【tkinter】用不到50行Python代码,写一个扫雷小游戏

文章目录定制按钮生成雷区主流程基础知识&#xff1a;StringVartkinter布局 定制按钮 学会了布局和绑定事件&#xff0c;就可以开发一些简单的应用&#xff0c;比如扫雷小游戏。从外观来看&#xff0c;扫雷就是一个按钮矩阵&#xff0c;左键点击按钮&#xff0c;如果按钮里埋…

myBaits Target Capture Kits;myBaits 靶向捕获试剂盒,快速捕获富集目标序列

myBaits Target Capture Kits可以快速捕获富集目标序列&#xff0c;提高NGS研究效率&#xff0c;兼容Illumina&#xff0c;PacBio 和 Nanopore等多种测序平台。Arbor Biosciences使用oligo合成专利技术&#xff0c;为您提供高质量、高性价比的捕获试剂盒。适用于各种基因组类型…

pytest简介

介绍pytest是一个非常成熟的全功能的Python测试框架&#xff0c;主要有以下几个特点&#xff1a;简单灵活&#xff0c;容易上手支持参数化能够支持简单的单元测试和复杂的功能测试&#xff0c;还可以用来做selenium/appnium等自动化测试、接口自动化测试&#xff08;pytestrequ…

我写了一个脚本,实现了图片分类问题模型训练的全自动化训练

众所周知,图片分类问题属于计算机视觉中比较容易解决的问题之一 但 这几天被数据集的问题搞得焦头烂额, 照理说分类问题的数据集应该比较好制作 但 如果之前没有现成的数据集 也会变得比较麻烦 直到我偶然发现了一个HuggingFace的图片搜索API 无限次调用 而且不需要身份验证 真…

如何实现报表集成?(五)——集成案例分享

在前面几篇&#xff0c;我们分别给大家介绍了报表工具的系统集成架构、用户同步/单点登录、资源集成和权限集成&#xff0c;从整体上对报表工具实现系统集成的各个方面都作了针对性的阐述。那别的用户实际上是如何做报表集成的呢&#xff1f; 这一篇&#xff0c;我们来看一下某…

408—二叉树与树

二叉树的一些概念&#xff1a;//二叉树有严格的左右子树之分&#xff0c;度数为2的树则没有对此进行要求。常见的两种二叉树&#xff1a;//如上E为满二叉树&#xff0c;每一层的结点个数都达到了当层能达到的最大结点数//满二叉树自上而下&#xff0c;从左到右依次进行编号&…

易于理解的完全立方体计算的多路数组聚集方法

自己琢磨半天终于搞懂了&#xff0c;可能是自己悟性不够吧-_-|| 多路数组聚集其实就是对维度(dimension)进行选择&#xff0c;保留一些常用的可以很方便地生成别的子立方体的立方体(cube)。对一个维做聚集(aggregation)其实就是按照这个维度的方向做加法&#xff0c;把这个维度…

Linux下的动静态库及链接

目录 常识 动态链接 静态链接 两者的比较 动态库与静态库 常识 我们平时写的代码和标准库是两回事&#xff0c;像C标准库提供给我们一些函数方便使用&#xff0c;降低程序员工作成本。比如写个printf("hello world"); 我们只是调用了库里的函数&#xff0c;并没…

字节跳动“技穷”,火山引擎“啃老”

文丨智能相对论作者丨沈浪「云」的赛道正在细化&#xff0c;是显而易见的趋势&#xff0c;诸如汽车云、营销云、视频云、零售云等等&#xff0c;大致可以理解为通过云计算等技术推动特定行业场景实现数字化转型的解决方案。之所以出现这种情况&#xff0c;存在多个层面的原因&a…

Kubernetes部署Postgresql

环境&#xff1a;Postgresql的Docker镜像 ->参考Docker安装部署PostgresqlCentos7.x kubernetes1.23.7 docker1.13.1 postgres12.7pg的docker镜像已经上传到云平台。Kubernetes参考&#xff1a;https://kubernetes.io/zh-cn/docs/concepts/configuration/configmap基本命…

Youngter-drive 题解

1.查壳 32bit&#xff0c;加了UPX壳 2.虚拟机脱壳 Youngter-drive脱壳3.静态分析寻找思路 跟进main_0函数 线程控制的知识不懂&#xff0c;去搜一下函数 createMutexW 函数 创建或打开命名或未命名的互斥对象。 HANDLE CreateMutexW( [in, optional] LPSECURITY_ATTRIBUTES lp…

通信原理笔记—部分响应基带传输系统

目录 基本设计思想&#xff1a; 问题的引入与考虑&#xff1a; 第一类部分响应系统: 定义奈奎斯特脉冲: 定义第一类部分响应系统的冲激响应: 第一类部分响应系统冲激响应与频率特性波形图: 第一类部分响应系统信号波形示例&#xff1a; 编码发送与接收解码过程示例: 第…

Biome-BGC生态系统模型与Python融合技术实践应用

查看原文>>> Biome-BGC生态系统模型与Python融合技术实践应用 Biome-BGC是利用站点描述数据、气象数据和植被生理生态参数&#xff0c;模拟日尺度碳、水和氮通量的有效模型&#xff0c;其研究的空间尺度可以从点尺度扩展到陆地生态系统。 在Biome-BGC模型中&#xf…

Tomcat 源码启动

要想学习 Tomcat 原理&#xff0c;看源码是最直接的方式&#xff0c;而想要理解源码&#xff0c;我们要想把它在本地跑起来。 下载源码 到 Tomcat 的官网 http://tomcat.apache.org 上下载 Tomcat 的源码 下载下来是一个压缩包文件 解压之后目录结构如下 用IDEA打开 在…

redis集群管理工具HHDBCS

参考地址: HHDBCS下载地址 Redis教程 1 快速介绍 1.1 什么是HHDBCS&#xff1f; HHDBCS是恒辉信达公司推出的通用数据库管理桌面工具&#xff0c;专为简化数据库的管理及数据管理成本而设计&#xff0c;让用户通过统一的桌面视图管理成千上万的异构数据库实例。 它采用了…

【Feign】Spring框架集成Feign

Spring框架集成Feign1、Feign-简介2、spring-cloud快速整合OpenFeign3、Feign日志4、Feign契约配置5、Feign配置超时时间6、Feign拦截器7、Feign断路器1、Feign-简介 Feign是Neflix开发的声明式、模块化的HTTP客户端&#xff0c;集成了Ribbon、RestTemplate实现了负载均衡的执…

快收藏,2023有这些财务分析模板就够了

相信很多的财务人都才刚刚经历一个兵荒马乱的年终&#xff0c;各种核算、整理、分析&#xff0c;工作量直线上升&#xff0c;说不定加班几点半个月都未必能歇一下。但不用担心&#xff0c;在接下来的2023里&#xff0c;可以通过BI财务分析报表模板来高效解决这些问题。 BI软件…

[python][VTK]vtk安装后测试代码

测试vtk版本为9.2.5 import vtk cone_a vtk.vtkConeSource() coneMapper vtk.vtkPolyDataMapper() coneMapper.SetInputConnection(cone_a.GetOutputPort()) coneActor vtk.vtkActor() coneActor.SetMapper(coneMapper) ren1 vtk.vtkRenderer() ren1.AddActor(coneActor…

黑马点评项目要点内容总结【面试用】

小众点评项目要点 文章目录小众点评项目要点1.使用Redis代替Session登录1.1 Session登录存在的问题1.2 使用Redis代替Session登录分析1.3 使用Redis登录的流程1.4 解决Redis中有效期问题2.使用Redis作为缓存2.1 为什么使用缓存2.2 缓存策略2.3 解决缓存穿透2.4 解决缓存雪崩2.5…