Spring boot使用本地IP库遇坑总结 有更新!

  |   0 评论   |   11 浏览

一、前言

IP信息是很多项目中都要用到的,但是总会由于某些原因导致只能使用免费接口。但是免费意味着不稳定,意味着速度慢。
具体体现就是,以前我一个项目就是用的免费接口,但是我在最近却发现项目(Spring boot + Maven)经常报错。然后一看报错信息发现是ip信息接口的问题。
最后呢,实在没有办法。决定使用本地IP库

二、使用

开始我是打算直接使用官方的maven库的,但是我用的是Spring boot嘛。就去Maven仓库搜索了一下
1568015187174png

然后就看见了Spring boot的快速开始类库,顿时心里乐开了花。然后看了一下使用,哇,真简单。
项目GayHub地址
具体使用就是

1、导maven库

<dependency>
	<groupId>com.github.vindell</groupId>
	<artifactId>spring-boot-starter-ip2region</artifactId>
	<version>${project.version}</version>
</dependency>

2、在Spring boot启动类添加注解

@EnableIP2region

3、在需要使用的类使用

@Autowired
IP2regionTemplate template;

template.binarySearch("127.0.0.1");

//使用template.要使用的算法,算法有(b-tree、binary、Memory)
//具体如下
template.memorySearch();
template.btreeSearch();
template.binarySearch();

三、这篇文章是遇坑总结嘛,这么顺利怎么可能就完了呢?

使用Spring boot - starter是快,但是数据库文件不是按照官方提供的文件来更新的。而且作者好像很忙,没啥时间管这个库。好了,这个虽然用是能用。但是我就不喜欢容易查到错误数据的库。
那怎么办呢?像最开始一样啊,使用最开始的官方库。

3.1 使用官方库

官方maven库,遇坑开始。按理来说,官方库怎么会有坑呢?

<dependency>
    <groupId>org.lionsoul</groupId>
    <artifactId>ip2region</artifactId>
    <version>1.7.2</version>
</dependency>

官方库使用较为麻烦,要自己手写一个工具类。下面是来源于网络的一个工具类。

public class IPUtil {

    public static String getIPInfo(String ip){
         try {
            DbConfig config = new DbConfig();
            InputStream inputStream = getClass().getResourceAsStream("classpath:/ip2region.db");
            byte[] mybyte = IOUtils.toByteArray(inputStream);
            DbSearcher searcher = new DbSearcher(config, mybyte);
            DataBlock dataBlock =  searcher.memorySearch(ip);
            System.out.println(dataBlock.toString());
            return dataBlock.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null; 
    }
}

3.2 坑

哼哼,说了使用较为麻烦。如果一个工具类能够搞定就怪了。你的直觉是对的,下面就开始报错了。

Caused by: java.lang.ArrayIndexOutOfBoundsException: -1
    at org.lionsoul.ip2region.DbSearcher.btreeSearch(DbSearcher.java:208)
    at org.lionsoul.ip2region.DbSearcher.btreeSearch(DbSearcher.java:309)

看了报错后第一时间看源码库,看有没有人问过。好,找不到。自己查查原因,看了一下确实没办法搞定。接着上网搜。搞不定,隐约看到了,不能使用maven打包数据库文件。嘿,我真TM。。。这个作者都提供maven库了,为啥不在READEME文件中说明不能用maven打包呢?但是只是说不能用maven打包,好像跟我的情况也没啥关系。但是我已经搞不定了,所以去官方发了一个问题反馈。但是作者提示的却是不能放在classpath里面。这。。。我也是醉了。我要写一个web项目我不放classpath里面,难道每次都多复制一个文件?复制?对,每次启动项目时将文件复制出来就好了,随即我想到了将文件复制到临时目录。好下面开始临时目录复制工具类

public class IPUtil{
    public static String getIPInfo(String ip){
        DbConfig config = null;
            try {
                config = new DbConfig();

                File f = ResourceUtils.getFile("classpath:DBFile/ip2region.db");
                System.out.println(f.exists());

                File file = new File(System.getProperty("java.io.tmpdir")+"/ip2region.db");
                if (!file.exists()){
                    FileCopyUtils.copy(f,file);
                }

                DbSearcher searcher = new DbSearcher(config, f.getPath());
                DataBlock dataBlock =  searcher.btreeSearch(ip);
                System.out.println(dataBlock.toString());
                return dataBlock.toString();
            }
		}
}

3.3 坑坑

好,你以为到这里应该好了。其实并没有,还是一样的结果。然后我就想到了不能用maven打包,然后我就去临时目录看了一下文件竟然有11M那么大,而我下载的文件仅有6M。随后我意识到了这不是classpath的锅。这其实是Maven过滤文件的问题。因为我们在pom.xml里面设置了maven对资源文件的过滤。如下:

<build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>classpath:templates</directory>
                <includes>
                    <include>**/*</include>
                </includes>
            </resource>
        </resources>
</build>

Maven会过滤所有文件,可能会导致文件被破坏。那怎么办呢?我们又不能不过滤文件。那就只能借助一款Maven的插件。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <configuration>
        <nonFilteredFileExtensions>
            <!-- 此处配置不需要过滤的文件的后缀名 -->
            <nonFilteredFileExtension>db</nonFilteredFileExtension>
            <nonFilteredFileExtension>dat</nonFilteredFileExtension>
        </nonFilteredFileExtensions>
    </configuration>
</plugin>

好了,到此为止,坑已经碰完了。我们已经能够使用这个本地库+它的查询算法了。

评论