Ip2Resion线上部署报数据越界及错误处理

上篇在本地测试调用Ip2Resigon解析行政区划 Ip2Region的Java本地实现运行正常,但部署到测试环境,抛出数组越界(java.lang.ArrayIndexOutOfBoundsException)异常。
环境信息
ip2Resion是2.7版本,对应文件后缀为 xdb

一、代码展示

调用解析关键代码如下所示。

@Service
public class Ip2RegionService implements IIp2RegionService {

	/**
	 * 功能:通过ip转化行政区划 并发使用,用整个 xdb 数据缓存创建的查询对象可安全的用于并发,
	 * 把这个 searcher 对象做成全局对象去跨线程访问。
	 * @param ip
	 * @return
	 */
	@Override
	public Ip2RegionCommon getDistrictByIp(String ip) {
		logger.info("getDistrictByIp方法入参为:" + ip);
		String region = "未解析到位置信息";
		// 数据文件路径
		String dbPath = this.getClass().getClassLoader().getResource("xdb/ip2region.xdb").getPath();
		logger.info("getDistrictByIp获取的dbPath为:" + dbPath);
		long startTime = System.currentTimeMillis();
		try {
			byte[] cBuff = null;
			Searcher searcher;
			// 1、加载整个 xdb 到内存。
			 cBuff = Searcher.loadContentFromFile(dbPath);
			// 2、创建一个完全基于内存的查询对象。
			searcher = Searcher.newWithBuffer(cBuff);
			// 3、调用查询方法
			region = searcher.search(ip);
			long endTime = System.currentTimeMillis();
			// 4、关闭资源 - 该 searcher 对象可以安全用于并发,等整个服务关闭的时候再关闭 searcher
			logger.info("getDistrictByIp解析出来的region为:" + region);
			// searcher.close();
			logger.info("getDistrictByIp方法执行耗时:" + (endTime - startTime) + "ms");
		} catch (Exception e) {
			logger.info("getDistrictByIp 执行出错,错误信息为:%s",e.getMessage());
			logger.logException("getDistrictByIp 执行出错,错误信息为:%s", e);
		}
		return this.getReginResult(region);
	}
	
	/**
	 * 功能:转换结果
	 * 数据格式: 国家|区域|省份|城市|ISP
	 * 内网IP格式: 0|0|0|内网IP|内网IP
	 * @param region
	 * @return
	 */
	public Ip2RegionCommon getReginResult(String region) {
		Ip2RegionCommon info = new Ip2RegionCommon();
		if(region.contains("|")) {
			String[] split = StringUtils.split(region, "|");
			info.setDistrictCountry(split[0]);
			info.setDistrictProvince(this.suppleDistrict(split[2]));
			info.setDistrictCity(split[3]);
			info.setDistrictIsp(split[4]);
		}
		return info;
	}
	
	/**
	 * 功能:补全省份名称
	 * @param provinceName
	 * @return
	 */
	private String suppleDistrict(String provinceName) {
		String province = "省份未知";
		switch(provinceName) {
			case "北京" :
				province = "北京市";
				break;
			case "天津" :
				province = "天津市";
				break;
			case "上海" :
				province = "上海市";
				break;
			case "重庆" :
				province = "重庆市";
				break;
			case "广西" :
				province = "广西壮族自治区";
				break;
			case "西藏" :
				province = "西藏自治区";
				break;
			case "宁夏" :
				province = "宁夏回族自治区";
				break;
			case "新疆" :
				province = "新疆维吾尔自治区";
				break;
			case "黑龙江" :
				province = "黑龙江省";
				break;
			case "内蒙古" :
				province = "内蒙古自治区";
				break;
			default :
				province = provinceName;
		}
		return province;
	}
	
}

异常信息日志展示如下。
在这里插入图片描述

二、问题分析

从打印日志看数据xdb文件读取成功,searcher对象创建成功,进入search方法里,在arraycopy时报错。
猜想是Java启动时给的内存不足,加大内存未见好使;
取到ip地址在本地单元测试执行,顺利解析,应该不是ip地址的问题;
再次想会不会只是创建了searcher对象,没有读取到内容呢?于是在网上继续查找,终于看到码云上有说少配置,详细可见参考文档。
maven resources 拷贝文件是默认会做 filter,会导致数据文件发生变化,导致文件不能被读

三、处理方案

明确原因后,在Java打包的pom文件中添加以下内容。指定 nonFilteredFileExtension 格式为xdb,问题解决。

<plugins>
	<plugin>
		<artifactId>maven-resources-plugin</artifactId>
		<configuration>
			<nonFilteredFileExtensions>
				<nonFilteredFileExtension>xdb</nonFilteredFileExtension>
			</nonFilteredFileExtensions>
		</configuration>
	</plugin>
</plugins>
参考文档

【1】https://gitee.com/596392912/mica/blob/master/mica-ip2region/README.md

你可能感兴趣的:(数据处理,后端开发,java,ip)