青島鑫隆建設(shè)集團(tuán)網(wǎng)站網(wǎng)絡(luò)推廣山東
上篇在本地測(cè)試調(diào)用Ip2Resigon解析行政區(qū)劃 Ip2Region的Java本地實(shí)現(xiàn)運(yùn)行正常,但部署到測(cè)試環(huán)境,拋出數(shù)組越界(java.lang.ArrayIndexOutOfBoundsException)異常。
環(huán)境信息
ip2Resion是2.7版本,對(duì)應(yīng)文件后綴為 xdb。
一、代碼展示
調(diào)用解析關(guān)鍵代碼如下所示。
@Service
public class Ip2RegionService implements IIp2RegionService {/*** 功能:通過(guò)ip轉(zhuǎn)化行政區(qū)劃 并發(fā)使用,用整個(gè) xdb 數(shù)據(jù)緩存創(chuàng)建的查詢對(duì)象可安全的用于并發(fā),* 把這個(gè) searcher 對(duì)象做成全局對(duì)象去跨線程訪問(wèn)。* @param ip* @return*/@Overridepublic Ip2RegionCommon getDistrictByIp(String ip) {logger.info("getDistrictByIp方法入?yún)?" + ip);String region = "未解析到位置信息";// 數(shù)據(jù)文件路徑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、加載整個(gè) xdb 到內(nèi)存。cBuff = Searcher.loadContentFromFile(dbPath);// 2、創(chuàng)建一個(gè)完全基于內(nèi)存的查詢對(duì)象。searcher = Searcher.newWithBuffer(cBuff);// 3、調(diào)用查詢方法region = searcher.search(ip);long endTime = System.currentTimeMillis();// 4、關(guān)閉資源 - 該 searcher 對(duì)象可以安全用于并發(fā),等整個(gè)服務(wù)關(guān)閉的時(shí)候再關(guān)閉 searcherlogger.info("getDistrictByIp解析出來(lái)的region為:" + region);// searcher.close();logger.info("getDistrictByIp方法執(zhí)行耗時(shí):" + (endTime - startTime) + "ms");} catch (Exception e) {logger.info("getDistrictByIp 執(zhí)行出錯(cuò),錯(cuò)誤信息為:%s",e.getMessage());logger.logException("getDistrictByIp 執(zhí)行出錯(cuò),錯(cuò)誤信息為:%s", e);}return this.getReginResult(region);}/*** 功能:轉(zhuǎn)換結(jié)果* 數(shù)據(jù)格式: 國(guó)家|區(qū)域|省份|城市|ISP* 內(nèi)網(wǎng)IP格式: 0|0|0|內(nèi)網(wǎng)IP|內(nèi)網(wǎng)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;}/*** 功能:補(bǔ)全省份名稱* @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 = "廣西壯族自治區(qū)";break;case "西藏" :province = "西藏自治區(qū)";break;case "寧夏" :province = "寧夏回族自治區(qū)";break;case "新疆" :province = "新疆維吾爾自治區(qū)";break;case "黑龍江" :province = "黑龍江省";break;case "內(nèi)蒙古" :province = "內(nèi)蒙古自治區(qū)";break;default :province = provinceName;}return province;}}
異常信息日志展示如下。
二、問(wèn)題分析
從打印日志看數(shù)據(jù)xdb文件讀取成功,searcher對(duì)象創(chuàng)建成功,進(jìn)入search方法里,在arraycopy時(shí)報(bào)錯(cuò)。
猜想是Java啟動(dòng)時(shí)給的內(nèi)存不足,加大內(nèi)存未見(jiàn)好使;
取到ip地址在本地單元測(cè)試執(zhí)行,順利解析,應(yīng)該不是ip地址的問(wèn)題;
再次想會(huì)不會(huì)只是創(chuàng)建了searcher對(duì)象,沒(méi)有讀取到內(nèi)容呢?于是在網(wǎng)上繼續(xù)查找,終于看到碼云上有說(shuō)少配置,詳細(xì)可見(jiàn)參考文檔。
maven resources 拷貝文件是默認(rèn)會(huì)做 filter,會(huì)導(dǎo)致數(shù)據(jù)文件發(fā)生變化,導(dǎo)致文件不能被讀。
三、處理方案
明確原因后,在Java打包的pom文件中添加以下內(nèi)容。指定 nonFilteredFileExtension 格式為xdb,問(wèn)題解決。
<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