隨着微軟正式發佈IronPython,推出基於第一款基於動態語言的開源編程工具;緊接着Sun又正式對外宣佈收購JRuby,Ruby將成爲JVM支持的第一個動態語言,動態語言一直圍繞在我們的身邊。如何使用動態語言給我們編寫Java Web UI帶來幫助?什麼樣的動態語言能夠適合Java開發團隊呢?SirsiDynix的架構師Travis Jensen通過五條粗略的標準來評估Groovy,JRuby,Jython這三種動態語言在Java上的表現。
-
動態語言與Java之間的交互
-
IDE工具的支持
-
Java開發者的學習曲線
-
可供選擇的Web框架
-
社區的支持
而由此得出的結論是Groovy將是在Java Web開發中最適合的動態語言。在這也不對這些評價多做議論,簡單的結合AOM這個JSF的實現,介紹一下幾種動態語言在Java Web開發中的使用。在熟悉AOM的過程中,發現了ELite這種新的動態語言,由於ELite與AOM屬於同一個開發團隊的產品,對於這兩者的配合使用也一併做了一個示例。
在進行以下內容的同時,需要對使用的開發環境做一個簡單的介紹:
至於對PATH或者JAVA_HOME等進行設置,這裏就不一一餒述了,
由於 OperaMasks中內嵌有ELite的支持,所以在使用 OperaMasks作爲Web框架開發的應用中可以很方便的使用ELite這種動態語言,不管是在xhtml頁面中直接當作EL表達式來使用,或者在後臺Bean中直接使用ELite編寫,都是非常自然和可靠的選擇。
ELite的介紹還需要從EL(Expression Language)表達式語言說起,在JSP 2.0中,推出了一種稱之爲Expression Language的表達式語言,主要目的是方便用戶存取後臺的Java Bean。在JSF 1.1中,由於JSP 2.0 的EL不能夠滿足所有的需求,因此,在JSF 1.1中也定義了一套自己的EL表達式語言;幸運的是,在 JSP 2.1與JSF 12中,這兩者進行了統一,並重新命名爲:Unified Expression Language,簡稱:EL。
ELite脫胎於AOM中的EL運行引擎,在JSR-252的基礎上對EL表達式語言做了很大的擴充,成爲了一種新的動態語言,並且ELite是一個集命令式和函數式風格爲一身的面向對象的程序設計語言,既有高階函數(first-class functions)、列表推導(list-comprehension)、模式匹配(pattern-matching)、延時求值(lazy-evaluation)等函數式語言所具有的語言特徵, 又具有和Java相近的語法結構,讓熟悉Java的使用者便於上手。
目前,ELIte 已經從 OperaMasks 中抽離出來,其項目主頁爲:[url]www.sourceforge.net/projects/aom-elite[/url],而在最新下載的Apusic Application Server 5.1或者最新的AOM2.0中都包含有ELite引擎。
ELite本身是一個可以獨立運行的動態語言引擎,如何單獨使用ELite可以參見[url]http://aom.group.javaeye.com/group/blog/170038[/url]的介紹。而在AOM中使用ELite是非常簡單的一件事情,建立一個Apusic 標準工程,給當前工程添加一個帶有AOM支持的web模塊,這個時候就可以在這個工程中使用ELite了。具體的Apusic Studio以及Apusic工程的介紹,請參見[url]http://www.operamasks.org/articles/studioProject/html_single[/url]等系列文章。通過一個簡單的示例,講解一下如何在AOM中使用ELite來進行Web應用的開發,希望能讓讀者對ELite的使用有一個初步的瞭解。
在WebContent目錄下新建一個Facelets文件calc_elite.xhtml
在 WEB-INF/scripts 裏面有一個 calc_elite.elite 的文件,代碼示例如下:
<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout"
xmlns:h="http://java.sun.com/jsf/html" renderKitId="AJAX">
<w:page title="Calculator">
<w:form id="calc" transient="true">
<layout:panelGrid columns="3">
<h:outputLabel for="first" />
<w:textField id="first" />
<h:message for="first" />
<h:outputLabel for="second" />
<w:textField id="second" />
<h:message for="second" />
<h:outputLabel for="result" />
<h:outputText id="result" />
</layout:panelGrid>
<br/>
<layout:panelGrid columns="4">
<w:button id="add" />
<w:button id="subtract" />
<w:button id="multiply" />
<w:button id="divide" />
</layout:panelGrid>
</w:form>
</w:page>
</f:view>
xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout"
xmlns:h="http://java.sun.com/jsf/html" renderKitId="AJAX">
<w:page title="Calculator">
<w:form id="calc" transient="true">
<layout:panelGrid columns="3">
<h:outputLabel for="first" />
<w:textField id="first" />
<h:message for="first" />
<h:outputLabel for="second" />
<w:textField id="second" />
<h:message for="second" />
<h:outputLabel for="result" />
<h:outputText id="result" />
</layout:panelGrid>
<br/>
<layout:panelGrid columns="4">
<w:button id="add" />
<w:button id="subtract" />
<w:button id="multiply" />
<w:button id="divide" />
</layout:panelGrid>
</w:form>
</w:page>
</f:view>
@Bind @Required first::double = 22;
@Bind @Required second::double = 7;
@Bind @Pattern("#,##0.00") result::double;
@Action void add() => result = first + second;
@Action void subtract() => result = first - second;
@Action void multiply() => result = first * second;
@Action void divide() => result = first / second;
聲明一個 double 的變量,語法形式是ELite語法,但同樣可以任意的利用各種Java的annotation | |
用到了 @Pattern 的標註,用來指定數字的顯示樣式。你可以參考 AOM API文檔。 | |
|
聲明一個@Action 方法,這個方法你還可以這樣寫:
|
@Action void add() {
result = first + second;
System.out.println("add method invoked");
}
result = first + second;
System.out.println("add method invoked");
}
那麼,calc_elite.xhtml 與 calc_elite.elite 是怎樣關聯起來的呢?在 operamasks.xml 中進行聲明:
<view-mapping>
<url-pattern>/calc_elite.xhtml</url-pattern>
<model-bean>/WEB-INF/scripts/calc_elite.elite</model-bean>
</view-mapping>
如果覺得在 operamasks.xml 中進行配置很繁瑣,那麼,還可以這樣:在頁面中通過<om:elite>標籤,將 ELite 代碼片斷放在其中。
<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout"
xmlns:h="http://java.sun.com/jsf/html" renderKitId="AJAX" xmlns:om="http://www.apusic.com/jsf/misc">
<om:elite>
<![CDATA[
@Bind @Required first::double = 22;
@Bind @Required second::double = 7;
@Bind result::double = 0;
@Action add()=> result = first + second;
@Action subtract() => result = first - second;
@Action multiply() => result = first * second;
@Action divide() => result = first / second;
]]>
</om:elite>
<w:page title="Calculator">
<w:form id="calc">
<layout:panelGrid columns="3">
<h:outputLabel for="first" />
<w:textField id="first" />
<h:message for="first" />
<h:outputLabel for="second" />
<w:textField id="second" />
<h:message for="second" />
<h:outputLabel for="result" />
<h:outputText id="result" />
</layout:panelGrid>
<br />
<layout:panelGrid columns="4">
<w:button id="add" />
<w:button id="subtract" />
<w:button id="multiply" />
<w:button id="divide" />
</layout:panelGrid>
</w:form>
</w:page>
</f:view>
xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout"
xmlns:h="http://java.sun.com/jsf/html" renderKitId="AJAX" xmlns:om="http://www.apusic.com/jsf/misc">
<om:elite>
<![CDATA[
@Bind @Required first::double = 22;
@Bind @Required second::double = 7;
@Bind result::double = 0;
@Action add()=> result = first + second;
@Action subtract() => result = first - second;
@Action multiply() => result = first * second;
@Action divide() => result = first / second;
]]>
</om:elite>
<w:page title="Calculator">
<w:form id="calc">
<layout:panelGrid columns="3">
<h:outputLabel for="first" />
<w:textField id="first" />
<h:message for="first" />
<h:outputLabel for="second" />
<w:textField id="second" />
<h:message for="second" />
<h:outputLabel for="result" />
<h:outputText id="result" />
</layout:panelGrid>
<br />
<layout:panelGrid columns="4">
<w:button id="add" />
<w:button id="subtract" />
<w:button id="multiply" />
<w:button id="divide" />
</layout:panelGrid>
</w:form>
</w:page>
</f:view>
這個例子只是簡單的介紹了一下ELite 在 AOM 中的應用,ELite能給使用者帶來的絕對不僅僅是這些,希望 ELite 能夠成爲您的另外一種奇妙的選擇。
作爲時下流行的動態語言Ruby來說,ROR(Ruby On Rails)的興起讓Ruby的風頭在快速開發中獨佔鰲頭。簡單快捷,完全的面向對象是Ruby的特點,而隨着JRuby的推出,在JVM上運行Ruby程序也已經成爲現實,那麼在使用JSF進行開發的過程中,是否也能使用Ruby這種快捷的動態語言呢?
當Spring2.0宣佈推出集成動態語言的Feature,也就意味着在Java Web 開發中可以通過Spring的引入而支持動態語言的使用,Spring目前支持的動態語言有JRuby,Groovy,BeanShell三種。當一個Web應用中集成有Spring環境,那麼在這個應用中使用動態語言就是一件很自然的事情,在這裏講述一下如何在一個JSF應用中來使用動態語言JRuby。
由於AOM本身也就是一個JSF實現,所以在這裏就偷個懶,直接將AOM當作一個普通的JSF來進行JRuby使用的示例環境了。同樣在Apusic Studio中建一個Apusic標準工程,給當前工程添加一個Web模塊,工程和Web模塊的相關配置這裏也就不詳細介紹,有興趣的朋友可以通過[url]http://www.operamasks.org[/url]去了解工具的一些使用細則。在AOM中使用Spring非常簡單,下載的AOM產品包下包含有Spring2.0以及AOM對Spring支持的插件,只需要將這些jar包加入到工程的Build Path中就可以了。目前最新的Apusic Studio已經提供了Spring IDE的支持,可以很方便的在工具中給當前工程添加Spring的依賴,即刻通過下載最新的Apusic Studio來體驗一下吧。
在WebContent目錄下新建一個Facelets文件jruby.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE HTML PUBLIC "" "">
<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout"
xmlns:ajax="http://www.apusic.com/jsf/ajax" xmlns:h="http://java.sun.com/jsf/html"
renderKitId="AJAX">
<w:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</w:head>
<w:page title="Insert title here">
<h:form>
<h:inputText value="#{myBean.text}"></h:inputText>
<h:commandButton action="#{myBean.click}" value="Submit"></h:commandButton>
You typed: #{myBean.text}
</h:form>
</w:page>
</f:view>
<!DOCTYPE HTML PUBLIC "" "">
<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout"
xmlns:ajax="http://www.apusic.com/jsf/ajax" xmlns:h="http://java.sun.com/jsf/html"
renderKitId="AJAX">
<w:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</w:head>
<w:page title="Insert title here">
<h:form>
<h:inputText value="#{myBean.text}"></h:inputText>
<h:commandButton action="#{myBean.click}" value="Submit"></h:commandButton>
You typed: #{myBean.text}
</h:form>
</w:page>
</f:view>
在這個頁面中引用的後臺Bean的名稱爲“myBean”,在AOM中可以很方便的用Java來編寫這個Bean,但在這裏不是我們的目的,我們將用JRuby來實現這個後臺Bean。
爲了使用Ruby實現這個後臺Bean,我們需要一個spring-jruby的接口,在web/src的jruby包下新建一個接口IMyBeanController
public interface IMyBeanController {
public String getText();
public void setText(String text);
public String click();
}
同樣在web/src的jruby包下新建一個MyBeanController.rb文件,以下是實現這個接口的Ruby代碼
require 'java'
include_class 'jruby.IMyBeanController'
class MyBeanController
include IMyBeanController
@text = nil
def setText(text)
@text = text
end
def getText
@text
end
def save
puts @text
end
end
include_class 'jruby.IMyBeanController'
class MyBeanController
include IMyBeanController
@text = nil
def setText(text)
@text = text
end
def getText
@text
end
def save
puts @text
end
end
最後一步是在WEB-INF目錄下的Spring的配置文件applicationContext.xml中定義這個後臺Bean
<lang:jruby id="myBean"
script-interfaces="jruby.MyBeanController"
script-source="classpath:jruby/MyBeanController.rb" scope="request">
</lang:jruby>
在這個用動態語言定義的後臺Bean中,也可以使用scope屬性來定義它的作用域,這個示例中我們使用的是“request”作用域。爲了能在JSF的後臺Bean中使用通過Spring配置的Bean,我們需要Spring-Jsf的配合使用,關於這方面的介紹在[url]http://www.operamasks.org/articles/magic-6/html_single[/url]這篇文章中有很詳細的介紹,在這裏我們重點放在如何使用JRuby上。當然通過這種方式,我們也可以將在這裏選用的動態語言改爲Groovy或者BeanShell,而Groovy與Java語言的緊密性,使得Groovy在Java程序中的使用更爲簡單,這裏之所以沒有選用Groovy來做示例,完全是出於隨機性,由於Spring對這幾種動態語言的兼容,使得示例選擇的語言變的不那麼關鍵。
使用動態語言編寫JSF的後臺Bean的這種方式很有趣也很靈活,但還是有一些缺點讓人覺得無奈
-
使用動態語言編寫的Bean爲了能與spring集成,需要實現一個Java接口。
-
對於後臺Bean中的屬性讀寫不夠靈活
然而使用動態語言編寫後臺Bean帶來的好處也是顯而易見的,例如修改Bean的內容後可以不用重啓應用或者重新部署應用,這個好處讓你眼前一亮了吧。關於如何在其他的JSF實現中使用JRuby,相信讀者都已經有一個清晰的思路了。