|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
到时我们不用学struts,不用学spring,不用学Hibernate,只要能把jsf学会了,完全可以替代所有的框架,包括AJAX,都知道AJAX并不是新技术,虽说我没深入学习jsf但我认为jsf应该已经能通过其它技术替代AJAX,实现无缝刷新。google|servlet 从这一点来讲GoogleEarth客户端是我们时期的手艺标记。GoogleEarth并不是是第一个地球扫瞄客户端,并且与它的前驱、不为人知的Keyhole十分类似。可是凭着Google的台甫和基本版对终极用户收费,它完成了市场浸透并失掉公认DD这是另外一个值得年夜书特书的风趣话题。
本文只要一个基础任务:即向你展现在servlet和GoogleEarth客户端之间发送和吸收信息是何等的简单。有了这类水平的交互,你就可以用基础的Java编程妙技创立假想的服务。
利用允许及合作者
停止本文发稿时GoogleEarth还处于beta阶段(版本号3.0.0616),允许证是贸易的(见客户真个匡助部分)。假如你想追求等价的开源典范,我倡议你往存眷优异的NasaWorldWind(Nasa天下风)项目
基本常识
GoogleEarth客户端以第二版的锁位标志言语(KML)剖析XML数据,它有一个公用的定名空间。复杂的KML设置信息大概会影响到GUI显现,开辟这类必要均衡利害的使用的难点在于必要懂得更多的KML细节而不是编程技能。KML实体的扼要列表包含:
*Placements(地位),标明在地球上的坐标
*Folders(夹子),匡助构造别的的特性信息
*Documents(文档),寄存大概包括作风元素的folder的容器
*Imageoverlays(图片叠加),用来增加图片
*Networklinks(收集链接),形貌在那边和怎样与服务器大概servlet(本文彩用的体例)毗连
本文为了简化的目标,次要切磋了folder、placement和network-link元素的利用;别的还用folder界说了一段路程(tour),它内里包括了一系列的placement。
在Windows上安装了GoogleEarth后,文件扩大名KML和MIME(MultipurposeInternetMailExtensions,多用处收集邮件扩大)范例“application/keyhole”即被注册。这意味着只需点击KML文件或经由过程TCP/IP吸收“application/keyhole”MIME范例的文件就会激活GoogleEarth客户端。
假如前往的KML文本为:
<Folder><name>HelloWorld[127.0.0.1]</name></Folder>
则程序将显现以下内容:
HelloWorldfolder的GUI显现
要想激活Earth客户端,只需扫瞄得当的URL地点--就比如从资本地点(http://localhost:8080/Tour/hello)下载HelloServlet源程序。如许就可以激活doGet()办法,然后重定向到doPost()办法,在一切的Web扫瞄器里城市看到以下了局:
protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException
{
doPost(request,response);
}
protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException
{
response.setContentType("application/keyhole");
PrintWriterout=response.getWriter();
Stringmessage="<Folder><name>HelloWorld["
+request.getRemoteAddr()+"]</name></Folder>";
out.println(message);
}
不要小视这段复杂的代码,内里的办法潜伏着玄机。服务器能够作为各类数据范例和GoogleEarth之间的中介。无妨假想像如许一个场景:在路程数据中包括有分歧的XML方言,在前往呼应前由服务器完成扩大作风言语(ExtensibleStylesheetLanguage)的转换。再进一步,服务器能够选择前往哪种呼应,以同意本性化处置。KML文档实体同意作风界说,可依据IP地点局限改动作风,使得分歧的用户看到的作风大概会纷歧样。
作为理论,我们将从利用GoogleEarth和输入KML文件入手下手。在GoogleEarth的顶部是Add菜单,能够在这里增加placement、folder和imageoverlay,然后用File菜单保留天生的KML文件。我激烈保举编纂导出的XML文件以懂得修改对GoogleEarth的影响。好了,让我们入手下手与这位天下之王共舞!
懂得乡村定位
本节给出一个面向教授教养的使用:一个用来传授先生乡村称号与地舆地位间干系的程序。我们将创立一个以相似于抽签的体例将乡村地位随机发送给客户真个servlet。乡村的地位(placement)用KML暗示。Placement实体里封装了HTML链接,将用户引诱到相干的风趣站点。如许我们就能够利用户在Web扫瞄器和GoogleEarth间举行交互。
先生能够经由过程在鼠标置于链接之上时呈现的菜单当选择Refresh来选择下一个placement,如所示。
革新收集链接天生一个新地位(在这里是伦敦)时的GUI显现
我们这个使用的背景处置用到了network-link(收集链接)实体,network-link从http://location加载数据文件。将此文件存于桌面并双击,GoogleEarth入手下手运转,并从服务器端加载上面的KML代码段。
City.kml
<?xmlversion="1.0"encoding="UTF-8"?>
<kmlxmlns="http://earth.google.com/kml/2.0">
<NetworkLink>
<description>Refreshme</description>
<name>RandomCity</name>
<visibility>1</visibility>
<open>1</open>
<refreshVisibility>1</refreshVisibility>
<flyToView>1</flyToView>
<Url>
<href>http://location</href>
</Url>
</NetworkLink>
</kml>
该设置中的实体寄义为:
*visibility(可见性),界说了收集链接是不是可见
*open(睁开),申明是不是睁开标签
*refreshVisibility(革新可见性),界说是不是代替用户对革新地位可见性的设定
*flyToView(巡查),假如设为1,用户能够在View窗口“飞越”地位上空
很多实体一般都能够跨根元素利用(如description)。注重标署名是巨细写敏感的,以是编码时要当心以避免呈现难以排查的毛病。在我看来,各标签值与它们对GUI的交互感化干系其实不老是切合逻辑的,因而你大概对任何新的KML代码段的使用都必要花些工夫。
注重
在默许情形下,Firefox、Opera和IE扫瞄器关于从Web上吸收的扩大名为kml的文件反响是分歧的。激活收集链接文件最通用的办法是制止服务器将KML文件初始化,并同意用户将文件下载到桌面,如许就可以经由过程双击来启动它们。另外一种更好的办法是将KML文件嵌进到JSP(JavaServerPages)页面里并同意JSP页面前往“application/keyhole”MIME范例的KML代码段。倘使对内容范例做修正并往失落XML形式,city.jsp就成了city.kml文件。
该代码的开首为:
<%response.setContentType("application/keyhole");%>
<NetworkLink> 回到后面的代码,servlet前往了一个在description元素中带有HTML代码的placement。为恪守XML标准,我们将HTML代码段放进<!CDATA[]]>支解标签中,以免使XML剖析器搅浑:
<Placemark>
<name>London</name>
<description>
<![CDATA[<ahref="http://www.visitlondon.com/choose_site/?OriginalURL=/">London</a>]]>
</description>
<address>London,UK</address>
<styleUrl>root://styleMaps#default+nicon=0x304+hicon=0x314</styleUrl>
<Point>
<coordinates>-0.1261969953775406,51.50019836425783,50</coordinates>
</Point>
</Placemark>
在placement里呈现了三个新实体:
*address(地点),包括地点的逻辑标签
*styleUrl,界说在此处要显现的图片
*Point/coordinates(点/坐标),地位的柱面坐标
Servlet经由过程以下代码天生一个随机的placement呼应:
manager.KMLRenderOfRandomPlacement();
我们的全部使用都是最基本的,servlet没有坚持跟踪形态。Management类依据数据的构造重画各个窗口。Manager.java的init办法将数据加载到propertybean数组中。明显,实在的使用必要与数据库通讯,象iBATIS或Hibernate如许的耐久层办理框架将会很有效。placementbean用来为前往的placement筹办数据,该bean有一个代表其本身的属性点。当开辟者对KML编程的细节和怎样抵达GoogleEarthGUI中的某个点有了更多的懂得以后,就能够对此模子举行扩大。
上面的QuizServlet是对Manager.java的轻量封装,该servlet对每一个post或get哀求都前往一个无效的KML呼应。
QuizServlet.java
packagetest.google.earth.servlet;
importjava.io.IOException;
importjava.io.PrintWriter;
importjavax.servlet.ServletException;
importjavax.servlet.http.*;
importjavax.servlet.ServletConfig;
importtest.google.earth.manager.Manager;
publicclassQuizServletextendsHttpServlet
{
privateManagermanager;
publicvoidinit(ServletConfigconfig)throwsServletException{
super.init(config);
this.manager=newManager();
manager.init();
}
protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException
{
doPost(request,response);
}
protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException
{
response.setContentType("application/keyhole");
PrintWriterout=response.getWriter();
out.println(manager.KMLRenderOfRandomPlacement());
}
}
Manager.java
packagetest.google.earth.manager;
importjava.util.Random;
importtest.google.earth.bean.PlacementBean;
importtest.google.earth.bean.PointBean;
publicclassManager{
privatePlacementBean[]cityArray;
privateStringstyleURL;
privateStringopen;
privateRandomgenerator;
privateintidx;
publicManager(){}
publicvoidinit(){
this.styleURL="root://styleMaps#default+nicon=0x304+hicon=0x314";
this.open="1";
this.generator=newRandom();
String[]coords={"-0.1261969953775406,51.50019836425783,50",
"12.5,41.889999,50","4.889999,52.369998,0"};
String[]name={"London","Italy","Amsterdam"};
String[]address={"London,UK","Rome,Italy","Amsterdam,Netherlands"};
String[]description={
"<ahref="http://www.visitlondon.com/choose_site/?OriginalURL=/">London</a>",
"<ahref="http://www.roma2000.it/">Rome</a>",
"<ahref="http://www.uva.nl/">UniversityofAmsterdam</a>"};
this.idx=coords.length;
cityArray=newPlacementBean[coords.length];
//Initthearrayofplacements
for(inti=0;i<coords.length;i++){
placementBeanplacementBean=newPlacementBean();
placementBean.setAddress(address);
placementBean.setDescription(description);
placementBean.setName(name);
placementBean.setOpen(open);
placementBean.setStyleURL(styleURL);
pointBeanpointBean=newPointBean();
pointBean.setCoordinate(coords);
placementBean.setCoordinates(pointBean);
this.cityArray=placementBean;
}
}
publicsynchronizedPlacementBeannextRandomPlacement(){
returncityArray[generator.nextInt(this.idx)];
}
publicsynchronizedStringKMLRenderOfRandomPlacement(){
returnrenderKMLPlacement(nextRandomPlacement());
}
privateStringrenderKMLPlacement(PlacementBeanpBean){
StringklmString="<Placemark>
"+
" <name>"+pBean.getName()+"</name>
"+
" <description><![CDATA["+pBean.getDescription()+"]]></description>"+
" <address>"+pBean.getAddress()+"</address>
"+
" <styleUrl>"+pBean.getStyleURL()+"</styleUrl>
"+
" <Point>
"+
" <coordinates>"+pBean.getCoordinates().getCoordinate()+"</coordinates>
"+
" </Point>
"+
"</Placemark>
";
returnklmString;
}
}
为了间接将远程服务器上的图片加到placement上,styleUrl标签必要一个指向Web的链接(如http:/imageServer/image.gif),这就使代码能在View窗口的placement处添补一个图片(在本使用中是一个国旗)。
对此办法做进一步研讨,就能够计划出一个场景:用户在与GoogleEarth客户端交互的同时还能填写Web表单。给出了这一基础构想的表示图。
做进一步研讨,就能够计划出一个场景:用户在与GoogleEarth客户端交互的同时还能填写Web表单。给出了这一基础构想的表示图。
基于表单的游览服务的潜伏基础构想
在两个servlet服务器的前端是ApacheWeb服务器。第一个是表单服务器,依据发送的参数前往Web表单;第二个是路程服务器,天生placement列表封装在folder中成为一个路程。路程服务器处置图片的URL,图片自己以静态体例存储于文件体系中以改良功能。
互动流程以下:
1.用户登录到表单服务器。
2.服务器经由过程目次服务(能够是轻量目次会见服务)考证用户身份,并将用户的IP地点存进一个会话表中。
3.表单服务重视定向到路程服务器。
4.路程服务器反省正在会话中的已注册用户的IP地点。
5.依据存储在数据库中的用户汗青信息前往一个路程。
6.GoogleEarth聚焦到一个地位(placement)并哀求一张图片。
7.用户点击placement中的一个链接,触宣布单服务器天生并前往一个表单。
8.先生填写表单,然后持续游览。
9.云云几番后,先生加入会话,激发使用向相干教员发送一个将先生的回覆转化为公用格局呈报的email,至此服务器完成了功课的托付。
因而可知,基于上述构思创立一个具有功效性和教导性的使用是大概的。但是,我们还不克不及以按期的体例间接从客户端向servlet反应信息,除非先生对地位举行革新。鄙人一部分我们将深切切磋这一成绩。
双向交换
在下面的代码示例中,收集链接必要守候我们的革新操纵。侥幸的是,我们可让GoogleEarth以get办法按期地发送View窗口顶用户的地位,以下所示:
<?xmlversion="1.0"encoding="UTF-8"?>
<kmlxmlns="http://earth.google.com/kml/2.0">
<Folder>
<description>Examplesofbidirectionalflowofinformation</description>
<name>NetworkLinks</name>
<visibility>1</visibility>
<open>1</open>
<NetworkLink>
<description>Letssendcoordinatesonceinawhile</description>
<name>MessagePushing</name>
<visibility>1</visibility>
<open>1</open>
<refreshVisibility>1</refreshVisibility>
<flyToView>0</flyToView>
<Url>
<href>http://localhost:8081/Tour/message</href>
<refreshInverval>2</refreshInverval>
<viewRefreshMode>onStop</viewRefreshMode>
<viewRefreshTime>1</viewRefreshTime>
</Url>
</NetworkLink>
</Folder>
</kml>
实践的举措由Url实体完成。viewRefreshTime标签订义了经由几秒服务器吸收下一套Earth坐标,viewRefreshMode标签设置为onStop就意味着当中断在View窗口里挪动时更新Earth坐标。是上述设置最后的效果的一个截图。
收集链接和联系关系HTML的GUI显现
好了,我们能够把那些厌恶的坐标发给服务器了。我们能够用它来做甚么呢?让我们从创立一个动静服务入手下手。给出了两个流程。
GoogleEarth、servlet和扫瞄器之间的信息流
起首,经由过程扫瞄器发送动静并吸收坐标:
1.扫瞄器以post办法发送参数名和动静
2.serlet以相似于以下情势的文本动静前往从GoogleEarth客户端收到的最初坐标:
Location:-0.134539,51.497,-0.117855,51.5034
IPaddress:127.0.0.1
Updated:FriOct2111:42:45CEST2005
其次,在servlet与GoogleEarth客户端之间传送坐标并吸收地位(placement):
1.每经由ΔT工夫,GoogleEarth经由过程get办法发送用户在View窗口中的坐标。
2.servlet把动静放在placement中前往,placement经由过程坐标来大略盘算在那边安排前往的动静。请注重我已从KML教程中将对中算法拷贝过去。
前往天生的地位(placement)相似于上面的KML:
<?xmlversion="1.0"encoding="UTF-8"?>
<kmlxmlns="http://earth.google.com/kml/2.0">
<Placemark>
<name><![CDATA[<fontcolor="red">AlanBerg</font>]]></name>
<description><![CDATA[BLAHBLAH<i>FriOct2111:42:45CEST2005</i>]]>
</description>
<Point>
<coordinates>4.889999,52.369998,0</coordinates>
</Point>
</Placemark>
</kml>
以下就是组成这一协吹打章的servlet代码:
MessageServlet.java
packagetest.google.earth.servlet;
importjava.io.IOException;
importjava.io.PrintWriter;
importjavax.servlet.ServletConfig;
importjavax.servlet.ServletException;
importjavax.servlet.http.*;
importtest.google.earth.bean.LastLocationBean;
importtest.google.earth.bean.LastMessageBean;
importjava.util.Date;
publicclassMessageServletextendsHttpServlet
{
privatestaticLastMessageBeanlastMessage=newLastMessageBean();
privatestaticLastLocationBeanlastLocation=newLastLocationBean();
publicvoidinit(ServletConfigconfig)throwsServletException{
super.init(config);
lastMessage.setMessage("NomessageYet");
lastMessage.setName("System");
lastMessage.setUpdated(newDate());
lastLocation.setCoords("Nocontactwithaclientyet");
lastLocation.setIpAddress("");
lastLocation.setUpdated(newDate());
}
protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException
{
Stringcoords=request.getParameter("BBOX");
if(coords==null){
return;
}
Stringmessage;
Stringname;
DatelastDate;
StringipAddress=request.getRemoteAddr();
synchronized(this){
lastLocation.setCoords(coords);
lastLocation.setIpAddress(ipAddress);
lastLocation.setUpdated(newDate());
message=lastMessage.getMessage();
name=lastMessage.getName();
lastDate=lastMessage.getUpdated();
}
response.setContentType("application/keyhole");
PrintWriterout=response.getWriter();
String[]coParts=coords.split(",");
floatuserlon;
floatuserlat;
try{
userlon=((Float.parseFloat(coParts[2])-Float.parseFloat(coParts[0]))/2)+
Float.parseFloat(coParts[0]);
userlat=((Float.parseFloat(coParts[3])-Float.parseFloat(coParts[1]))/2)+
Float.parseFloat(coParts[1]);
}catch(NumberFormatExceptione){
return;
}
StringklmString="<?xmlversion="1.0"encoding="UTF-8"?>
"
+"<kmlxmlns="http://earth.google.com/kml/2.0">
"
+"<Placemark>
"
+"<name><![CDATA[<fontcolor="red">"+name+"</font>]]></name>
"
+"<description><![CDATA["+message+"<br><i>"+lastDate+"</i>]]></description>
"
+"<Point>
"
+"<coordinates>"+userlon+","+userlat+",0</coordinates>
"
+"</Point>
"
+"</Placemark>
"
+"</kml>
";
out.println(klmString);
}
protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException
{
Stringname=request.getParameter("name");
if(name==null){
return;
}
Stringmessage;
PrintWriterout;
synchronized(this){
lastMessage.setMessage(request.getParameter("message"));
lastMessage.setName(name);
lastMessage.setUpdated(newDate());
message="<pre>
Location:"+lastLocation.getCoords()+
"
IPaddress:"+lastLocation.getIpAddress()+
"
Updated:"+lastLocation.getUpdated();
}
response.setContentType("text/html");
out=response.getWriter();
out.println(message);
}
}
来自扫瞄器的动静保留在静态成员LastMessageBean中,坐标保留在LastLocationBean中,且每一个bean都只要一个实例。别的,在实行getting或setting操纵时对一切的静态bean都举行同步。我们用单个实例来到达简化的目标,有助于限定要编写的代码数目。但是,更有有用代价的示例应具有跟踪IP地点的会话办理功效并天生响应的处置了局。
有一个不起眼的毛病,在placement实体的名字标签里利用HTML标签会招致显现成绩:全部标签在GoogleEarth客户真个“places”菜单区按HTML显现,但在View窗口里却按文本显现。我以为这类纷歧致是个bug。
在本示例中GoogleEarth客户端推送坐标,servlet前往KML代码段。既然晓得能用坐标推奉上下文联系关系信息,我们能够强迫经由过程段中的链接来举行交互,需要的话还可让扫瞄器成为宿主。本文展现了怎样把持GoogleEarth客户端,至此你已具有了一个创立本人互动路程的观点性工具箱。
但是我同意你的观点,对于大型项目来说,应该是采用框架的一部分,根据功能的不同而改进,欢迎你能再提出些宝贵意见,我会多多学习的。说到jbuilder,我可能是个人感觉,用的时候确实没有vs爽,我最喜欢的IDE是netbeans,谢谢。 |
|