小工具      在线工具  汉语词典  dos游戏  css  js  c++  java

过滤器,监听器,拦截器的原理与在Servlet和Spring的应用

# Spring,servlet,spring,mvc 额外说明

收录于:18天前

在Java Web的开发中,最原始和初期的学习都是从Servlet开始的,Servlet是Java最为耀眼的技术,也是Java EE的技术变革。目前大火主流的框架spring boot也的spring mvc部分也是基于拓展servlet完成的。回到之前的文章spring 实现了对servlet的封装,来构造控制器controller的过程:Spring MVC 框架基础知识,以及Servlet相关知识

在Java Web开发过程中,除了servlet之外,还有比较重要的拦截器、过滤器、监听器。它们的具体功能如下:

  1. Servlet:Web 容器是运行在服务器端的 Java 应用程序。它与平台和协议无关,并且可以动态生成网页。它工作在客户端请求和服务器响应之间的中间层。

  2. 过滤器:过滤器是可重用的代码片段,可用于转换 HTTP 请求、响应和标头信息。 Filter不像Servlet,它不能生成请求或响应,它只修改对某个资源的请求,或者修改来自某个资源的响应。

  3. Listener:监听器,监听器主要用于监听。通过监听器,您可以监听Web服务器中的执行动作,并根据其要求做出相应的响应。

  4. 拦截器:拦截器主要用于拦截程序并进行相应的处理。例如,拦截器可用于验证权限、记录请求信息日志、判断用户是否登录等。

  5. ssm中web.xml中配置了servlet、filter、listener,web.xml中没有配置interceptor。 Spring的拦截器是在spring.xml中配置的。在spring boot中,大多是通过配置类注入。他们的关系如下图所示:

在这里插入图片描述

Servlet学习网站

过滤器

Servlet 过滤器是可在 Servlet 编程中使用的 Java 类,具有以下用途:

  • 在客户端请求访问后端资源之前拦截它们。
  • 在将服务器的响应发送回客户端之前对其进行处理。

规范建议的各类过滤器:

(1)身份验证过滤器(Authentication Filters)。
(2)数据压缩过滤器(Data compression Filters)。
(3)加密过滤器(Encryption Filters)。
(4)触发资源访问事件过滤器。
(5)图像转换过滤器(Image Conversion Filters)。
(6)日志记录和审核过滤器(Logging and Auditing Filters)。
(7)mime-TYPE 链过滤器(MIME-TYPE Chain Filters)。
(8)标记化过滤器(Tokenizing Filters)。
(9)XSL/T 过滤器(XSL/T Filters),转换 XML 内容。
过滤器被部署在部署描述符文件 web.xml 中,然后映射到您的应用程序的部署描述符中的 Servlet 名称或 URL 模式。

当 Web 容器启动您的 Web 应用程序时,它会为您在部署描述符中声明的每个过滤器创建一个实例。过滤器按照它们在部署描述符中声明的顺序执行。

在这里插入图片描述

Servlet 过滤器示例:

  • 生产过滤器 Filter 和 Web 容器 servlet

过滤器是一个包装 Servlet,因此两者都必须存在

//servlet
//导入必需的 java 库
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/demo")

//扩展 HttpServlet 类
public class DemoServlet extends HttpServlet {
    

	// 处理 GET 方法请求的方法
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
	{
    
		// 设置响应内容类型
		response.setContentType("text/HTML;charset=UTF-8");

		PrintWriter out = response.getWriter();
		String title = "HTTP Header 请求实例";
		String docType =
			"<!DOCTYPE html> \n";
			out.println(docType +
			"<html>\n" +
			"<head><meta charset=\"utf-8\"><title>" + title + "</title></head>\n"+
			"<body bgcolor=\"#f0f0f0\">\n" +
			"<h1 align=\"center\">" + title + "</h1>\n" +
			"<table width=\"100%\" border=\"1\" align=\"center\">\n" +
			"<tr bgcolor=\"#949494\">\n" +
			"<th>Header 名称</th><th>Header 值</th>\n"+
			"</tr>\n");

		Enumeration headerNames = request.getHeaderNames();

		while(headerNames.hasMoreElements()) {
    
			String paramName = (String)headerNames.nextElement();
			out.print("<tr><td>" + paramName + "</td>\n");
			String paramValue = request.getHeader(paramName);
			out.println("<td> " + paramValue + "</td></tr>\n");
		}
		out.println("</table>\n</body></html>");
	}
	// 处理 POST 方法请求的方法
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
		this.doGet(request, response);
	}
}
//Filter过滤器
// 导入必需的 java 库
import java.io.*;
import javax.servlet.*;
import javax.servlet.Http.*;
import java.util.*;

// 实现 Filter 类
public class LogFilter implements Filter  {
    
   public void  init(FilterConfig config) throws ServletException {
    
	// 获取初始化参数
	String site = config.getInitParameter("Site"); 
	// 输出初始化参数
	System.out.println("网站名称: " + site); 
}
   public void  doFilter(ServletRequest request, 
                 ServletResponse response,
                 FilterChain chain) 
                 throws java.io.IOException, ServletException {
    

      // 获取客户机的 IP 地址 
      String ipAddress = request.getRemoteAddr();

      // 记录 IP 地址和当前时间戳
      System.out.println("IP "+ ipAddress + ", Time "
                                       + new Date().toString());

      // 把请求传回过滤链
      chain.doFilter(request,response);
   }
   public void destroy( ){
    
      /* 在 Filter 实例被 Web 容器从服务移除之前调用 */
   }
}
  • web.xml配置servlet和Filter以及过滤器和web容器的映射关系

//过滤器配置
<filter>
	<filter-name>LoginFilter</filter-name>
	<filter-class>com.test.LogFilter</filter-class>
	<init-param>
		<param-name>Site</param-name>
		<param-value>kubiji在线教程</param-value>
	</init-param>
</filter>

//servlet配置

<servlet>  
  <!-- 类名 -->  
  <servlet-name>DemoServlet</servlet-name>  
  <!-- 所在的包 -->  
  <servlet-class>com.=test.DemoServlet</servlet-class>  
</servlet>  
<servlet-mapping>  
  <servlet-name>DemoServlet</servlet-name>  
  <!-- 访问的网址 -->  
  <url-pattern>/demo</url-pattern>  
</servlet-mapping> 


//Servlet Filter Mapping

<filter-mapping>
  <filter-name>LogFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

过滤范围:

一个过滤器的作用范围与路径配置有关url-pattern可以配置/*所有路径也可以配置某个web容器,所以Web 应用程序可以根据特定的目的定义若干个不同的过滤器链:

<filter>
   <filter-name>LogFilter</filter-name>
   <filter-class>com.kubiji.test.LogFilter</filter-class>
   <init-param>
	  <param-name>test-param</param-name>
	  <param-value>Initialization Paramter</param-value>
   </init-param>
</filter>

<filter>
   <filter-name>AuthenFilter</filter-name>
   <filter-class>com.kubiji.test.AuthenFilter</filter-class>
   <init-param>
	  <param-name>test-param</param-name>
	  <param-value>Initialization Paramter</param-value>
   </init-param>
</filter>

<filter-mapping>
   <filter-name>LogFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

<filter-mapping>
   <filter-name>AuthenFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

过滤器应用顺序:

web.xml 中过滤器映射元素的顺序决定了 Web 容器将过滤器应用到 servlet 的顺序。要反转过滤器的顺序,您只需反转 web.xml 文件中的过滤器映射元素。

SpringMVC的过滤器位于spring-web-[xxx].jar工具包下:

在这里插入图片描述
如上所示的spring-web.jar包结构所示, Spring的web包中中提供有很多过滤器,这些过滤器位于org.springframework.web.filter并且理所当然地实现了javax.servlet.Filter

然而,有几种方法可以实现它:

    (1) 直接实现Filter,这一类过滤器只有CompositeFilter;

    (2) 继承抽象类GenericFilterBean,该类实现了javax.servlet.Filter,这一类的过滤器只有一个,即DelegatingFilterProxy;

    (3) 继承抽象类OncePerRequestFilter,该类为GenericFilterBean的直接子类,这一类过滤器包括CharacterEncodingFilter、HiddenHttpMethodFilter、HttpPutFormContentFilter、RequestContextFilter和ShallowEtagHeaderFilter;

    (4) 继承抽象类AbstractRequestLoggingFilter,该类为OncePerRequestFilter的直接子类,这一类过滤器包括CommonsRequestLoggingFilter、Log4jNestedDiagnosticContextFilter和ServletContextRequestLoggingFilter。

过滤器放置在容器结构中的什么位置?

过滤器放置在 Web 资源之前,可以在请求到达应用它的 Web 资源(可以是 Servlet、Jsp 页面,甚至 HTML 页面)之前拦截传入请求,并在请求到达之前拦截传出请求。返回给客户端。 。过滤器:用于拦截客户端和所请求资源之间的请求,目的是重用代码。过滤器链,web.xml 中最先配置的将首先被调用。一些初始化参数也可以在过滤器中配置。

Java中的Filter并不是标准的Servlet。它无法处理用户请求或生成对客户端的响应。它主要用于预处理HttpServletRequest,也可用于后处理HttpServletResponse。这是一个典型的加工链。

  1. 过滤器触发时序:

过滤器在请求进入容器之后、请求进入 servlet 之前进行预处理。请求完成后、Servlet处理完毕后、返回给前端之前的返回也是如此。

简介: 过滤器包装 servlet,servlet 包装拦截器。

  1. 过滤器的触发时机是容器后,servlet之前,所以过滤器的doFilter( ServletRequest request, ServletResponse response, FilterChain chain)的入参是ServletRequest ,而不是httpservletrequest。因为过滤器是在httpservlet之前。
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    
    System.out.println("before...");
    chain.doFilter(request, response);
    System.out.println("after...");
}

chain.doFilter(request, response)这个方法的调用作为分水岭。事实上调用Servlet的doService()方法是在chain.doFilter(request, response)这个方法中进行的。

  1. 过滤器是JavaEE标准,使用函数回调来实现。在请求进入容器之后、进入Servlet之前进行预处理,在请求返回前端之后进行后处理。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

弹簧启动过滤器

在 Spring 中,过滤器在 web.xml 文件中配置和声明。所有过滤器都在 web.xml(Web 容器的配置文件)中定义。在springboot中,web.xml文件消失了。各种配置都被Java类替代。 @Configuration注解标记的是配置类而不是xml配置文件。

因此过滤器也通过注解注入到IOC容器中,注解@WebFilter声明一个过滤器,里面的参数,filterName 为过滤器名字,urlPatterns 为过滤器的范围,initParams 为过滤器初始化参数。

@Order(1)
@WebFilter(filterName = "piceaFilter", urlPatterns = "/*" , initParams = {
    
        @WebInitParam(name = "URL", value = "http://localhost:8080")})

使用包扫描@ServletComponentScan("com.example.demofilter.filter")在启动类自动注册Filter。

@Order(1)
@WebFilter(filterName = "myFilter",urlPatterns = {
    "/*"})
public class MyFilter implements Filter {
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    
        System.out.println("初始化过滤器");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
        System.out.println("before filter");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("after filter");
    }

    @Override
    public void destroy() {
    
        System.out.println("过滤器被销毁了");
    }

@WebFilter注解,filterName属性代表过滤器的名称,urlPatter代表要拦截的URL资源,可以是一个也可以是多个。用于将类声明为过滤器。这个注解会在部署时被容器处理,容器会根据具体的属性配置部署相应的类作为过滤器。该注解有一些常用属性如下表(以下属性均为可选属性,但value、urlPatterns、servletNames必须至少包含其中之一,且value和urlPatterns不能共存。如果同时指定,value通常被忽略。值

@Order(1)的意思是如果有多个拦截器的话,就是设置这个拦截器的运行级别。数字越小,执行越早。

@Configuration
public class FilterConfig {
    
    @Bean
    public FilterRegistrationBean registFilter(){
    
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new MyFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setName("Filter1");
        registrationBean.setOrder(1);
        return registrationBean;
    }
}

@ServletComponentScan:在SpringBootApplication上使用@ServletComponentScan注解后,Servlet、Filter、Listener可以直接通过@WebServlet、@WebFilter、@WebListener注解自动注册,无需其他代码。

拦截器

拦截器方法都是通过代理来调用的,拦截器是基于Java反射机制实现的。

在这里插入图片描述
第一个不是,第二个才是,Interceptor是spring中特有的概念。在 Spring中,当请求发送到 Controller 时,在被Controller处理之前,它必须经过 Interceptors(0或多个)。Spring Interceptor是一个非常类似于Servlet Filter 的概念 。

在这里插入图片描述
在这里插入图片描述

以下情况:

public class LogInterceptor extends HandlerInterceptorAdapter {
    

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
        long startTime = System.currentTimeMillis();
        System.out.println("brefore login --- ");
        System.out.println("Request URL: " + request.getRequestURL());
        System.out.println("Start Time: " + System.currentTimeMillis());

        request.setAttribute("startTime", startTime);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    
        System.out.println("login --- ");
        System.out.println("Request URL: " + request.getRequestURL());
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    
        System.out.println("after loggin --- ");

        long startTime = (Long) request.getAttribute("startTime");
        long endTime = System.currentTimeMillis();
        System.out.println("Request URL: " + request.getRequestURL());
        System.out.println("End Time: " + endTime);

        System.out.println("Time Taken: " + (endTime - startTime));
    }
}
@Configuration
public class MyInterceptorConfig extends WebMvcConfigurationSupport {
    
    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
    
        // 将上面自定义好的拦截器添加进去。
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
        super.addInterceptors(registry);
    }
}

Interceptor的拦截范围实际上是Controller方法,实际上相当于基于AOP的方法拦截。因为Interceptor只拦截Controller方法,所以需要注意的是,返回到ModelAndView并渲染后,后续的处理就会脱离Interceptor的拦截范围。

拦截器必须实现 HandlerInterceptor 接口,并且可以选择实现 preHandle()、postHandle() 和 afterCompletion() 方法。 preHandle()在调用Controller方法之前执行,postHandle()在Controller方法正常返回后执行,afterCompletion()无论Controller方法是否抛出异常都会执行。参数 ex 是 Controller 方法抛出的异常(未抛出的异常为 null )

使用拦截器

过滤器和拦截器的区别:

拦截器InterceptorFilter过滤器一样,它俩都是面向切面编程——AOP 的具体实现
拦截器是基于java的反射机制的,而过滤器是基于函数回调。
拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

在这里插入图片描述

拦截器的概念

SpringMVC中Interceptor的主要作用是拦截用户的url请求,并在执行handler方法之前和之后添加一些特殊的请求。 SpringMVC中的Interceptor也是非常重要和有用的。其主要功能是拦截用户请求并进行相应处理。例如可以用来验证权限,或者判断用户是否登录等。

在这里插入图片描述
在这里插入图片描述

监听器

Servlet的监听器Listener是一个服务器端程序,它实现了javax.servlet.ServletContextListener接口。当 Web 应用程序启动时它也会启动。它仅初始化一次,并在 Web 应用程序停止时销毁。主要功能是:做一些初始的内容添加工作,设置一些基础内容,比如一些参数或者一些固定的对象等。

监听器是一个实现特定接口的普通Java程序。该程序专门用于监视另一个Java对象的方法调用或属性更改。当被监控对象发生上述事件时,监听器的某个方法会立即执行。

开始使用听众

Servle监听器
在Servlet规范中定义了多种类型的监听器,它们用于监听的事件源分别 ServletContext, HttpSession和ServletRequest这三个域对象。servlet监听器的注册不是直接注册在事件源上,而是由WEB容器负责注册,开发人员只需在web.xml文件中使用标签配置好监听器。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

. . .

相关推荐

额外说明

JAVA数据库数据类型及使用

一、数据库数据类型 1、整数类型 (1).TINYINT(tinyint):大小为1个字节,有符号范围(-128 to 127)、无符号范围(0 to 255)mySQL没有布尔类型,直接使用tinyint表示。 (2)、SMALLINT(smallin

额外说明

ssm+thymeleaf国际化

文章目录 一. 国际化项目结构和注意点 二.在xml配置类中配置相关国际化内容 三.国际化切换控制配置类 四.展示 一. 国际化项目结构和注意点 注意国际化文件必须在resource下,且文件后缀形如_zh_CN.properties这是springbo

额外说明

100天精通Oracle-实战系列(第19天)RMAN 从 Windows 至 Linux 跨系统恢复 Oracle 数据库

RMAN 从 Windows 至 Linux 跨系统恢复 Oracle 数据库(第19天) ->返回总目录<- 在实际工作中,偶尔会碰到将 Oracle 数据库从 Windows 迁移到 Linux 系统的诉求,RMAN 也是支持跨系统恢复的,只要查看

额外说明

JDBC使用数据库连接池连接数据库(DBCP,C3P0,Druid)

写在前面 虽然在实际开发中关于这些操作都不会让我们去写,但是掌握这代码的逻辑编写对我们使用框架有一定的帮助。 学习JDBC:请关注专栏——JDBC学习——内容详细 相关文章: JDBC总述 JDBC链接Mysql数据库 JDBC完成对数据库数据操作(增,

额外说明

几秒读懂C++虚函数调用的汇编代码实现

VC++常用功能开发汇总(专栏文章列表,欢迎订阅,持续更新...)https://blog.csdn.net/chenlycly/article/details/124272585C++软件异常排查从入门到精通系列教程(专栏文章列表,欢迎订阅,持续更新.

额外说明

Idea:Can`t download sources,Sources not found for "********"

1.情景 最近在准备写关于源码阅读的文章,但是我下载的maven资源都是编译后的.class文件,在阅读的时候难度很大,比较走运的是,Idea是一个很优秀的编译器,在这里你打开.class文件后,他会询问你要不要下载源代码,大多时候都可以直接下载源代码来

额外说明

手把手教你SpringBoot+Redis+MySQL搭建个人博客(二)-----引入MySQL数据库并实现通过properties实现多个数据库环境自动切换配置

目录 一、关于三种环境 二、引入MySQL 1、准备数据 2.编写mapper和bean 3.准备service 4.单元测试 5.Controller 6.注解法配置MapperScan 7.项目本地测试 8.当前pom.xml 三、配置三种prope

额外说明

【Java 进阶篇】Bootstrap 快速入门

Bootstrap 是一个流行的开源前端框架,它使网页开发更加容易和高效。无论您是一个有经验的开发者还是一个初学者,本文将带您深入了解 Bootstrap,从基础概念到实际示例,以帮助您快速入门这个强大的工具。 什么是 Bootstrap? Bootst

额外说明

项目四:利用ECharts可视化Spring Boot后端提供的数据

文章目录 一、提出任务 (一)班级数据 (二)运行效果 二、完成任务 (一)创建数据库与表 1、创建数据库 2、创建数据表 (二)创建Spring Boot项目 (三)创建班级实体类 (四)创建班级映射器接口 (五)创建班级映射器配置文件 (六)创建班级

额外说明

MyBatis框架学习笔记04:利用MyBatis实现条件查询

文章目录 一、查询需求 二、打开MyBatisDemo项目 三、对学生表实现条件查询 (一)创建学生映射器配置文件 (二)在MyBatis配置文件里注册学生映射器配置文件 (三)创建学生映射器接口 (四)创建测试类TestStudentMapper 1、

ads via 小工具