锁定老帖子 主题:3行代码,实现IP到地理位置的反查功能
精华帖 (2) :: 良好帖 (5) :: 新手帖 (6) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-06-22
最后修改:2010-06-22
一.功能介绍
通过传入的IP地址,返回IP所在的地理位置。如传入“58.16.209.19”,返回“贵州省六盘水市 ”。 返回的地理位置又分为3种精确度,程序可以按照自身需要选择。三种精确度分别为:地区(省直辖市级),城市(地市级),详细位置。例如对于“58.16.209.19”,三种精度的值为: 地区:贵州 城市:贵州省六盘水市 详细地址:六枝特区腾龙网吧 二.3行代码实现地域查询 //第1行,获取IP反查服务(JSP中写的) IPLocationService ipService = (IPLocationService) GuzzWebApplicationContextUtil.getGuzzContext(session.getServletContext()).getService("IPService") ; //第2行,执行查询。findLocation方法传入要查询的IP地址。 LocationResult result = (LocationResult) ipService.findLocation("58.16.209.19").get() ; //第3行,按照精确度要求,读取地理位置 System.out.println("城市:" + result.cityName) ; 三.性能如何? 上面的第1步需要获取IP反查服务,此服务有3个实现客户端,一个为远程方法调用(phprpc协议实现,类似hessian的一个协议),一个是socket长连接,一个nio。 针对这两种实现,在内网下进行性能测试。测试方法:单线程,串行执行查询请求。查询IP:59.66.106.0,返回地理位置:清华大学。 性能测试结果: PHPRPC实现:执行1000次查询,耗时1339ms。 Socket实现:执行1000次查询,耗时84ms;执行10000次查询,耗时843ms。 NIO socket实现:执行1000次查询,耗时115ms;执行10000次查询,耗时1247ms。 Socket长连接模式为连接池实现,可以配置多个socket并行计算。对于绝大部分的应用,应该都能满足要求。PHPRPC为短连接,每次查询都建立一个http连接进行查询。 四.如何配置到我的系统中? 上面的IP反查为guzz的服务,因此需要应用程序首先将guzz框架配置进去。Guzz框架不具有应用侵入性,不会影响现有系统运转。配置方法:http://code.google.com/p/guzz/wiki/TutorialConfig Guzz框架整合完毕后,只需要将IP反查服务在guzz中声明即可。声明包含3步(以socket的IP服务为例): 1. 将IP反查的实现jar包放到项目lib中。Jar包在附件中,包含源代码。 2. 在guzz.xml中增加此服务: <service name="IPService" configName="fundIPServiceSocketClient" class="org.guzz.service.dir.impl.socket.IPLocationServiceSocketClientImpl" /> 3. 配置服务参数(guzz的properties文件): [fundIPServiceSocketClient] pool.maxActive=5 host=services.guzz.org port=11546 参数中包含连接池大小,服务地址和端口。 配置完服务以后,就可以按照上一节的方式进行IP反查了。如附件中的示例jsp实现。 五.LocationResult介绍 执行查询时,返回的是LocationResult对象,此对象有一些方法和变量按照不同精确度和用途存储地理信息。LocationResult介绍: public class LocationResult implements Serializable { /**如:对于国外地区,值为“海外”;对于cityName中不包含省市信息的,如“清华大学”,值为地区名称,如“北京”*/ 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() ; } } 六.我的查询请求不多,如何配置phprpc方式的查询(不需要保持socket连接池)? 第1步:在系统中配置phprpc框架。详细请参看:http://phprpc.org 第2步:将刚才guzz.xml中IPService服务换成PHPRPC实现: <service name="IPService" configName="fundIPServiceClient" class="org.guzz.service.dir.impl.IPLocationServiceClientImpl" /> 第3步:配置服务参数(properties文件): [fundIPServiceClient] rpc.protocol=phprpc rpc.serviceURL=http://services.guzz.org/service/IPService 七.其他: 1. JDK1.6+。如果使用JDK1.5,将源代码在1.5下编译即可。 2. 没看明白如何配置服务? 看这里:http://code.google.com/p/guzz/wiki/TutorialService 3. IP反查可不可以异步执行? 可以。ipService.findLocation(ip)返回的就是异步接口,在需要的时候调用get()即可;异步方法也支持超时,调用getOrCancel(5L, TimeUnit.SECONDS)可以让接口最多等待5秒,随后超时返回null。如果服务端故障,ipService.findLocation(ip)返回null。 4. 为什么会返回null? 没有查询到就返回null,null也很有用,如网易评论中的“火星网友”。 5. 支持spring IOC吗? 支持。如果使用spring,IPService可以通过spring bean配置并进行注入。这样只需要2行代码即可。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-06-22
如果客户电脑上不了网,还能起作用吗?
工作原理好像是,客户将ip送到services.guzz.org:11546,你们那再解析,最后将解析结果返送回来, 如果这样,觉着还是安装ocx好一点 |
|
返回顶楼 | |
发表时间:2010-06-22
duronshi 写道 如果客户电脑上不了网,还能起作用吗?
工作原理好像是,客户将ip送到services.guzz.org:11546,你们那再解析,最后将解析结果返送回来, 如果这样,觉着还是安装ocx好一点 要是这样,直接提供一个rest服务多好。 |
|
返回顶楼 | |
发表时间:2010-06-22
hareamao 写道 duronshi 写道 如果客户电脑上不了网,还能起作用吗?
工作原理好像是,客户将ip送到services.guzz.org:11546,你们那再解析,最后将解析结果返送回来, 如果这样,觉着还是安装ocx好一点 要是这样,直接提供一个rest服务多好。 有phprpc的实现,短连接方式,http请求,类似于rest。不过速度比socket连接池比要慢很多(15倍)。对于性能要求比较高的应用不大适合。 |
|
返回顶楼 | |
发表时间:2010-06-22
duronshi 写道 如果客户电脑上不了网,还能起作用吗?
工作原理好像是,客户将ip送到services.guzz.org:11546,你们那再解析,最后将解析结果返送回来, 如果这样,觉着还是安装ocx好一点 services.guzz.org:11546只是一个服务端,在内网部署或者自己实现一个即可。 地址,端口,协议都是可以控制的。 |
|
返回顶楼 | |
发表时间:2010-06-22
什么搜索三行代码,这个没有意义的,这是个噱头。愿意的话,一行代码也是可以的。
关键还是IP的这个地址映射是否全面,准确。 |
|
返回顶楼 | |
发表时间:2010-06-22
dmqianlicao 写道 什么搜索三行代码,这个没有意义的,这是个噱头。愿意的话,一行代码也是可以的。
关键还是IP的这个地址映射是否全面,准确。 纯真IP数据库,一共有37万多个IP段,应该是免费IP库中能找到的最精确的了。 |
|
返回顶楼 | |
发表时间:2010-06-22
我们公司还是用的收费IP 库,都有误差,更何况免费的
|
|
返回顶楼 | |
发表时间:2010-06-23
love_ai87 写道 我们公司还是用的收费IP 库,都有误差,更何况免费的
恩,准确度的确要靠IP库。收费IP据我了解一般每个月更新一次,很麻烦。你们每个系统更新一遍还是有一个集中的地方,只在1个地方做1次更新? 我的这种实现方式可以确保无论多少系统使用,只在1个地方更新就行了,而且使用的系统开发也非常简单,只要几行代码。对于IP库,这个是可以随时升级和调整的;如果大企业使用,要求更精确,可以在内网部署一套服务端,将IP库换成付费版本就行了。 |
|
返回顶楼 | |
发表时间:2010-06-23
|
|
返回顶楼 | |