一、什麼是DirectJNgine
DirectJNgine是Java版Ext Direct API的實現,它允許應用程序使用ExtJS調用Java方法,從而使JavaScript調用Java方法變得透明,擺脫過去繁瑣費時的調用方法。
二、下載DirectJNgine
DirectJNgine下載地址:http://code.google.com/p/directjngine/,目前最新版本爲1.3,下載後解壓即可,裏面包含有DirectJNgine類庫(lib)、幫助文檔(doc)、實例(demo)等。要使用DirectJNgine當然少不了Extjs類庫支持,Ext類庫在http://www.sencha.com很容易找到,不再囉嗦。下載完畢將ExtJS類文件拷貝至項目的WebContent目錄下。
三、項目中使用DirectJNgine依賴文件
項目中使用DirectJNgine需要將以下jar文件添加至web應用程序的WEB-INF/lib目錄下:
(1)DirectJNgine.jar:位於deliverables/directingine.xxx.jar;
(2)DirectJNgine使用第三方類庫:①位於lib/*.jar下的所用文件,子目錄除外;②位於lib/runtimeonly/*.jar
如果需要啓用客戶端參數調試模式,需要在web app項目中加入下面兩個Js文件:
(3)djn-remote-call-support.js:位於deliverables/ djn-remote-call-support.js;
(4)ejn-assert.js:位於deliverables/ejn-assert.js。
四、DirectJNing實例
在Extjs/examples/direct目錄下可以查看到ExtJS提供的一些使用DirectAPI的例子,這些例子都採用PHP作爲服務器端處理。當然在服務器端採用JAVA也很容易,不用擔心,下面就來看以實際例子看DirectJNgine如何運作。
4、1實例說明
本例按照DirectJNing官方提供文檔實例進行演示,項目目錄結構圖一:
圖一
說明:
(1) Java Resources:src目錄存放服務器端Java文件,其中log4j.properties可以參考DirectJNgine下載目錄中提供的配置信息根據自己項目情況做配置即可;
(2) WebContent/djn和WebContent/ejn存放djn-remote-call-support.js、deliverables/ejn-assert.js,這步不是必須的;
(3) Ext-3.3.3:存放ExtJs類庫文件;
(4) test:存放實例源碼,本例靜態代碼文件爲testAction.html,下面會用到。
其他文件內容就不詳述。
4、2 在web.xml中配置DirectJNgineServlet
在web.xml文件中添加如下配置:
<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>
<!—moreparameters –->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>DjnServlet</servlet-name>
<url-pattern>/djn/directprovider/*</url-pattern>
</servlet-mapping>
com.softwarementors.extjs.djn.servlet.DirectJNgineServlet即爲DierctJNgine的Servlet引擎。初始化參數debug設置爲true,DirectJNgine會爲我們動態生成-dubug.js文件,不懂先不管後邊一看便知。Servlet url-pattern必須使用“/*”結尾,官方推薦使用/djn/directprovider/*就別改了。
當然還用其他參數,別急慢慢來,這步是使用DirectJNgine的最基礎配置,接着往下看。
4、3 設計服務器端Java方法
服務器端代碼如下:
package com.demo.ext.directjngine;
importcom.softwarementors.extjs.djn.config.annotations.DirectMethod;
public class TestAction {
@DirectMethod
public StringdoEcho(String data){
return data;
}
@DirectMethod
public double multiply(String num){
try{
double num_ = Double.parseDouble(num);
return num_*0.8;
}catch( NumberFormatException e){
throw e;
}
}
}
說明:
(1) TestAction實現兩個方法:deEcho()實現返回輸入參數,multiply()則對輸入的參數做八折操作並返回折扣價。
(2) @DirectMethod則對以上兩個方法做註解,表明這些方法會被客戶端調用,這兩個方法會被DirectJNgine引擎自動生成客戶端代碼(可能不理解,沒管理往下看,實踐完後自然明白)。
EirectJNgine還有其他註解參數,先不管,目前掌握這個就夠了,待原理搞懂了自己便可嘗試使用其他參數。
4、3 讓JavaScript能夠使用服務器端方法
接下來就要配置4.2中的DirectMethod,使它能夠暴露給js客戶端,從而調用服務器端方法,很簡單,只需要把4.2中的TestAction類在web.xml中配置下即可。web.xml配置代碼如下:
<servlet>
……
<init-param>
<param-name>apis</param-name>
<param-value>test</param-value>
</init-param>
<init-param>
<param-name>test.apiFile</param-name>
<param-value>test/testApi.js</param-value>
</init-param>
<init-param>
<param-name>test.apiNamespace</param-name>
<param-value>Ext.test</param-value>
</init-param>
<init-param>
<param-name>test.classes</param-name>
<param-value>com.demo.ext.directjngine.TestAction </param-value>
</init-param>
……
</servlet>
參數都是鍵值對形式,以下配置說明:
鍵apis:可以理解把本模塊應用程序起個別名,以便組織模塊(個人理解)。本模塊命名爲test,如果有多個用逗號分隔即可;
鍵%apiName%.apiFile:本例中%apiName%=test(test.apiFile)即在apis中定義的別名,用於定義DirectJNgine自動生成的js代碼存放位置。在本例存放到test/testApi.js中,這個文件服務器端會自動生成,注意這裏的生成路徑相對於webapp的跟目錄。%apiName%.apiFile後面的“.apiFile”爲固定模式,我們只需要根據項目配置%apiName%即可;
鍵%apiName%.aipNamespace:用於定義自動生成js代碼的命名空間。同上我們只需要替換%apiName%爲test即可。
鍵%apiName%.classes:爲本模塊依賴的後端java類,它的值可以有多個類,用逗號分隔即可。本例中就是com.demo.ext.directjngine.TestAction,這樣客戶端js就可以調用TestAction中所有使用@DirectMethod註解的方法。
通過以上配置服務器端Java類的方法就暴露給客戶端JavaScript了,下面說下如何調用這些方法。發佈項目重啓web服務,可以查看到test文件夾下多了三個文件分別是:testApi.js、testApi-debug.js和testApi-min.js。打開testApi.js代碼如下:
/**********************************************************************
*
* Codegenerated automatically by DirectJNgine
* Copyright(c) 2009, Pedro Agulló Soliveres
*
* DO NOTMODIFY MANUALLY!!
*
**********************************************************************/
Ext.namespace( 'Ext.test');
Ext.test.PROVIDER_BASE_URL=window.location.protocol+ '//' + window.location.host + '/' +(window.location.pathname.split('/').length>2 ?window.location.pathname.split('/')[1]+ '/' : '') + 'djn/directprovider';
Ext.test.POLLING_URLS = {
message :Ext.test.PROVIDER_BASE_URL + '/poll/message' /* () => String -- calls com.demo.ext.directjnging.TestAction.handlMessagePoll*/
}
Ext.test.REMOTING_API = {
url:Ext.test.PROVIDER_BASE_URL,
type:'remoting',
actions: {
TestAction: [
{
name:'doEcho'/*(String) => String */,
len: 1,
formHandler: false
},
{
name:'multiply'/*(String) => double */,
len:1,
formHandler: false
}
]
}
}
有點感覺了吧,接着往下看。
4、4 Ext.Direct調用服務器端方法
4.4.1 引入自動生成的js文件
在testAction.html<head></head>引入如下代碼:
<head>
……
<link rel="stylesheet"type="text/css"
href="../ext-3.3.3/resources/css/ext-all.css"/>
<script type="text/javascript"
src="../ext-3.3.3/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../ext-3.3.3/ext-all.js"></script>
<script type="text/javascript" src="testApi.js"></script>
……
<script type="text/javascript">
Ext.onReady(function(){
//下面再擴充
});
</script>
</head>
說明:
(1) 引入ext基礎文件包含css和js文件;
(2) 引入testApi.js:這個文件時自動生成的,具體引用路徑就是我們在test.apiFile中定義的路徑,由於本例直接定義在test/testApi.js,與testAction.html同一級目錄所以就直接引用沒有加入目錄結構,根據自己定義路徑引用相應的文件
4.4.2通過Ext.Drect註冊服務器端方法
爲使Extjs能夠調用java方法,需要註冊一個遠程供應器。擴充Ext.onReady以便註冊服務器端方法,代碼如下:
Ext.onReady(function(){
Ext.Direct.addProvider(
Ext.test.REMOTING_API
);
});
這裏Ext.test是我們在web.xml定義Servlet參數的test.apiNamespace的值,REMOTING_API是自動生成的testApi.js中定義的供應器配置。
4.4.3調用服務器端方法
我們通過構造一個TextField和一個DisplayField組件用於接收參數並輸出處理後內容,通過Button組件調用事件,我們先看運行效果,再分析代碼原理。繼續擴充Ext.onReady代碼如下:
Ext.onReady(function(){
Ext.Direct.addProvider(
Ext.test.REMOTING_API
);
var text = new Ext.form.TextField({//輸入參數容器
fieldLabel:"輸入內容",
width:230
});
var out = newExt.form.DisplayField({ //輸出內容容器
cls: 'x-form-text',
fieldLabel:"輸出內容",
width:230
});
var btn = new Ext.Button({ //觸發調用事件
text:"調用Java方法",
handler:function(){
var value = text.getValue();
TestAction.doEcho(value,function(result ,e){ //這裏是調用方法
var t = e.getTransaction();
var content = String.format('成功調用{0}.{1} ,返回數據爲:{2}',t.action,t.method,result);
out.setValue(content);
});
}
});
var panel = newExt.form.FormPanel({
title:"簡單Ext.Direct例子",
width:400,
autoScroll:true,
applyTo:Ext.getBody(),
items:[text,out],
bbar:[btn]
});
});
運行頁面數據數據點擊按鈕前如下圖二:
圖二
點擊“調用Java方法”按鈕後,如圖三所示:
圖三
從上圖可以看出成功調用java方法,並返回數據。
4、7 Ext.Direct調用過程分析
(1)在4.3中我們看到,DirectJNgine通過web.xml配自動生成了testApi.js文件,通過查看Ext.Direct源碼發現,Ext.Direct把我們使用@DirectMethod註冊的方法都按照事件方法進行註冊,事件名默認就是我們的函數名,如:”doEcho()等”。
(2)我們使用“類名.方法名”進行調用,方法參數依次傳入,最後傳入JavaScript函數作回調函數,用於接收服務端返回結果,如:TestAction.doEcho(value,function(result,e){……});如果有三個輸入參數則按照如下形式調用:TestAction.doEcho(value1, value2, value3,function(result,e){……})。下面看下本例中調用過程:
TestAction.doEcho(value,function(result ,e){
var t = e.getTransaction();
var content = String.format('成功調用{0}.{1} ,返回數據爲:{2}',t.action,t.method,result);
out.setValue(content);
});
回調函數通過參數result接收返回數據,附加參數e爲事件對象,它包含調用的Action和method名等其他信息。
五、總結
到這裏DirectJNgine的簡單使用方法基本介紹完畢,不知道你有沒有爲Ext.Direct這種數據通訊方案感到興奮,至少我稍微興奮了一把。它可以:後端實現和前臺調用徹底分離,同樣的後臺實現可以很快換成其他方案,如Java換成php或.net,前端調用不需要任何改變,這一特性體現在它採用JSON作爲數據交換格式,即testApi.js中自動生成的Ext.test.REMOTING_API。
轉載請標明出處。歡迎交流,作者微博:http://t.qq.com/yubong