SpringBoot结合ip2region实现博客评论显示IP属地
你好呀,我是小邹。
在现代的Web应用中,特别是博客和论坛类网站,为用户提供地理定位服务(如显示用户所在地理位置)可以极大地增强用户体验。本文将详细探讨如何使用Java和相关技术栈来实现在博客评论中显示用户的地址信息,特别关注如何利用ip2region库解析IP地址获取地理位置。
效果图:

技术栈:
- 后端框架:Spring Boot
- 数据库:MySQL
- 前端技术:HTML, CSS, JavaScript
- 地理编码库:
ip2region - 辅助库:
Apache Commons IO,Lombok
代码分析:IpParseUtil 类
这个类位于com.zou.blog.util包下,提供了几个关键方法用于解析IP地址并获取用户的地理位置信息。
ip2region文件:https://github.com/lionsoul2014/ip2region/blob/master/data/ip2region.xdb
package com.zou.blog.util;import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;/*** ip解析工具** @author zxf* @version v1.0.0* @date 2024/7/14 20:26*/
@Slf4j
public class IpParseUtil {/*** 解析ip地址** @param ipStr 字符串类型ip 例:192.168.0.1* @return 返回结果形式(国家 | 区域 | 省份 | 城市 | ISP) 例 [中国, 0, 河北省, 衡水市, 电信]*/public static List<String> parse(String ipStr) {return parse(ipStr, null);}/*** 自定义解析ip地址** @param ipStr ip 字符串类型ip 例:1970753539(经过转换后的)* @param index 想要获取的区间 例如:只想获取 省,市 index = [2,3]* @return 返回结果例 [北京,北京市]*/public static List<String> parse(String ipStr, int[] index) {try {//获得文件流时,因为读取的文件是在打好jar文件里面,不能直接通过文件资源路径拿到文件,但是可以在jar包中拿到文件流//ResourcePatternResolver的实现方法,可以匹配到各种部署时的各种文件类型例如war,jar,zip等等findPathMatchingResourcesResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();Resource[] resources = resolver.getResources("ip2region.xdb");Resource resource = resources[0];InputStream is = resource.getInputStream();File target = new File("ip2region.xdb");FileUtils.copyInputStreamToFile(is, target);is.close();Searcher searcher = new Searcher(String.valueOf(target), null, null);long ip = Searcher.checkIP(ipStr);return parse(ip, index, searcher);} catch (Exception e) {log.error("ip解析为long错误,ipStr:[{}],错误信息:[{}]", ipStr, e.getMessage(), e);throw new RuntimeException("系统异常!");}}/*** 自定义解析ip地址** @param ip ip Long类型ip* @param index 想要获取的区间 例如:只想获取 省,市 index = [2,3]* @return 返回结果例 [湖南省, 衡阳市]*/public static List<String> parse(Long ip, int[] index, Searcher searcher) {List<String> regionList = new ArrayList<>();try {String region = searcher.search(ip);log.info("获取到的城市信息:" + region);String[] split = region.split("\\|");if (index == null) {regionList = Arrays.asList(split);} else {for (int i : index) {regionList.add(split[i]);}}//关闭资源searcher.close();} catch (Exception e) {log.error("根据ip解析地址失败,ip:[{}],index[{}],报错信息:[{}]", ip, index, e.getMessage(), e);throw new RuntimeException("系统异常!");}return regionList;}/*** 获取IP方法** @author zxf*/public static String getIpAddr(HttpServletRequest request) {if (request == null) {return "unknown";}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("X-Forwarded-For");}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.getHeader("X-Real-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}return ip;}public static void main(String[] args) {String ip = "218.20.32.122";List<String> parse = parse(ip);System.out.println(parse);}}
关键方法解析:
-
parse(String ipStr)方法:- 接收一个字符串类型的IP地址,如"192.168.0.1"。
- 返回一个列表,其中包含解析得到的地理位置信息,格式为:[国家, 区域, 省份, 城市, ISP]。
-
parse(String ipStr, int[] index)方法:- 提供了更灵活的参数
index,允许开发者选择返回特定范围的信息,例如仅省份和城市。 - 返回一个列表,只包含由
index参数指定的地理位置信息部分。
- 提供了更灵活的参数
-
getIpAddr(HttpServletRequest request)方法:- 从HTTP请求中提取客户端的IP地址,考虑到可能存在的代理服务器情况。
集成到博客评论系统:
要在博客评论中显示用户的位置信息,你可以在处理评论提交的控制器中集成IpParseUtil类的方法。
-
获取IP地址:
在评论提交的控制器中,使用getIpAddr方法从HTTP请求中获取用户IP地址。 -
解析IP地址:
调用parse方法解析IP地址,获取用户的地理位置信息。 -
保存位置信息:
将解析得到的位置信息保存至评论模型中,如Comment实体的location字段。
// 在评论控制器中
@PostMapping("/comments")
public ResponseEntity<Comment> createComment(@RequestBody Comment comment, HttpServletRequest request) {String ip = IpParseUtil.getIpAddr(request);List<String> location = IpParseUtil.parse(ip);comment.setLocation(location);// ...保存评论到数据库...
}
显示位置信息:
在前端展示评论时,从location字段读取并显示信息。
<!-- 前端HTML示例 -->
<div class="comment"><p>By: {{ comment.user.name }}</p><p>Location: {{ comment.location.join(", ") }}</p><p>{{ comment.content }}</p>
</div>
通过上述步骤,我们成功实现了在博客评论中显示用户地址信息的功能,这不仅增加了博客的互动性,还为用户提供了一种直观的地理位置参考。使用Java和ip2region库,我们可以高效准确地解析IP地址并获取地理位置信息,从而提升用户体验和网站的吸引力。
相关文章:
SpringBoot结合ip2region实现博客评论显示IP属地
你好呀,我是小邹。 在现代的Web应用中,特别是博客和论坛类网站,为用户提供地理定位服务(如显示用户所在地理位置)可以极大地增强用户体验。本文将详细探讨如何使用Java和相关技术栈来实现在博客评论中显示用户的地址信…...
设计模式使用场景实现示例及优缺点(行为型模式——策略模式)
在遥远的王国里,有三个重要的角色:国王策略模式、他的皇家顾问算法家族,以及年轻的骑士接口。国王策略模式统治着整个王国,他的职责是确保每一个编程问题都能找到最合适的解决方案。 有一天,王国遇到了一场危机。编程王…...
ReactRouter v6升级的步骤
React Router v6 引入了一个 Routes 组件,它有点像 Switch ,但功能要强大得多。与 Switch 相比, Routes 的主要优势在于: <Routes> 中的所有 <Route> 和 <Link> 都是相对的。这导致在 <Route path> 和 &…...
【JVM实战篇】内存调优:内存问题诊断+案例实战
文章目录 诊断内存快照在内存溢出时生成内存快照MAT分析内存快照MAT内存泄漏检测的原理支配树介绍如何在不内存溢出情况下生成堆内存快照?MAT查看支配树MAT如何根据支配树发现内存泄漏 运行程序的内存快照导出和分析快照**大文件的处理** 案例实战案例1:…...
专业条码二维码扫描设备和手机二维码扫描软件的区别?
条码二维码技术已广泛应用于我们的日常生活中,从超市结账到公交出行,再到各类活动的入场验证,条码二维码的便捷性不言而喻,而在条码二维码的扫描识别读取过程中,专业扫描读取设备和手机二维码扫描软件成为了两大主要工…...
基于嵌入式Linux的高性能车载娱乐系统设计与实现 —— 融合Qt、FFmpeg和CAN总线技术
随着汽车智能化的发展,车载娱乐系统已成为现代汽车的标配。本文介绍了一个基于Linux的车载娱乐系统的设计与实现过程。该系统集成了音视频娱乐、导航、车辆信息显示等功能,旨在提供安全、便捷、丰富的驾驶体验。 1. 项目概述 随着汽车智能化的发展&…...
探索IP形象设计:快速掌握设计要点
随着市场竞争的加剧,越来越多的企业开始关注品牌形象的塑造和推广。在品牌形象中,知识产权形象设计是非常重要的方面。在智能和互联网的趋势下,未来的知识产权形象设计可能会更加关注数字和社交网络。通过数字技术和社交媒体平台,…...
泛微Ecology8明细表对主表赋值
文章目录 [toc]1.需求及效果1.1 需求1.2 效果2.思路与实现3.结语 1.需求及效果 1.1 需求 在明细表中的项目经理,可以将值赋值给主表中的项目经理来作为审批人员 1.2 效果 在申请人保存或者提交后将明细表中的人名赋值给主表中对应的值2.思路与实现 在通过js测…...
opencv—常用函数学习_“干货“_5
目录 十五、图像分割 简单阈值分割 (threshold) 自适应阈值分割 (adaptiveThreshold) 颜色范围分割 (inRange) 分水岭算法 (watershed) 泛洪填充 (floodFill) GrabCut算法 (grabCut) 距离变换 (distanceTransform) 最大稳定极值区域检测 (MSER) 均值漂移滤波 (pyrMean…...
JAVA零基础学习1(CMD、JDK、环境变量、变量和键盘键入、IDEA)
JAVA零基础学习1(CMD、JDK、环境变量、变量和键盘键入、IDEA) CMD常见命令配置环境变量JDK的下载和安装变量变量的声明和初始化声明变量初始化变量 变量的类型变量的作用域变量命名规则示例代码 键盘键入使用 Scanner 类读取输入步骤示例代码 常用方法处…...
Redis的安装配置及IDEA中使用
目录 一、安装redis,配置redis.conf 1.安装gcc 2.将redis的压缩包放到指定位置解压 [如下面放在 /opt 目录下] 3.编译安装 4.配置redis.conf文件 5.开机自启 二、解决虚拟机本地可以连接redis但是主机不能连接redis 1.虚拟机网络适配器网络连接设置为桥接模式…...
ubuntu 物理内存爆炸而不使用虚拟内存的问题
ubuntu 物理内存不足时有时候会不去使用虚拟内存,让虚拟内存空闲,而直接关闭占用内存的进程,如果在进行模型测试或训练时,就会导致训练或测试进程被杀死。 1. 修改 swappiness: cat /proc/sys/vm/swappiness sudo sysc…...
Python实现音频均衡和降噪
使用librosa库来读取音频文件,音频处理是一个复杂过程,这里只是简单的进行降噪和均衡。 import librosa import soundfile as sf def improve_audio_quality(input_file, output_file): # 读取音频文件 audio, sample_rate librosa.load(input_…...
【JavaScript 算法】贪心算法:局部最优解的构建
🔥 个人主页:空白诗 文章目录 一、贪心算法的基本概念贪心算法的适用场景 二、经典问题及其 JavaScript 实现1. 零钱兑换问题2. 活动选择问题3. 分配问题 三、贪心算法的应用四、总结 贪心算法(Greedy Algorithm)是一种逐步构建解…...
Azcopy Sync同步Azure文件共享
文章目录 Azcopy Sync同步文件共享一、工作原理二、安装 AzCopy在 Windows 上在 Linux 上 三、资源准备1. 创建源和目标 Azure 存储账户2. 创建源和目标文件共享3. 确定路径4. 生成源和目的存储账户的共享访问签名(SAS)令牌配置权限示例生成的 URL 四、A…...
单例模式 饿汉式和懒汉式的区别
单例模式(Singleton Pattern)是设计模式中最简单、最常见、最容易实现的一种模式。它确保一个类仅有一个实例,并提供一个全局访问点。单例模式主要有两种实现方式:饿汉式(Eager Initialization)和懒汉式&am…...
Python中的模块和包的定义以及如何在Python中导入和使用它们
在Python中,模块(Module)和包(Package)是组织代码以便重用和共享的基本单元。它们使得Python代码更加模块化,易于管理和维护。 模块(Module) 模块是一个包含Python代码的文件&…...
设计模式使用场景实现示例及优缺点(结构型模式——组合模式)
结构型模式 组合模式(Composite Pattern) 组合模式使得用户对单个对象和组合对象的使用具有一致性。 有时候又叫做部分-整体模式,它使我们树型结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元…...
《系统架构设计师教程(第2版)》第11章-未来信息综合技术-06-云计算(Cloud Computing) 技术概述
文章目录 1. 相关概念2. 云计算的服务方式2.1 软件即服务 (SaaS)2.2 平台即服务 (PaaS)2.3 基础设施即服务 (IaaS)2.4 三种服务方式的分析2.4.1 在灵活性2.4.2 方便性方 3. 云计算的部署模式3.1 公有云3.2 社区云3.3 私有云3.4 混合云 4. 云计算的发展历程4.1 虚拟化技术4.2 分…...
网络安全工作者如何解决网络拥堵
网络如同现代社会的血管,承载着信息的血液流动。然而,随着数据流量的激增,网络拥堵已成为不容忽视的问题,它像是一场数字世界的交通堵塞,减缓了信息传递的速度,扰乱了网络空间的秩序。作为网络安全的守护者…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
华为OD机考-机房布局
import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseSystem.out.println(solve(in.nextLine()));}}priv…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
