如何使用Spring Boot和ip2region为您的应用程序添加IP地址定位功能

本文介绍了如何在SpringBoot项目中整合ip2region库,利用注解和AOP技术实现在API接口请求中自动获取IP地址的地理位置信息,同时优化了查询性能,如vIndex索引缓存和xdb文件缓存以达到毫秒级查询响应。
摘要由CSDN通过智能技术生成

支持亿级别的 IP 数据段行数,默认的 region 信息都固定了格式:国家|区域|省份|城市|ISP,缺省的地域信息默认是0。region信息支持完全自定义,例如:你可以在 region 中追加特定业务需求的数据,例如:GPS信息/国际统一地域信息编码/邮编等。也就是你完全可以使用ip2region来管理你自己的IP定位数据。

基于xdb文件的查询,单次查询响应时间在十微秒级别,可通过如下两种方式开启内存加速查询:
1.vIndex索引缓存: 使用固定的512KiB的内存空间缓存vector index数据,减少一次IO磁盘操作,保持平均查询效率稳定在10-20微秒之间。

2.xdb整个文件缓存: 将整个xdb文件全部加载到内存,内存占用等同于xdb文件大小,无磁盘IO操作,保持微秒级别的查询效率。

本文主要介绍基于SpringBoot整合ip2region,利用注解AOP实现获取接口请求的IP所在地。

1、目录结构

目录结构
1、Ip: 作用在方法上的注解,用来标注需要获取ip所在城市的资源接口。
2、IpAop: 切面类,扫描方法上的Ip 注解,进行逻辑处理。
3、TestResource:资源接口,也就是要获取请求IP所在城市的接口。
4、IP2RegionUtilip2region 的工具类,加载iPhoneregion.xdb 文件,并提供方法,入参为IP地址,返回的参数为IP所在城市,格式为国家|区域|省份|城市|ISP
5、Ip2RegionApplication: 启动类。
6、ip2region.xdb: ip2region数据包。

2、maven 依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.2</version>
        <relativePath/>
    </parent>

    <groupId>com.caibw</groupId>
    <artifactId>ip2region</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>21</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.lionsoul</groupId>
            <artifactId>ip2region</artifactId>
            <version>2.7.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

3、编码实现

3.1、Ip注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @auth: caibw
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Ip {

}

3.2、IpAop切面类

package com.caibw.ip2region.aop;

import com.caibw.ip2region.utils.IP2RegionUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * @auth: caibw
 */
@Aspect
@Component
public class IpAop {

    private static final Logger log = LoggerFactory.getLogger(IpAop.class);

    private static final String UNKNOWN = "unknown";
    private HttpServletRequest request;
    private IP2RegionUtils ip2RegionUtils;

    public IpAop(HttpServletRequest request, IP2RegionUtils ip2RegionUtils) {
        this.request = request;
        this.ip2RegionUtils = ip2RegionUtils;
    }

    @Pointcut("@annotation(com.caibw.ip2region.annotations.Ip)")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint point) throws Throwable {
        String ipAddress = getIpAddress(request);
        String region = ip2RegionUtils.getRegion(ipAddress);
        // region格式:国家|区域|省份|城市|ISP
        log.info("ip:{},region:{}", ipAddress, region);
        return point.proceed();
    }

	// 获取 IP 地址
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        ip = "183.14.90.103";
        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;
    }
}

3.3、TestResource资源接口

import com.caibw.ip2region.annotations.Ip;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;

/**
 * @auth: caibw
 */
@RestController
public class TestResource {

    @Ip
    @GetMapping("test")
    public String test() {
        return "test:" + LocalDateTime.now();
    }
}

3.4、IP2RegionUtils工具类

import org.lionsoul.ip2region.xdb.Searcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;

/**
 * @auth: caibw
 */
@Component
public class IP2RegionUtils implements ApplicationRunner {

    private static final Logger log = LoggerFactory.getLogger(IP2RegionUtils.class);

    private static Searcher searcher = null;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        try {
            log.info("开始加载 ip2region 数据文件");
            InputStream inputStream = getClass().getClassLoader().getResourceAsStream("ip2region.xdb");
            byte[] bytes = new byte[inputStream.available()];
            inputStream.read(bytes);
            inputStream.close();
            searcher = Searcher.newWithBuffer(bytes);
            log.info("成功加载 ip2region 数据文件。");
        } catch (IOException e) {
            log.error("加载 ip2region 失败。{}",e.getMessage());
        }
    }

    public static String getRegion(String ip) {
        if (Objects.isNull(searcher)) {
            log.error("IP2RegionUtils 没有成功加载数据文件");
            return null;
        }
        try {
            return searcher.search(ip);
        } catch (Exception e) {
            log.error("IP 格式错误:{}",e.getMessage());
            return null;
        }
    }
}

3.5、ip2region.xdb 数据文件和源代码

在绑定资源中,免费下载。

  • 26
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

禅心小光头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值