使用ip2region数据库

This commit is contained in:
2023-11-22 17:17:05 +08:00
parent 5e04d06e7c
commit 92adee5e57
4 changed files with 48 additions and 84 deletions

View File

@@ -1,29 +1,22 @@
package cn.lihongjie.coal.ip;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.model.CityResponse;
import jakarta.annotation.PostConstruct;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.*;
import java.net.InetAddress;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
@Service
@Slf4j
@@ -37,84 +30,38 @@ class IpQueryService {
private String geolite2DownloadUrl;
private DatabaseReader reader;
@Value("classpath:ip/ip2region.xdb")
Resource dbFile;
private Searcher searcher;
private static boolean isPrivateAddress(InetAddress inetAddress) {
byte[] addressBytes = inetAddress.getAddress();
int byte1 = addressBytes[0] & 0xff;
int byte2 = addressBytes[1] & 0xff;
return (byte1 == 10) ||
(byte1 == 172 && (byte2 >= 16 && byte2 <= 31)) ||
(byte1 == 192 && byte2 == 168);
}
@SneakyThrows
public static void main(String[] args){
System.out.println(isPrivateAddress(InetAddress.getByName("192.168.0.1")));
}
@SneakyThrows
@PostConstruct
public void init() {
log.info("开始初始化GeoLite2-City本地数据库");
Path dbPath = Path.of("./GeoLite2-City/GeoLite2-City.mmdb");
Path dbDir = dbPath.getParent();
if (Files.notExists(dbDir)) {
Files.createDirectories(dbDir);
// 2、使用上述的 cBuff 创建一个完全基于内存的查询对象。
try {
searcher = Searcher.newWithBuffer(dbFile.getContentAsByteArray());
} catch (Exception e) {
log.warn("failed to new searcher with buffer", e);
return;
}
if (Files.exists(dbPath)) {
log.info("发现默认数据库文件: {}", dbPath);
} else if (StringUtils.isNotEmpty(environment.getProperty("geolite2.city.path"))) {
dbPath = Path.of(environment.getProperty("geolite2.city.path"));
log.info("发现环境变量数据库文件: {}", dbPath);
} else {
log.info("没有找到数据库文件, 下载数据库文件");
File downloadPath = dbPath.getParent().resolve("GeoLite2-City.tar.gz").toFile();
FileUtils.copyURLToFile(
new URL(geolite2DownloadUrl), downloadPath, 10 * 1000, 30 * 1000);
TarArchiveInputStream tarIn =
new TarArchiveInputStream(
new GzipCompressorInputStream(
new BufferedInputStream(new FileInputStream(downloadPath))));
TarArchiveEntry tarEntry = tarIn.getNextTarEntry();
Path newDbFile = null;
// tarIn is a TarArchiveInputStream
while (tarEntry != null) { // create a file with the same name as the tarEntry
File destPath = dbDir.resolve(tarEntry.getName()).toFile();
log.info(destPath.toString());
if (tarEntry.isDirectory()) {
destPath.mkdirs();
} else {
destPath.createNewFile();
if (destPath.getName().endsWith("mmdb")) {
newDbFile = destPath.toPath();
}
// byte [] btoRead = new byte[(int)tarEntry.getSize()];
byte[] btoRead = new byte[1024];
// FileInputStream fin
// = new FileInputStream(destPath.getCanonicalPath());
BufferedOutputStream bout =
new BufferedOutputStream(new FileOutputStream(destPath));
int len = 0;
while ((len = tarIn.read(btoRead)) != -1) {
bout.write(btoRead, 0, len);
}
bout.close();
btoRead = null;
}
tarEntry = tarIn.getNextTarEntry();
}
tarIn.close();
if (newDbFile != null) {
Files.move(newDbFile, dbPath);
}
}
reader = new DatabaseReader.Builder(dbPath.toFile()).build();
log.info("加载 ip2region.db 成功");
}
@SneakyThrows
@@ -122,14 +69,21 @@ class IpQueryService {
if (reader != null) {
InetAddress ipAddress = InetAddress.getByName(ipaddr);
boolean siteLocalAddress = ipAddress.isSiteLocalAddress();
if (siteLocalAddress) {
if (ipAddress.isAnyLocalAddress()) {
return "服务器本机地址";
}
if (ipAddress.isLoopbackAddress()) {
return "本地回环地址";
}
if (isPrivateAddress(ipAddress)) {
return "内网地址";
}
try {
CityResponse city = reader.city(ipAddress);
return city.getCountry().getName() + city.getCity().getName();
String search = searcher.search(ipaddr);
return search.replace("|0|", "").replace("|", "");
} catch (Exception e) {
return "";
}

Binary file not shown.