一个困扰我很长时间的Bug,如图:
技术框架:Java+SpringBoot+Maven
功能背景:使用GeoLite2,获取ip所在的地区
事件回溯
- 下载[GeoLite2-Country.mmdb]文件
- 把文件放到resources下加载到java中
- 读取文件,并进行加载
- 报错:Could not find a MaxMind DB metadata marker in this file
- 代码为:
// 只允许中国的ip访问
private static final String[] ALLOWED_COUNTRIES = {"CN"}; // allowed countries
static DatabaseReader reader = null;
static {
try {
InputStream inputStream =
Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream("GeoLite2-Country.mmdb");
reader = new DatabaseReader.Builder(inputStream).build();
} catch (IOException e) {
log.error(e.getMessage(), e);
throw new ResponseJsonException(Errors.ERROR);
}
}
public static boolean isAllowed(String ipAddress) {
try {
// 读取文件
InetAddress inetAddress = InetAddress.getByName(ipAddress);
CountryResponse response = reader.country(inetAddress);
String countryCode = response.getCountry().getIsoCode();
for (String allowedCountry : ALLOWED_COUNTRIES) {
if (allowedCountry.equals(countryCode)) {
return true;
} else {
log.error("非国内ip,禁止访问,ip为{},国家为:{}", ipAddress, countryCode);
throw new ResponseJsonException(Errors.Error);
}
}
return false;
} catch (Exception e) {
log.error("isAllowed: {}", e.getMessage());
throw new ResponseJsonException(Errors.Error);
}
}
问题解决过程
在网上找了一堆解决办法,比如:
java - GeoLite2 database gets corrupt when added to jar - Stack Overflow
https://github.com/maxmind/MaxMind-DB-Reader-dotnet/issues/41
但是都没有解决我的问题,然后就一直找办法
...
...
然后找不到办法,就在本地debug了好久
突然我发现把[GeoLite2-Country.mmdb]文件,不放到项目里,就可以成功读取,但是不知道为什么
又开始debug
...
...
...
我又惊奇的发现,打包前和打包后,文件大小不一致
打包前是6.2M(打包前,文件在resources下)
打包后是9.6M(打包后,文件在target/classes下)
然后google一下,确实会有这个问题:「SpringBoot打包后,资源文件大小被更改」
但是不知道为啥,呜呜呜。有木有会的小伙伴,告诉我一下。
解决方案
解决方案其实很简单:
打包时排除资源文件即可,也就是:在pom文件中,增加过滤
代码片段为:
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>*.mmdb</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>*.mmdb</include>
</includes>
</resource>
完整代码为:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>*.mmdb</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>*.mmdb</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
<finalName>ROOT</finalName>
</build>