当前位置: 首页 > news >正文

SpringBoot过滤器获取Bean-请求重复可读-获取请求体数据-用户IP归属地获取

文章目录

    • 一.获取Bean
    • 二. Request重复可读
    • 三. 过滤器获取Body请求体数据
    • 四.用户ip获取


一.获取Bean

网上一些论调说Filter无法注入Bean的原因是加载顺序: listener—>filter—>servlet导致的.我不赞同.
原因:默认机制下,在SpringBoot应用启动时,IOC容器就开始实例化对象并把对象注入到代码片段里.和加载顺序无关. 无法通过自动注入获取的原因是因为自动注入的前提是两个都加入容器中的对象,才能引用.那由于某些原因不能直接把当前类注入容器中.我们可以通过一个application上下文引用工具类,维护Bean内容.这也能有力证明,和加载顺序无关,否则凭啥我application能注入,自动注入不行?

SpringContextUtils

public class SpringContextUtil {private static ApplicationContext applicationContext;//获取上下文public static ApplicationContext getApplicationContext() {return applicationContext;}//设置上下文public static void setApplicationContext(ApplicationContext applicationContext) {SpringContextUtil.applicationContext = applicationContext;}//通过名字获取上下文中的beanpublic static Object getBean(String name) {return applicationContext.getBean(name);}//通过类型获取上下文中的beanpublic static Object getBean(Class<?> requiredType) {return applicationContext.getBean(requiredType);}}

接着在启动类设置Bean

@SpringBootApplication(scanBasePackages = {"com.vector"}) // SpringBoot应用的标识
@MapperScan("com.vector.**.mapper") // 扫描mapper接口
public class VectorMemberApplication {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(VectorMemberApplication.class, args);SpringContextUtil.setApplicationContext(context);}
}

使用方式

SpringContextUtil.getBean(AuthStrategyContent.class);
SpringContextUtil.getBean(类名/类型名);

二. Request重复可读

一个InputStream对象在被读取完成后,将无法被再次读取,始终返回-1;
InputStream并没有实现reset方法(可以重置首次读取的位置),无法实现重置操作;

Servlet中提供了一个HttpServletRequestWrapper请求包装类.这个自定义的requestWrapper继承了HttpServletRequestWrapper ,HttpServletRequestWrapper 是一个ServletRequest的包装类同时也是ServletRequest的实现类。在这个自定义的requestWrapper里,用一个String做缓存,在构造方法里先把request的body中的数据缓存起来,然后重写了getInputStream,返回这个缓存的body,而不是从流中读取。这样,在需要多次读取body的地方,只需要在过滤器中把原来的request换成这个自定义的request,然后把这个自定义的带缓存功能的request传到后续的过滤器链中。

重复可读工具类

/*** 构建可重复读取inputStream的request** @author vector*/
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper {private final byte[] body;public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException {super(request);request.setCharacterEncoding(SystemConstants.UTF8);response.setCharacterEncoding(SystemConstants.UTF8);body = HttpHelper.getBodyString(request).getBytes(SystemConstants.UTF8);}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(getInputStream()));}@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream bais = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic int read() throws IOException {return bais.read();}@Overridepublic int available() throws IOException {return body.length;}@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) {}};}
}

使用方式

 protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {// 重复可读requestRepeatedlyRequestWrapper repeatedlyRequestWrapper =new RepeatedlyRequestWrapper(request,response);//获取tokenString token = repeatedlyRequestWrapper.getHeader(JwtUtil.JWT_HEADER);if (StringUtils.isBlank(token)) {//放行filterChain.doFilter(repeatedlyRequestWrapper, response);return;}//解析token//放行filterChain.doFilter(repeatedlyRequestWrapper, response);}

三. 过滤器获取Body请求体数据

在业务层中我们常用@RequestBody 他帮我们读取了.但是在过滤器中是原生的request请求.我们知道可以通过getParamter()获取参数.但是请求体是二进制流,我们无法直接使用.需要流转对象序列化.
如下.

    /*** 获取request中的json用户信息** @param request* @return* @throws IOException*/private UserLogin getUserByRequest(HttpServletRequest request) throws IOException {StringBuffer sb = new StringBuffer();InputStream is = request.getInputStream();InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);String s = "";while ((s = br.readLine()) != null) {sb.append(s);}String userInfo = sb.toString();JsonMapper jsonMapper = new JsonMapper();UserLogin userLogin = null;try {userLogin = jsonMapper.readValue(userInfo, UserLogin.class);} catch (JsonProcessingException e) {throw new AuthenticationServiceException(HttpCodeEnum.BAD_REQUEST.getMsg() + "json转换异常");}return userLogin;}

四.用户ip获取

public class IpUtil {/*** 获取登录用户的IP地址* 路由追踪,避免代理影响准确性* @param request* @return*/public static String getIpAddr(HttpServletRequest request) {String ip = request.getHeader("x-forwarded-for");if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}if ("0:0:0:0:0:0:0:1".equals(ip)) {ip = "127.0.0.1";}if (ip.split(",").length > 1) {ip = ip.split(",")[0];}return ip;}/*** 通过IP获取地址(需要联网)** @param ip* @return*/public static String getIpInfo(String ip) {if ("127.0.0.1".equals(ip)) {ip = "127.0.0.1";}String info = "";try {URL url = new URL("备案查询网太平洋/淘宝/其他" + ip);HttpURLConnection htpcon = (HttpURLConnection) url.openConnection();htpcon.setRequestMethod("GET");htpcon.setDoOutput(true);htpcon.setDoInput(true);htpcon.setUseCaches(false);InputStream in = htpcon.getInputStream();BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));StringBuffer temp = new StringBuffer();String line = bufferedReader.readLine();while (line != null) {temp.append(line).append("\r\n");line = bufferedReader.readLine();}bufferedReader.close();JSONObject obj = null;try {obj = (JSONObject) JSON.parse(temp.toString());} catch (JSONException e) {throw new JSONException("JSON解析错误:" + temp.toString(), e);}// @TODO 按照ip给的地址格式进行解析if (obj.getIntValue("code") == 200) {JSONObject data = obj.getJSONObject("ipdata");info += data.getString("info1") + " ";info += data.getString("info2") + " ";info += data.getString("info3") + " ";info += data.getString("isp");}} catch (MalformedURLException e) {e.printStackTrace();} catch (ProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}return info;}
}

相关文章:

SpringBoot过滤器获取Bean-请求重复可读-获取请求体数据-用户IP归属地获取

文章目录一.获取Bean二. Request重复可读三. 过滤器获取Body请求体数据四.用户ip获取一.获取Bean 网上一些论调说Filter无法注入Bean的原因是加载顺序: listener—>filter—>servlet导致的.我不赞同. 原因:默认机制下&#xff0c;在SpringBoot应用启动时&#xff0c;IOC…...

有哪些特别小众而有趣的编程语言呢?

相对较小众的编程语言&#xff0c;还要有趣&#xff1f;发表一些个人看法&#xff0c;如果不对大家口味&#xff0c;大家轻喷&#xff0c;留情留情。 Rust&#xff1a;Rust是一种系统编程语言&#xff0c;致力于提供高性能、可靠性和安全性。Rust具有内存安全和线程安全的特性&…...

vue中使用高德

首先我们要申请高德地图的key&#xff0c;当前升级过后高德地图使用也需要加上安全秘钥 注册账号 访问高德地图开发平台根据实际情况填写就可以&#x1f35c;&#xff08;实名认证的时候选择个人就可以&#xff0c;如果是企业级的项目&#xff0c;可能会涉及人员变动&#xf…...

React class组件和hooks setState异步更新数据详解

一、 class组件setState详解 1.class组件setState异步更新数据详解 class Father extends React.Component{state {num:0}addHandler () > { this.setState({num: 100})console.log(state中的值,this.state.num)}render() { return (<div><button onClick{this…...

ToBeWritten之嵌入式操作系统

也许每个人出生的时候都以为这世界都是为他一个人而存在的&#xff0c;当他发现自己错的时候&#xff0c;他便开始长大 少走了弯路&#xff0c;也就错过了风景&#xff0c;无论如何&#xff0c;感谢经历 转移发布平台通知&#xff1a;将不再在CSDN博客发布新文章&#xff0c;敬…...

git 实际开发中使用-解决问题

前言 git代码版本管理工具&#xff0c;打破常规的物理传输&#xff0c;更新&#xff0c;合并&#xff0c;回滚提高了开发效率和可追溯性。 网上的资料会把所有的命令都很全也很多&#xff0c;导致对刚刚了解的同学不友好&#xff0c;很难实际使用。 每个人都有自己使用git的习…...

新星计划·2023-第1期 - Python赛道报名入口 -〖你就是下一个新星〗

↓↓↓报名方式&#xff1a;&#xff08;下滑到本页面底部&#xff09;重要提醒&#xff1a;这里是 新星计划2023-第1期 - Python赛道报名入口&#xff0c;一经报名&#xff0c;不可更换。报名入口点击此处跳转 一、新星计划 新星计划是一个以发掘潜力新人、培养优质博主为目…...

Android LowMemoryKiller概述

Agenda Low memory killer 概述 内核空间LMK ULMK‐vmpressure ULMK‐PSI Low memory killer 概述 lowmemorykiller的作用就是当内存比较紧张的时候去及时杀掉一些对用户来说不那么重要的进程&#xff0c;回收内存&#xff0c;保证手机的正常运行。安卓平台lowmemorykiller机…...

特殊操作流——案例:游戏次数

需求&#xff1a;请求程序实现猜数字小游戏只能试玩三次&#xff0c;如果还想玩&#xff0c;提示&#xff1a;游戏已经结束&#xff0c;想玩请充值&#xff08;www.itcast.cn&#xff09; 思路&#xff1a; 写一个游戏类&#xff0c;里面有一个猜数字的小游戏 写一个测试类&am…...

git clone connect to gitlab sign in token弹窗让我输入用户名和密码

系列文章目录 文章目录系列文章目录前言前言 当我使用git bash输入命令&#xff1a;git clone https://gitlab.freedesktop.org/raqm/raqm.git libraqm 弹窗 ASUSLAPTOP-0R30I78P MINGW64 /e/krita-dev $ git clone https://gitlab.freedesktop.org/raqm/raqm.git libraqm C…...

【Blender】如何在Blender中添加HDRI环境贴图

​ 什么是HDRI环境贴图 环境贴图或HDRI贴图是在Blender中照亮3D场景并实现逼真效果的最有效和最快捷的方法之一。 HDRIs本质上是现实世界照明的快照&#xff0c;其中包含高动态范围成像&#xff08;HDRI&#xff09;的准确照明细节。HDRI是一个包含亮度信息&#xff08;从暗…...

前端监控指的是什么?

前端监控分为三个方面&#xff1a; 异常监控&#xff08;监控前端页面的报错&#xff09;性能监控&#xff08;监控页面的性能&#xff09;用户行为监控&#xff08;监控用户的行为&#xff0c;计算PV、UV、在线时间等、数据监控即我们常说的埋点 例子1 在后端突然上线了某个需…...

.net core 面试题 2023

文章目录1. 什么是 ASP.net core2. .net 术语3. 托管资源 和 非托管资源4. GC 和 垃圾回收5. .net中所有类的基类6. 如何实现对象的深拷贝7. 依赖注入&#xff0c;为什么使用依赖注入8. IOC容器的注入方法9. ASP.net core 中 服务生命周期10. scoped的 service 可以注入到 sing…...

和ChatGPT关于Swing music的一场对话(上篇)

什么是 Swing Music &#xff1f; Swing Music 是一款漂亮的自托管音乐播放器&#xff0c;适用于您的本地音频文件。就像一个更酷的 Spotify …但带上你自己的音乐。 第一次在 reddit 上看到 Swing Music&#xff0c;就被其 UI 吸引了 但源码站点的releases 中只有 windows 和 …...

java版工程项目管理系统源码 Spring Cloud+Spring Boot+Mybatis+Vue+ElementUI+前后端分离 功能清单

ava版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显示1…...

debian 10 扩展分区容量

debian 10 扩展分区容量1、扩展分区原因2、添加一块磁盘3、命令记录3.1、新增加的磁盘是/dev/sdb3.2、使用磁盘/dev/sdb 创建物理卷3.3、 把物理卷/dev/sdb加入到卷组debian-vg中3.4、查看物理卷、逻辑卷3.5、扩展逻辑卷/tmp3.6、逻辑卷组debian-vg 空余空间被用掉10g 还剩90g可…...

【无功优化】基于改进遗传算法的电力系统无功优化研究【IEEE30节点】(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

LeetCode 218. 天际线问题

城市的 天际线 是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。给你所有建筑物的位置和高度&#xff0c;请返回 由这些建筑物形成的 天际线 。 每个建筑物的几何信息由数组 buildings 表示&#xff0c;其中三元组 buildings[i] [lefti, righti, heighti] 表示&#xf…...

Logstash:使用自定义正则表达式模式

有时 Logstash Grok 没有我们需要的模式。 幸运的是我们有正则表达式库&#xff1a;Oniguruma。在很多时候&#xff0c;如果 Logstash 所提供的正则表达不能满足我们的需求&#xff0c;我们选用定制自己的表达式。 定义 Logstash 是一种服务器端数据处理管道&#xff0c;可同时…...

常见的一致性问题及解决

什么是一致性 一致性问题主要是因为分布式系统中的多个节点之间可能存在网络延迟、故障等原因导致的。具体而言&#xff0c;分布式系统中的数据一致性问题可以分为以下几种类型&#xff1a; 强一致性&#xff1a;指在任何时间点&#xff0c;所有节点中的数据都是一致的。这种…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

STM32---外部32.768K晶振(LSE)无法起振问题

晶振是否起振主要就检查两个1、晶振与MCU是否兼容&#xff1b;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容&#xff08;CL&#xff09;与匹配电容&#xff08;CL1、CL2&#xff09;的关系 2. 如何选择 CL1 和 CL…...

脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)

一、OpenBCI_GUI 项目概述 &#xff08;一&#xff09;项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台&#xff0c;其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言&#xff0c;首次接触 OpenBCI 设备时&#xff0c;往…...

Linux中《基础IO》详细介绍

目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改&#xff0c;实现简单cat命令 输出信息到显示器&#xff0c;你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...