免费好用的 ip 地址查询工具

0 概述

  • 不知道各位有没有好奇过,下图这个效果是怎么做到的呢?
    在这里插入图片描述

  • 想要知道一个位置信息,要么就是使用 GPS,要么就是使用 IP 地址查询。但是 GPS 定位获取地址的前提是要打开它,IP 地址查询有在线查询,也有离线查询,我现在要介绍的这款工具,就是一个离线的 IP 地址库,名为:ip2region

  • 它是一款很好用的离线 IP 地址定位库和 IP 定位数据管理框架,支持国内和国外的 IP 查询,Gitee 上已有 7.4K stars

  • Gitee 地址:仓库地址

1 快速上手

  • 我们已经了解了 ip2region 了,现在我们开始写一个 demo 测试一下
  • 测试开始前,首先需要到上述仓库地址中,拉取代码到本地,进入 data 文件夹,把 ip2region.xdb 文件复制到 SpringBoot 项目中的 resources 资源目录下
    在这里插入图片描述

    补充:直接获取 ip2region.xbd 文件,可以关注微信公众号:EzCoding,回复 ip 即可获取

  • 引入依赖
    <dependency>
       <groupId>org.lionsoul</groupId>
       <artifactId>ip2region</artifactId>
       <version>2.6.5</version>
    </dependency>
    
    <!-- 以下依赖在后续测试时会使用,与 ip2region 本身无关 -->
    <dependency>
       <groupId>commons-io</groupId>
       <artifactId>commons-io</artifactId>
       <version>2.6</version>
    </dependency>
    <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
       <optional>true</optional>
    </dependency>
    <dependency>
       <groupId>cn.hutool</groupId>
       <artifactId>hutool-all</artifactId>
       <version>5.8.7</version>
    </dependency>
    
  • 测试 IP 、测试代码
    在这里插入图片描述
    import lombok.extern.slf4j.Slf4j;
    import org.lionsoul.ip2region.xdb.Searcher;
    import java.io.File;
    import java.util.Objects;
    
    /**
     * 测试demo
     *
     * @Author Jasper
     * @Time 2024/02/20
     * @公众号:EzCoding
     */
    @Slf4j
    public class Ip2RegionUtil {
    
        public static String getCityInfo(String ip) {
            String dbPath = Objects.requireNonNull(Ip2RegionUtil.class.getResource("/ip2region.xdb")).getPath();
            File file = new File(dbPath);
            if (file.exists()) {
                try {
                    // 创建查询对象
                    Searcher searcher = Searcher.newWithFileOnly(dbPath);
                    return searcher.search(ip);
                } catch (Exception e) {
                    log.error("异常:{}", e.getMessage(), e);
                }
            }
            return "";
        }
    
        public static void main(String[] args) {
            System.out.println(getCityInfo("127.0.0.1"));
            System.out.println(getCityInfo("186.63.44.21"));
        }
    }
    
  • 输出结果如下:
    0|0|0|内网IP|内网IP
    阿根廷|0|0|0|西班牙电信
    

2 整合到项目中

  • 通过上述 demo 演示,已初步掌握了 ip2region 的使用,那么如何整合到项目里呢?如何知道用户一访问就知道用户的 IP 地址呢?
  • 如果直接在每个接口或需要记录 IP 的接口都引入这个方法的话,耦合太高,并且增加了代码的复杂度和冗余度,因此推荐使用通过 自定义注解 + AOP 的方式来实现整合。
  • step1、定义一个自定义注解
    import java.lang.annotation.*;
    
    /**
     * 自定义注解
     *
     * @Author Jasper
     * @Time 2024/02/20
     * @公众号:EzCoding
     */
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface Ip {
    
    }
    
  • step2、定义切面
    import cn.hutool.json.JSONUtil;
    import lombok.extern.slf4j.Slf4j;
    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.springframework.stereotype.Component;
    import javax.servlet.http.HttpServletRequest;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 切面
     *
     * @Author Jasper
     * @Time 2024/02/20
     * @公众号:EzCoding
     */
    @Aspect
    @Component
    @Slf4j
    public class IpAspect {
    
        @Pointcut("@annotation(com.example.demo.ip2regin.Ip)")
        public void pointcut(){
    
        }
    
        @Around("pointcut()")
        public Object doAround(ProceedingJoinPoint joinPoint){
            HttpServletRequest request = HttpContextUtil.getHttpServletRequest();
            Map<String, Object> map = new HashMap<>();
            String ip = IpUtil.getIpAddr(request);
            try {
                String cityInfo = Ip2RegionUtil.getCityInfo(ip);
                joinPoint.proceed();
                map.put("ip", ip);
                map.put("cityInfo", cityInfo);
            } catch (Throwable e) {
                log.error("切面获取ip异常:{}", e.getMessage(), e);
            }
            return JSONUtil.toJsonStr(map);
        }
    
    }
    
  • step3、使用到的工具类
    import javax.servlet.http.HttpServletRequest;
    
    public class IpUtil {
    
        private static final String UNKNOWN = "unknown";
    
        protected IpUtil() {
    
        }
    
        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;
        }
    }
    
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.Objects;
    
    public class HttpContextUtil {
    
        private HttpContextUtil() {
    
        }
    
        public static HttpServletRequest getHttpServletRequest() {
            return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        }
    
        public static HttpServletResponse getHttpServletResponse() {
            return ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getResponse();
        }
    }
    
  • step4、Controller 层
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    /**
    * Controller 层
    *
    * @Author Jasper
    * @Time 2024/02/20
    * @公众号:EzCoding
    */
    @RestController
    @RequestMapping("/ip2region")
    public class Ip2RegionController {
    
        @GetMapping("/test")
        @Ip
        public String test(){
            return "hello ip2region";
        }
    }
    
  • step5、访问测试
    在这里插入图片描述

  • 以上就是有关 ip2region 的全部内容了,赶快收藏起来以备不时之需。
  • 创作不易,感谢阅读,若您喜欢这篇文章,不妨传承这份知识的力量,点个赞或关注我吧~
  • 微信公众号:EzCoding
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值