Google Maps API 初体验

最近真不知道干什么好了,想什么都学,但什么都学不好,不过体验了一把Google Maps API感觉不错,Google真的是太强悍了,也许就是我未来的目标吧。

进行GMapAPI开发首先得申请Google Maps API密钥,http://code.google.com/intl/zh-CN/apis/maps/里有详细的入门说明,在获得密钥之后就可以开始开发之旅了,我首先按照Google提供的开发人员指南进行基础知识的学习,然后就照着书上的例子做了个IP地理位置可视化查询系统,虽然很简单但却非常有趣。

首先需要下载IP数据库和相关API,我选择的是MaxMind的免费GeoLiteCity数据库并且有丰富的API支持,GeoLiteCity数据库下载地址为http://www.maxmind.com/download/geoip/database/,选择下载GeoLiteCity.dat.gz并解压,同时下载官方提供的APIhttp://www.maxmind.com/download/geoip/api/,可以选择自己擅长的开发语言,我选择的是Java API,开发环境是MyEclipse6.6。

地图定位查询主要分为两个步骤,第一,获取待查询的IP;第二,利用MaxMind API进行查询并返回查询结果。在MyEclipse中新建一个Web Project,导入下载得到的GeoIPJava-1.2.3 API,同时将IP数据库文件GeoLiteCity.dat放置在WebRoot下。

服务器端使用JSP,以下是search.jsp中<body>元素的Java代码:

 <body>
    <%
     //获得用户请求查询的数据
     String queryString = (String)request.getParameter("q");
     PrintWriter outWriter;
     String ip = "";
  //如果查询数据为空则返回主机地址
  if (queryString == null || queryString.equals("")) {
   ip = InetAddress.getLocalHost().toString();
   if (ip == null || ip.equals(""))
    System.out.println("Cannot get your IP address!");
  }
  else {
   //用正则表达式检验查询数据是否为有效IP
   String pattern = "^(//d{1,3}//.//d{1,3}//.//d{1,3}//.//d{1,3})$";
   if (queryString.matches(pattern)) {
    ip = queryString;
    System.out.println("The IP address is valid.");
   }
   //如果无效则验证查询数据是否为有效域名
   else {
    try {
     ip = InetAddress.getByName(queryString).toString();
     ip = ip.split("/")[1];
     if (!ip.matches(pattern)){
      System.out.println("Invalid domain!");
      response.setContentType("text/xml");
      response.setCharacterEncoding("utf-8");
      outWriter = response.getWriter();
      outWriter.print("alert('Invalid domain!')");
     }
    }
    catch (UnknownHostException e) {
     System.out.println("Invalid domain!");
    }
   }
  }
  try {
   //建立LookupService实例开始查询
   LookupService query = new LookupService("./GeoLiteCity.dat", LookupService.GEOIP_STANDARD);
   Location location = query.getLocation(ip);
   //返回查询结果,包括IP地址位置的国家名称和代码,地区,城市以及经纬度
   if (location != null) {
    String responseText = "loadGeoInfo('" + queryString + "', '" + ip + "', '"
     + location.countryCode + "', '" + location.countryName + "', '"
     + location.region + "', '" + location.city + "', "
     + location.latitude + ", " + location.longitude + ");";
   
    response.setContentType("text/xml");
    response.setCharacterEncoding("utf-8");
    outWriter = response.getWriter();
    System.out.println(responseText);
    outWriter.print(responseText);
   }
   else {
    System.out.println("The information for " + ip + " is not available now.");
   }
  }
  catch (FileNotFoundException e) {
   System.out.println("Cannot find the file!");
  }
    %>
  </body>

对于GeoIPJava-1.2.3 API的使用也十分简单,这个库的核心类是LookupService类,可根据需要选择适当的方法。需要注意的是Java本身提供的java.net.InetAddress,java.net.*是网络编程的核心类库,InetAddress提供了互联网协议(IP)地址的相关处理。

客户端程序采用Ajax技术。Google Maps API本身提供了相当便捷的使用Ajax方法,主要有两种异步调用方法,一种是使用GXmlHttp对象,另一种是使用GDownloadUrl()函数。我对两种方法均进行了试验,下面查询页面index.html的代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>GeoIp Seeker</title>
 
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="this is my page">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
   
    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->

<!--导入Google Maps API,注意将API密钥替换成自己的 -->
 <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAvzhO6PilSOgUJFEfrExL3hR957vyFaxVOlU_EF_7ZUt9iexMPhT-MjdYiZc-avowGkYL8tEk8rSwOg&sensor=false" type="text/javascript">
 </script>
 <script type="text/javascript">
  var map; //全局GMap2对象
  var marker; //用于标识查询IP的GMarker地标
 
  //初始化
  function load() {
   if (GBrowserIsCompatible()) {
    map = new GMap2(document.getElementById("map"));
    map.setCenter(new GLatLng(39.92, 116.46), 2);
    //添加相应Control控件
    map.addControl(new GSmallMapControl());
    map.addControl(new GMapTypeControl());
    //设定地图类型为混合地图
    map.setMapType(G_HYBRID_MAP);
   }
  }

  //相应查询栏的回车
  function pressEnter(event, q) {
   //如果输入了回车则执行查询
   if (event.keyCode == 13 || event.keyCode == 10) {
    createRequest(q);
   }
  }
 
  //查询函数,使用GXmlHttp对象
  function createRequest(q){
    var request = GXmlHttp.create();
    var url = "search.jsp";
    //打开GXmlHttp对象,可设置三个参数,第一个为获取方法的类型POST或GET,第二个为发送请求的URL地址,第三个为获取模式,同步为真异步为假
    request.open("POST", url, true);
    request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    //表单数据
    var formData = "q=" + q;
    //定义响应的回调函数,可采用如下闭包形式,也可将回调函数单独提出
    request.onreadystatechange = function() {
     if(request.readyState == 4){
      if(request.status == 200){
       //获取服务器端返回的数据
       text = request.responseText;
       fun = text.split("/n")[0];
       alert(fun);
       (fun);
      }
      else{
      alert("failed for searching!");
      }
     }
    };
    //发送异步请求
    request.send(formData);
   }
 
  //查询函数,采用GDownloadUrl()方法
  function getGeoInfo(q) {
   GDownloadUrl("search.jsp?q=" + q, function(data){
    fun = data.split("/n")[0];
     (fun);
   })
  }
 
  //在地图上定位目标IP并添加信息窗口显示详细信息
  function loadGeoInfo(q, ip, country_code, country, region, city, latitude, longtitude) {
   //信息内容,包括查询数据、IP、国家名称、国家代码、省份、城市以及经纬度
   var info = "<div align=/"left/" style=/"overflow:X; font-size:12px/">"
     + "<span style=/"font-size:14px/"><strong>" + q + "</strong></span><br/>"
     + "<strong>IP:</strong> &nbsp;" + ip + "<br />"
     + "<strong>国家:</strong> &nbsp;" + country + "<br />"
     + "<strong>代码:</strong> &nbsp;" + country_code + "<br />"
     + "<strong>省份:</strong> &nbsp;" + region + "<br />"
     + "<strong>城市:</strong> &nbsp;" + city + "<br />"
     + "<strong>经度:</strong> &nbsp;" + longtitude + "<br />"
     + "<strong>纬度:</strong> &nbsp;" + latitude + "<br />"
     + "</div>";
   var point = new GLatLng(latitude, longtitude);
   //移动地图到新的位置
   map.panTo(point);
   //如果创建了marker地标,则关闭当前的信息窗口并移除地标
   if(marker) {
    map.closeInfoWindow();
    map.removeOverlay(marker);
   }
   //创建新的地标
   marker = new GMarker(point);
   map.addOverlay(marker);
   //显示信息窗口
   marker.openInfoWindowHtml(info);
  }
 </script>
 <style>
  td{
   text-align:center;
  }
 </style>
  </head>
 
  <body οnlοad="load()" οnunlοad="GUnload()">
   <table cellspacing="0" cellpadding="0" width="600" border="0" align="center">
    <tbody>
     <tr>
      <td height="25">
       <form οnsubmit="return false;">
        <label for="q">请输入IP或域名
         <input maxlength="50" size="25" name="q" id="q" οnkeypress="pressEnter(event, this.value);" />
         <input type="button" value="查找" id="search" οnclick="getGeoInfo(q.value);" />
        </label>
       </form>
      </td>
     </tr>
     <tr>
      <td>
       <div id="map" style="width:750px;height:520px"></div>
      </td>
     </tr>
    </tbody>
   </table>
  </body>
</html>
其中JavaScript部分关于Google Maps API的使用有详细注释,同时也可参考Google官方的入门指南或者API说明等资料,这里想说明几个问题,也是我在编写过程中遇到的问题。

一个是Ajax的问题。这里我采用了上述提到的两种方法,查询时如果点击查询按钮将会执行getGeoInfo方法使用GDownloadUrl()函数,如果按回车则会执行createRequest方法使用GXmlHttp对象,效果是一样的。其中GXmlHttp对象跟传统的XmlHttpRequest对象基本没有区别,数据和方法也基本一样,包括常用的responseText、onreadystatechange等数据,open()、send()等方法。而GDownloadUrl(url,onload)函数应该说是一个简化版的异步处理函数,只能使用GET方法,不判断加载状态,只是在完全加载后调用回调函数,其中第一个参数为需要用GET方法获取的URL,第二个参数是完全加载后的回调函数。其中的data数据等同于GXmlHttp对象的responseText数据,即服务器返回的查询结果。

第二个是关于回调函数的问题。这里的回调函数都采用了闭包形式的写法,当然也可将回调函数单独提出。据说即将推出的J2SE7.0最新特性就是开始支持闭包,说明Java也开始向Groovy、PHP、JS、Python等优秀的动态或脚本语言学习引入闭包特性。回调函数建议采用()函数,直接执行函数,较为简单,无需再对返回的数据进行解析处理,不过要注意所执行函数中的参数类型,string类的参数一定要加上单引号,我就是弄了很长时间()都没有执行最后才发现是这个问题。

下面是程序演示,出现了几个比较有意思的结果:

 

上面两张分别是Google和谷歌中国的服务器地址,一个在硅谷,一个在北京,这倒也不奇怪,不过我放大了谷歌中国的域名位置,结果很尴尬:

我又检验了sina的服务器地址,地标同样是很尴尬的落在了北海中央,MaxMind的IP数据库的经纬度看来只能精确到城市了。

不小心查了一下峰哥做的大班论坛的服务器地址,结果却是在我的出生地合肥,峰哥说他只是在外面租了个服务器到底在哪也不知道,看来这只能是一个未解之谜了。

最后再提醒一下,建议使用GoogleChrome浏览器,对Google Maps的支持不是一般的好,原来使用IE时地图老是显示的不太稳定。信谷歌,得永生!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值