1. 问题描述
在springboot项目中集成ip2region包,一开始参考了《崛起于Springboot2.X之集成ip2region(31) 》文章,运行测试都没有问题,在此感谢作者的倾情奉献。
但项目打成可执行的jar包后再运行,却显示找不到ip2region.db,经调试后发现
String dbPath = IpUtil.class.getResource("/ip2region/ip2region.db").getPath();
返回的路径如下:
file:/D:/ws_java/esl/yunque-fs/target/demo2-0.0.3-SNAPSHOT.jar!/BOOT-INF/classes!/ip2region/ip2region.db
这个路径很显然无法被io读取,所以造成了无法找到资源文件的错误。
2. 解决办法
虽然绝对路径无法使用,但仍然可以获取到文件内容,代码如下:
IpUtil.class.getClassLoader().getResourceAsStream("classpath:ip2region/ip2region.db")
那么就可以把文件内容存储到一个临时文件中,这样就可以直接使用新的临时文件了。
具体代码如下:
String dbPath = IpUtil.class.getResource("/ip2region/ip2region.db").getPath();
System.out.println(dbPath);
File file = new File(dbPath);
if (file.exists() == false) {
String tmpDir = System.getProperties().getProperty("java.io.tmpdir");
dbPath = tmpDir + "ip.db";
System.out.println(dbPath);
file = new File(dbPath);
FileUtils.copyInputStreamToFile(IpUtil.class.getClassLoader().getResourceAsStream("classpath:ip2region/ip2region.db"), file);
}
在windows上临时目录如下:
C:\Users\ADMINI~1\AppData\Local\Temp\ip.db
这样就可以解决找不到资源文件的问题了。
3. 完整代码
public class IpUtil {
public static String getCityInfo(String ip){
try {
//db
String dbPath = IpUtil.class.getResource("/ip2region/ip2region.db").getPath();
System.out.println(dbPath);
File file = new File(dbPath);
if (file.exists() == false) {
String tmpDir = System.getProperties().getProperty("java.io.tmpdir");
dbPath = tmpDir + "ip.db";
System.out.println(dbPath);
file = new File(dbPath);
FileUtils.copyInputStreamToFile(IpUtil.class.getClassLoader().getResourceAsStream("classpath:ip2region/ip2region.db"), file);
}
//查询算法
int algorithm = DbSearcher.BTREE_ALGORITHM; //B-tree
//DbSearcher.BINARY_ALGORITHM //Binary
//DbSearcher.MEMORY_ALGORITYM //Memory
try {
DbConfig config = new DbConfig();
DbSearcher searcher = new DbSearcher(config, dbPath);
//define the method
Method method = null;
switch (algorithm) {
case DbSearcher.BTREE_ALGORITHM:
method = searcher.getClass().getMethod("btreeSearch", String.class);
break;
case DbSearcher.BINARY_ALGORITHM:
method = searcher.getClass().getMethod("binarySearch", String.class);
break;
case DbSearcher.MEMORY_ALGORITYM:
method = searcher.getClass().getMethod("memorySearch", String.class);
break;
}
DataBlock dataBlock = null;
if (Util.isIpAddress(ip) == false) {
System.out.println("Error: Invalid ip address");
}
dataBlock = (DataBlock) method.invoke(searcher, ip);
return dataBlock.getRegion();
} catch (Exception e) {
e.printStackTrace();
}
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
}