<html>
<head>
<script type="text/javascript">
var oWD = new ActiveXObject("Word.Application");
var oDC = oWD.Documents.Add("",0,1);
var oRange =oDC.Range(0,1);
function word(id,way){
var sel = document.body.createTextRange();
sel.moveToElementText(id);
sel.select();
sel.execCommand(way);
oRange.Paste();
}
function test(){
var table=document.getElementById('table1');
var table_cells = table.rows[0].cells;
var form_elements = document.getElementById('huahai');
word(div_content,'Copy'); //調(diào)用word函數(shù),將div_content范圍內(nèi)容拷貝到word里面。
for(i=0;i<table_cells.length;i++){
oRange =oDC.Range(oRange.End-1,oRange.End); //設(shè)定位置依次由上往下、從左往右
var sel = document.body.createTextRange();
sel.moveToElementText(table_cells[i]); //將單元格內(nèi)容復(fù)制到word
sel.select();
sel.execCommand("Copy");
sel.moveEnd('character'); //不加這句導(dǎo)出不了,里面參數(shù)為character、不是copy
oRange.Paste();
oRange =oDC.Range(oRange.End-1,oRange.End);
}
oRange =oDC.Range(oRange.End-1,oRange.End); //復(fù)制不同的東西,需要寫這句繼續(xù) 寫死的這句話就是位置
var img = document.getElementById('img');
word(img,'Copy');//將img范圍內(nèi)容拷貝到word里面。
oRange =oDC.Range(oRange.End-1,oRange.End);
var text_area = document.getElementById('text_area');
word(text_area,'Copy');//將text_area范圍內(nèi)容拷貝到word里面。
oRange =oDC.Range(oRange.End-1,oRange.End);
oWD.Application.Visible = true; //這句意思是所有操作完畢后,在顯示出來,如果寫在里面,會(huì)發(fā)現(xiàn)word打開后,什么標(biāo)簽啊、內(nèi)容啊就跟打字機(jī)一樣往里面填
}
</script>
</head>
<body>
<form action="" id="huahai" >
<div align="center">
<div align="center" id="div_content">
<h2>
<font color="red">測(cè)試導(dǎo)出word</font>
</h2>
<h4>
<font color="red">測(cè)試導(dǎo)出word</font>
</h4>
</div>
<table id="table1">
<tr>
<td>姓名</td><td><input type="text" size="5"></td>
<td>年齡</td><td><input type="text" size="5"></td>
</tr>
<table>
<div id="img">
<hr/>
<img src="MM.jpg" height="45%" width="30%">
</br>
</div>
<div id="text_area">
<textarea name="warn_task" wrap="off" cols="80" rows="12">區(qū)域內(nèi)容:</textarea>
</textarea>
<hr />
</div>
<input type="button" onclick="javascript:test();" value="測(cè)試">
</div>
</form>
</body>
</html>
"同步模式"就是上一段的模式,后一個(gè)任務(wù)等待前一個(gè)任務(wù)結(jié)束,然后再執(zhí)行,程序的執(zhí)行順序與任務(wù)的排列順序是一致的、同步的;"異步模式"則完全不同, 每一個(gè)任務(wù)有一個(gè)或多個(gè)回調(diào)函數(shù)(callback),前一個(gè)任務(wù)結(jié)束后,不是執(zhí)行后一個(gè)任務(wù),而是執(zhí)行回調(diào)函數(shù),后一個(gè)任務(wù)則是不等前一個(gè)任務(wù)結(jié)束就執(zhí) 行,所以程序的執(zhí)行順序與任務(wù)的排列順序是不一致的、異步的。
"異步模式"非常重要。在瀏覽器端,耗時(shí)很長的操作都應(yīng)該異步執(zhí)行,避免瀏覽器失去響應(yīng),最好的例子就是Ajax操作。在服務(wù)器端,"異步模式"甚至是唯一的模式,因?yàn)閳?zhí)行環(huán)境是單線程的,如果允許同步執(zhí)行所有http請(qǐng)求,服務(wù)器性能會(huì)急劇下降,很快就會(huì)失去響應(yīng)。
本文總結(jié)了"異步模式"編程的4種方法,理解它們可以讓你寫出結(jié)構(gòu)更合理、性能更出色、維護(hù)更方便的Javascript程序。
一、回調(diào)函數(shù)
這是異步編程最基本的方法。
假定有兩個(gè)函數(shù)f1和f2,后者等待前者的執(zhí)行結(jié)果。
如果f1是一個(gè)很耗時(shí)的任務(wù),可以考慮改寫f1,把f2寫成f1的回調(diào)函數(shù)。
function f1(callback){
setTimeout(function () {
// f1的任務(wù)代碼
callback(); }, 1000);
}
執(zhí)行代碼就變成下面這樣:
采用這種方式,我們把同步操作變成了異步操作,f1不會(huì)堵塞程序運(yùn)行,相當(dāng)于先執(zhí)行程序的主要邏輯,將耗時(shí)的操作推遲執(zhí)行。
回調(diào)函數(shù)的優(yōu)點(diǎn)是簡單、容易理解和部署,缺點(diǎn)是不利于代碼的閱讀和維護(hù),程序的流程會(huì)很混亂,而且每個(gè)任務(wù)只能指定一個(gè)回調(diào)函數(shù)。
二、事件監(jiān)聽
另一種思路是采用事件驅(qū)動(dòng)模式。任務(wù)的執(zhí)行不取決于代碼的順序,而取決于某個(gè)事件是否發(fā)生。
還是以f1和f2為例。首先,為f1綁定一個(gè)事件(這里采用的jQuery的寫法)。
上面這行代碼的意思是,當(dāng)f1發(fā)生done事件,就執(zhí)行f2。然后,對(duì)f1進(jìn)行改寫:
function f1(){
setTimeout(function () {
// f1的任務(wù)代碼
f1.trigger('done'); }, 1000);
}
f1.trigger('done')表示,執(zhí)行完成后,立即觸發(fā)done事件,從而開始執(zhí)行f2。
這種方法的優(yōu)點(diǎn)是比較容易理解,可以綁定多個(gè)事件,每個(gè)事件可以指定多個(gè)回調(diào)函數(shù)。缺點(diǎn)是整個(gè)程序都要變成事件驅(qū)動(dòng)型,運(yùn)行流程會(huì)變得很不清晰。
三、發(fā)布/訂閱
上一節(jié)的"事件",完全可以理解成"信號(hào)"。
我們假定,存在一個(gè)"信號(hào)中心",某個(gè)任務(wù)執(zhí)行完成,就向信號(hào)中心"發(fā)布"(publish)一個(gè)信號(hào),其他任務(wù)可以向信號(hào)中心"訂閱"(subscribe)這個(gè)信號(hào),從而知道什么時(shí)候自己可以開始執(zhí)行。這就叫做"發(fā)布/訂閱模式"(publish-subscribe pattern),又稱"觀察者模式"(observer pattern)。
這個(gè)模式有多種實(shí)現(xiàn),下面采用的是Ben Alman的Tiny Pub/Sub,這是jQuery的一個(gè)插件。
首先,f2向"信號(hào)中心"jQuery訂閱"done"信號(hào)。
jQuery.subscribe("done", f2);
然后,f1進(jìn)行如下改寫:
function f1(){
setTimeout(function () {
// f1的任務(wù)代碼
jQuery.publish("done"); }, 1000);
}
jQuery.publish("done")的意思是,f1執(zhí)行完成后,向"信號(hào)中心"jQuery發(fā)布"done"信號(hào),從而引發(fā)f2的執(zhí)行。
此外,f2完成執(zhí)行后,也可以取消訂閱(unsubscribe)。
jQuery.unsubscribe("done", f2);
這種方法的性質(zhì)與"事件監(jiān)聽"類似,但是明顯優(yōu)于后者。因?yàn)槲覀兛梢酝ㄟ^查看"消息中心",了解存在多少信號(hào)、每個(gè)信號(hào)有多少訂閱者,從而監(jiān)控程序的運(yùn)行。
四、Promises對(duì)象
Promises對(duì)象是CommonJS工作組提出的一種規(guī)范,目的是為異步編程提供統(tǒng)一接口。
簡單說,它的思想是,每一個(gè)異步任務(wù)返回一個(gè)Promise對(duì)象,該對(duì)象有一個(gè)then方法,允許指定回調(diào)函數(shù)。比如,f1的回調(diào)函數(shù)f2,可以寫成:
function f1(){
var dfd = $.Deferred();
setTimeout(function () {
// f1的任務(wù)代碼
dfd.resolve();
}, 500);
return dfd.promise;
}
這樣寫的優(yōu)點(diǎn)在于,回調(diào)函數(shù)變成了鏈?zhǔn)綄懛ǎ绦虻牧鞒炭梢钥吹煤芮宄矣幸徽椎?a target="_blank">配套方法,可以實(shí)現(xiàn)許多強(qiáng)大的功能。
比如,指定多個(gè)回調(diào)函數(shù):
再比如,指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù):
而且,它還有一個(gè)前面三種方法都沒有的好處:如果一個(gè)任務(wù)已經(jīng)完成,再添加回調(diào)函數(shù),該回調(diào)函數(shù)會(huì)立即執(zhí)行。所以,你不用擔(dān)心是否錯(cuò)過了某個(gè)事件或信號(hào)。這種方法的缺點(diǎn)就是編寫和理解,都相對(duì)比較難。
第一步,在web.xml中配置DirectJNgine Servlet.我配置的web.xml如下:
在web.xml配置文件中寫:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- 以下為DirectJNgine servlet 默認(rèn)配置-->
<servlet>
<servlet-name>DjnServlet</servlet-name>
<servlet-class>com.softwarementors.extjs.djn.servlet.DirectJNgineServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>providersUrl</param-name>
<param-value>djn/directprovider</param-value>
</init-param>
<!-- DirectJNgine servlet 默認(rèn)配置-->
<!-- api域:對(duì)應(yīng)下面的各個(gè)param-name的前綴,可以設(shè)置多個(gè)不同的域-->
<init-param>
<param-name>apis</param-name>
<param-value>
mynamespace
</param-value>
</init-param>
<!-- mynamespace對(duì)應(yīng)上面的api域。MyAction對(duì)應(yīng)生成的js相應(yīng)的文件夾.服務(wù)器運(yùn)行后,將在MyAction/下存放自動(dòng)生成的3個(gè)js文件。這里的名稱分別為
MyActionApi.js,MyActionApi-debug.js,MyActionApi-min.js
-->
<init-param>
<param-name>mynamespace.apiFile</param-name>
<param-value>MyAction/MyActionApi.js</param-value>
</init-param>
<!-- mynamespace.對(duì)應(yīng)上面的域."Ext.zhouyang"為命名空間所對(duì)應(yīng)的值。會(huì)在頁面加載時(shí)候用上. -->
<init-param>
<param-name>mynamespace.apiNamespace</param-name>
<param-value>Ext.zhouyang</param-value>
</init-param>
<!-- mynamespace.對(duì)應(yīng)上面的域. 要使用的類的全路徑名 -->
<init-param>
<param-name>mynamespace.classes</param-name>
<param-value>
com.softwarementors.extjs.djn.MyAction.MyAction
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DjnServlet</servlet-name>
<url-pattern>/djn/directprovider/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>
index.html
</welcome-file>
</welcome-file-list>
</web-app>
第二步,使你的服務(wù)器端方法對(duì)JavaScript可見,其實(shí)就是說對(duì)客戶端可見。
以我的demo為例,我想在hello.html中調(diào)用服務(wù)器端的方法。于是,我在hello.html中添加如下一段話。
<!--以下為DirectJNgine的基礎(chǔ)JS文件,放在djn目錄下,直接引用就可以。-->
<script type="text/javascript" src="../djn/djn-remote-call-support.js"></script>
<script type="text/javascript" src="../ejn/ejn-assert.js"></script>
<!--以上為DirectJNgine的基礎(chǔ)JS文件.-->
<script type="text/javascript" src="MyActionApi.js"></script>
前兩個(gè)script引用,是用來調(diào)用directjngine提供的默認(rèn)的一些操作函數(shù)。只需引用即可,不需要關(guān)注太多。
最后一個(gè)js,在啟動(dòng)服務(wù)器前,你是看不到的。因?yàn)樗莇irectjngine項(xiàng)目,根據(jù)你的配置自動(dòng)生成的。至于其中到底是怎樣,下面我會(huì)詳細(xì)介紹。
第三步,設(shè)計(jì)服務(wù)器端的方法。如函數(shù)名稱,是否需要返回值等等。因?yàn)樵趆ello.html頁面,我將會(huì)調(diào)用方法。
具體調(diào)用代碼將在最后的hello.html代碼說明部分進(jìn)行集中說明。
第四步,使用Java語言,編寫服務(wù)器端的方法。附上代碼如下:
- package com.softwarementors.extjs.djn.MyAction;
- import com.softwarementors.extjs.djn.config.annotations.DirectMethod;
- public class MyAction {
- @DirectMethod
- public String doEcho(String parm)
- {
- return "參數(shù)是" + parm;
- }
- @DirectMethod
- public String doShow()
- {
- return "i am not easy";
- }
- }
注意:
@DirectMethod這個(gè)標(biāo)簽很重要,就是通過這個(gè)標(biāo)簽和web.xml的一些配置,才會(huì)動(dòng)態(tài)生成第二步中需要引入的js。這種書寫方式下, 你在Java代碼中書寫的方法名稱就是你在前臺(tái)JS調(diào)用的方法名稱。如果你覺得這樣子不安全,或是不專業(yè)。那么可以通過定義別名的方法對(duì)方法進(jìn)行訪問。書 寫形式如下:
@DirectMethod( method="nameyouwant")
這樣子定義之后,前臺(tái)JS調(diào)用服務(wù)器端方法時(shí),方法的名稱就是你紅色定義的名稱了。
把類編譯好后,把class文件放入WEB-INF\classes相應(yīng)的包目錄下。要與web.xml中class文件的包的目錄結(jié)構(gòu)相同。
第五步,告訴DirectJNgine 去哪里尋找服務(wù)器端的方法。
在web.xml的配置中,有如下代碼:
<init-param>
<param-name>mynamespace.classes</param-name>
<param-value>
com.softwarementors.extjs.djn.MyAction.MyAction
</param-value>
</init-param>
在這里需要注意,mynamespace.classes的紅色部分,一定要與web.xml上面的apis變量的mynamespace相同。
其次,com.softwarementors.extjs.djn.MyAction.MyAction 為第四步中書寫的類的全路徑名稱,如果有多個(gè)類,則用英文逗號(hào)分隔。
第六步,為了讓Extjs可以調(diào)用我們的服務(wù)器端方法,我們需要注冊(cè)一個(gè)遠(yuǎn)程調(diào)用提供者即a remoting provider。你需要做的就是在hello.html代碼中,加入如下語句,為某一個(gè)空間注冊(cè)一個(gè)遠(yuǎn)程調(diào)用提供者:
//此處通過命名空間,添加初始化遠(yuǎn)程調(diào)用API
Ext.zhouyang.REMOTING_API.enableBuffer = 0;
Ext.Direct.addProvider(Ext.zhouyang.REMOTING_API);
注意:上面的Ext.zhouyang為在web.xml變量中mynamespace.apiNamespace已經(jīng)定義。
第七步,通過JavaScript進(jìn)行調(diào)用服務(wù)器端的方法。
MyAction.doShow(function(result, e){
var t = e.getTransaction();
if(e.status){
out.append(
String.format('<p><b>Successful call to {0}.{1} with response:</b><xmp>{2}</xmp></p>',
t.action,
t.method,
Ext.encode(result)));
}else{
out.append(
String.format('<p><b>Call to {0}.{1} failed with message:</b><xmp>{2}</xmp></p>',
t.action,
t.method,
e.message));
}
out.el.scroll('b', 100000, true);
});
//doEcho函數(shù),此函數(shù)有參數(shù)。
var parm = txtparm.value; //要傳入后臺(tái)的參數(shù)
MyAction.doEcho(parm, function(result, e){
var t = e.getTransaction();
if(e.status){
out.append(String.format('<p><b>Successful call to {0}.{1} with response:</b><xmp>{2}</xmp></p>',
t.action, t.method, Ext.encode(result)));
}else{
out.append(String.format('<p><b>Call to {0}.{1} failed with message:</b><xmp>{2}</xmp></p>',
t.action, t.method, e.message));
}
out.el.scroll('b', 100000, true);
});
上面的代碼排版有點(diǎn)亂,這里先做些說明,這個(gè)demo的下載網(wǎng)址,我最后會(huì)附送。可以直接查看代碼。
可以看到,對(duì)于函數(shù)的結(jié)構(gòu)。如果需要傳入?yún)?shù),則把參數(shù)寫在函數(shù)前面。
因?yàn)镴avaScript調(diào)用服務(wù)器端方法是異步的,所以,最好的方法就是定義一個(gè)回調(diào)函數(shù)處理數(shù)據(jù),而不是讓程序終止。
所以,對(duì)于上面的兩個(gè)方法,最后都定義了一個(gè)回調(diào)函數(shù)。這個(gè)函數(shù)的作用是用來處理服務(wù)器端返回的數(shù)據(jù)。
參數(shù)result是服務(wù)器端方法返回的數(shù)據(jù),e是一個(gè)even對(duì)象,包括一個(gè)事務(wù)對(duì)象,這個(gè)對(duì)象包含action和method的名稱和其他一些信息。
e.status表示服務(wù)器端成功執(zhí)行了函數(shù)。如果返回false,則表示服務(wù)器端出現(xiàn)了錯(cuò)誤。通過e.message就可以查看出錯(cuò)信息。
其他參數(shù)說明:
<init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param>
如果設(shè)置為true,在tomcat的log目錄下的stdout_2010****.log文件中會(huì)輸入相關(guān)的打印信息。如:
INFO : com.softwarementors.extjs.djn.servlet.DirectJNgineServlet - "Servlet GLOBAL configuration: debug=true, providersUrl=djn/directprovider, minify=true, batchRequestsMultithreadingEnabled=true, batchRequestsMinThreadsPoolSize=16, batchRequestsMaxThreadsPoolSize=80, batchRequestsMaxThreadsPerRequest=8, batchRequestsMaxThreadKeepAliveSeconds=60, gsonBuilderConfiguratorClass=com.softwarementors.extjs.djn.gson.DefaultGsonBuilderConfigurator, dispatcherClass=com.softwarementors.extjs.djn.servlet.ssm.SsmDispatcher, jsonRequestProcessorThreadClass=com.softwarementors.extjs.djn.servlet.ssm.SsmJsonRequestProcessorThread, contextPath=--not specified: calculated via Javascript--, createSourceFiles=true" ()
INFO : com.softwarementors.extjs.djn.servlet.DirectJNgineServlet - "Servlet GLOBAL configuration: registryConfiguratorClass=" ()
INFO : com.softwarementors.extjs.djn.servlet.DirectJNgineServlet - "Servlet APIs configuration: apis=mynamespace" ()
INFO : com.softwarementors.extjs.djn.servlet.DirectJNgineServlet - "Servlet 'mynamespace' Api configuration: apiNamespace=Ext.zhouyang, actionsNamespace=, apiFile=MyAction/MyActionApi.js => Full api file: C:\Program Files\Apache Software Foundation\Tomcat 6.0\webapps\directdemo\MyAction\MyActionApi.js, classes=com.softwarementors.extjs.djn.MyAction.MyAction" ()
INFO : com.softwarementors.extjs.djn.jscodegen.CodeFileGenerator - "Creating source files for APIs..." ()
如果非調(diào)試狀態(tài),則可以置為false。
完成上面的步驟后,啟動(dòng)tomcat,發(fā)現(xiàn)在\Tomcat 6.0\webapps\directdemo\MyAction 目錄下生成了三個(gè)文件。
如下:
MyActionApi.js,MyActionApi-debug.js,MyActionApi-min.js。其中的MyActionApi.js就是我們?cè)诘诙街幸氲腏avaScript。
它的作用相當(dāng)于Server端代碼的API一樣,因?yàn)橛兴拇嬖冢蛻舳说木W(wǎng)頁才知道服務(wù)器端都定義了些什么方法。我的demo中,生成的MyActionApi.js的代碼如下:
/**********************************************************************
*
* Code generated automatically by DirectJNgine
* Copyright (c) 2009, Pedro Agulló Soliveres
*
* DO NOT MODIFY MANUALLY!!
*
**********************************************************************/
Ext.namespace( 'Ext.zhouyang');
Ext.zhouyang.PROVIDER_BASE_URL=window.location.protocol + '//' + window.location.host + '/' + (window.location.pathname.split('/').length>2 ? window.location.pathname.split('/')[1]+ '/' : '') + 'djn/directprovider';
Ext.zhouyang.POLLING_URLS = {
}
Ext.zhouyang.REMOTING_API = {
url: Ext.zhouyang.PROVIDER_BASE_URL,
type: 'remoting',
actions: {
MyAction: [
{
name: 'doEcho'/*(String) => String */,
len: 1,
formHandler: false
},
{
name: 'doShow'/*() => String */,
len: 0,
formHandler: false
}
]
}
}
可以看到,包括函數(shù)名稱,參數(shù)類型,參數(shù)個(gè)數(shù)等都有定義。
至此,directjngine、Ext Direct調(diào)用Java服務(wù)器端方法大功告成。
分頁查詢時(shí)加上
itemid = deviceIdCtl.getValue();
rfid1 = rfid.getValue();
if (itemid == undefined || itemid == '')
itemid = "";
if (rfid1 == undefined || rfid1 == '')
rfid1 = "";
typeStore.on("beforeload",function(){ //分頁條件不丟失方法
typeStore.baseParams={
'itemid' : itemid,'rfid' : rfid1
}
});
typeStore.load( {
params : {
'itemid' : itemid,
'rfid' : rfid1,
'start' : 0,
'limit' : 20
}
});
JavaScript操作XML是通過XML DOM來完成的 Ie 下面是用ActiveX對(duì)象來實(shí)現(xiàn)的。
那么什么是XML DOM呢?
XML DOM 是:
- 用于 XML 的標(biāo)準(zhǔn)對(duì)象模型
- 用于 XML 的標(biāo)準(zhǔn)編程接口
- 中立于平臺(tái)和語言
- W3C 的標(biāo)準(zhǔn)
XML DOM 定義了所有XML 元素的對(duì)象和屬性,以及訪問它們的方法(接口)。
也就是說:
XML DOM 是用于查詢、添加、修改、刪除XML 元素的標(biāo)準(zhǔn)。
ie創(chuàng)建 xml
function xmlcreate() {
var version = [
'MSXML2.DOMDocument6.0',
'MSXML2.DOMDocument3.0',
'MSXML2.DOMDocument'
];
for(var i=0; i<version.length;i++) {
try {
var xml = new ActiveXObject(version[i]);
return xml;
}catch(e) {
}
}
throw new Error('您的系統(tǒng)不支持MSXML庫');
}
//載入XML文件,兩種方式:1.加載XML字符loadXML();2.加載XML外部文件load()
xml.loadXML('<root>\n<user>Lee</user>\n</root>'); //加載XML字符串
alert(xml.xml);
打印第一個(gè)內(nèi)容 必須用標(biāo)準(zhǔn)DOM
alert(xml.getElementsByTagName('user')[0].firstChild.nodeValue);
加載外部xml
xml.load('a.xml');
動(dòng)態(tài)添加xml
xml.load('a.xml');
var b = xml.createElement('bbb');
var root = xml.documentElement;
root.appendChild(b);
alert(xml.xml);
服務(wù)器端 同步/異步
在服務(wù)器端 默認(rèn)用的異步加載 沒加載完畢 就打印 肯定出不來
把這個(gè)值設(shè)為false 就能同步加載了
xml.async = false;
但是如果xml過大 會(huì)造成假死狀態(tài)
不過異步比較好 但是異步又獲取不到內(nèi)容 這該怎么辦呢
有個(gè)事件
xml.onreadystatechange = function
這個(gè)事件可以判斷是否加載完成 不過要先載入事件 先把事件加載到內(nèi)存中 然后再載入xml
事件里面有個(gè)屬性 xml.readyState 可以判斷是否加載完成
這個(gè)函數(shù)等xml全部加載好 開始處理
xml.onreadystatechange = function() {
if(xml.readyState ==4){ //如果正確就輸出
if(xml.parseError == 0) {
alert(xml.xml);
}else { //如果錯(cuò)誤 就返回
var a = "錯(cuò)誤代碼"+xml.parseError.errorCode+'\r\n';
a += "錯(cuò)誤行號(hào)"+xml.parseError.line+'\r\n';
a += "錯(cuò)誤上一行"+xml.parseError.linepos+'\r\n';
a += "錯(cuò)誤信息"+xml.parseError.reason+'\r\n';
alert(a);
}
}
}
DOM2操作xml
//create xml 第一個(gè)參數(shù) 命名空間 第二個(gè) 根節(jié)點(diǎn) 第三個(gè) 文檔聲明
var xml = document.implementation.createDocument('','root',null); //創(chuàng)建xml
var user = xml.createElement('user');
xml.documentElement.appendChild(user); //插入user
alert(xml.getElementsByTagName('user')[0].tagName); //取得user
dom2也有l(wèi)oad方法 默認(rèn)也是異步的 可以通過設(shè)置同步來加載
獲取一條信息
var xml = document.implementation.createDocument("",'root',null);
xml.async = false;
xml.load('a.xml');
alert(xml.getElementsByTagName('url')[0].firstChild.nodeValue);
也可以 通過 textContent 不過 ie不支持
alert(xml.getElementsByTagName('url')[0].textContent);
dom如果異步的話 怎么判斷是否加載完成呢 可以通過load方法判斷 比ie簡單了很多
var xml = document.implementation.createDocument("",'root',null);
xml.onload = function(){
alert(xml.getElementsByTagName('url')[0].textContent);
}
xml.load('a.xml');
ps 不過 load 只支持 firefox 和最新版本的opera
但是 w3c提供了2個(gè)對(duì)象處理xml
var xml = new DOMParser(); //實(shí)例化xml對(duì)象
var a= "<root><user>gwyy</user></root>";
var xmldom = xml.parseFromString(a,'text/xml'); //通過xml對(duì)象創(chuàng)建xml
var seria = new XMLSerializer() //序列號(hào)xml
var z = seria.serializeToString(xmldom);
alert(z);
DOM2沒有錯(cuò)誤對(duì)象 出錯(cuò)了 會(huì)給你返回一段xml格式的錯(cuò)誤信息
//判斷錯(cuò)誤
var errors = xmldom.getElementsByTagName('parsererror');
if(errors.length > 0) {
throw new Error('錯(cuò)誤信息:'+errors[0].textContent);
}
下面是跨瀏覽器創(chuàng)建xml
//跨瀏覽器創(chuàng)建
function createxml(xmlstr) {
var xml = null;
if(typeof window.DOMParser != "undefined") {
xml = (new DOMParser).parseFromString(xmlstr,'text/xml');
var errors = xml.getElementsByTagName('parsererror');
if(errors.length > 0){
throw new Error('錯(cuò)誤信息:'+errors);
}
} else if(typeof window.ActiveXObject != "undefined") {
var version = [
'MSXML2.DOMDocument6.0',
'MSXML2.DOMDocument3.0',
'MSXML2.DOMDocument'
];
for(var i=0;i<version.length;i++) {
try{
xml = new ActiveXObject(version[i]);
return xml;
}catch(e){
}
}
xml.loadXML(xmlstr);
if(xml.parseError != 0) {
throw new Error('錯(cuò)誤信息'+xml.parseError.reason);
}
return xml;
} else {
throw new Error('你的系統(tǒng)或?yàn)g覽器不支持xml');
}
return xml;
}
//序列化
function serializerXMl(xmlstr) {
var xml = "";
if(typeof window.XMLSerializer != "undefined") {
xml = (new XMLSerializer()).serializeToString(xmlstr);
} else if(typeof xmlstr.xml != "undefined"){
xml = xmlstr.xml;
}
return xml;
}
//實(shí)現(xiàn)
var xmlstr = "<root><user>aaaa</user></root>";
var xmldom = createxml(xmlstr);
alert(serializerXMl(xmldom));
為了跨瀏覽器 xml 只能放棄從外部加載xml
PK 一、常用到的類:
Struts1:
ActionServlet[process()]:當(dāng)ActionServlet實(shí)例接受到HTTP請(qǐng)求之后,在doGet()或doPost()方法都會(huì)調(diào)用process()方法來處理請(qǐng)求;
RequestProcessor[processPreprocess()]: 當(dāng)ActionServlet接收到客戶請(qǐng)求后,會(huì)進(jìn)行一連串的初始化操作,然后,就會(huì)將客戶請(qǐng)求轉(zhuǎn)交給合適的處理器進(jìn)行處理,這個(gè)合適的處理器就是 org.apache.struts.action.RequestProcessor,調(diào)用processPreprocess()方法該方法不執(zhí)行任 何操作,直接返回true,子類可以覆蓋這個(gè)方法,執(zhí)行客戶化的預(yù)處理請(qǐng)求操作;
PlugIn:主要用于struts1.x中的過濾器,插件(數(shù)據(jù)類型轉(zhuǎn)換),國際化等;
Action:ForwardAction、includeAction、DispatchAction、MappingDispatchAction、LookupDispatchAction、SwitchAction的實(shí)現(xiàn)接口;
ActionForm:ActionForm用于封裝用戶的請(qǐng)求參數(shù),而請(qǐng)求參數(shù)是通過JSP頁面的表單域傳遞過來的。因此應(yīng)保證ActionForm的參數(shù),與表單域的名字相同;
ActionForward:ActionForward 是 Struts的核心類之一,其基類僅有4個(gè)屬性:name / path / redirect / classname。在基于Struts的Web應(yīng)用程序開發(fā)過程中,Action操作完畢后程序會(huì)通過Struts的配置文件struts- config.xml鏈接到指定的ActionForward,傳到Struts的核心類ActionServlet,ActionServlet使用 ActionForward提供的路徑,將控制傳遞給下一個(gè)步驟。ActionForward控制接下來程序的走向。ActionForward代表一個(gè) 應(yīng)用的URI,它包括路徑和參數(shù),例如:path=“/modify.do?method=edit&id=10”;
ActionMapping:將 特定請(qǐng)求映射到特定Action的相關(guān)信息存儲(chǔ)在ActionMapping中,ActionServelt將ActionMapping傳送到 Action類的perform()方法,Action將使用ActionMapping的findForward()方法,此方法返回一個(gè)指定名稱的 ActionForward,這樣Action就完成了本地轉(zhuǎn)發(fā)。若沒有找到具體的ActionForward,就返回一個(gè)null;
struts-config.xml:struts-config.xml是Struts的主要配置文件,在該文件中,可以配置數(shù)據(jù)源、form-bean、action和plug-in(插件)和資源文件的信息。
-------------------------------------------------------------------------------------------------------------------
Struts2:
FilterDispatcher:org.apache.struts2.dispatcher.FilterDispatcher 是Struts2的主要的Filter,負(fù)責(zé)四個(gè)方面的功能:執(zhí)行Actions、清除ActionContext、維護(hù)靜態(tài)內(nèi)容、清除request生 命周期內(nèi)的XWork的interceptors;
ActionSupport:ActionSupport類是一個(gè)工具類,它已經(jīng)實(shí)現(xiàn)了Action接口。除此之外,它還實(shí)現(xiàn)了Validateable接口,提供了數(shù)據(jù)校驗(yàn)功能。通過繼承該ActionSupport類,可以簡化Struts 2的Action開發(fā)。
ServletActionContext[getResponse()]:Struts 2利用ServletActionContext類用來維護(hù)Servlet對(duì)象,把Servlet對(duì)象放到了ServletActionContext 中,例如request、response、application、Session等。ServletActionContext利用 ThreadLocal來維護(hù)不同線程的Servlet對(duì)象,因此可以使用ServletActionContext類獲取到。這種方式也可以叫做非注射 方式(非IoC方式);
ModelDriven[getModel()]:實(shí) 現(xiàn)了modelDriven接口可以在action中直接獲得例如User對(duì)象,它會(huì)將ObjectgetModel()取得的User放到 ValueStack中。可以理解為將這個(gè)User的屬性追加到Action中。它主要是作用是實(shí)現(xiàn)類似Struts的FormBean功能;
MethodFilterInterceptor:Struts2提供了一個(gè) MethodFilterInterceptor類對(duì)Action中方法過濾的功能,MethodFilterInterceptor是 AbstractInterceptor類的子類,如果要實(shí)現(xiàn)攔截器方法過濾功能,則需要繼承MethodFilterInterceptor。用戶只需 要重寫MethodFilterInteceptor中的doInterceptor(ActionInvocation action)即可。其內(nèi)容實(shí)際上與interceptor一樣。
struts.xml:struts.xml 為Struts 2的核心配置文件。struts.xml文件主要負(fù)責(zé)管理應(yīng)用中的Action映射,以及該Action包含的Result定義等。struts.xml 中主要配置Struts項(xiàng)目的一些全局的屬性,用戶請(qǐng)求和響應(yīng)Action之間的對(duì)應(yīng)關(guān)系,以及配置Action中可能用到的參數(shù),以及處理結(jié)果的返回頁 面。還包括各種攔截器的配置等。
======================================================================================================
PK 二、工作流程:
Struts1:
發(fā)布Struts Web服務(wù)時(shí),根據(jù)web.xml初始化ActionServlet,ActionContext等內(nèi)容.在接到一個(gè)HttpRequest請(qǐng)求 后,ActionServlet 根據(jù)struts-config.xml中的配置內(nèi)容,將請(qǐng)求的參數(shù)傳到對(duì)應(yīng)的Formbean中,并設(shè)置session.然后根據(jù)請(qǐng)求中的Action 參數(shù),在struts-config.xml中查找指定的Action,并調(diào)用此Action來處理請(qǐng)求.根據(jù)Action的處理結(jié)果,會(huì)返回一個(gè)forward變量,此時(shí)通過mapping.findForward()查找出對(duì)應(yīng)的forward所標(biāo)示的Action或者JSP頁面,將請(qǐng)求轉(zhuǎn)到下一個(gè)處理.如果是forward指向JSP頁面,則輸出到前臺(tái).
---------------------------------------------------------------------------------------------------
Struts2:
(1)客戶端提交一個(gè)HttpServletRequest請(qǐng)求(.action或JSP頁面);
(2)請(qǐng)求被提交到一系列Filter過濾器,如ActionCleanUp和FilterDispatcher等;
(3)FilterDispatcher是Struts2控制器的核心,它通常是過濾器鏈中的最后一個(gè)過濾器;
(4)請(qǐng)求發(fā)到FilterDispatcher后,FilterDispatcher詢問ActionMapper是否需要調(diào)用某個(gè)Action來處理這個(gè)Request(一般根據(jù)URL后綴是否為.action來判斷);
(5)如果ActionMapper決定需要調(diào)用某個(gè)Action,FilterDispatcher則把請(qǐng)求交到ActioProxy,由其進(jìn)行處理;
(6)ActionProxy通過Configuration Manager(它會(huì)訪問struts.xml)詢問框架的配置文件,找到需要調(diào)用的Action類;
(7)ActionProxy創(chuàng)建一個(gè)ActionInvocation實(shí)例,而ActionInvocation通過代理模式調(diào)用Action,(在調(diào)用之前會(huì)根據(jù)配置文件加載相關(guān)的所有Interceptor攔截器);
(8)Action執(zhí)行完畢后,返回一個(gè)result字符串,此時(shí)再按相反的順序通過Interceptor攔截器;
(9) 最后ActionInvocation負(fù)責(zé)根據(jù)struts.xml中配置的result元素,找到與返回值對(duì)應(yīng)的result,決定進(jìn)行下一步輸出.
PK 三、Struts1和Struts2的區(qū)別和對(duì)比:
Action 類:
Struts1、要求Action類繼承一個(gè)抽象基類。Struts1的一個(gè)普遍問題是使用抽象類編程而不是接口。
Struts2、Action類可以實(shí)現(xiàn)一個(gè)Action接口,也可實(shí)現(xiàn)其他接口,使可選和定制的服務(wù)成為可能。Struts2提供一個(gè) ActionSupport基類去 實(shí)現(xiàn) 常用的接口。Action接口不是必須的,任何有execute標(biāo)識(shí)的POJO對(duì)象都可以用作Struts2的Action對(duì)象。
線程模式:
Struts1、 Action是單例模式并且必須是線程安全的,因?yàn)閮H有Action的一個(gè)實(shí)例來處理所有的請(qǐng)求。單例策略限制了Struts1 Action能作的事,并且要在開發(fā)時(shí)特別小心。Action資源必須是線程安全的或同步 的。
Struts2、Action對(duì)象為每一個(gè)請(qǐng)求產(chǎn)生一個(gè)實(shí)例,因此沒有線程安全問題。(實(shí)際上,servlet容器給每個(gè)請(qǐng)求產(chǎn)生許多可丟棄的對(duì)象,并且不會(huì)導(dǎo)致性能和垃圾回收問題)。
Servlet 依賴:
Struts1、Action 依賴于Servlet API ,因?yàn)楫?dāng)一個(gè)Action被調(diào)用時(shí)HttpServletRequest 和 HttpServletResponse被傳遞給execute方法。
Struts2、Action不依賴于容器,允許Action脫離容器單獨(dú)被測(cè)試。如果需要,Struts2 Action仍然可以訪問初始的request和response。但是,其他的元素減少或者消除了直接訪問HttpServetRequest 和 HttpServletResponse的必要性。
可測(cè)性:
Struts1、 測(cè)試Struts1 Action的一個(gè)主要問題是execute方法暴露了servlet API(這使得測(cè)試要依賴于容器)。一個(gè)第三方擴(kuò)展--Struts TestCase--提供了一套Struts1的模擬對(duì)象(來進(jìn)行測(cè) 試)。
Struts2、Action可以通過初始化、設(shè)置屬性、調(diào)用方法來測(cè)試,“依賴注入”支持也使測(cè)試更容易。
捕獲輸入:
Struts1、 使用ActionForm對(duì)象捕獲輸入。所有的ActionForm必須繼承一個(gè)基類。因?yàn)槠渌鸍avaBean不能用作ActionForm,開發(fā)者經(jīng) 常創(chuàng)建多余的類捕獲輸入。動(dòng)態(tài)Bean(DynaBeans)可以作為創(chuàng)建傳統(tǒng)ActionForm的選擇,但是,開發(fā)者可能是在重新描述(創(chuàng)建)已經(jīng)存 在的JavaBean(仍然會(huì)導(dǎo)致有冗的 javabean)。
Struts2、 直接使用Action屬性作為輸入屬性,消除了對(duì)第二個(gè)輸入對(duì)象的需求。輸入屬性可能是有自己(子)屬性的rich對(duì)象類型。Action屬性能夠通過 web頁面上的taglibs訪問。Struts2也支持ActionForm模式。rich對(duì)象類型,包括業(yè)務(wù)對(duì)象,能夠用作輸入/輸出對(duì)象。這種 ModelDriven 特性簡化了taglib對(duì)POJO輸入對(duì)象的引用。
表達(dá)式語言:
Struts1、整合了JSTL,因此使用JSTL EL。這種EL有基本對(duì)象圖遍歷,但是對(duì)集合和索引屬性的支持很弱。使用標(biāo)準(zhǔn)JSP機(jī)制把對(duì)象綁定到頁面中來訪問。
Struts2、Struts2可以使用JSTL,但是也支持一個(gè)更強(qiáng)大和靈活的表達(dá)式語言--"Object Graph Notation Language" (OGNL).綁定值到頁面(view)。使用 "ValueStack"技術(shù),使taglib能夠訪問值而不需要把你的頁面(view)和對(duì)象綁定起來。ValueStack策略允許通過一系列名稱相同但類型不同的屬性重用頁面(view)。
類型轉(zhuǎn)換:
Struts1、ActionForm 屬性通常都是String類型。Struts1使用Commons-Beanutils進(jìn)行類型轉(zhuǎn)換。每個(gè)類一個(gè)轉(zhuǎn)換器,對(duì)每一個(gè)實(shí)例來說是不可配置的。
Struts2、使用OGNL進(jìn)行類型轉(zhuǎn)換。提供基本和常用對(duì)象的轉(zhuǎn)換器。
校驗(yàn):
Struts1、支持在ActionForm的validate方法中手動(dòng)校驗(yàn),或者通過Commons Validator的擴(kuò)展來校驗(yàn)。 同一個(gè)類可以有不同的校驗(yàn)內(nèi)容,但不能校驗(yàn)子對(duì)象。
Struts2、支持通過validate方法和XWork校驗(yàn)框架來進(jìn)行校驗(yàn)。XWork校驗(yàn)框架使用為屬性類類型定義的校驗(yàn)和內(nèi)容校驗(yàn),來支持chain校驗(yàn)子屬性。
Action的執(zhí)行控制:
Struts1、支持每一個(gè)模塊有單獨(dú)的Request Processors(生命周期),但是模塊中的所有Action必須共享相同的生命周期。
Struts2、支持通過攔截器堆棧(Interceptor Stacks)為每一個(gè)Action創(chuàng)建不同的生命周期。堆棧能夠根據(jù)需要和不同的Action一起使用。
xml文件:
Xml代碼
<?xml version="1.0" encoding="GB2312"?>
<RESULT>
<VALUE>
<NO>A1234</NO>
<ADDR>河南省鄭州市</ADDR>
</VALUE>
<VALUE>
<NO>B1234</NO>
<ADDR>河南省鄭州市二七區(qū)</ADDR>
</VALUE>
</RESULT>
第一種 DOM 實(shí)現(xiàn)方法:
Java代碼
import java.io.File; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document; import org.w3c.dom.NodeList; public class MyXMLReader2DOM { public static void main(String arge[]) { long lasting = System.currentTimeMillis(); try { File f = new File("data_10k.xml"); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(f); NodeList nl = doc.getElementsByTagName("VALUE"); for (int i = 0; i < nl.getLength(); i++) { System.out.print("車牌號(hào)碼:"+ doc.getElementsByTagName("NO").item(i).getFirstChild().getNodeValue()); System.out.println("車主地址:"+ doc.getElementsByTagName("ADDR").item(i).getFirstChild().getNodeValue()); System.out.println("運(yùn)行時(shí)間:" + (System.currentTimeMillis() - lasting) + "毫秒"); } } } catch (Exception e) { e.printStackTrace(); } } } |
第二種,DOM4J實(shí)現(xiàn)方法:
Java代碼
import java.io.*; import java.util.*; import org.dom4j.*; import org.dom4j.io.*; public class MyXMLReader2DOM4J { public static void main(String arge[]) { long lasting = System.currentTimeMillis(); try { File f = new File("data_10k.xml"); SAXReader reader = new SAXReader(); Document doc = reader.read(f); Element root = doc.getRootElement(); Element foo; for (Iterator i = root.elementIterator("VALUE"); i.hasNext();) { foo = (Element) i.next(); System.out.print("車牌號(hào)碼:" + foo.elementText("NO")); System.out.println("車主地址:" + foo.elementText("ADDR")); } System.out.println("運(yùn)行時(shí)間:" + (System.currentTimeMillis() - lasting) + "毫秒"); } } catch (Exception e) { e.printStackTrace(); } } } |
第三種 JDOM實(shí)現(xiàn)方法:
Java代碼
import java.io.*; import java.util.*; import org.jdom.*; import org.jdom.input.*; public class MyXMLReader2JDOM { public static void main(String arge[]) { long lasting = System.currentTimeMillis(); try { SAXBuilder builder = new SAXBuilder(); Document doc = builder.build(new File("data_10k.xml")); Element foo = doc.getRootElement(); List allChildren = foo.getChildren(); for (int i = 0; i < allChildren.size(); i++) { System.out.print("車牌號(hào)碼:"+ ((Element) allChildren.get(i)).getChild("NO").getText()); System.out.println("車主地址:"+ ((Element) allChildren.get(i)).getChild("ADDR").getText()); } System.out.println("運(yùn)行時(shí)間:" + (System.currentTimeMillis() - lasting) + "毫秒"); } } catch (Exception e) { e.printStackTrace(); } } } |
第四種SAX實(shí)現(xiàn)方法:
Java代碼
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class MyXMLReader2SAX extends DefaultHandler {
java.util.Stack tags = new java.util.Stack();
public MyXMLReader2SAX() {
super();
}
public static void main(String args[]) {
long lasting = System.currentTimeMillis();
try {
SAXParserFactory sf = SAXParserFactory.newInstance();
SAXParser sp = sf.newSAXParser();
MyXMLReader2SAX reader = new MyXMLReader2SAX();
sp.parse(new InputSource("data_10k.xml"), reader);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("運(yùn)行時(shí)間:" + (System.currentTimeMillis() - lasting)
+ "毫秒");
}
public void characters(char ch[], int start, int length)
throws SAXException {
String tag = (String) tags.peek();
if (tag.equals("NO")) {
System.out.print("車牌號(hào)碼:" + new String(ch, start, length));
}
if (tag.equals("ADDR")) {
System.out.println("地址:" + new String(ch, start, length));
}
}
public void startElement(String uri, String localName, String qName,
Attributes attrs) {
tags.push(qName);
}
}