一.功能介紹
?
通過(guò)傳入的IP地址,返回IP所在的地理位置。如傳入“58.16.209.19”,返回“貴州省六盤水市 ”。
?返回的地理位置又分為3種精確度,程序可以按照自身需要選擇。三種精確度分別為:地區(qū)(省直轄市級(jí)),城市(地市級(jí)),詳細(xì)位置。例如對(duì)于“58.16.209.19”,三種精度的值為:
?- 地區(qū):貴州?????
- 城市:貴州省六盤水市????
- 詳細(xì)地址:六枝特區(qū)騰龍網(wǎng)吧??
二.3行代碼實(shí)現(xiàn)地域查詢?- ??
- IPLocationService?ipService?=?(IPLocationService)?GuzzWebApplicationContextUtil.getGuzzContext(session.getServletContext()).getService("IPService")?;??
- ??
- ??
- LocationResult?result?=?(LocationResult)?ipService.findLocation("58.16.209.19").get()?;??
- ??
- ??
- System.out.println("城市:"?+?result.cityName)?;??
三.性能如何??上面的第1步需要獲取IP反查服務(wù),此服務(wù)有3個(gè)實(shí)現(xiàn)客戶端,一個(gè)為遠(yuǎn)程方法調(diào)用(phprpc協(xié)議實(shí)現(xiàn),類似hessian的一個(gè)協(xié)議),一個(gè)是socket長(zhǎng)連接,一個(gè)nio。
?針對(duì)這兩種實(shí)現(xiàn),在內(nèi)網(wǎng)下進(jìn)行性能測(cè)試。測(cè)試方法:?jiǎn)尉€程,串行執(zhí)行查詢請(qǐng)求。查詢IP:59.66.106.0,返回地理位置:清華大學(xué)。
?性能測(cè)試結(jié)果:?PHPRPC實(shí)現(xiàn):執(zhí)行1000次查詢,耗時(shí)1339ms。
?Socket實(shí)現(xiàn):執(zhí)行1000次查詢,耗時(shí)84ms;執(zhí)行10000次查詢,耗時(shí)843ms。
?NIO socket實(shí)現(xiàn):執(zhí)行1000次查詢,耗時(shí)115ms;執(zhí)行10000次查詢,耗時(shí)1247ms。
?Socket長(zhǎng)連接模式為連接池實(shí)現(xiàn),可以配置多個(gè)socket并行計(jì)算。對(duì)于絕大部分的應(yīng)用,應(yīng)該都能滿足要求。PHPRPC為短連接,每次查詢都建立一個(gè)http連接進(jìn)行查詢。
?四.如何配置到我的系統(tǒng)中??上面的IP反查為guzz的服務(wù),因此需要應(yīng)用程序首先將guzz框架配置進(jìn)去。Guzz框架不具有應(yīng)用侵入性,不會(huì)影響現(xiàn)有系統(tǒng)運(yùn)轉(zhuǎn)。配置方法:
http://code.google.com/p/guzz/wiki/TutorialConfig?Guzz框架整合完畢后,只需要將IP反查服務(wù)在guzz中聲明即可。聲明包含3步(以socket的IP服務(wù)為例):
?1. 將IP反查的實(shí)現(xiàn)jar包放到項(xiàng)目lib中。Jar包在附件中,包含源代碼。
?2. 在guzz.xml中增加此服務(wù):
?- <service?name="IPService"?configName="fundIPServiceSocketClient"?class="org.guzz.service.dir.impl.socket.IPLocationServiceSocketClientImpl"?/>??
3. 配置服務(wù)參數(shù)(guzz的properties文件):
?- [fundIPServiceSocketClient]??
- pool.maxActive=5??
- host=services.guzz.org??
- port=11546??
參數(shù)中包含連接池大小,服務(wù)地址和端口。
?配置完服務(wù)以后,就可以按照上一節(jié)的方式進(jìn)行IP反查了。如附件中的示例jsp實(shí)現(xiàn)。
?五.LocationResult介紹?執(zhí)行查詢時(shí),返回的是LocationResult對(duì)象,此對(duì)象有一些方法和變量按照不同精確度和用途存儲(chǔ)地理信息。LocationResult介紹:
?- ??????
- public?class?LocationResult?implements?Serializable?{??
- ??????
- ??????
- ????public?String?cityMarker?;??
- ??
- ??????
- ????public?String?cityName?;??
- ??????
- ??????
- ????public?String?detailLocation?;??
- ??????
- ??????
- ????public?String?areaName?;??
- ??????
- ?????
- ?
- ??
- ????public?String?getMarkedCityName(){??
- ????????if(cityMarker?==?null){??
- ????????????return?cityName?;???
- ????????}else{??
- ????????????return?cityMarker?+?cityName?;??
- ????????}??
- ????}??
- ??????
- ????public?String?toString(){??
- ????????StringBuilder?sb?=?new?StringBuilder()?;??
- ????????sb.append("cityMarker:").append(cityMarker)??
- ??????????.append("cityName:").append(cityName)??
- ??????????.append("detailLocation:").append(detailLocation)??
- ??????????.append("areaName:").append(areaName)?;??
- ??????????
- ????????return?sb.toString()?;??
- ????}??
- ??????
- ????}??
六.我的查詢請(qǐng)求不多,如何配置phprpc方式的查詢(不需要保持socket連接池)??第1步:在系統(tǒng)中配置phprpc框架。詳細(xì)請(qǐng)參看:
http://phprpc.org?第2步:將剛才guzz.xml中IPService服務(wù)換成PHPRPC實(shí)現(xiàn):
?- <service?name="IPService"?configName="fundIPServiceClient"?class="org.guzz.service.dir.impl.IPLocationServiceClientImpl"?/>??
第3步:配置服務(wù)參數(shù)(properties文件):
?- [fundIPServiceClient]??
- rpc.protocol=phprpc??
- rpc.serviceURL=http://services.guzz.org/service/IPService??
七.其他:?1.
?JDK1.6+。如果使用JDK1.5,將源代碼在1.5下編譯即可。
?2.
?沒看明白如何配置服務(wù)? 看這里:
http://code.google.com/p/guzz/wiki/TutorialService?3.
?IP反查可不可以異步執(zhí)行? 可以。ipService.findLocation(ip)返回的就是異步接口,在需要的時(shí)候調(diào)用get()即可;異步方法也支持超時(shí),調(diào)用getOrCancel(5L, TimeUnit.SECONDS)可以讓接口最多等待5秒,隨后超時(shí)返回null。如果服務(wù)端故障,ipService.findLocation(ip)返回null。
?4.
?為什么會(huì)返回null? 沒有查詢到就返回null,null也很有用,如網(wǎng)易評(píng)論中的“火星網(wǎng)友”。
?5.
?支持spring IOC嗎??支持。如果使用spring,IPService可以通過(guò)spring bean配置并進(jìn)行注入。這樣只需要2行代碼即可。
?