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;
}
}