posts - 77, comments - 54, trackbacks - 0, articles - 0
  IT博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

AJAX是“异步的JavaScript和XML”的缩写。这是一项技术,而不是一个如Struts一样的框架。为什么在AJAX周围会有这么多的关注呢?这是因为AJAX使web页面看起来并不像一个平面的文档,而更像用户所期望的如桌面应用的动态GUI应用程序。AJAX技术能在很多的浏览器上使用(包括IE和Netscape/Mozilla)。它已经为Microsoft(用于Outlook的web客户端)和Google(用户Google Maps和Gmail)所使用。

  未使用AJAX之前

  目前大多数的Struts应用都是标准的“如同一个平面文档的web页面”的结构。如果你想模仿一些桌面应用程序(比如那些使用Java Swing,Visual Basic,或者Delphi建立的应用程序),那么你有两个选择:你可以发送所有的可能作为页面的一部分被请求的信息,使用大量的JavaScript来操作其动态的显示(一个很慢并且非企业级Java的方法);或者你可以不改变形式地提交到后台服务器(一种有效的方法) 。AJAX提高给你了融合前面的最佳解决方案:动态的页面,但是大多数的应用是在你的web服务器的Java程序来处理的。

  AJAX 101

  AJAX和现有的动态HTML技术非常相似,并在其上增加了一个发送到“后台”服务器的请求来获取需要的新的或者更新的信息。AJAX的机制在其他地方已经有详细的说明――请查看本文后的Resources来获取更多。但是你至少需要知道:

  •   1. XMLHttpRequest (如果你使用的是IE浏览器的话,则是Microsoft.XMLHTTP的ActiveX的对象)。这些对象,你可以在web页面中使用JavaScript调用。他们允许你作为后台的调用方式来请求web服务器的内容(例如,在表单提交后,屏幕并不像平时一样显示“空白”)。
  •   2. XMLHttpRequest 和Microsoft.XMLHTTP 返回的内容可以作为XML或者文本来处理。JavaScript(在你页面上的)可以使用请求的新内容来更新页面。
  •   3. 整个处理过程可以由普通的JavaScript事件来触发:onclick,onchange,onblur,等。

  在你的Struts应用中使用AJAX

  你阅读了本文,然后你会对使用AJAX来创建动态的web页面感兴趣,并且想知道如何将它加入到你的Struts应用中。这只是选择之一。那么你会如何选择呢?

  •   · 等待,知道Struts的下一个版本融合了AJAX技术。如果Struts开发者准备开发一个新的应用,这或许会是一个好的选择。再后面,可能会是要求JSF也这样做――对其本身并不一件坏事,但是对于已经存在的系统这将会带来最根本的改变。
  •   · 你也可以直接采用新的方法,比如Direct Web Remoting (DWR) 和Ruby on Rails,这些都是专为建立AJAX应用的。如果你考虑不使用Struts来开发web的话,那么这些都是很又用的框架,并且值得一试。但是,这也同时意味着你必须要重写你的应用。
  •   · 在你已经存在的Struts应用中增加AJAX。既然AJAX只是一项技术而并非框架,那么它就很容易融入到Struts中。作为现有的系统,其稳定性(如,保持现有的库文件)是相当重要的。所以这个方法被推荐,并且我们将在后面详细介绍。

  我们选择在Struts应用中增加AJAX的优势是:

  •   1. 它并不需要任何新的库文件或者服务器代码;只需要使用现有的Struts库文件和action。
  •   2. 解决方案中所有部分――JavaScript,XML,Java和Struts――早已为广泛所知。
  •   3. 此应用可以一块一块地移植到AJAX;我们可以确定哪些部分对用户有益,并首先将它们更新到动态AJAX显示。

  实现方案

  我们如何真正的贯彻我们的选择呢?我们首先应该注意一个“标准的”(没有AJAX)Struts应用是如何工作的。在此应用中,一个一般的事件流程如下:

  •   1. 使用点击超链接或者表单的提交按钮,用户发送请求。
  •   2. web服务器运行处理请求的Struts Action来生成一个web页面。
  •   3. 浏览器显示web页面。
  •   4. 当用户点击保存的时候,信息由Struts框架中一个ActionForm类来转换并发送到服务器。
  •   5. 然后,Struts框架调用Struts Action来出来请求(如,保存数据到数据库中)。
  •   6. 页面再一次回传,处理流程继续。

  现有的Struts应用

  一个演示事件流程的简单Struts应用可以在以下地址下载: struts-non-ajax.zip。此基于Struts的应用,是基于用户的输入显示或者隐藏蓝色和绿色的表格。图1显示了载入初始页面的画面。图2显示了用户输入值并点击了提交后的画面。虽然简单,但它已经足以表示一个Struts的工作流程。

  图 1. 没有AJAX的例子:初始屏幕

  图 2. 没有AJAX的例子:输入值并点击了提交

  服务器端的代码是:一个Struts Action使用struts-config.xml 中定义的值转发到(相同的)JSP。这个例子代码中一些需要注意的地方是:

  •   ·struts-config.xml文件将所有的请求重定向到http://localhost:8080/struts-non-ajax/(或者和你自己的服务器相同)的index.jsp。
  •   · index.jsp 包含了一个两个文本框的Struts form(showBlue和showGreen)。该页面同样包含了标签,但是如同两个文本框被初始化为空,标签之间的内容并不显示。
  •   · 用户输入值(true或者false)并点击提交按钮,处理控制(经过Struts框架,读取struts-config.xml)提交到SampleAction类中。
  •   ·SampleAction记录下值,然后转发到index.jsp。一个成熟的Struts应用可能会处理更多的事情,不如保存或者查询数据库等。
  •   · index.jsp 现在重新处理请求;如果ShowBlue或者ShowGreen的值是true,这些表格就显示出来。

  该应用并没有任何“错误”。类似的Struts项目好多年都是这样做的。但是,我们如何在不添加复杂的JavaScript或者频繁的表单提交的前提下,为此应用增加动态的元素呢?

  我们的第一个Struts AJAX应用

  观察下下面的图3和图4。第一眼看上去,它们和前面的例子没有说明区别。它们的不同之处在于,页面载入后(图3)然后文本框中的值改变了,窗体自动提交而不显示空白的,然后在图4中显示结果。普通的提交按钮仍然在,你也可以选择使用它。

  图 3. 页面载入后的AJAX例子

  图 4. AJAX调用后的AJAX例子

  添加AJAX是出奇的容易。服务器端的代码和前面的例子是一样的: 一个Struts的ActionForm来后去数据,一个Struts的Action来执行需要的任务(例如,存储数据库)然后转发到适当的JSP页面来显示结果。

  继续

  如果你希望就此停止阅读(跳过这个例子的工作说明),但是这里的是和你需要转换你的Struts应用到一个Struts-AJAX应用同样的风格:

  •   1. 在你的web页面中引入一个Ajax.js (该文件是struts-ajax.zip 例文件中的一部分)。Ajax.js 包含了所有需要发送和接收AJAX调用的JavaScript方法。
  •   2. 确保你希望在AJAX调用中更新的web页面的部分包含在标签中,并且给每个标签一个id。
  •   3. 当一些事件触发的时候就更新页面(例如,文本框的the onchange()方法),调用retrieveURL()方法,通过URL传递到需要执行服务器端处理的Struts Action。
  •   4. 为了页面的显示/更新,最简单的方法是Struts Action转发回同样的页面。在本例中,showGreen/showBlue 文本框中的onchange()方法来触发AJAX调用。

  JavaScript方法retrieveURL()调用服务器的Struts(通过URL),获取JSP响应,然后更新显示页面中的 标签中的部分。就是这么简单!

  AJAX解决方案的细节

  我们将例子变为AJAX-Struts应用的时候,需要三个变化:

  •   1. 增加一个JavaScript方法来完成到服务器的“背后的”AJAX调用。
  •   2. 增加JavaScript代码来接收服务器的响应并更新页面。
  •   3. 在JSP页面增加标签标签,这个标签中内容将在AJAX调用中更新。
  我们将详细的说明上面的每一步。
 发送AJAX请求到服务器

  有两个方法(在下面列出)用于发送请求到服务器。

  · retrieveURL()方法获得服务器的URL和Struts form。URL用于使用AJAX,form的值用于传递到服务器。

  · getFormAsString()方法用于将retrieveURL()中form命名的值组装成查询字符串,并发送到服务器。

  使用方法很简单,使用onclick()/onChange()事件来触发retrieveURL()更新显示。

  在这两个方法中有一些有趣的东西。

  在retrieveURL()方法中,req.onreadystatechange = processStateChange (注意,没有括号)这一行来告诉浏览器在服务器响应到达的时候调用processStateChange()方法(该方法将在后面介绍)。retrieveURL()方法中(现在已经是AJAX的标准了)同样决定是使用IE浏览器(ActiveX)还是使用Netscape/Mozilla (XmlHttpRequest) 来实现跨浏览器兼容。

  getFormAsString()方法将HTML form转换成字符串连接在URL后面(这样就允许我们发送HTTP GET请求)。这个字符串是经过转换的(比如,空格转换成%20等),并且是一个Struts能将其组装成ActionForm的格式(并不需要Struts清楚的明白这个是来之AJAX的请求)。注意,在本例中我们使用HTTP GET,使用HTTP POST的方法也是类似的。

function retrieveURL(url,nameOfFormToPost) {

//将url转换成字符串
url=url+getFormAsString(nameOfFormToPost);

//调用AJAX
if (window.XMLHttpRequest) {

// 非IE浏览器
req = new XMLHttpRequest();
req.onreadystatechange = processStateChange;
try {
req.open("GET", url, true);
} catch (e) {
alert("Server Communication Problem\n"+e);
}
req.send(null);
} else if (window.ActiveXObject) {
// IE

req = new ActiveXObject("Microsoft.XMLHTTP");
if (req) {
req.onreadystatechange=processStateChange;
req.open("GET", url, true);
req.send();
}
}
}

getFormAsString() 是一个“私有” 方法,在retrieveURL()中使用。

function getFormAsString(formName){

//设置返回字符串
returnString ="";

//取得表单的值
formElements=document.forms[formName].elements;

//循环数组,组装url
//像'/strutsaction.do&name=value'这样的格式

for(var i=formElements.length-1;i>=0; --i ){
//转化每一个值
returnString+="&"
+escape(formElements[i].name)+"="
+escape(formElements[i].value);
}

//返回字符串
return returnString;
}

  根据AJAX的响应更新web页面

  到现在为止,我们学习过了使用JavaScript来完成AJAX调用(前面列出),Struts Action,ActionForm以及JSP(基本没有变化,只是增加了标签)。为了完善我们对Struts-AJAX项目的了解,我们需要了解三个用于根据服务器返回的结果而更新页面的JavaScript方法。

  •   · processStateChange(): 该方法在AJAX调用前设定。它在服务器响应到达后由XMLHttpRequest/Microsoft.XMLHTTP 对象调用。
  •   ·splitTextIntoSpan(): 根据响应,循环取出数组中的元素组装成NewContent。
  •   ·replaceExistingWithNewHtml(): 根据span元素数组,循环搜索,将里面的元素调换掉页面中和它的'someName'相同的中的内容。注意,我们使用的是req.responseText 方法来获得返回的内容(它允许我们操作任何文本的响应)。与此相对于的是req.responseXml (它的作用更大,但是要求服务器返回是XHTML或者XML)。

function processStateChange() {

if (req.readyState == 4) { // 完成
if (req.status == 200) { // 响应正常

//将响应的文本分割成Span元素
spanElements =
splitTextIntoSpan(req.responseText);

//使用这些Span元素更新页面
replaceExistingWithNewHtml(spanElements);

} else {
alert("Problem with server response:\n "
+ req.statusText);
}
}
}
replaceExistingWithNewHtml() 是为processStateChange()使用的“私有”方法。

function replaceExistingWithNewHtml
(newTextElements){

//循环newTextElements
for(var i=newTextElements.length-1;i>=0;--i){

//判断是否以 if(newTextElements[i].
indexOf("-1){

//获得span的名字- 设置在第一和第二个引号之间
//确认span元素是以下的格式
//NewContent
startNamePos=newTextElements[i].
indexOf('"')+1;
endNamePos=newTextElements[i].
indexOf('"',startNamePos);
name=newTextElements[i].
substring(startNamePos,endNamePos);

//获得内容-在第一个>标记后的所有内容
startContentPos=newTextElements[i].
indexOf('>')+1;
content=newTextElements[i].
substring(startContentPos);

//现在更新现有的Document中的元素,
// 确保文档存在该元素
if(document.getElementById(name)){
document.getElementById(name).
innerHTML = content;
}
}
}
splitTextIntoSpan() 是为processStateChange() 使用的“私有”方法。
function splitTextIntoSpan(textToSplit){

//分割文档
returnElements=textToSplit.
split("")

//处理每个元素
for(var i=returnElements.length-1;i>=0;--i){

//删除掉第一个span后面的元素
spanPos = returnElements[i].
indexOf("

//如果找到匹配的,获得span前的内容
if(spanPos>0){
subString=returnElements[i].
substring(spanPos);
returnElements[i]=subString;
}
}
return returnElements;
}

  新的控制流

  添加以下的JavaScript代码到我们的应用中,以下的步骤将在服务器和浏览器中执行。

  •   1. 如同一个普通Struts应用装载页面。
  •   2. 用户改变文本框的值,触发一个onChange() 事件,调用retrieveURL() 方法。
  •   3. 该JavaScript方法通过发送Struts明白的表单变量(后台)请求到服务器的Struts Action。
  •   4. 该JavaScript方法同样设定了第二个JavaScript方法的名字,此方法将到服务器响应完毕后调用。本例子中,设定为processStateChange() 方法。
  •   5. 如我们所预期的,服务器响应完毕,调用processStateChange() 方法。
  •   6. JavaScript在(新的)服务器响应中循环取出所有元素。将页面上存在与获得元素名字相同的 中的元素替换掉。

  在你的应用中设计AJAX

  以上描述的JavaScript方法能在大多数的应用中使用,包括比我们的例子复杂得多的。但是,在使用之前,你需要注意以下几点:

  · 避免复制代码,最好在初始化请求(如,显示完整的页面)和AJAX(更新部分页面)请求中使用相同的Struts Action和JSP。

  ·在公共的Action(控制器)中,决定JSP页面(所有的JSP页面或者其中的一部分)中的一个区域需要传送到浏览器。通过在web服务器的session或者ActionForm中设定标记来让JSP页面知道哪些部分需要提交。

  · 在JSP中,使用Struts 或者JSTL标签来决定提交的HTML区域。

  使用AJAX的本例子,可以在以下下载: struts-Ajax.zip

  结语

  AJAX技术允许我们在创建和使用web应用的时候完全的改变。本文介绍了一个简单的技术,在现有的Struts应用中增加Struts的处理。它允许我们利用我们已有的东西,不仅仅是代码,还包括了开发的技能。作为一个好的产品,它同样允许我们写出更清晰,更具移植性的Java Struts应用。

版权声明:Techtarget获Matrix授权发布,如需转载请联系Matrix
作者:作者:Paul Browne;pawenwen(作者的blog:http://blog.matrix.org.cn/page/pawenwen)
译文:
点击

posted @ 2006-06-07 13:52 东人EP 阅读(304) | 评论 (0)编辑 收藏

 

首先我们今天要用到的是Ajax.NET Professional ,您可以从http://www.schwarz-interactive.de/ 获取关于AJAX.NET的相关信息。其次还需要知道XML数据岛的相关知识。

下面我们先来看一个简单的绑定例子:

第一步先确定XML数据源

<xml ID="xmlData" name="xmlData">

 <root>

<METADATA>

 <AUTHOR>John Smith</AUTHOR>

 <GENERATOR>Visual Notepad</GENERATOR>

 <PAGETYPE>Reference</PAGETYPE>

 <ABSTRACT>Specifies a data island</ABSTRACT>

</METADATA>

<METADATA>

 <AUTHOR>John Smith2</AUTHOR>

 <GENERATOR>Visual Notepad2</GENERATOR>

 <PAGETYPE>Reference2</PAGETYPE>

 <ABSTRACT>Specifies a data island2</ABSTRACT>

</METADATA>

<METADATA>

 <AUTHOR>John Smith3</AUTHOR>

 <GENERATOR>Visual Notepad3</GENERATOR>

 <PAGETYPE>Reference3</PAGETYPE>

 <ABSTRACT>Specifies a data island3</ABSTRACT>

</METADATA>

 </root>

</xml>


第二步确定绑定容器,在这里我们使用Table

<TABLE dataSrc="#xmlData" border=1>

 <TR>

<TD><span dataFld="AUTHOR">loading...</span></TD>

<TD><span dataFld="GENERATOR">loading...</span></TD>

<TD><span dataFld="PAGETYPE">loading...</span></TD>

<TD><span dataFld="ABSTRACT">loading...</span></TD>

 </TR>

</TABLE>


把这两段代码Copy到您的HTMl页面运行既可看到效果。

第一段是我们的XML数据源,也就是要绑定的数据,METADATA结点相当于表名, AUTHOR、GENERATOR、PAGETYPE、ABSTRACT相当于列名,下面的Table是用来显示数据的容器。<TABLE dataSrc="#xmlData" border=1>是指定Table的数据源,<span dataFld="AUTHOR">loading...</span>绑定字段名。

好了,知道这些之后就再来看如何结合Ajax实现无刷新绑定。

第一步:配置Ajax,在Web.config文件中加入配置节:

<httpHandlers>

<add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.AjaxHandlerFactory, AjaxPro"/>

</httpHandlers>


第二步,编写返回数据集的代码:

public class MyClass

{

 [AjaxMethod]

 public string GetDataSet()

 {

DataSet dst = new DataSet();

DataTable dt = new DataTable();

dt.Columns.Add("Text");

dt.Columns.Add("Number");

Random random = new Random(Guid.NewGuid().GetHashCode());

for (int i = 0; i < random.Next(10,20); i++)

{

 DataRow row = dt.NewRow();

 row["Text"] = Guid.NewGuid().ToString("N");

 row["Number"] = random.Next(100);

 dt.Rows.Add(row);

}

dst.Tables.Add(dt);

string text = "";

using(MemoryStream ms = new MemoryStream())

{

 dst.WriteXml(ms);

 ms.Position = 0;

 StreamReader sr = new StreamReader(ms);

 text = sr.ReadToEnd();

}

return text;

 }

}



第三步:在Page_Load中注册该方法,AjaxPro.Utility.RegisterTypeForAjax(typeof(WebTest1.AjaxTest1));(WebTest1是名称空间的名字)

第四步:添加客户端绑定

<INPUT onclick="WebTest1.MyClass.GetDataSet(callback)" type="button" value="GetDataSet">

<div id="oDataPanel">

</div>

<TABLE datasrc="#xmlData" WIDTH="500" BORDER="1"

CELLSPACING="1" CELLPADDING="1">

 <thead>

<tr>

 <th width="70%">姓名</th>

 <th width="30%">年龄</th>

</tr>

 </thead>

 <TR>

<TD><span datafld="Text"></span></TD>

<TD><span datafld="Number"></span></TD>

 </TR>

</TABLE>

<div id="oDataPanel">是准备用来存放Xml数据源的容器



第五步:编定加载数据的JavaScript代码

function callback(res)

{

if(!res.error)

{

document.all.oDataPanel.innerHTML = '<xml id="xmlData">'+ res.value +'</xml>';

}

else

{

alert(res.error.Message);

}

}

posted @ 2006-06-07 13:48 东人EP 阅读(292) | 评论 (0)编辑 收藏

一,国内网站
    1.163--------------------http://mail.163.comhttp://www.126.com
    2.新浪--------------------新浪手机- 新浪评论

二,国外网站
  1. 64pola.pl: AJAX Multiplayer Chess Server
  2. A9 Maps
  3. A9.com
  4. AgileGallery.com
  5. AJAX Dictionary
  6. AJAX Translator
  7. ajaxWrite
  8. Apple Store
  9. Ask.com
  10. Ask.com Maps
  11. AskAlexia.com
  12. Backbase
  13. BaeBo
  14. BaseCamp
  15. BetFair.com
  16. BlinkList
  17. BloxPress.org
  18. Box.net
  19. BubbleShare.com
  20. Colr.org
  21. CommonTimes.org
  22. Convea.com
  23. Diggilicious.com
  24. DutchPIPE.org
  25. Edgeio.com
  26. Eyespot.com: Editing video in your browser
  27. Flickr.com
  28. Form Assembly
  29. Gap.com
  30. Gmail
  31. Google Calendar
  32. Google Groups
  33. Google Maps
  34. Google Personalized Home
  35. Google Reader
  36. Google Suggest
  37. GotAPI.com
  38. GPlotter
  39. Hive7.com
  40. InstantDomainSearch.com
  41. Jacuba.com
  42. Jobby
  43. Kayak.com
  44. Kiko
  45. KillSwitchCollective.com
  46. Linkaroo
  47. Meebo
  48. MSN Virtual Earth
  49. NearBinder.com
  50. Netvibes.com
  51. ObjectGraph Dictionary
  52. Orkut.com
  53. Panic Goods Apparel
  54. Protopage
  55. Ripped Tickets
  56. SimplyHired.com
  57. SoloModels.com
  58. Spotback.com
  59. Sproutliner
  60. Start.com beta
  61. Ta-daLists
  62. TagWorld
  63. TeamSlide.com
  64. TicketSavvy.com
  65. Top 10 Ajax Applications
  66. Top 10 Ajax Applications (Part 2)
  67. Webezz.net
  68. WikiUpload.com
  69. Yahoo! Instant Search
  70. Yahoo! Tech
  71. Zillow.com

posted @ 2006-06-07 12:59 东人EP 阅读(246) | 评论 (0)编辑 收藏

作为J2EE开发人员,我们似乎经常关注“后端机制(backend mechanics)”。我们通常会忘记,J2EE的主要成功之处在Web应用程序方面;许多原因使得人们喜欢利用Web开发应用程序,但主要还是因为其易于部署的特点允许站点以尽可能低的成本拥有上百万的用户。遗憾的是,在过去几年中,我们在后端投入了太多的时间,而在使我们的Web用户界面对用户自然和响应灵敏方面却投入不足。

本文介绍一种方法,Ajax,使用它可以构建更为动态和响应更灵敏的Web应用程序。该方法的关键在于对浏览器端的JavaScript、DHTML和与服务器异步通信的组合。本文也演示了启用这种方法是多么简单:利用一个Ajax框架(指DWR)构造一个应用程序,它直接从浏览器与后端服务进行通信。如果使用得当,这种强大的力量可以使应用程序更加自然和响应灵敏,从而提升用户的浏览体验。

该应用程序中所使用的示例代码已打包为单独的WAR文件,可供下载。

简介

术语Ajax用来描述一组技术,它使浏览器可以为用户提供更为自然的浏览体验。在Ajax之前,Web站点强制用户进入提交/等待/重新显示范例,用户的动作总是与服务器的“思考时间”同步。Ajax提供与服务器异步通信的能力,从而使用户从请求/响应的循环中解脱出来。借助于Ajax,可以在用户单击按钮时,使用JavaScript和DHTML立即更新UI,并向服务器发出异步请求,以执行更新或查询数据库。当请求返回时,就可以使用JavaScript和CSS来相应地更新UI,而不是刷新整个页面。最重要的是,用户甚至不知道浏览器正在与服务器通信:Web站点看起来是即时响应的。

虽然Ajax所需的基础架构已经出现了一段时间,但直到最近异步请求的真正威力才得到利用。能够拥有一个响应极其灵敏的Web站点确实激动人心,因为它最终允许开发人员和设计人员使用标准的HTML/CSS/JavaScript堆栈创建“桌面风格的(desktop-like)”可用性。

通常,在J2EE中,开发人员过于关注服务和持久性层的开发,以至于用户界面的可用性已经落后。在一个典型的J2EE开发周期中,常常会听到这样的话,“我们没有可投入UI的时间”或“不能用HTML实现”。但是,以下Web站点证明,这些理由再也站不住脚了:

所有这些Web站点都告诉我们,Web应用程序不必完全依赖于从服务器重新载入页面来向用户呈现更改。一切似乎就在瞬间发生。简而言之,在涉及到用户界面的响应灵敏度时,基准设得更高了。

定义Ajax

Adaptive Path公司的Jesse James Garrett这样定义Ajax:

Ajax不是一种技术。实际上,它由几种蓬勃发展的技术以新的强大方式组合而成。Ajax包含:

  • 基于CSS标准的表示;
  • 使用Document Object Model进行动态显示和交互;
  • 使用XMLHttpRequest与服务器进行异步通信;
  • 使用JavaScript绑定一切。

这非常好,但为什么要以Ajax命名呢?其实术语Ajax是由Jesse James Garrett创造的,他说它是“Asynchronous JavaScript + XML的简写”。

Ajax的工作原理

Ajax的核心是JavaScript对象XmlHttpRequest。该对象在Internet Explorer 5中首次引入,它是一种支持异步请求的技术。简而言之,XmlHttpRequest使您可以使用JavaScript向服务器提出请求并处理响应,而不阻塞用户。

在创建Web站点时,在客户端执行屏幕更新为用户提供了很大的灵活性。下面是使用Ajax可以完成的功能:

  • 动态更新购物车的物品总数,无需用户单击Update并等待服务器重新发送整个页面。
  • 提升站点的性能,这是通过减少从服务器下载的数据量而实现的。例如,在Amazon的购物车页面,当更新篮子中的一项物品的数量时,会重新载入整个页面,这必须下载32K的数据。如果使用Ajax计算新的总量,服务器只会返回新的总量值,因此所需的带宽仅为原来的百分之一。
  • 消除了每次用户输入时的页面刷新。例如,在Ajax中,如果用户在分页列表上单击Next,则服务器数据只刷新列表而不是整个页面。
  • 直接编辑表格数据,而不是要求用户导航到新的页面来编辑数据。对于Ajax,当用户单击Edit时,可以将静态表格刷新为内容可编辑的表格。用户单击Done之后,就可以发出一个Ajax请求来更新服务器,并刷新表格,使其包含静态、只读的数据。

一切皆有可能!但愿它能够激发您开始开发自己的基于Ajax的站点。然而,在开始之前,让我们介绍一个现有的Web站点,它遵循传统的提交/等待/重新显示的范例,我们还将讨论Ajax如何提升用户体验。

Ajax可用于那些场景?——一个例子:MSN Money页面

前几天,在浏览MSN Money页面的时候,有一篇关于房地产投资的文章引起了我的好奇心。我决定使用站点的“Rate this article”(评价本文)功能,鼓励其他的用户花一点时间来阅读这篇文章。在我单击vote按钮并等待了一会儿之后,整个页面被刷新,在原来投票问题所在的地方出现了一个漂亮的感谢画面。

而Ajax能够使用户的体验更加愉快,它可以提供响应更加灵敏的UI,并消除页面刷新所带来的闪烁。目前,由于要刷新整个页面,需要传送大量的数据,因为必须重新发送整个页面。如果使用Ajax,服务器可以返回一个包含了感谢信息的500字节的消息,而不是发送26,813字节的消息来刷新整个页面。即使使用的是高速Internet,传送26K和1/2K的差别也非常大。同样重要的是,只需要刷新与投票相关的一小节,而不是刷新整个屏幕。

让我们利用Ajax实现自己的基本投票系统。

原始的Ajax:直接使用XmlHttpRequest

如上所述,Ajax的核心是JavaScript对象XmlHttpRequest。下面的示例文章评价系统将带您熟悉Ajax的底层基本知识:http://tearesolutions.com/ajax-demo/raw-ajax.html。注:如果您已经在本地WebLogic容器中安装了ajax-demo.war,可以导航到http://localhost:7001/ajax-demo/raw-ajax.html

浏览应用程序,参与投票,并亲眼看它如何运转。熟悉了该应用程序之后,继续阅读,进一步了解其工作原理细节。

首先,您拥有一些简单的定位点标记,它连接到一个JavaScriptcastVote(rank)函数。

function castVote(rank) {
  var url = "/ajax-demo/static-article-ranking.html";
  var callback = processAjaxResponse;
  executeXhr(callback, url);
}

该函数为您想要与之通信的服务器资源创建一个URL并调用内部函数executeXhr,提供一个回调JavaScript函数,一旦服务器响应可用,该函数就被执行。由于我希望它运行在一个简单的Apache环境中,“cast vote URL”只是一个简单的HTML页面。在实际情况中,被调用的URL将记录票数并动态地呈现包含投票总数的响应。

下一步是发出一个XmlHttpRequest请求:

function executeXhr(callback, url) {
  // branch for native XMLHttpRequest object
  if (window.XMLHttpRequest) {
    req = new XMLHttpRequest();
    req.onreadystatechange = callback;
    req.open("GET", url, true);
    req.send(null);
  } // branch for IE/Windows ActiveX version
  else if (window.ActiveXObject) {
    req = new ActiveXObject("Microsoft.XMLHTTP");
    if (req) {
      req.onreadystatechange = callback;
      req.open("GET", url, true);
      req.send();
    }
  }
}

如您所见,执行一个XmlHttpRequest并不简单,但非常直观。和平常一样,在JavaScript领域,大部分的工作量都花在确保浏览器兼容方面。在这种情况下,首先要确定XmlHttpRequest是否可用。如果不能用,很可能要使用Internet Explorer,这样就要使用所提供的ActiveX实现。

executeXhr()方法中最关键的部分是这两行:

req.onreadystatechange = callback;
req.open("GET", url, true);

第一行定义了JavaScript回调函数,您希望一旦响应就绪它就自动执行,而req.open()方法中所指定的“true”标志说明您想要异步执行该请求。

一旦服务器处理完XmlHttpRequest并返回给浏览器,使用req.onreadystatechange指派所设置的回调方法将被自动调用。

function processAjaxResponse() {
  // only if req shows "loaded"
  if (req.readyState == 4) {
    // only if "OK"
    if (req.status == 200) {
      502 502'votes').innerHTML = req.responseText;
    } else {
      alert("There was a problem retrieving the XML data:
" +
      req.statusText);
    }
  }
} 

该代码相当简洁,并且使用了几个幻数,这使得难以一下子看出发生了什么。为了弄清楚这一点,下面的表格(引用自http://developer.apple.com/internet/webcontent/xmlhttpreq.html)列举了常用的XmlHttpRequest对象属性。

属性

描述

onreadystatechange

每次状态改变所触发事件的事件处理程序

readyState

对象状态值:

  • 0 = 未初始化(uninitialized)
  • 1 = 正在加载(loading)
  • 2 = 加载完毕(loaded)
  • 3 = 交互(interactive)
  • 4 = 完成(complete)

responseText

从服务器进程返回的数据的字符串形式

responseXML

从服务器进程返回的DOM兼容的文档数据对象

status

从服务器返回的数字代码,比如404(未找到)或200(就绪)

statusText

伴随状态码的字符串信息

现在processVoteResponse()函数开始显示出其意义了。它首先检查XmlHttpRequest的整体状态以保证它已经完成(readyStatus == 4),然后根据服务器的设定询问请求状态。如果一切正常(status == 200),就使用innerHTML属性重写DOM的“votes”节点的内容。

既然您亲眼看到了XmlHttpRequest对象是如何工作的,就让我们利用一个旨在简化JavaScript与Java应用程序之间的异步通信的框架来对具体的细节进行抽象。

Ajax: DWR方式

按照与文章评价系统相同的流程,我们将使用Direct Web Remoting(DWR)框架实现同样的功能。

假定文章和投票结果存储在一个数据库中,使用某种对象/关系映射技术来完成抽取工作。为了部署起来尽可能地简单,我们不会使用数据库进行持久性存储。此外,为使应用程序尽可能通用,也不使用Web框架。相反,应用程序将从一个静态HTML文件开始,可以认为它由服务器动态地呈现。除了这些简化措施,应用程序还应该使用Spring Framework关联一切,以便轻松看出如何在一个“真实的”应用程序中使用DWR。

现在应该下载示例应用程序并熟悉它。该应用程序被压缩为标准的WAR文件,因此您可以把它放置到任何一个Web容器中——无需进行配置。部署完毕之后,就可以导航到http://localhost:7001/ajax_demo/dwr-ajax.html来运行程序。

可以查看HTML源代码,了解它如何工作。给人印象最深的是,代码如此简单——所有与服务器的交互都隐藏在JavaScript对象ajaxSampleSvc的后面。更加令人惊讶的是,ajaxSampleSvc服务不是由手工编写而是完全自动生成的!让我们继续,看看这是如何做到的。

引入DWR

如同在“原始的Ajax”一节所演示的那样,直接使用XmlHttpRequest创建异步请求非常麻烦。不仅JavaScript代码冗长,而且必须考虑服务器端为定位Ajax请求到适当的服务所需做的工作,并将结果封送到浏览器。

设计DWR的目的是要处理将Web页面安装到后端服务上所需的所有信息管道。它是一个Java框架,可以很轻松地将它插入到Web应用程序中,以便JavaScript代码可以调用服务器上的服务。它甚至直接与Spring Framework集成,从而允许用户直接向Web客户机公开bean。

DWR真正的巧妙之处是,在用户配置了要向客户机公开的服务之后,它使用反射来生成JavaScript对象,以便Web页面能够使用这些对象来访问该服务。然后Web页面只需接合到生成的JavaScript对象,就像它们是直接使用服务一样;DWR无缝地处理所有有关Ajax和请求定位的琐碎细节。

让我们仔细分析一下示例代码,弄清它是如何工作的。

应用程序细节:DWR分析

关于应用程序,首先要注意的是,它是一个标准的Java应用程序,使用分层架构(Layered Architecture)设计模式。使用DWR通过JavaScript公开一些服务并不影响您的设计。

下面是一个简单的Java服务,我们将使用DWR框架直接将其向JavaScript代码公开:

package com.tearesolutions.service;

public interface AjaxSampleSvc { 
  Article castVote(int rank);
}

这是一个被简化到几乎不可能的程度的例子,其中只有一篇文章可以投票。该服务由Spring管理,它使用的bean名是ajaxSampleSvc,它的持久性需求则依赖于ArticleDao。详情请参见applicationContext.xml。

为了把该服务公开为JavaScript对象,需要配置DWR,添加dwr.xml文件到WEB-INF目录下:

				
						
								
										
												
										
										
										
										
								
						
				

dwr.xml文件告诉DWR哪些服务是要直接向JavaScript代码公开的。注意,已经要求公开Spring bean ajaxSampleSvc。DWR将自动找到由应用程序设置的SpringApplicationContext。为此,必须使用标准的servlet过滤器ContextLoaderListener来初始化Spring ApplicationContext。

DWR被设置为一个servlet,所以把它的定义添加到web.xml:

						
								
										Ajax Examples
										
												
      org.springframework.web.context.ContextLoaderListener
  
										
										
												ajax_sample
												com.tearesolutions.web.AjaxSampleServlet
												1
										
										
												dwr-invoker
												DWR Servlet
												Direct Web Remoter Servlet
												uk.ltd.getahead.dwr.DWRServlet
												
														debug
														true
												
										
										
												ajax_sample
												/ajax_sample
										
										
												dwr-invoker
												/dwr/*
												

做完这些之后,可以加载http://localhost:7001/ajax-demo/dwr,看看哪些服务可用。结果如下:

图3. 可用的服务

单击ajaxSampleSvc链接,查看有关如何在HTML页面内直接使用服务的示例实现。其中包含的两个JavaScript文件完成了大部分的功能:

ajaxSampleSvc.js是动态生成的:

function ajaxSampleSvc() { }

ajaxSampleSvc.castVote = function(callback, p0)
{ 
  DWREngine._execute(callback, '/ajax-demo/dwr', 
 'ajaxSampleSvc', 'castVote', p0);
}

现在可以使用JavaScript对象ajaxSampleSvc替换所有的XmlHttpRequest代码,从而重构raw-ajax.html文件。可以在dwr-ajax.html文件中看到改动的结果;下面是新的JavaScript函数:

function castVote(rank) {
  ajaxSampleSvc.castVote(processResponse, rank);
}
function processResponse(data) {
 var voteText = "

Thanks for Voting!

" + "

Current ranking: " + data.voteAverage + " out of 5

" + "

Number of votes placed: " + data.numberOfVotes + "

"; 502 502'votes').innerHTML = voteText; }

惊人地简单,不是吗?由ajaxSampleSvc对象返回的Article域对象序列化为一个JavaScript对象,允许在它上面调用诸如numberOfVotes()和voteAverage()之类的方法。在动态生成并插入到DIV元素“votes”中的HTML代码内使用这些数据。

下一步工作

在后续文章中,我将继续有关Ajax的话题,涉及下面这些方面:

  • Ajax最佳实践

像许多技术一样,Ajax是一把双刃剑。对于一些用例,其应用程序其实没有必要使用Ajax,使用了反而有损可用性。我将介绍一些不适合使用的模式,突出说明Ajax的一些消极方面,并展示一些有助于缓和这些消极方面的机制。例如,对Nerfilix电影浏览器来说,Ajax是合适的解决方案吗?或者,如何提示用户确实出了一些问题,而再次单击按钮也无济于事?

  • 管理跨请求的状态

在使用Ajax时,最初的文档DOM会发生一些变化,并且有大量的页面状态信息存储在客户端变量中。当用户跟踪一个链接到应用程序中的另一个页面时,状态就丢失了。当用户按照惯例单击Back按钮时,呈现给他们的是缓存中的初始页面。这会使用户感到非常迷惑!

  • 调试技巧

使用JavaScript在客户端执行更多的工作时,如果事情不按预期方式进行,就需要一些调试工具来帮助弄清出现了什么问题。

结束语

本文介绍了Ajax方法,并展示了如何使用它来创建一个动态且响应灵敏的Web应用程序。通过使用DWR框架,可以轻松地把Ajax融合到站点中,而无需担心所有必须执行的实际管道工作。

特别感谢Getahead IT咨询公司的Joe Walker和他的团队开发出DWR这样神奇的工具。感谢你们与世界共享它!

下载

本文中演示的应用程序源代码可供下载:/info/codedown/200604576.htm(1.52 MB)。

参考资料

原文出处      An Introduction To Ajax

																		

posted @ 2006-06-07 12:56 东人EP 阅读(240) | 评论 (0)编辑 收藏

保守来说,AJAX在现在是热得不能再热的技术。没有人能否认,它拥有大批的支持者。在CNN上,它从二月份的一个不被看好的词语到十月份成长成一个初具雏形的技术。所以,有必要要看看为什么AJAX能发展成为现在的样子,为什么它能不断成长,并且在短的时间内迅速变得无处不在。所以,我用午夜谈话的风格,来给出需要AJAX技术的十大理由。

使用AJAX的十大理由:

10 XAML, XUL, XForms...等等。

9 服务端技术的不确定性。

8 Web2.0。

7 被软件工业领袖们强势采用。

6 和Flex 和 Flash等技术的很好的集成。

5 边际成本低。

4 能使常规的Web应用受益。

3 跨浏览器和跨平台。

2 以可用性和用户体验为王。

1 基于公开标准。

十大理由第一名:公开标准

让我们从第一条开始,AJAX技术是基于被各大浏览器和平台都支持的公开标准的技术。这意味着该技术不怕技术提供商的技术封锁。组成AJAX技术的大多数技术都能放心的使用很多年,而那些不是热点的、最新的和未经考验的技术只能使用一段时间。现在,对于绝大多数的用户和企业来说,浏览器是一个可信任的应用平台,这在五年前就不是个问题了。对于AJAX来说,FIREFOX浏览器的基础Mozilla 1.0的发布并且支持XML HTTP Request对象是一个转折点。这种允许异步数据交换的技术好多年前就被IE浏览器支持了。这种支持和FIREFOX浏览器的大量被采用真正的使人们理解了跨浏览器的富Internet应用成为了可能。

1)JavaScript or ECMA Script (Standard ECM A- 262):一个有趣的事情是,Javascript是经过长时间后才成为被人们接受的技术,长时间以来,很多公司采用非Javascript技术的方针,幸运的是,这种状况被迅速的改变。

http://www.ecma-international.org/publications/standards/Ecma-262.htm

2)XML:是一个来自W3C的、被广泛应用的标准。

http://www.w3.org/XML/

3)HTML:http://www.w3.org/MarkUp/.

4)CSS:http://www.w3.org/Style/CSS/.

5)XML HTTP Request Object:被Internet Explorer、Mozilla-based、Safari和Opera浏览器支持。

十大理由第二名:可用性

开发人员和设计人员开始认识到不仅大型的用户体验在市场上是成功的,而且也认识到这样体验是怎么来影响用户的开销的。基于AJAX技术的google地图比传统的选择MapQuest更成功,证明了提供更好的用户体验的产品的成功。AJAX技术是使网络应用有更好的可用性的一个领导性的技术。它允许从服务器端请求少量的信息,而不是整个网页。它增加了页面数据的更新但同时减少了页面的刷新和刷新等待,这些问题从网络已诞生就折磨着Web应用。

人们已经知道他们需要一个优秀的用户界面并且有对该界面的投资意愿。前提条件是:用户能够快速的取得信息不管数据是一个内部网的应用还是一个广域网的服务。

十大理由第三名:跨浏览器和跨平台的兼容性

IE和基于Mozilla的FIREFOX是占据市场分额最大的两个浏览器,并且它们都支持在浏览器上轻松创建基于AJAX的WEB应用。现在开发运行在更为先进的WEB浏览器上的基于AJAX的富WEB应用成为了可能。这是为什么AJAX应用变得如此流行的一个最重要的原因。其实很多开发人员多年前就意识到AJAX技术流行的可能,但一直没有流行是因为浏览器厂商的原因。感谢Mozilla和FIREFOX。

十大理由第四名:使常规的WEB应用受益

AJAX技术是当今WEB应用的门面——WEB应用获得的利益超过了桌面应用。这些利益包括部署应用的低投入、维护方便、缩短开发时间和不需要安装。这些都是促使商业和用户自从上世纪九十年代以来采用WEB应用的优点。AJAX技术不但能使WEB应用获得益处,而且使最终用户受益。

十大理由第五名:促使技能、工具和技术的升级

由于AJAX基于这些年一直使用的一些公开标准,很多的开发人员就会有新的技术方面的要求以便能够开发AJAX应用。但这并不意味着开发团队从基于HTML和FORM的应用转移到富AJAX型应用需要很高的学习曲线。同时,这意味着开发WEB应用的开发团体需要加速将他们的用户接口升级到AJAX,但并不需要一个大规模的升级和重写他们的WEB应用。自从上世纪九十年代以来,在开发基于浏览器应用方法花了大量投资的那些系统强烈的希望能在现有的应用的基础上增加用户体验。

十大理由第六名:能和Flex 和 Flash等技术的很好的集成

大多数的开发社区都不再支持Flash vs AJAX的火热讨论,这两种技术都在不同的场合拥有各自的优点和缺点,但是它们有大量的机会可以集成到一起工作。很多的开发人员和技术提供商意识到这一点,并且开发出了伟大的产品来集成Flex和AJAX协调使用。我们也热切的期望看到两者能在Macromedia里一起工作。

十大理由第七名:采用率

AJAX被业内领袖广泛采用证明了市场的欢迎程度和该技术组的正确。每一个该技术的使用者都成为了胜利者:包括google、yahoo、Amazon和微软等等。是google地图吸引了WEB开发人员的目光,当人们开始调查是什么原因使得google有着如此惊人的用户体验的时候,人们揭开了罩在AJAX头上的面纱。

当然,仅仅是google使用AJAX是不够使得这项技术跨越从支流到主流的鸿沟的。但是,如果你看一看使用AJAX技术的客户如eBusiness Applications (www.ebusinessapps.com) or Tibco (http://www.tibco.com)等的表单时,你就会发现财富500强包括主要的金融机构、政府机构、航空公司和其他主要商业机构采用AJAX,并且在AJAX成为硬通货之前很早就开始使用了。

十大理由第八名:WEB2.0

喜欢也好,厌恶也罢。WEB2.0运行吸引了开发人员、风险投资商、市场和最终用户等所有的目光。这些明确的促进了AJAX的早期应用。当大肆的宣传过去以后,我们将会看到什么呢?从BackPack到google地图,AJAX界面是WEB2.0应用的主要的组成。大量的宣传有助于加速采用AJAX,而在可用性上的获益会使得该技术被广发应用。WEB2.0的一个主要原则是使用WEB作为一个应用开发的平台,而不仅仅是一个网页。高的可用性和交互能力的用户界面是一切应用平台的主要组成部分。

十大理由第九名:AJAX基于服务器技术的不确定性

和AJAX技术的浏览器的独立性相同,该技术也兼容所有的标准型的服务器和服务端语言,如PHP, ASP. ASP.Net, Perl, JSP, Cold Fusion等等,选择属于你的那种然后开始。这使得AJAX开发独立,因为所有的开发人员都能使用并且一起讨论相同的表现层。

十大理由第十名:基于WEB的下一代RIA技术还没有出现

今天就使用XUL技术开发应用的人是伟大的,因为现在90%的浏览器还不支持这种技术,对于大多数的实际应用来说,使用这种技术不切合实际。然而,AJAX开发人员应该给出一部分的注意力在这些技术,如XAML 和XUL上。毫无疑问,这些技术将使开发富WEB应用变得简单。但是它们可能相互不兼容并且拥有不同的市场需求或动力。

在今后一段时间,AJAX技术将极大的提高WEB应用的可用性。AJAX技术并不完美,不是“火箭科学”许多的开发人员和技术公司始终在尝试RIA的其他更好的技术。而实际的问题是AJAX技术现在已经存在并且应用的很好,它跨浏览器、跨平台,而且不管是用户还是开发人员都喜欢它的作用。特征鲜明的AJAX应用如google地图已经成为了本领域的领导者(还有人使用MapQuest吗?)同样的,领先的财富500强使用AJAX技术并且贡献了开发工具给社区了。一般来说,业内在使用AJAX技术上取得了一致并且正在使用它。再强调一次,RIA应用和WEB应用使用了AJAX获得的一个主要的优势不仅仅是开发人员的一个工具,而是一个现象:它改变了我们开发WEB应用的方式。没人能说得清楚在RIA应用方面,哪一种技术会取代它,会在什么时候取代它;但是很多因素都支持AJAX应用应该持续好多年。

关于作者

Andre Charland从事Internet软件开始超过十年之久,他是eBusiness Applications (www.ebusinessapps.com)公司的主席和创建者之一。他和Dave Johnson在1998年创建了该公司。他主要的经验在可用性、市场、项目管理和基于构件的软件开发。所受教育包括:在Vancouver, BC的Simon Fraser University,他在那里读计算机科学和工商管理。他作为开发者、管理者和架构师等不同身份有上百个Internet项目的经验。

posted @ 2006-06-07 12:53 东人EP 阅读(136) | 评论 (0)编辑 收藏

 1 /*
 2     递归(recursion)
 3     递归是常用的一种解决问题的方法,即把问题逐渐简化。
 4     递归的基本思想就是“自己调用自己”,一个使用递归技术的方法将直接或间接地调用自身的方法。
 5     利用递归可以用简单程序解决复杂的问题。
 6     我们先来看看一个用递归求阶乘的例子,如下所示。
 7 */

 8 public   class   recursion
 9 {
10      static   long  function( int  n)
11      {
12          if  (n  ==   1 )
13          {
14              return   1 ;
15         }

16          else
17          {
18              return  n  *  function(n - 1 );
19         }

20     }

21
22      public   static   void  main(String[] args) 
23      {
24          int  n  =   10 ;
25         System.out.println(n  +   " !=  "   +  function(n));
26     }

27 }

28 /*
29     程序的输出结果为:
30     10!=3628800
31     递归的结构主要包括两部分:
32     1.定义递归头:任何一个递归方法都必须有一个递归头,也就是递归终止的条件。
33        即要解决的问题被简化到足够简单时,将可以直接获得问题的答案,而不必再调用自身。
34        例如上例中求1!可以直接得到1,就是递归头。
35     2.定义如何从同性质的简化问题求得当前问题。
36        问题的解答依赖于一个同性质问题的解答,而解答这个同性质的问题就是用不同的参数来调用递归方法自身。
37        例如上例中求n!这个问题,被划分为求(n-1)!和(n-1)!*n两个步骤。
38        依次类推求(b-1)!可以继续划分。。。。。
39 */

40 /*
41     下面我们利用递归来求解8个皇后问题。
42     8个皇后问题说得是:在国际象棋的棋盘上,放置8个皇后,如何放才能使得这8个皇后无论横着看,竖着看,斜着看都不在同一条直线上。
43     如图所示是一种可能的摆放情况:其中放置皇后的地方标记Q。
44 */

45 //  Queen.Java
46 import  javax.swing. * ;
47 public   class  Queens
48 {
49      int [] a  =   new   int [ 8 ];
50      int [] b  =   new   int [ 15 ];
51      int [][] c  =   new   int [ 8 ][ 8 ];
52
53      void  next( int  i)
54      {
55          for ( int  j = 0 ; j  <   8 ; j ++ )
56          {
57              if (a[j]  ==   0   &&  b[i + j}
  ==   0   &&  c[i - j + 7 ==   0 )
58              {
59                 a[j]  =  b[i + j]  =  c[i - j + 7 =   1 ;
60                 Queen[i][j]  =   1 ;
61                  if (i < 7 )
62                  {
63                     next(i + 1 );
64                 }

65                  else
66                  {
67                     String output  =   new  String();
68                      for ( int  m = 0 ; m  <   8 ; m ++ )
69                      {
70                          for ( int  n = 0 ; n  <   8 ; n ++ )
71                             output  +=   "      "   +  d[m][n]  +   "       " ;
72                         output  +=   " \n " ;
73                     }

74                      // 每种可能的情况以0、1表示(1表示皇后)输出
75                     JTextArea outputArea  =   new  JTextArea();
76                     outputArea.setText(output);
77                     JOptionPane.showMessageDialog( null , outputArea,  " One Possible distribution " , JOptionPane.INFORMATION_MESSAGE);
78                 }

79                 a[j]  =  b[i + j]  =  c[i - j + 7 =  Queen[i][j]  =   0 ;
80             }

81         }

82     }

83
84      public   static   void  main(String args[])
85      {
86         Queens one  =   new  Queens();
87         one.next( 0 );
88         System.exit( 0 );
89     }

90 };

posted @ 2006-06-07 10:25 东人EP 阅读(303) | 评论 (0)编辑 收藏

AJAX实例入门

一、开门见山

  这些时间,瞎子也看得见,AJAX正大踏步的朝我们走来。不管我们是拥护也好,反对也罢,还是视而不见,AJAX像一阵潮流,席转了我们所有的人。

  关于AJAX的定义也好,大话也好,早有人在网上发表了汗牛充栋的文字,在这里我也不想照本宣科。

  只想说说我感觉到的一些优点,对于不对,大家也可以和我讨论:

  首先是异步交互,用户感觉不到页面的提交,当然也不等待页面返回。这是使用了AJAX技术的页面给用户的第一感觉。

  其次是响应速度快,这也是用户强烈体验。

  然后是与我们开发者相关的,复杂UI的成功处理,一直以来,我们对B/S模式的UI不如C/S模式UI丰富而苦恼。现在由于AJAX大量使用JS,使得复杂的UI的设计变得更加成功。

  最后,AJAX请求的返回对象为XML文件,这也是一个潮流,就是WEB SERVICE潮流一样。易于和WEB SERVICE结合起来。

  好了,闲话少说,让我们转入正题吧。

  我们的第一个例子是基于Servlet为后台的一个web应用。

  二、基于Servlet的AJAX

  这是一个很常见的UI,当用户在第一个选择框里选择ZHEJIANG时,第二个选择框要出现ZHEJIANG的城市;当用户在第一个选择框里选择JIANGSU时,第二个选择框里要出现JIANGSU的城市。

  首先,我们来看配置文件web.xml,在里面配置一个servlet,跟往常一样:

<web-app version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<servlet>
<servlet-name>SelectCityServlet</servlet-name>
<servlet-class>com.stephen.servlet.SelectCityServlet</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>SelectCityServlet</servlet-name>
<url-pattern>/servlet/SelectCityServlet</url-pattern>
</servlet-mapping>

</web-app>

  然后,来看我们的JSP文件:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>MyHtml.html</title>

<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">

<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->

</head>
<script type="text/javascript">
function getResult(stateVal) {
  var url = "servlet/SelectCityServlet?state="+stateVal;
  if (window.XMLHttpRequest) {
  req = new XMLHttpRequest();
  }else if (window.ActiveXObject) {
  req = new ActiveXObject("Microsoft.XMLHTTP");
  }
  if(req){
  req.open("GET",url, true);
  req.onreadystatechange = complete;
  req.send(null);
  }
}
function complete(){
  if (req.readyState == 4) {
  if (req.status == 200) {
  var city = req.responseXML.getElementsByTagName("city");
  file://alert(city.length);
  var str=new Array();
  for(var i=0;i<city.length;i++){
  str[i]=city[i].firstChild.data;
  }
  file://alert(document.getElementById("city"));
  buildSelect(str,document.getElementById("city"));
  }
  }
}
function buildSelect(str,sel) {
  sel.options.length=0;
  for(var i=0;i<str.length;i++) {
  sel.options[sel.options.length]=new Option(str[i],str[i])
  }
}
</script>
<body>
<select name="state" onChange="getResult(this.value)">
  <option value="">Select</option>>
  <option value="zj">ZEHJIANG</option>>
  <option value="zs">JIANGSU</option>>
</select>
<select id="city">
  <option value="/blog/">CITY</option>
</select>
</body>
</html>

  第一眼看来,跟我们平常的JSP没有两样。仔细一看,不同在JS里头。

  我们首先来看第一个方法:getResult(stateVal),在这个方法里,首先是取得XmlHttpRequest;然后设置该请求的url:req.open("GET",url, true);接着设置请求返回值的接收方法:req.onreadystatechange = complete;该返回值的接收方法为——complete();最后是发送请求:req.send(null);

  然后我们来看我们的返回值接收方法:complete(),这这个方法里,首先判断是否正确返回,如果正确返回,用DOM对返回的XML文件进行解析。关于DOM的使用,这里不再讲述,请大家参阅相关文档。得到city的值以后,再通过buildSelect(str,sel)方法赋值到相应的选择框里头去。

  最后我们来看看Servlet文件:

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* @author Administrator
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class SelectCityServlet extends HttpServlet {


  public SelectCityServlet() {
  super();
  }

  public void destroy() {
  super.destroy();
  }

  public void doGet(HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
  response.setContentType("text/xml");
  response.setHeader("Cache-Control", "no-cache");
  String state = request.getParameter("state");
  StringBuffer sb=new StringBuffer("<state>");
  if ("zj".equals(state)){
  sb.append("<city>hangzhou</city><city>huzhou</city>");
  } else if("zs".equals(state)){
  sb.append("<city>nanjing</city><city>yangzhou</city><city>suzhou</city>");
  }
  sb.append("</state>");
  PrintWriter out=response.getWriter();
  out.write(sb.toString());
  out.close();
  }
}

  这个类也十分简单,首先是从request里取得state参数,然后根据state参数生成相应的XML文件,最后将XML文件输出到PrintWriter对象里。

  到现在为止,第一个例子的代码已经全部结束。是不是比较简单?我们进入到第二个实例吧!这次是基于JSP的AJAX的一个应用。

  三、基于JSP的AJAX

这个例子是关于输入校验的问题,我们知道,在申请用户的时候,需要去数据库对该用户性进行唯一性确认,然后才能继续往下申请。

  这种校验需要访问后台数据库,但又不希望用户在这里提交后等待,当然是AJAX技术大显身手的时候了。

  首先来看显示UI的JSP:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Check.html</title>

<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">

<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->

</head>
<script type="text/javascript">
var http_request = false;
function send_request(url) {//初始化、指定处理函数、发送请求的函数
http_request = false;
file://开始初始化XMLHttpRequest对象
if(window.XMLHttpRequest) { file://Mozilla 浏览器
  http_request = new XMLHttpRequest();
  if (http_request.overrideMimeType) {//设置MiME类别
  http_request.overrideMimeType('text/xml');
  }
}
else if (window.ActiveXObject) { // IE浏览器
  try {
  http_request = new ActiveXObject("Msxml2.XMLHTTP");
  } catch (e) {
  try {
  http_request = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (e) {}
  }
}
if (!http_request) { // 异常,创建对象实例失败
  window.alert("不能创建XMLHttpRequest对象实例.");
  return false;
}
http_request.onreadystatechange = processRequest;
// 确定发送请求的方式和URL以及是否同步执行下段代码
http_request.open("GET", url, true);
http_request.send(null);
}
// 处理返回信息的函数
  function processRequest() {
  if (http_request.readyState == 4) { // 判断对象状态
  if (http_request.status == 200) { // 信息已经成功返回,开始处理信息
  alert(http_request.responseText);
  } else { file://页面不正常
  alert("您所请求的页面有异常。");
  }
  }
  }
function userCheck() {
var f = document.form1;
var username = f.username.value;
if(username=="") {
  window.alert("The user name can not be null!");
  f.username.focus();
  return false;
}
else {
  send_request('check1.jsp?username='+username);
}
}

</script>
<body>
<form name="form1" action="" method="post">
User Name:<input type="text" name="username" value="">&nbsp;
<input type="button" name="check" value="check" onClick="userCheck()">
<input type="submit" name="submit" value="submit">
</form>
</body>
</html>

  所有的JS都跟上一个例子一样,不同的只是对返回值的操作,这次是用alert来显示:alert(http_request.responseText);

  我们来看处理逻辑JSP:

<%@ page contentType="text/html; charset=gb2312" language="java" errorPage="" %>
<%
String username= request.getParameter("username");
if("educhina".equals(username)) out.print("用户名已经被注册,请更换一个用户名。");
else out.print("用户名尚未被使用,您可以继续。");
%>

  非常简单,先取得参数,然后作处理,最后将结果打印在out里。
  我们的第三个例子仍然以这个唯一性校验为例子,这次结合Struts开发框架来完成AJAX的开发。

  四、基于Struts的AJAX

  首先,我们仍然是对Struts应用来做配置,仍然是在struts-config,xml文件里做配置,如下:

<action type="com.ajax.CheckAction"
  scope="request" path="/ajax/check">
  <forward name="success" path="/check.jsp"/>
</action>


  跟普通的Struts应用的配置一样,只是没有ActionForm的配置。

  下面是Action类:

package com.ajax;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;

/**
* @author Administrator
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class CheckAction extends Action
{
public final ActionForward execute(ActionMapping mapping, ActionForm form,
  HttpServletRequest request,
  HttpServletResponse response)
throws Exception
{
  System.out.println("haha...............................");
  String username= request.getParameter("username");
  System.out.println(username);
  String retn;
  if("educhina".equals(username)) retn = "Can't use the same name with the old use,pls select a difference...";
  else retn = "congraducation!you can use this name....";
  PrintWriter out=response.getWriter();
  out.write(retn);
  out.close();
  return mapping.findForward("success");
}
public static void main(String[] args)
{
}
}

  我们可以看到里面的逻辑跟上例中Servlet里的逻辑一样。最后,我们来看看JSP:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Check.html</title>

<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="this is my page">

<!--<link rel="stylesheet" type="text/css" href="./styles.css">-->

</head>
<script type="text/javascript">
var http_request = false;
function send_request(url) {//初始化、指定处理函数、发送请求的函数
http_request = false;
file://开始初始化XMLHttpRequest对象
if(window.XMLHttpRequest) { file://Mozilla 浏览器
  http_request = new XMLHttpRequest();
  if (http_request.overrideMimeType) {//设置MiME类别
  http_request.overrideMimeType('text/xml');
  }
}
else if (window.ActiveXObject) { // IE浏览器
  try {
  http_request = new ActiveXObject("Msxml2.XMLHTTP");
  } catch (e) {
  try {
  http_request = new ActiveXObject("Microsoft.XMLHTTP");
  } catch (e) {}
  }
}
if (!http_request) { // 异常,创建对象实例失败
  window.alert("不能创建XMLHttpRequest对象实例.");
  return false;
}
http_request.onreadystatechange = processRequest;
// 确定发送请求的方式和URL以及是否同步执行下段代码
http_request.open("GET", url, true);
http_request.send(null);
}
// 处理返回信息的函数
  function processRequest() {
  if (http_request.readyState == 4) { // 判断对象状态
  if (http_request.status == 200) { // 信息已经成功返回,开始处理信息
  alert(http_request.responseText);
  } else { file://页面不正常
  alert("您所请求的页面有异常。");
  }
  }
  }
function userCheck() {
var f = document.forms[0];
var username = f.username.value;
if(username=="") {
  window.alert("The user name can not be null!");
  f.username.focus();
  return false;
}
else {
  send_request('ajax/check.do?username='+username);
}
}

</script>
<body>
<form name="form1" action="" method="post">
User Name:<input type="text" name="username" value="">&nbsp;
<input type="button" name="check" value="check" onClick="userCheck()">
<input type="submit" name="submit" value="/blog/submit">
</form>
</body>
</html>

  我们可以看到,JSP基本是一样的,除了要发送的url:ajax/check.do?username="+username。

  最后,我们来看一个基于Struts和AJAX的复杂一些的例子,如果不用AJAX技术,UI的代码将十分复杂
 
 

posted @ 2006-06-06 21:45 东人EP 阅读(464) | 评论 (1)编辑 收藏

把鼠标放在图元上点击一下,就能出现tips,但是这个tips的内容是系统生成的,并且只能显示一行,也不知道能不能编程修改它的显示方式,所以我就写了几行代码,来实现自定义的多行tips显示。

步骤:
1)在Winform中加入MapControl和一个TextBox
2)将TextBox的属性MultiLine设为True, Visable设为False,BorderStyle设为FixSingle
3)捕获MapControl1的MouseDown和MouseUp事件,函数内容如下:

        private void mapControl1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            //如果没有转载任何tab文件,则返回
           if(mapControl1.Map.Layers.Count == 0 || this.currentLayerName=="")//currentLayerName是顶层Layer的名字,同时也是Table的名字
                return;
           MapInfo.Engine.Selection selection=MapInfo.Engine.Session.Current.Selections.DefaultSelection;
           MapInfo.Data.Table table=MapInfo.Engine.Session.Current.Catalog.GetTable(currentLayerName);
           MapInfo.Data.IResultSetFeatureCollectionfeatureCollection=selection[table];
            //如果没有选中任何图元,或者选中多个图元,则返回
            if(featureCollection==null||featureCollection.Count!=1)
                return;

            //取第一个图元
            MapInfo.Geometry.Geometry geometry=featureCollection[0].Geometry;
            //创建连接和命令来查询table中的数据
            MapInfo.Data.MIConnection connection=new MapInfo.Data.MIConnection();
            MapInfo.Data.MICommand command=connection.CreateCommand();
            command.CommandText="SELECT * FROM "+currentLayerName+" WHERE Objwithin @featureObject";
            command.Parameters.Add("@featureObject",geometry);
            connection.Open();
            MapInfo.Data.MIDataReader dataReader=command.ExecuteReader();
            int n=dataReader.FieldCount;
            this.textBoxInfoTips.Clear();
            //把查询到的内容放进tips中
            for(int i=0;i<n;i++)
            {
              this.textBoxInfoTips.AppendText(dataReader.GetName(i)+"\t");
            }
            this.textBoxInfoTips.AppendText("\n");
            while(dataReader.Read())
            {
                for(int i=0;i<n;i++)
                {
                    object o=dataReader.GetValue(i);
                    if(o==DBNull.Value)
                      this.textBoxInfoTips.AppendText("null\t");
                    else
                      this.textBoxInfoTips.AppendText(o.ToString()+"\t");
                }
                this.textBoxInfoTips.AppendText("\n");
            }
            //改变tips的显示位置
            this.textBoxInfoTips.Location=new System.Drawing.Point(e.X,e.Y+50);
            this.textBoxInfoTips.Visible=true;
        }

        private void mapControl1_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            this.textBoxInfoTips.Visible=false;
        }

=====
代码已测试通过。

posted @ 2006-06-01 11:51 东人EP 阅读(700) | 评论 (1)编辑 收藏

1 设置图层可选状态
/**//// <summary>
/// 改变层的可选择状态
/// </summary>
/// <param name="selectableStatus"></param>
/// <returns></returns>
public bool LayerSelectableStatusUpdate(string tableAlias,bool selectableStatus)
{
 if(mapControl1.Map.Layers[tableAlias]==null)
  return false;

 

MapInfo.Mapping.LayerHelper.SetSelectable(mapControl1.Map.Layers[tableAlias],selectableStatu

s);
 return true;
}

 2 设置层的可用状态


/**//// <summary>
/// 改变层的可用状态为status
/// </summary>
/// <param name="layerName"></param>
/// <param name="status"></param>
public void LayerEnableStatusUpdate(string layerName,bool status)
{
 if(mapControl1.Map.Layers[layerName]!=null && mapControl1.Map.Layers[layerName].Enabled!

=status)
 {
  mapControl1.Map.Layers[layerName].Enabled=status;
 }
}
 3 层居中,看全图


/**//// <summary>
/// 使指定层全部呈现在地图的可见范围中
/// </summary>
/// <param name="tableAlias">层别名</param>
public void LayerCenter(string layerName)
{
 MapInfo.Data.Table[] tables=new MapInfo.Data.Table[1];
 tables[0] = MapInfo.Engine.Session.Current.Catalog.GetTable(layerName);
 if(tables[0]==null)
  return;
 if(mapControl1.Map.Layers[layerName]==null)
  return;

 if(mapControl1.Map.Layers[layerName].Enabled == false)
  mapControl1.Map.Layers[layerName].Enabled = true;

 MapInfo.Mapping.IMapLayerFilter iMapLayerFilter =

MapInfo.Mapping.MapLayerFilterFactory.FilterByTable(tables);
 MapInfo.Mapping.MapLayerEnumerator mapLayerEnumerator =

mapControl1.Map.Layers.GetMapLayerEnumerator(iMapLayerFilter);
 mapControl1.Map.SetView(mapLayerEnumerator);
 OnFeatureUnclick();
}

 

4 放大缩小地图


/**//// <summary>
/// 放大地图
/// </summary>
/// <param name="times">放大倍数,有效值1-10</param>
public void ZoomIn(uint times)
{
 if(times<1 || times>10) return;
 MapInfo.Geometry.Distance previousZoom=this.mapControl1.Map.Zoom;
 mapControl1.Map.Zoom=new MapInfo.Geometry.Distance(previousZoom.Value/

(2*times),previousZoom.Unit);
}
/**//// <summary>
/// 缩小地图
/// </summary>
/// <param name="times">缩小倍数,有效值1-10</param>
public void ZoomOut(uint times)
{
 if(times<1 || times>10) return;
 MapInfo.Geometry.Distance previousZoom=this.mapControl1.Map.Zoom;
 mapControl1.Map.Zoom=new MapInfo.Geometry.Distance(previousZoom.Value*

(2*times),previousZoom.Unit);
}
 

5 移动层的顺序
mapControl1.Map.Layers.Move(index1,index2);

6 图元/图层透明


/**//// <summary>
/// 设置层的透明与否
/// </summary>
/// <param name="layerName">层名</param>
/// <param name="opaqueType">不透明类型 ALL 全部不透明 BORDER 只有边界不透明(内部透明)

NONE 全部透明</param>
/// <param name="borderColor">如果是边界不透明,此处设置边界颜色</param>
public void LayerTransparent(string layerName,OpaqueType opaqueType,System.Drawing.Color

borderColor)
{

 MapInfo.Styles.CompositeStyle compositeStyle = GetOpaqueStyle(opaqueType,borderColor);

 //创建连接和命令来更新table中的数据
 MapInfo.Data.MIConnection connection=new MapInfo.Data.MIConnection();
 connection.Open();
 MapInfo.Data.MICommand command=connection.CreateCommand();
 command.CommandText = "update " + layerName + " set obj=obj,MI_Style=@style";
 command.Parameters.Add("@style",compositeStyle);
 command.Prepare();
 command.ExecuteNonQuery();

 //关闭连接
 command.Cancel();
 command.Dispose();
 connection.Close();
 connection.Dispose();
}
/**//// <summary>
/// 创建style
/// </summary>
/// <param name="opaqueType">不透明类型:ALL全部不透明(白色实心);BORDER边界不透明(填充部

分透明);NONE全透明</param>
/// <param name="borderColor">如果opaqueType=BORDER,此处设定边界颜色</param>
/// <returns>组合style</returns>
private MapInfo.Styles.CompositeStyle GetOpaqueStyle(OpaqueType

opaqueType,System.Drawing.Color borderColor)
{
 MapInfo.Styles.SimpleInterior simpleInterior;
 if(opaqueType==OpaqueType.ALL)
  simpleInterior= new MapInfo.Styles.SimpleInterior(); //缺省构造函数是白色实心
 else
  simpleInterior= new MapInfo.Styles.SimpleInterior(1); //0是线透明,1是面透明
 
 MapInfo.Styles.LineWidth lineWidth = new

MapInfo.Styles.LineWidth(1,MapInfo.Styles.LineWidthUnit.Point);

 MapInfo.Styles.SimpleLineStyle simpleLineStyle;
 if(opaqueType==OpaqueType.ALL)
  simpleLineStyle = new MapInfo.Styles.SimpleLineStyle(lineWidth);
 else if(opaqueType==OpaqueType.BORDER)
  simpleLineStyle = new MapInfo.Styles.SimpleLineStyle(lineWidth,2,borderColor); //2表示填充

透明,即能够显示轮廓
 else
  simpleLineStyle = new MapInfo.Styles.SimpleLineStyle(lineWidth,0); //0表示全部透明,即连轮

廓都看不到

 MapInfo.Styles.AreaStyle areaStyle = new

MapInfo.Styles.AreaStyle(simpleLineStyle,simpleInterior);

 MapInfo.Styles.CompositeStyle compositeStyle = new

MapInfo.Styles.CompositeStyle(areaStyle,null,null,null);
 
 return compositeStyle;
}

 

7 选择全部图元


MapInfo.Engine.Session.Current.Catalog.Search(
 table,
 MapInfo.Data.SearchInfoFactory.SearchAll(),
 MapInfo.Engine.Session.Current.Selections.DefaultSelection,
 MapInfo.Data.ResultSetCombineMode.Replace);

 
8 设置坐标系
缺省情况下,MapXtreme使用的CoordSys是经纬度投影(LongLat)和WGS84基准面。我想修改投影类型为

CoordSysType.TransverseMercator ,基准面为DatumID.Pulkovo1942
   MapInfo.Geometry.CoordSysFactory

coordSysFactory=MapInfo.Engine.Session.Current.CoordSysFactory;
   mapControl1.Map.SetDisplayCoordSys(coordSysFactory.CreateCoordSys("mapinfo:coordsys

8,1001,7,117,0,1,20500000,0"));
  
   coordSysFactory.CreateCoordSys("mapinfo:coordsys 8,1001,7,117,0,1,20500000,0") 默认的原点

是(B=0,L=117),如果要把原点设在(23,117)应该怎么写这个字符串呢?
   coordSysFactory.CreateCoordSys("mapinfo:coordsys 8,1001,7,114,23,1,20500000,25000000")
  
9 保存新画的层为tab文件
下面的源码是新建一个永久表,然后在表中添加feature,然后保存为硬盘上的tab文件。


        private MapInfo.Data.Table CreateNewMapDataTable(string tableName)
        {
            //以下代码是建立永久表
           MapInfo.Data.TableInfoNative

tableInfoNative=newMapInfo.Data.TableInfoNative(tableName);
            tableInfoNative.TablePath=@"D:\DATA\"+tableName+".TAB";
           tableInfoNative.Columns.Add(MapInfo.Data.ColumnFactory.CreateIntColumn("ID"));
           tableInfoNative.Columns.Add(MapInfo.Data.ColumnFactory.CreateStyleColumn());
           MapInfo.Geometry.CoordSys coordSys =mapControl1.Map.GetDisplayCoordSys();
          

tableInfoNative.Columns.Add(MapInfo.Data.ColumnFactory.CreateFeatureGeometryColumn(coordSys)

);
           MapInfo.Data.Table table

=MapInfo.Engine.Session.Current.Catalog.CreateTable(tableInfoNative);

            //以下代码是建立临时表
//           MapInfo.Data.TableInfo tableInfo

=MapInfo.Data.TableInfoFactory.CreateTemp(tableName);          
//           tableInfo.Columns.Add(MapInfo.Data.ColumnFactory.CreateIntColumn("ID"));
//           MapInfo.Data.Table table

=MapInfo.Engine.Session.Current.Catalog.CreateTable(tableInfo);

            MapInfo.Mapping.FeatureLayer featureLayer =

newMapInfo.Mapping.FeatureLayer(table);
            this.mapControl1.Map.Layers.Add(featureLayer);
            return table;
        }

        private void AddFeaturesAndSave()
        {
           MapInfo.Styles.SimpleLineStyle simpleLineStyle =

newMapInfo.Styles.SimpleLineStyle(new

MapInfo.Styles.LineWidth(1,MapInfo.Styles.LineWidthUnit.Point));
           MapInfo.Styles.CompositeStyle compositeStyle =

newMapInfo.Styles.CompositeStyle(null,simpleLineStyle, null, null);
           MapInfo.Geometry.CoordSys coordSys =mapControl1.Map.GetDisplayCoordSys();

            MapInfo.Data.Table table = CreateNewMapDataTable("NewTable");
            MapInfo.Data.TableInfo tableInfo = table.TableInfo;
            while(……)
            {
               MapInfo.Data.Feature feature = newMapInfo.Data.Feature(tableInfo.Columns);

                feature.Geometry = ……
                feature.Style = ……
                feature["ID"] = ……
                table.InsertFeature(feature);
            }
            tableInfo.WriteTabFile(); //保存为.tab文件

            mapControl1.Refresh();
        }

10 计算缩放比例


/**//// <summary>
/// 重画控件时计算缩放比例
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void mapControl1_Paint(object sender,PaintEventArgs e)
{
 MapInfo.Geometry.Distance zoomDistance=this.mapControl1.Map.Zoom;
 double zoom=Convert.ToDouble(Convert.ToInt32(zoomDistance.Value*16.09))/10;
 this.statusBar1.Text="缩放比例:"+zoom.ToString()+" 千米";
}

posted @ 2006-06-01 11:48 东人EP 阅读(2521) | 评论 (0)编辑 收藏


向地图中加入点程序代码
// 由桌面坐标转换为地理坐标 
System.Drawing.PointF DisplayPoint = new PointF(e.X,e.Y);
MapInfo.Geometry.DPoint MapPoint = new MapInfo.Geometry.DPoint();
MapInfo.Geometry.DisplayTransform converter = this.mapControl1.Map.DisplayTransform;
converter.FromDisplay(DisplayPoint, out MapPoint);
this.statusBar1.Text = "Cursor Location: " + MapPoint.x.ToString() + ", " + MapPoint.y.ToString();
MapInfo.Geometry.Point pnt = new MapInfo.Geometry.Point(this.mapControl1.Map.GetDisplayCoordSys(), MapPoint);
Table table = Session.Current.Catalog.OpenTable(@"C:\Map\CHCTY_2K.tab");      

MapInfo.Styles.SimpleVectorPointStyle vs = new MapInfo.Styles.SimpleVectorPointStyle();
MapInfo.Styles.CompositeStyle cs = new MapInfo.Styles.CompositeStyle(null, null, null, vs);      
Feature f = new Feature(pnt, cs);      
//MapInfo.Data.Key k = table.InsertFeature(f);


// 打开需要编辑的表
Table table = Session.Current.Catalog.OpenTable(@"C:\Map\CHCTY_2K.tab");
// 定义列集合 
Columns cols = new Columns();
cols.Add(ColumnFactory.CreateFeatureGeometryColumn(mapControl1.Map.GetDisplayCoordSys()));
cols.Add(ColumnFactory.CreateStringColumn("Place_Name", 40));
cols.Add(ColumnFactory.CreateStringColumn("Country", 40));
cols.Add(ColumnFactory.CreateStringColumn("Latitude", 20));
cols.Add(ColumnFactory.CreateStringColumn("Longitude", 20));
cols.Add(ColumnFactory.CreateStyleColumn());
// 定义图形特征
MapInfo.Geometry.FeatureGeometry fg = new MapInfo.Geometry.Point(mapControl1.Map.GetDisplayCoordSys(), new DPoint(pnt.X, pnt.Y)) as FeatureGeometry;
// 定义图形特征类型
MapInfo.Styles.SimpleVectorPointStyle vs = new MapInfo.Styles.SimpleVectorPointStyle(35, Color.Chocolate, 15);
MapInfo.Styles.CompositeStyle cs = new MapInfo.Styles.CompositeStyle(null, null, null, vs); 
string strLatitude;
string strLongitude;
this.TransformCoordSysToDMS(pnt.X, pnt.Y, out strLongitude, out strLatitude);
// 写入其他信息窗体
InformationForm infoForm = new InformationForm(strLongitude, strLatitude);
infoForm.ShowDialog();
// 为插入的记录付值
object[] sValue = new object[6]{fg, infoForm.Place_Name, infoForm.Country, infoForm.Latitude, infoForm.Longitude, cs};
Feature fe = new Feature(cols, sValue);
table.InsertFeature(fe); 

posted @ 2006-06-01 11:46 东人EP 阅读(838) | 评论 (3)编辑 收藏

仅列出标题
共8页: 1 2 3 4 5 6 7 8