过滤器,监听器与拦截器的区别

过滤器,监听器与拦截器的区别

​ 过滤器和监听器不是Spring MVC中的组件,而是Servlet的组件,由Servlet容器来管理。拦截器是Spring MVC中的组件,由Spring容器来管理

​ Servlet过滤器与Spring MVC 拦截器在Web应用中所处的层次如下图所示:
在这里插入图片描述

过滤器Filter

过滤器是Servlet的高级特性之一,是实现Filter接口的Java类。其基本功能就是对Servlet的调用进行干预,在Servlet请求和响应的过程中增加一些特定的功能。

应用场景

在过滤器中修改字符编码(CharacterEncodingFilter)、在过滤器中修改HttpServletRequest的一些参数,如:过滤低俗文字、危险字符、敏感词过滤、响应信息压缩、控制权限、控制转向、做一些业务逻辑判断等

工作原理

使用Filter完整的流程是:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。

  1. 当服务器启动,会创建Filter对象,并调用init方法,只调用一次。

  2. 当访问资源,路径与Filter的拦截路径匹配,会执行Filter中的doFilter方法,

  3. 当服务器关闭时,会调用Filter的destroy方法来进行销毁操作。

Filter接口

通过看Filter接口代码,其有三个方法:

public interface Filter {default void init(FilterConfig filterConfig) throws ServletException {}void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;default void destroy() {}
}
  • init(FilterConfig conf)方法:用于执行过滤器的初始化工作,web容器会在web项目启动时自动调用该方法。

  • doFilter(ServletRequest request,SerlvetResponse response,FilterChain chain)方法:当请求和响应被过滤器拦截后,都会交给doFilter来处理:其中两个参数分别是被拦截request和response对象,可以使用chain的doFliter方法来放行。

  • destroy()方法:用于释放关闭Filter对象打开的资源,在web项目关闭时,由web容器自动调用该方法。

开发一个Filter

开发一个过滤器比较简单,第一步实现Filter接口,第二步配置过滤器
实现Filter接口:

import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseCookie;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;@Component
@WebFilter(filterName = "myFilter",urlPatterns = {"/*"})
public class MyFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {//获取filter名字String filterName = filterConfig.getFilterName();//获取filter里配置的init-param配置指定参数的值,如果参数不存在,则返回 nullString email = filterConfig.getInitParameter("email");//获取filter里配置的init-param配置所有参数值,如果过滤器没有初始化参数,则返回一个空的 EnumerationEnumeration<String> initParameterNames = filterConfig.getInitParameterNames();//返回对调用者在其中执行操作的 ServletContext 的引用。ServletContext servletContext = filterConfig.getServletContext();}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;//统一编码处理httpRequest.setCharacterEncoding("UTF-8");httpResponse.setContentType("text/html;charset=UTF-8");//添加name属性httpRequest.setAttribute("name", "tom");//获取请求中的所有cookieCookie[] cookies = httpRequest.getCookies();if (cookies != null) {StringBuilder sb = new StringBuilder();for (Cookie cookie : cookies) {String cookieName = cookie.getName();String cookieValue = cookie.getValue();//设置cookie的相关属性ResponseCookie lastCookie = ResponseCookie.from(cookieName, cookieValue).httpOnly(true).sameSite("Lax").build();httpResponse.addHeader(HttpHeaders.SET_COOKIE, lastCookie.toString());}filterChain.doFilter(httpRequest, httpResponse);}}@Overridepublic void destroy() {}
}

配置Filter:
(1)在web.xml中配置

<filter><filter-name>myFilter</filter-name><filter-class>com.lsl.mylsl.filter.MyFilter</filter-class><init-param><param-name>email</param-name><param-value>15***011@qq.com</param-value></init-param>
</filter>
<filter-mapping><filter-name>myFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

<filter>配置

fliter-name:指为过滤器的名字

filter-class:过滤器的完整类名

init-param:用于为过滤器指定初始化参数,它的子元素指定参数的名字

<filter-mapping>配置

filter-name:你在<fliter>中声明的filter-name

url-patten:设置 filter 所拦截的请求路径(过滤器关联的URL样式)

(2)注解配置

@WebFilter(filterName = "myFilter",urlPatterns = {"/*"})

(3)配置类配置

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyFilterConfig {@Beanpublic FilterRegistrationBean myFilter(){FilterRegistrationBean fb = new FilterRegistrationBean();//设置filter启动顺序fb.setOrder(1);fb.setFilter(new MyFilter());fb.addInitParameter("email","15***11@qq.com");//设置拦截请求规则,这里拦截所有请求fb.addUrlPatterns("/*");return fb;}
}

三种Filter配置的优缺点:

    第一种xml的配置需要在xml中写配置,但是现在大部分是springboot项目开发,都是重注解轻配置,现在不怎么使用了。如果xml中配置了多个filter,那么按上下先后顺序依次起作用。第二种注解配置,写法比较简单,但是有一个缺点,多个filter没法控制先后顺序。如果想用这个注解,但是还想控制filter的先后顺序,网上有个说法,就是按filter的名字首字母顺序来确定先后顺序,比如有多个filter的名字是AdminFilter和UserFilter,那么就是前者先生效后者后生效。第三种配置类配置,我个人比较倾向于这个(当然如果就是一个简单filter,用注解最简单方便),有xml配置的所有功能。可以定义启动顺序,初始化参数等。

拦截器Interceptor

Spring MVC中的拦截器( Interceptor)类似于Servlet中的过滤器( Filter ),它主要用于拦截用户请求并作出相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。

工作原理

一个拦截器,只有 preHandle 方法返回 true , postHandle 、 afterCompletion 才有可能被执行;如果 preHandle 方法返回 false ,则该拦截器的 postHandle 、 afterCompletion 必然不会被执行。拦截器不是Filter,却实现了Filter的功能,其原理在于:

    所有的拦截器 (Interceptor) 和处理器 (Handler) 都注册在 HandlerMapping 中。Spring MVC 中所有的请求都是由 DispatcherServlet 分发的。当请求进入 DispatcherServlet.doDispatch() 时候,首先会得到处理该请求的 Handler (即 Controller 中对应的方法)以及所有拦截该请求的拦截器。拦截器就是在这里被调用开始工作的。

应用场景

拦截器本质上是面向切面编程(AOP),符合横切关注点的功能都可以放在拦截器中来实现,主要的应用场景包括:

  • 登录验证,判断用户是否登录。
  • 权限验证,判断用户是否有权限访问资源,如校验token
  • 日志记录,记录请求操作日志(用户Ip,访问时间等),以便统计请求访问量。
  • 处理Cookie、本地化、国际化、主题等。
  • 性能监控,监控请求处理时长等。

拦截器执行顺序

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

拦截器接口HandlerInterceptor

package org.springframework.web.servlet;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;public interface HandlerInterceptor {default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {return true;}default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {}default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {}
}

从代码可以看出,拦截器接口有三个方法,分别的作用是:

preHandle方法叫做预处理方法,本方法在控制器方法(MyController的方法)之前执 行,用户的请求最先到达此方法,在这个方法中可以获取请求的信息,验证请求是否符合要求。以验证用户是否登录,验证用户是否有权限访问某个链接地址(url)。如果返回true则放行,返回false则拦截。

postHandle方法叫做后处理方法。在controller中的方法之后执行的。能够获取到处理器方法的返回值 mv,可以修改mv中的数据和视图。可以影响到最后的执行结果。主要是对原来的执行结果做二次修正

afterCompletion方法最后执行的方法,在页面渲染之后执行。在请求处理完成后执行的,框架中规定是当你的视图处理完成后,对视图进行了forword。就任务请求处理完成。一般做资源回收工作的,程序请求过程中创建了一些对象。在这里可以删除,吧占用的内存回收

开发一个拦截器Interceptor

开发一个拦截器需要2步,第一步实现HandlerInterceptor接口来定义一个拦截器,第二步就是配置拦截器了

(1)定义一个拦截器:

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {//在拦截的请求了添加属性,在对应请求的controller中的request中就可以获取该参数了//比如String userName = (String)request.getAttribute("userName");request.setAttribute("userName","lsl");//获取cookieCookie[] cookies = request.getCookies();//设置header属性response.addHeader("SameSite","Lax");//添加cookieCookie cookie = new Cookie("name","lsl");response.addCookie(cookie);return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {HandlerInterceptor.super.afterCompletion(request, response, handler, ex);}
}

(2)配置拦截器:

package com.lsl.mylsl.interceptor;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** 拦截器配置类*/
@Configuration
public class MyInterceptorConfig implements WebMvcConfigurer {/*** 配置拦截器* @param registry*/@Overridepublic void addInterceptors(InterceptorRegistry registry){registry.addInterceptor(myInterceptor()).addPathPatterns("/api/lsl/**")//需要拦截的请求.addPathPatterns("/api/mjx/**")//需要拦截的请求.excludePathPatterns("/api/debug/**")//不拦截的请求.excludePathPatterns("api/lsl/getName");//不拦截的请求}/*** 注入拦截器到spring容器* @return*/@Beanpublic MyInterceptor myInterceptor(){return new MyInterceptor();}
}

过滤器与拦截器工作流程

在这里插入图片描述

过滤器和拦截器区别

运行的顺序不同:

过滤器是Servlet容器接收到请求后,在Servlet被调用之前运行的,而拦截器则是在Servlet被调用之后,但是在响应发送到客户端之前来运行的
在这里插入图片描述

配置方式不同:

过滤器是在web.xml里面进行配置的,拦截器是在Spring的配置文件中去进行配置

依赖的对象不同:

过滤器依赖于Servlet容器,而拦截器不依赖与Servlet容器

操作的对象不同:

过滤器中只能对request和response进行操作,拦截器可以对request,response,handler,modelAndView,execption进行操作,相当于拦截器多了对于Spring MVC生态下组件的一个操作能力
在这里插入图片描述

通俗理解:

(1)过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。(理解:就是一堆字母中取一个B)
**(2)拦截器(Interceptor)**在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。(理解:就是一堆字母中,干预它,通过验证的少点,顺便干点别的东西

转发和重定向区别

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

javaWeb项目--二级评论完整思路

先来看前端需要什么吧&#xff1a; 通过博客id&#xff0c;首先需要显示所有一级评论&#xff0c;包括评论者的头像&#xff0c;昵称&#xff0c;评论时间&#xff0c;评论内容 然后要显示每个一级评论下面的二级评论&#xff0c;包括&#xff0c;评论者的头像&#xff0c;昵称…

【Spring】-Spring中Bean对象的存取

作者&#xff1a;学Java的冬瓜 博客主页&#xff1a;☀冬瓜的主页&#x1f319; 专栏&#xff1a;【Framework】 主要内容&#xff1a;往spring中存储Bean对象的三大方式&#xff1a;XML方式(Bean标签)&#xff1b;五大类注解&#xff1b;方法注解。从spring中取对象的两种方式…

查看单元测试用例覆盖率新姿势:IDEA 集成 JaCoCo

1、什么是 IDEA IDEA 全称 IntelliJ IDEA&#xff0c;是 Java 编程语言开发的集成环境。IntelliJ 在业界被公认为最好的 Java 开发工具&#xff0c;尤其在智能代码助手、代码自动提示、重构、JavaEE 支持、各类版本工具(git、SVN 等)、JUnit、CVS 整合、代码分析、 创新的 GUI…

DNS:使用 bind9 配置主从权威DNS服务器

写在前面 分享一些 使用 bind9 配置主从权威名称服务器的笔记理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守其一生&#xff0c;全心全意&#xff0c;永不停息。所有其它的路都是不完整的&#xff0c;是人的逃避方式…

ML类CFAR检测器在不同环境中检测性能的分析

摘要&#xff1a;该文是楼主翻阅书籍以及一些论文总结出来的关于ML(均值)类CFAR检测器在不同环境中的性能对比&#xff0c;以及优缺点的总结&#xff0c;可以帮助大家面对不同情形如何选择CFAR问题。由于楼主见识短浅&#xff0c;文中难免出现不足之处&#xff0c;望各位指出。…

怎么做Tik Tok海外娱乐公会呢?新加坡市场怎么样?

一、为什么选择TikTok直播 1. 海外市场潜力巨大 • 自2016年始&#xff0c;多家直播平台陆续拓展至东南亚、中东、俄罗斯、日韩、欧美、拉美等地区。 • 海外市场作为直播发展新蓝海&#xff0c;2021年直播行业整申请cmxyci体规模达百亿美元&#xff0c;并维持高速增长。 &a…

geeemap学习总结(1)——Anaconda-VSCode-geemap环境安装与配置

配置conda geemap 环境 通过Anaconda配置geemap环境较为方便&#xff0c;首先需在系统中完成 Anaconda安装。创建名为geemap的环境conda create -n geemap切换到新建的环境conda activate geemap安装geemap依赖包conda install -c conda-forge geemap 安装mambaconda install …

网络编程 tcp udp http编程流程 网络基础知识

讲解 网络基础知识网络编程tcp编程流程图示理解bind和accept函数理解监视套接字和链接套接字理解linux和window下的编程实现tcp特点 udp编程流程图示理解udp特点 http编程流程图示理解编程实现-网站服务器 网络基础知识 OSI分层&#xff1a;应用层 表示层 会话层 传输层 网络层…

上传图片视频

分布式文件系统MinIo MinIO提供多个语言版本SDK的支持&#xff0c;下边找到java版本的文档&#xff1a; 地址&#xff1a;https://docs.min.io/docs/java-client-quickstart-guide.html MinIO测试&#xff08;上传、删除、下载&#xff09; public class MinioTest {MinioC…

Centos7.9编写分布式集群大数据系统_自启动脚本---Linux工作笔记058

由于为了方便,系统在启动的时候,设置成系统所有的,集群软件都自动启动,这样,可以减少,运维成本,要不然,这么多,工具,有的还不知道放到什么位置了,一个个去启动,非常麻烦. 首先编辑: 编辑这个文件: 然后编辑这个文件,写上自己,自启动脚本的位置,然后保存 :wq 然后再给这个文件…

【RabbitMQ】golang客户端教程5——使用topic交换器

topic交换器&#xff08;主题交换器&#xff09; 发送到topic交换器的消息不能具有随意的routing_key——它必须是单词列表&#xff0c;以点分隔。这些词可以是任何东西&#xff0c;但通常它们指定与消息相关的某些功能。一些有效的routing_key示例&#xff1a;“stock.usd.ny…

8月11日上课内容 nginx的多实例和动静分离

多实例部署 在一台服务器上有多个tomcat的服务。 配置多实例之前&#xff0c;看单个实例是否访问正常。 1.安装好 jdk 2.安装 tomcat cd /opt tar zxvf apache-tomcat-9.0.16.tar.gz mkdir /usr/local/tomcat mv apache-tomcat-9.0.16 /usr/local/tomcat/tomcat1 cp -a /usr…

利用三维内容编辑器制作VR交互课件,简单好用易上手

随着虚拟现实技术的不断发展&#xff0c;越来越多的教育机构开始尝试将其应用于教育教学中。然而&#xff0c;要实现这一目标并不容易&#xff0c;需要专业的技术支持和开发团队。 为了解决这一问题&#xff0c;广州华锐互动研发了三维内容编辑器&#xff0c;它是一种基于虚拟现…

“掌握类与对象,点亮编程之路“(下)

White graces&#xff1a;个人主页 &#x1f649;专栏推荐:《C语言入门知识》&#x1f649; &#x1f649; 内容推荐:“掌握类与对象&#xff0c;点亮编程之路“(上)&#x1f649; &#x1f439;今日诗词:春风得意马蹄疾&#xff0c;一日看尽长安花&#x1f439; 目录 &…

fork创建多个子进程

fork创建多个子进程 示例代码 fork1.c #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h>int main(int argc,char **argv) {int i, j;pid_t pid;for (i 0; i < 3; i){pid fork();if (pid < 0){perror(&q…

Python 11道字典练习题

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 有字典 dic {“k1”: “v1”, “k2”: “v2”, “k3”: “v3”}&#xff0c;实现以下功能&#xff1a; 1、遍历字典 dic 中所有的key 参考答案&#xff1a; dic {k1: v1,k2:v2,k3:v3}for k in dic.keys():print(k)2、遍历…

Apollo让自动驾驶如此简单

前言&#xff1a; 最近被新能源的电价闹的不行&#xff0c;买了电车的直呼上当了、不香了。但电车吸引人不只是公里油耗低&#xff0c;还有良好的驾车使用感。比如辅助驾驶、甚至是自动驾驶。今天来介绍一个头部自动驾驶平台Apollo&#xff0c;Apollo是一个开源的、自动驾驶的软…

在SpringMVC环境下json字符串与对象转化 配置和对象方法

目录 1..json的使用 字符串与对象转化 2.通过spring配置的形式直接接受json格式字符串转化 1..json的使用 字符串与对象转化 1.导入一个json的jar坐标 <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</…

el-dialog嵌套,修改内层el-dialog样式(自定义样式)

el-dialog嵌套使用时,内层的el-dialog要添加append-to-body属性 给内层的el-dialog添加custom-class属性,添加自定义类名 <el-dialog:visible.sync"dialogVisible"append-to-bodycustom-class"tree-cesium-container"><span>这是一段信息<…

详细教程:如何搭建废品回收小程序

废品回收是一项环保举措&#xff0c;通过回收和再利用废弃物品&#xff0c;可以减少资源浪费和环境污染。近年来&#xff0c;随着智能手机的普及&#xff0c;小程序成为了推广和运营的重要工具。本文将详细介绍如何搭建一个废品回收小程序。 1. 进入乔拓云网后台 首先&#xf…