SpringBoot 快速实现IP地址解析
如果使用本地ip 解析的话,我们将会借助ip2region,该项目维护了一份较为详细的本地ip 地址对应表,如果为了离线环境的使用,需要导入该项目依赖,并指定版本,不同版本的方法可能存在差异。
<dependency><groupId>org.lionsoul</groupId><artifactId>ip2region</artifactId><version>2.6.3</version>
</dependency>
官方gitee:gitee.com/lionsoul/ip…
开发
在使用时需要将 xdb 文件下载到工程文件目录下,使用ip2region即使是完全基于 xdb 文件的查询,单次查询响应时间在十微秒级别,可通过如下两种方式开启内存加速查询:
-
vIndex 索引缓存 :使用固定的 512KiB 的内存空间缓存 vector index 数据,减少一次 IO 磁盘操作,保持平均查询效率稳定在10-20微秒之间。
-
xdb 整个文件缓存:将整个 xdb 文件全部加载到内存,内存占用等同于 xdb 文件大小,无磁盘 IO 操作,保持微秒级别的查询效率。
/*** ip查询*/
@Slf4j
public class IPUtil {private static final String UNKNOWN = "unknown";protected IPUtil(){ }/*** 获取 IP地址* 使用 Nginx等反向代理软件, 则不能通过 request.getRemoteAddr()获取 IP地址* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,* X-Forwarded-For中第一个非 unknown的有效IP字符串,则为真实IP地址*/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();}return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;}public static String getAddr(String ip){String dbPath = "src/main/resources/ip2region/ip2region.xdb";// 1、从 dbPath 加载整个 xdb 到内存。byte[] cBuff;try {cBuff = Searcher.loadContentFromFile(dbPath);} catch (Exception e) {log.info("failed to load content from `%s`: %s\n", dbPath, e);return null;}// 2、使用上述的 cBuff 创建一个完全基于内存的查询对象。Searcher searcher;try {searcher = Searcher.newWithBuffer(cBuff);} catch (Exception e) {log.info("failed to create content cached searcher: %s\n", e);return null;}// 3、查询try {String region = searcher.searchByStr(ip);return region;} catch (Exception e) {log.info("failed to search(%s): %s\n", ip, e);}return null;}
}
这里我们将ip 解析封装成一个工具类,包含获取IP和ip 地址解析两个方法,ip 的解析可以在请求中获取。获取到ip后,需要根据ip ,在xdb 中查找对应的IP地址的解析,由于是本地数据库可能存在一定的缺失,部分ip 存在无法解析的情况。
在线解析
如果想要获取更加全面的ip 地址信息,可使用在线数据库,这里提供的是 whois.pconline.com 的IP解析,该IP解析在我的使用过程中表现非常流畅,而且只有少数的ip 存在无法解析的情况。
@Slf4j
public class AddressUtils {// IP地址查询public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";// 未知地址public static final String UNKNOWN = "XX XX";public static String getRealAddressByIP(String ip) {String address = UNKNOWN;// 内网不查询if (IpUtils.internalIp(ip)) {return "内网IP";}if (true) {try {String rspStr = sendGet(IP_URL, "ip=" + ip + "&json=true" ,"GBK");if (StrUtil.isEmpty(rspStr)) {log.error("获取地理位置异常 {}" , ip);return UNKNOWN;}JSONObject obj = JSONObject.parseObject(rspStr);String region = obj.getString("pro");String city = obj.getString("city");return String.format("%s %s" , region, city);} catch (Exception e) {log.error("获取地理位置异常 {}" , ip);}}return address;}public static String sendGet(String url, String param, String contentType) {StringBuilder result = new StringBuilder();BufferedReader in = null;try {String urlNameString = url + "?" + param;log.info("sendGet - {}" , urlNameString);URL realUrl = new URL(urlNameString);URLConnection connection = realUrl.openConnection();connection.setRequestProperty("accept" , "*/*");connection.setRequestProperty("connection" , "Keep-Alive");connection.setRequestProperty("user-agent" , "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");connection.connect();in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));String line;while ((line = in.readLine()) != null) {result.append(line);}log.info("recv - {}" , result);} catch (ConnectException e) {log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);} catch (SocketTimeoutException e) {log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);} catch (IOException e) {log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);} catch (Exception e) {log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);} finally {try {if (in != null) {in.close();}} catch (Exception ex) {log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);}}return result.toString();}
}
场景
那么在开发的什么流程获取ip 地址是比较合适的,这里就要用到我们的拦截器了。拦截进入服务的每个请求,进行前置操作,在进入时就完成请求头的解析,ip 获取以及ip 地址解析,这样在后续流程的全环节,都可以复用ip 地址等信息。
/*** 对ip 进行限制,防止IP大量请求*/
@Slf4j
@Configuration
public class IpUrlLimitInterceptor implements HandlerInterceptor{@Overridepublic boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) {//更新全局变量Constant.IP = IPUtil.getIpAddr(httpServletRequest);Constant.IP_ADDR = AddressUtils.getRealAddressByIP(Constant.IP);Constant.URL = httpServletRequest.getRequestURI();return true;}@Overridepublic void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) {//通过本地获取// 获得ip// String ip = IPUtil.getIpAddr(httpServletRequest);//解析具体地址// String addr = IPUtil.getAddr(ip);//通过在线库获取// String ip = IpUtils.getIpAddr(httpServletRequest);// String ipaddr = AddressUtils.getRealAddressByIP(ipAddr);// log.info("IP >> {},Address >> {}",ip,ipaddr);}@Overridepublic void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {}
}
如果想要执行我们的ip 解析拦截器,
需要在spring boot的视图层进行拦截才会触发我们的拦截器。
@Configuration
public class WebConfig implements WebMvcConfigurer {@AutowiredIpUrlLimitInterceptor ipUrlLimitInterceptor;//执行ip拦截器@Overridepublic void addInterceptors(InterceptorRegistry regivastry){registry.addInterceptor(ipUrlLimitInterceptor)// 拦截所有请求.addPathPatterns("/**");}
}相关文章:
SpringBoot 快速实现IP地址解析
如果使用本地ip 解析的话,我们将会借助ip2region,该项目维护了一份较为详细的本地ip 地址对应表,如果为了离线环境的使用,需要导入该项目依赖,并指定版本,不同版本的方法可能存在差异。 <dependency>…...
亚马逊、速卖通,阿里国际等平台测评如何用自养号测评补单
在电商领域,补单是一种常见的推广方式。它能够优化商品销售、留下优质评论、打压竞品和赶走跟卖等,具有很多好处。然而,补单也存在安全性问题,有些卖家找人补单后店铺反而出了问题。因此,了解测评系统是非常重要的的。…...
ubuntu挂载ext4文件系统
文章目录 1.虚拟机分配10G磁盘用来挂载ext4文件系统2.磁盘分区3.创建文件系统4.挂载文件系统5.卸载文件系统6.使用ior测试ext4三种日志模式(1)ordered(2)journal(3)writeback 1.虚拟机分配10G磁盘用来挂载e…...
MySQL 读写分离
目录 一、什么是读写分离? 二、为什么要读写分离呢? 三、什么时候要读写分离? 四、主从复制与读写分离 五、MySQL 读写分离原理 六、企业 使用MySQL 读写分离场景 1)基于程序代码内部实现 2)基于中间代理层实现…...
【多线程例题】顺序打印abc线程
顺序打印-进阶版 方法一:三个线程竞争同一个锁,通过count判断是否打印 方法二:三个线程同时start,分别上锁,从a开始,打印后唤醒b 三个线程分别打印A,B,C 方法一:通过co…...
WebSocket工具类
最近的项目在整长连接WebSocket,之前也写过一个感觉没有这个全面。提供个工具类WebSocketHelper和Java-WebSocket-1.3.9.jar包以及一个HttpURLConnectionUtil 1、WebSocketHelper import android.util.Log;import org.java_websocket.client.WebSocketClient; imp…...
Linux 的 crontab
Linux 的 crontab 是一个用于在特定时间运行命令或脚本的工具。每个用户都可以创建自己的 crontab 文件来安排定时任务。 以下是使用 Linux crontab 的基本步骤: 打开终端或命令行界面。 输入以下命令来编辑当前用户的 crontab 文件: crontab -e如果是…...
十二.Redis模拟集群搭建
配置环境 查看环境信息 127.0.0.1:6379> info replication #查看当前redis的信息 # Replication role:master #角色 master主机 connected_slaves:0 #从机数量为0 master_failover_state:no-failover master_replid:115f37a0ec195680ef754d6915738b0c0a05f450 master_replid…...
IDEA导入微服务项目后自动将微服务展示在service面板中
有时候,不会自动将微服务展示在service面板中。 添加service面板: service面板: 更新所有maven,就可以自动将微服务展示在service面板中。...
MySQL体系结构及执行过程
一、MySQL体系结构 1、网络连接层 客户端连接器(Client Cnnectors):提供支持与MySQL服务器建立连接。 建立连接命令:mysql -h -u -p -h指定MySQL服务的IP 若本地连接则不需要 每一个连接均会保存用户权限,中途修改权…...
21. MySQL基础知识
文章目录 一、索引B Tree 原理1. 数据结构2. 操作3. 与红黑树的比较 MySQL 索引1. BTree 索引2. 哈希索引3. 全文索引4. 空间数据索引 索引优化1. 独立的列2. 多列索引3. 索引列的顺序4. 前缀索引5. 覆盖索引 索引的优点索引的使用条件 二、查询性能优化使用 Explain 进行分析优…...
【ArcGIS Pro微课1000例】0029:绘制全球海洋波纹荡漾效果图
本文讲解ArcGIS Pro3.0中,基于全球航洋面状矢量数据,绘制震撼全球海洋波纹荡漾效果图。 文章目录 一、效果预览二、效果制作三、参数详解一、效果预览 绘制好的海水波纹荡漾效果图如下: 下面我们来学习绘制过程。 二、效果制作 波纹荡漾效果需要在全局或者局部场景中制作…...
2023“钉耙编程”中国大学生算法设计超级联赛(3)8-bit Zoom
2023“钉耙编程”中国大学生算法设计超级联赛(3)8-bit Zoom 题解 有一张尺寸为 n n n\times n nn的图片,你要将图片放大成大小为 n Z 100 n Z 100 \dfrac{nZ}{100}\times \dfrac{nZ}{100} 100nZ100nZ的图片。 当下列任何一个条件不成…...
【PWN · ret2text | 伪rand()】[HDCTF 2023]pwnner
伪随机数以及ctypes库的初步接触 目录 前言 一、题目 二、解题思路 三、exp 总结 前言 一道简单的ret2text,加上一些伪随机的知识,对于本蒟蒻萌新来说,比较新,值得记录。 一、题目 栈溢出保护、PIE保护都没有开。反汇编后…...
第五章:通过对抗擦除的目标区域挖掘:一种简单的语义分割方法
0.摘要 我们研究了一种逐步挖掘具有鉴别性的物体区域的原则方法,使用分类网络来解决弱监督语义分割问题。分类网络只对感兴趣对象中的小而稀疏的鉴别性区域有响应,这与分割任务的要求相背离,分割任务需要定位密集、内部和完整的区域以进行像素…...
自定义view - 玩转字体变色
自定义View步骤: 1>:values__attrs.xml,定义自定义属性; 2>:在第三个构造方法中获取自定义属性; 3>:onMeasure【不是必须的】; 4>:onDraw:绘制代…...
工业边缘网关HiWoo Box的4G/5G CPE功能:为现场无线设备提供网络
引言 随着工业物联网的快速发展,现场设备的无线连接需求越来越迫切。然而,在一些室外或者不方便布网的场景下,为现场的无线设备提供网络仍然是一个挑战。为了满足这一需求,工业边缘网关HiWoo Box引入了4G/5G CPE(Cust…...
Set 和 Map 数据结构
数据结构Set ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。 Set本身是一个构造函数,用来生成Set数据结构。 // 数组去重 const set new Set([1, 2, 3, 4, 4]); [...set] // [1, 2, 3, 4]目前个人感觉Se…...
nginx根据url参数动态代理
nginx根据url参数动态代理 请求url格式,其中参数proxy后面的url就是需要访问的真实地址: http://localhost:9388/?proxyhttp://localhost:8038/Content/layui/font/iconfont.woff?v256 http://localhost:9388/?proxyhttp://localhost:8072/article/A…...
TCP协议(收集和记录)
收集写的比较好的文章 TCP四次挥手详解 四次挥手介绍的非常详细, 重点介绍了各种异常情况下协议是如何处理的, 异常处理可以做到两点: 让连接保活, 也许只是一次连接异常让连接死掉后不影响后续的操作, 重点介绍了TIME_WAIT...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
