Springboot教程(二)——过滤器、拦截器

过滤器

过滤器可以在调用控制器方法之前进行一些操作,过滤器类一般放在filter包下。

配置类注册

使用过滤器时,要实现Filter接口,并重写doFilter方法:

class TestFilter : Filter {override fun doFilter(request: ServletRequest?, response: ServletResponse?, chain: FilterChain?) {// 逻辑chain?.doFilter(request, response)}
}

这里要注意,过滤器最后应调用chain.doFilter(request, response)方法,将请求交给后一个过滤器。当然,有些时候不想交给后一个过滤器,也可以不写

要启用过滤器,需要写一个配置类,用@Configuration标注。在配置类中,定义一个方法,用@Bean标注,这个方法需要先获取一个FilterRegistrationBean<T>对象,用于注册过滤器,再对这个对象进行一些操作,最后返回这个对象。这里面有一个泛型,表示要注册的过滤器的类型:

@Configuration
class TestConfig {@Beanfun getFilter(): FilterRegistrationBean<TestFilter>{val bean = FilterRegistrationBean<TestFilter>()// 逻辑return bean}}

 它的基本操作如下:

    @Beanfun getFilter(): FilterRegistrationBean<TestFilter>{val bean = FilterRegistrationBean<TestFilter>()bean.filter = TestFilter()    // 设置注册过滤器的对象bean.order = 1                // 设置过滤器优先级,值越小优先级越高,1是最顶级bean.addUrlPatterns("/index") // 设置过滤的路径bean.setName("testFilter")    // 设置过滤器的名字return bean}

我们来实践一下:

在项目下创建filter包,在filter包下创建TestFilter类:

package com.example.c0101.filterimport jakarta.servlet.Filter
import jakarta.servlet.FilterChain
import jakarta.servlet.ServletRequest
import jakarta.servlet.ServletResponseclass TestFilter : Filter {override fun doFilter(request: ServletRequest?, response: ServletResponse?, chain: FilterChain?) {println("doFilter")chain?.doFilter(request, response)}
}

这个类实现了Filter接口,重写了doFilter方法,表示过滤器的操作。在这里面只是打印了"doFilter"的信息。

在项目下创建config包,在config包下创建TestConfig类:

package com.example.c0101.configimport com.example.c0101.filter.TestFilter
import org.springframework.boot.web.servlet.FilterRegistrationBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration@Configuration
class TestConfig {@Beanfun getFilter(): FilterRegistrationBean<TestFilter>{val bean = FilterRegistrationBean<TestFilter>()bean.filter = TestFilter()    // 设置注册过滤器的对象bean.addUrlPatterns("/index") // 设置过滤的路径return bean}}

这个类用于注册一个TestFilter的过滤器。

在项目下创建controller包,在controller包下创建TestController类:

package com.example.c0101.controllerimport org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController@RestController
class TestController {@RequestMapping("/index")fun index(): String{println("进入index方法")return "这是主页"}
}

这个控制器注册了/index的路径,返回一个"这是主页"的字符串。

我们用浏览器访问http://127.0.0.1:8080/index,然后回到idea里,发现控制台输出:

doFilter
进入index方法

因为过滤器会在进入方法之前执行


@WebFilter注解注册

将@WebFilter标注在过滤器类上,可以快速注册一个过滤器。但是,@WebFilter需要和@Component同时使用,这样才能被Spring Boot扫描到:

@WebFilter("/index")
@Component
class TestFilter : Filter {override fun doFilter(request: ServletRequest?, response: ServletResponse?, chain: FilterChain?) {println("doFilter")chain?.doFilter(request, response)}
}

Spring Boot的扫描

提到了“被Spring Boot扫描到”,那就讲一下扫描。Spring Boot的主类是创建项目时就自带的XXXApplication.kt内定义的XXXApplication:

@SpringBootApplication
class C0101Applicationfun main(args: Array<String>) {runApplication<C0101Application>(*args)
}

这个类被@SpringBootApplication注解标注,这个注解源码的最核心注解有如三个:

  • @SpringBootConfiguration 让项目采用Java注解的配置方式,而不是xml配置方式
  • @EnableAutoConfiguration 开启自动配置,启动时可以自动加载配置文件和配置类
  • @ComponentScan 启动组件扫描器。组件扫描器可以扫描被@Component注解标注的类

所以说,一个类想要被扫描到,就必须被@Component注解标注。我们之前学的@Controller、@Configuration等注解,其实上内部都有@Component注解,因此可以被扫描到

@WebFilter实践

删除原来项目的配置类和config包,在TestFilter类上标注:

@WebFilter("/index")
@Component

运行代码,在浏览器访问http://127.0.0.1:8080/index,控制台输出:

doFilter
进入index方法

和我们之前的结果一样

拦截器

定义一个拦截器类,需要继承HandlerInterceptor接口,通过重写preHandle、postHandle、afterCompletion方法,设置一个请求的不同时期的拦截方法:

事件
收到请求
过滤器doFilter方法
拦截器preHandle方法
控制器对应的方法
拦截器postHandle方法
解析视图
请求结束
拦截器afterCompletion方法

定义拦截器的代码如下:

class TestInterceptor : HandlerInterceptor {override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {println("preHandle")return true}override fun postHandle(request: HttpServletRequest,response: HttpServletResponse,handler: Any,modelAndView: ModelAndView?) {println("postHandle")}override fun afterCompletion(request: HttpServletRequest,response: HttpServletResponse,handler: Any,ex: Exception?) {println("afterCompletion")}
}

这里面preHandle方法的返回值如果为true表示正常执行,如果为false表示阻止请求正常执行

注册一个拦截器,需要创建配置类,继承WebMvcConfigurer接口并重写addInterceptors方法,这个方法会传入一个registry参数,我们需要调用它的addInterceptor方法,并接收它的返回值,再用这个返回值调用addPathPatterns方法设置要拦截的路径:

@Configuration
class TestConfig : WebMvcConfigurer{override fun addInterceptors(registry: InterceptorRegistry) {val regist = registry.addInterceptor(TestInterceptor())regist.addPathPatterns("/index")}
}

我们来实践一下

网站的某些路径需要用户先登录才能访问,那么如何确保用户已经登录呢?

最常用的做法是,在用户登录后给用户一个访问令牌,用户访问其他路径时,需要将访问令牌传给服务器,服务器再对访问令牌进行判断。我们可以通过拦截器简单的模拟拦截访问令牌:

创建一个interceptor包,创建TestInterceptor类:

package com.example.c0101.interceptorimport jakarta.servlet.http.HttpServletRequest
import jakarta.servlet.http.HttpServletResponse
import org.springframework.web.servlet.HandlerInterceptorclass TestInterceptor : HandlerInterceptor {override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {val token = request.getParameter("token")return if (token == "token") true else{response.status = 401val outputStream = response.outputStreamoutputStream.write("令牌错误".toByteArray())false}}}

代码首先通过request.getParameter方法获取token参数(访问令牌),然后判断这个访问令牌是否正确(为了方便起见,我们通过判断访问令牌是否为"token"来判断访问令牌是否正确),如果正确则请求正常执行,否则通过response.setStatus方法设置请求状态码(401:当前请求需要用户验证),然后通过response.getOutputStream获取响应的输出流,再向这个输出流写入"令牌错误"的信息,然后阻止请求执行

关于request、response这里不多讲,它们是Servlet里的类的对象

接下来创建config包,再config包下创建TestConfig类:

package com.example.c0101.configimport com.example.c0101.interceptor.TestInterceptor
import org.springframework.context.annotation.Configuration
import org.springframework.web.servlet.config.annotation.InterceptorRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer@Configuration
class TestConfig : WebMvcConfigurer{override fun addInterceptors(registry: InterceptorRegistry) {val regist = registry.addInterceptor(TestInterceptor())regist.addPathPatterns("/index")}
}

将/index路径注册了TestInterceptor拦截器

接下来用postman访问http://127.0.0.1:8080/index,进行传入token和不传入token的测试:

 可以发现,拦截器成功拦截了令牌错误的访问

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

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

相关文章

怎么消除照片上的路人?分享几个无痕消除工具

穿梭于繁忙的街头&#xff0c;我们总会在不经意间捕捉到那些精彩的瞬间&#xff0c;但往往也会因为一些无关的路人破坏了整个画面的和谐。在摄影后期处理中&#xff0c;消除照片中的路人是一项常见的需求。现在&#xff0c;让我们一起探索如何巧妙地消除照片中的路人&#xff0…

Elasticsearch使用function_score查询酒店和排序

需求 基于用户地理位置&#xff0c;对酒店做简单的排序&#xff0c;非个性化的推荐。酒店评分包含以下&#xff1a; 酒店类型&#xff08;依赖用户历史订单数据&#xff09;&#xff1a;希望匹配出更加符合用户使用的酒店类型酒店评分&#xff1a;评分高的酒店用户体验感好ge…

2024河北国际光伏展

2024河北国际光伏展是一个专门展示和促进光伏技术与产业发展的国际性展览会。该展览会将于2024年在中国河北省举办&#xff0c;吸引来自世界各地的光伏企业、专家、学者和投资者参加。 展览会将展示最新的光伏技术和产品&#xff0c;包括太阳能电池板、光伏组件、逆变器、储能系…

洛谷 P2678 [NOIP2015 提高组] 跳石头(二分答案)

前提知识&#xff1a; 二分法往下其实有一些小分支&#xff0c;最常见的是二分查找&#xff0c;然后就是二分答案&#xff0c;浮点数二分等等 主要谈谈二分查找和二分答案的具体区别&#xff0c;我们不能光报个菜名随口就来&#xff0c;一问具体也说不出来个所以然。 前提&a…

GB28181 —— Ubuntu20.04下使用ZLMediaKit+WVP搭建GB28181流媒体监控平台(连接带云台摄像机)

最终效果 简介 GB28181协议是视频监控领域的国家标准。该标准规定了公共安全视频监控联网系统的互联结构, 传输、交换、控制的基本要求和安全性要求, 以及控制、传输流程和协议接口等技术要求,是视频监控领域的国家标准。GB28181协议信令层面使用的是SIP(Session Initiatio…

物联网手持终端机 超高频RFID手持终端工业级盘点PDA设备

在数字化时代&#xff0c;物联网手持终端机已经成为各行业不可或缺的工具。联强优创自主研发远距离手柄式超高频RFID读写手持终端&#xff0c;搭载高性能UHF读写模块&#xff0c;距离可达1-15米&#xff0c;基于IMPINJ E710芯片超高频模块与设备完美兼容&#xff0c;支持协议标…

图论基础(一)

一、图论 图论是数学的一个分支&#xff0c;它以图为研究对象。图论中的图是若干给定的点&#xff08;顶点&#xff09;以及连接两点的线&#xff08;边&#xff09;构成的图像&#xff0c;这种图形通常用来描述某些事物之间的某种特定关系&#xff0c;用点代表事物&#xff0c…

3.机器学习-十大算法之一线性回归算法(LinearRegression)原理讲解

3️⃣.机器学习-十大算法之一线性回归算法&#xff08;LinearRegression&#xff09;原理讲解 个人简介理解算法线性回归的一般模型 什么是线性&#xff1f;什么是非线性&#xff1f;什么是回归分析&#xff1f;损失函数算法优缺点优点缺点&#xff1a; 示例数学公式误差概率密…

Linux 内存管理概述(偏实战,略理论,附链接)

基础理论 1. 内存映射 可以参考&#xff1a; Linux内存映射 - 知乎 写的很详细&#xff0c;而且也有代码分析 2. 虚拟内存的空间分布 通过这张图你可以看到&#xff0c;用户空间内存&#xff0c;从低到高分别是五种不同的内存段。只读段&#xff0c;包括代码和常量等。数据段…

试用北大库博Cobot-SCA工具

最近试用北大软件工具的库博-SCA工具&#xff0c;其产品全称是库博软件成分分析与同源漏洞检测工具软件。这个产品名称有点长&#xff0c;至于原因&#xff0c;可能是为了与市场上其它SCA工具进行区分吧。北大库博SCA不是像大多数SCA工具&#xff0c;解析构建文件中的依赖组件进…

亿道丨三防平板丨手持平板丨加固平板丨助力地震救援

自土耳其发生7.8级大地震以来&#xff0c;一直都牵动着世人的心。2023年2月10日&#xff0c;据法新社最新消息&#xff0c;强震已造成土耳其和叙利亚两国超2万人遇难。报道称&#xff0c;相关官员和医护人员表示&#xff0c;地震造成土耳其17674人死亡&#xff0c;叙利亚则有33…

Linux--查看网络性能指标

一、性能指标有哪些&#xff1f; 带宽&#xff0c;表示链路的最大传输速率&#xff0c;单位是 b/s &#xff08;比特 / 秒&#xff09;&#xff0c;带宽越大&#xff0c;其传输能力就越强。延时&#xff0c;表示请求数据包发送后&#xff0c;收到对端响应&#xff0c;所需要的…

跟着cherno手搓游戏引擎【25】封装2DRenderer,封装shader传参,自定义Texture

封装2DRenderer&#xff1a; Renderer.h: #include"ytpch.h" #include"Renderer.h" #include <Platform/OpenGL/OpenGLShader.h> #include"Renderer2D.h" namespace YOTO {Renderer::SceneData* Renderer::m_SceneData new Renderer::S…

在IDEA中创建vue hello-world项目

工作中最近在接触vue前端项目&#xff0c;记录一下从0搭建一个vue hello world项目的步骤 1、本地电脑安装配置node、npm D:\Project\vue\hello-world>node -v v14.21.3 D:\Project\vue\hello-world>npm -v 6.14.18 D:\Project\vue\hello-world> 2、设置npm国内淘…

C语言指针总结2

前言 本篇博客紧接着指针总结1来总结下数组和指针的关系&#xff0c;让我们一起来看一下数组与指针的“爱恨情仇”。 欢迎关注个人主页&#xff1a;小张同学zkf 若有问题&#xff0c;评论区见 文章目录 1. 数组名的理解2. 使用指针访问数组3. 一维数组传参的本质4. 冒泡排序5.…

Layer1 明星项目 Partisia Blockchain 何以打造互操作、可创新的数字经济网络

我们的目标是创建一个以用户为中心的全新数字经济网络&#xff1a;在去信任化和公平透明的环境下&#xff0c;所有的隐私数据都能够得到天然保障&#xff0c;企业、用户等各角色的协作与共享将会更顺利地进行。 —— Partisia Blockchain 团队 作为一个以 Web3 安全为技术方向的…

数字化转型与制造企业绿色创新质量——基于供需双侧机制的再检验(2011-2022年)

参照马红&#xff08;2023&#xff09;的做法&#xff0c;本团队对来自软科学《数字化转型与制造企业绿色创新质量—基于供需双侧机制的再检验》一文中的基准回归部分进行复刻 一、数据介绍 数据名称&#xff1a;数字化转型与制造企业绿色创新质量 参考期刊&#xff1a;《软…

ClickHouse 指南(三)最佳实践 -- 跳数索引

Data Skipping Indexes Data Skipping Indexes 2 1、简介 影响ClickHouse查询性能的因素很多。在大多数情况下&#xff0c;关键因素是ClickHouse在计算查询WHERE子句条件时是否可以使用主键。因此&#xff0c;选择适用于最常见查询模式的主键对于有效的表设计至关重要。 然…

光学3D表面轮廓仪微纳米三维形貌一键测量

光学3D表面轮廓仪(白光干涉仪)利用白光干涉原理&#xff0c;以0.1nm分辨率精准捕捉物体的表面细节&#xff0c;实现三维显微成像测量&#xff0c;被广泛应用于材料学领域的研究和应用。 了解工作原理与技术 材料学领域中的光学3D表面轮廓仪&#xff0c;也被称为白光干涉仪&am…

05 动力云客之分页查询用户 + 查询用户详情 + 新增用户

1. 用户列表分页查询实现 核心 使用pageHelper实现分页 GetMapping(value "api/users")//分页的参数可以不传, 不传就默认设置为1public R userPage(RequestParam(value "current", required false) Integer current) {if (current null) {current …