使用Stripes進行Java Web開發(fā)_JSP教程
推薦:Java mail 詳解與實例綜述:Java Mail API的開發(fā)是SUN為Java開發(fā)者提供公用API框架的持續(xù)努力的良好例證。提倡公用框架,反對受限于供應(yīng)商的解決方案,充分預(yù)示著一個日益開放的開發(fā)環(huán)境的建立。 Java Mail API的結(jié)構(gòu)本身證明了它的開發(fā)者的基本目標(biāo)之一--軟件開發(fā)的工作量應(yīng)該取
Stripes是一個以讓程序員的web開發(fā)簡單而高效為準(zhǔn)則來設(shè)計的基于動作的開源Java web框架。本文將介紹Stripes與其它如Struts之類基于動作的框架的區(qū)別和其提供的一些存在于Ruby on Rails之中的簡單性。Stripes是一個以讓程序員的web開發(fā)簡單而高效為準(zhǔn)則來設(shè)計的基于動作的開源Java web框架。傳統(tǒng)的Java web開發(fā)著眼于借去耦(Decoupling)來實現(xiàn)其靈活性,但導(dǎo)致多個的配置文件,額外的對象,和其他資源的分散。這些困難造成相當(dāng)多的程序員的更高的學(xué)習(xí)時間和低下的效率。其結(jié)果是有些Java程序員被一些非Java的框架所吸引去了:Ruby on Rails或者Django。一些Java web框架,如Stripes,正在開始從這些非Java框架中汲取其成功經(jīng)驗:簡單而高效的開發(fā)。本文將介紹Stripes與其它如Struts之類基于動作的框架的區(qū)別和其提供的一些存在于Ruby on Rails之中的簡單性。
圖1是典型的用Stripes寫的應(yīng)用程序中的正常事件流程和組件。
如你所見,其流程基本上就是一個MVC框架。Stripes和其他的基于動作的框架的一個主要的區(qū)別是沒有一個外部的配置文件。我們隨后將看到,Stripes用annotation和約定而非配置來提高產(chǎn)出和減少雜亂。
編寫你的第一個Stripe動作(Action)
讓我們現(xiàn)在就開始通過創(chuàng)建Hello World例程來了解Stripes框架和理解其運作。HelloWorldAction類將提示用戶輸入姓氏和名字然后在另一個View里面顯示,首先我們來編寫controller類。
{
@ValidateNestedProperties(
{
@Validate(field = "firstName", required = true, on = {"hello"}),
@Validate(field = "age", required = true, minvalue = 13, on = {"hello"})
})
private Person person;
private ActionBeanContext context;
@DefaultHandler public Resolution index()
{
return new ForwardResolution("Hello.jsp");
}
public Resolution hello()
{
return new ForwardResolution("SayHello.jsp");
}
public void setPerson(String person) {this.person = person;}
public String getPerson() { return person;}
public void setContext(ActionBeanContext c) {this.context = c; }
public ActionBeanContext getContext() {return context; }}
Controller類是一個實現(xiàn)了Stripes特有接口ActionBean的POJO(Plain Old Java Object,譯注:讀破粥)。所有的Stripes動作類都要實現(xiàn)這一接口以讓StripesDispatcher servlet在運行服務(wù)時為其注入一個ActionBeanContext對象。ActionBeanContext對象可以讓你存取的對象如request、response、和servlet context等servlet API。大多數(shù)時候在Stripes應(yīng)用中是不用讀取這些底層API對象的。
ActionBeanContext類還提供當(dāng)前動作的狀態(tài)并可以添加信息消息和錯誤消息到當(dāng)前動作中。ActionBeanContext的變量和其讀寫方法可以放在一個基類里面,因為所有的Stripes動作都要實現(xiàn)之。
Controller類的其他部分對于任何Java程序員來說都是很面熟的。有一個Person對象和其讀寫方法是用來讀寫用戶的姓名給view的。雖然這僅僅是一個簡單的嵌套對象,Stripes可以通過Java集合、泛型支持、和下標(biāo)化的屬性來實現(xiàn)更復(fù)雜完善的數(shù)據(jù)捆綁。因為Stripes可以處理復(fù)雜數(shù)據(jù)捆綁,你的領(lǐng)域?qū)ο螅―omain Object)可以在其他需要它們的層重用。例如:通過Stripes你可以很容易的收集一個領(lǐng)域?qū)ο蟮男畔ⅲ缓笥闷渌腜OJO框架,如Hibernate或者EJB3來對其進行持久化。
Person對象變量上有一個Stripes驗證annotation用來保證用戶在激活hello方法的時候已經(jīng)輸入了姓名。如果用戶沒有輸入這兩個必需的變量,原始頁會被返回,并顯示一個相關(guān)的錯誤消息。該驗證只有在hello事件被申請的時候才會被激活,因為annotation的屬性中指定了(on = {"hello"})。Stripes還會使用實用默認法則,根據(jù)驗證方法和變量名稱產(chǎn)生一個錯誤信息。例如,如果Person類的firstName變量在提交的時候沒有提供,用戶將看到:
Person First Name is a required field.
這條消息是通過將Person.firstName進行刻讀化處理后得到的。如果有必要,這些錯誤消息可以被重載來提供更多的客戶自定義功能。
另外還有一個Integer類型的變量age,是Person對象的一個屬性。Stripes首先試圖對request中命為person.age的parameter轉(zhuǎn)換為Integer類型,并將其捆綁到Person對象上。在Person對象的age變量被付值以后,Stripes將驗證該Integer值是否小于13。如果用戶輸入了一個字符串而非整數(shù),用戶得到這個消息:
The value (Mark) entered in field Person Age must be a valid number.
若是用戶輸入了一個小于13的整數(shù),用戶將看到這個消息:
The minimum allowed value for Age is 13.
同樣地,我們沒有必要為這些錯誤消息提供任何外部的配置文件。Annotation提供的驗證與你的變量在同一個位置上,使得程序員定位驗證、理解驗證的內(nèi)容、和對驗證進行維護變動更容易。
這個Stripes動作還有兩個可被激活的方法(稱為事件)。事件是ActionBean類中有如下特征的方法:
public Resolution eventName
請注意index方法被標(biāo)注為@DefaultHandler annotation。因為在本動作中有多個事件,其中一個必須被指定為默認事件。如果調(diào)用本動作的URL沒有指定哪個事件,Stripes則查找標(biāo)注有@DefaultHandler annotation的事件,并執(zhí)行。
顯示層(View)
現(xiàn)在讓我們給Hello World例程加上顯示層的邏輯。Stripes默認支持JSP為顯示層的標(biāo)準(zhǔn)技術(shù),不過你也可以用其他的顯示層技術(shù),比如FreeMaker。除了Stripes的tag庫以外,沒有什么新的東西要學(xué)。Hello.jsp是初始的顯示,可以讓用戶輸入和提交姓名。
......
<stripes:errors/>
<stripes:form beanclass="com. myco. web. stripes. action. example. HelloWorldAction"> Say hello t <br> First name:
<stripes:text name="person.firstName"/> <br> Age:<stripes:text name="person.age"/><br>
<stripes:submit name="hello" value="Say Hello"/>
</stripes:form>
......
這個JSP易讀易維護。而Stripes用于form和input的tag跟對應(yīng)的HTML代碼非常相似。stripes:form tag包含一個beanclass屬性,其值為我們前面定義的controller類的完整類名。我們可以用stripes:form中的action屬性來替換beanclass屬性,但是beanclass屬性可以讓你在以后對Stripes動作進行重構(gòu)的時候更加方便。如果你要用在stripes:form tag中使用action屬性,方法如下:
有一個stripes:input tag指定了一個名為person.firstName屬性,其作用是將其儲存的輸入值付給controller的Person對象的firstName變量中。最后,stripes:submit tag指定一個name屬性來告訴Stripes的HelloWorldAction類使用哪一個事件。
我們現(xiàn)在已經(jīng)完成了提交姓名的值給HelloWorldAction,剩下的就是在另一個view中將其反饋給用戶了。
......
<stripes:errors/>
<h2>Hello {actionBean.person.firstName} your age is {actionBean.person.age} </h2> <p/>
<stripes:link beanclass="com.myco.web.stripes.action. example.HelloWorldAction"> Say Hello Again
</stripes:link>
......
本JSP將自己通過一個對動作的引用讀取person的姓名信息并顯示。為達到這一目的,Stripes自動在request的屬性中添加一個名為actionBean動作對象,以供JSTL存取。最后,我們用了一個strips:link tag來建立一個返回HelloWorldAction地鏈接從而可以讓我們輸入不同的姓名。我們以可以通過如下辦法顯式地創(chuàng)建一個指向index事件的stripes:link:
Say Hello Again
</stripes:link>
因為我們已經(jīng)用annotation把index方法標(biāo)記為@DefaultHandler,Stripes無須event屬性也知道要執(zhí)行哪一個方法。
用約定、不用配置文件
我們現(xiàn)在有了Java組件,我們該做配置了,把動作映射的一個URL上,并將其連接到我們的兩個view上面去。等一下!我們在用Stripes,我們不需要外部配置文件!
雖然這聽來好像好得不像是真的,但這的確是Stripes的一項最具生產(chǎn)效率的功能。Stripes使用約定而非配置文件來映射動作到URL上。我們也無須使用一個外部配置文件來把view映射到一個個標(biāo)記名字上。這意味著程序員不用再為了一個標(biāo)記名字——比方說SUCCESS——的實際來源,而在配置文件中跳來跳去了。沒有必要在Java和view組件的外部進行配線,因而導(dǎo)致更好地維護性和更高的生產(chǎn)率。
Stripes是如何提供隱式的URL映射而無需在外部配置每一個動作或者而外的annotation呢?這個可以從Stripes在web.xml中的配置以及它是如何通過實用默認法建立URL映射來解釋。首先,我們來看看Servlet過濾器:StripesFilter。其在web.xml中的默認配置如下:
<display-name>Stripes Filter</display-name>
<filter-name>StripesFilter</filter-name>
<filter-class> net.sourceforge.stripes.controller.StripesFilter </filter-class>
<init-param>
<param-name>ActionResolver.UrlFilters</param-name>
<param-value>/WEB-INF/classes</param-value>
</init-param>
</filter>
當(dāng)Servlet容器啟動的時候,StripesFilter對其init-param元素執(zhí)行初始化。其中最重要的init-param元素就是ActionResolver.UrlFilters參數(shù)。這個參數(shù)告訴Stripes到哪里查找跟Stripes有關(guān)的類。這個例子里面,Stripes將查找/WEB-INF/classes目錄下的所有實現(xiàn)ActionBean接口的類。每一個被找到的類和其綁定的URL都將被加入一個Map中。
讓我們來看看Stripes是如何處理我們的HelloWorldAction動作為例子吧。因為HelloWorldAction類位于/WEB-INF/classes目錄下,所以會被認為是一個Stripes servlet。在我們的例子當(dāng)中,其完整類名是com.myco.web.stripes.action.example.HelloWorldAction。隨后,其完整類名將按照如下法則被翻譯成一個URL綁定。
1. 將含有www、web、stripes、和action的部分及其以前的內(nèi)容刪掉。在我們的例子有三個上述單詞,所以我們得到了example.HelloWorldAction。
2. 如果類名中包涵帶Action或Bean的尾巴,刪掉。因為我們的類名以Action結(jié)尾,我們得到了example.HelloWorld。
3. 將.替換為/,我們得到了example/HelloWorld。
4. 最后,添加上一個尾綴(默認是.action)從而完成了URL綁定。最后的結(jié)果是example/HelloWorld.action。
現(xiàn)在Stripes找到了ActionBean類并為其創(chuàng)建了一個URL綁定,然后存放在一個java.util.Map<String, Class<? extends ActionBean>>之中。其中key參數(shù)是URL綁定,value參數(shù)是實現(xiàn)ActionBean的類名。下面是我們的例子中的Map:
URL綁定:/example/HelloWorld.action
ActionBean類:com.myco.web.stripes.action.example.HelloWorldAction
我們要看的第二個組件是Stripes如何把URL綁定翻譯成你正在做的這個ActionBean類。這是Stripes調(diào)度servlet的職責(zé),在web.xml中的配置如下:
<servlet-name>StripesDispatcher</servlet-name>
<servlet-class>
net.sourceforge.stripes.controller.DispatcherServlet </servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>StripesDispatcher</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
StripesDispatcher的一個職責(zé)就是將URL解析為Stripes的ActionBean類。當(dāng)用戶激活URL http://host/uri/example/HelloWorld.action的時候,Stripes調(diào)度servlet將在URL映射表中查詢并找到com.myco.web.stripes.action.example.HelloWorldAction類,并實例化產(chǎn)生該類的一個實例。最后,index方法被激活,因為在annotation中它被定義為默認局柄而在該URL中并沒有指定一個事件。
如果我們想要直接執(zhí)行HelloWorldAction中的hello方法怎么辦?應(yīng)該象下面這個URL這樣把事件的名字放在request的參數(shù)中:
http://host/uri/example/HelloWorld.action?hello=&firstName=Mark&age=13
請注意我們沒有給hello這個request參數(shù)名指定任何值。在這個情況下,StripesDispatcher會把hello這個這個request參數(shù)名和HelloWorldAction類中個一個帶有public Resolution hello()簽名的函數(shù)識別并映射。該方法名城在初始化的時候為了性能而緩存在另一個Map中。
我們已經(jīng)看到Stripes的基礎(chǔ)以及如果創(chuàng)建簡單的動作和一些該框架是如何運作的細節(jié)。通過在web.xml中的初始化,我們能夠避免用多個單獨的XML配置文件來把我們的顯示層組建寫在一起。這很重要,原因如下:首先,如果你需要任何改動,你可以看到一個URL就立即知道你該查看哪一個類。其次,我們不需要任何單獨的工具來在你的配置文件過大而且不可管理的時候幫助你。通過消除掉配置文件,我們不再需要給框架一大堆的metadata。最后,我們不再需要為一個獨立的用來描述我們的組件是如果相互關(guān)聯(lián)的文件來一刻不停維護了。
Ajax
要不要更高級的功能?那我們就來看看Stripes是怎么處理Ajax的。我們將把先前的Hello World例程改成使用Ajax調(diào)用Stripes動作。本例子的源代碼可以在本文資源中找到。首先,我們對Hello.jsp作改動使其引用Prototype JavaScript函數(shù)庫。我們還要為Ajax調(diào)用增加一個JavaScript函數(shù),并更改提交按鈕為其添加一個onclick事件:
......
<script src="{pageContext.request.contextPath}/js/prototype.js" type="text/javascript">
</script>
<script type="text/javascript">
function sayHelloAjax(){
var myAjax = new Ajax.Updater('hello', "<stripes:url beanclass="com. myco. web. stripes. action. example. HelloWorldAction" event="sayHelloAjax"/>", { method: 'get', parameters: Form.serialize('helloForm') });
}
</script>
......
�。約tripes:errors/>
�。約tripes:form beanclass="com. myco. web. stripes. action. example. HelloWorldAction" id="helloForm">
Say hello t
�。糱r> First name:
�。約tripes:text name="person.firstName"/><br>
Age:<stripes:text name="person.age"/><br>
�。約tripes:button name="helloAjax" value="Say Hello" onclick="sayHelloAjax()"/>
<div id="hello"></div>
�。�/stripes:form> ......
stripes:button有一個onclick事件將會調(diào)用HelloWorldAction類中的sayHelloAjax方法并將其結(jié)果返回在一個叫hello的div tag中。下面是我們要在HelloWorldAction中介紹的一個新方法:
{
return new ForwardResolution("SayHelloAjax.jsp");
}
這個方法沒有多少工作,因為Stripes已經(jīng)承擔(dān)了姓名內(nèi)容的綁定。因此,本方法唯一的責(zé)任就是轉(zhuǎn)發(fā)到一個叫SayHelloAjax.jsp的頁面片斷上去。該葉面片段的內(nèi)容如下:
Spring整合
Stripes還內(nèi)置了對Spring支持。你可以自動地將Spring bean諸如到你的動作中。按照Stripes的風(fēng)格,除了Spring上下文配置文件以外不需要任何外部配置文件。如果我們Spring的配置文件如下:
<property name="target">
<bean class="com.myco.service.impl.PersonServiceImpl"/>
</property>
</bean>
要把person服務(wù)注入到一個Stripes動作中,得增加一個跟Spring bean的名字一致的屬性和setter。Stripes提供了@SpringBean annotation來查詢正確的Spring bean以注入到動作之中。下面是我們要在動作類中包含的例子:
@SpringBeanpublic void setBlogService(BlogService blogService)
{
this.blogService = blogService;
}
本文無法囊括Stripes的所有高級功能。但是,Stripes有非常完整的文檔。Stripes還包含了一個與Tiles類似但無需外部配置文件的layout管理器。另外,攔截器還可以用于生命周期事件的各處、文件上載等等等等。
結(jié)論
Stripes是一個既強大又簡單的Java web框架。Stripes利用了Java 5的annotation和泛型功能,從而使得Java程序員避免維護外部配置文件并增加工作效率。Stripes可以簡化困難的web開發(fā)工作,并使得簡單的工作更加簡單!
分享:解答JavaMail的安裝和配置問題問. 我如何安裝 JavaMail API 實現(xiàn)? 答:解壓縮分發(fā)的 zip 文件,并編輯 CLASSPATH 環(huán)境變量以包含 mail.jar 文件,該文件包括在 JavaMail API 分發(fā)中。你也需要 JavaBeans Activation Framework(參見下面)的實現(xiàn)。參閱 README 文件(在分發(fā)中),獲得其
- jsp response.sendRedirect不跳轉(zhuǎn)的原因分析及解決
- JSP指令元素(page指令/include指令/taglib指令)復(fù)習(xí)整理
- JSP腳本元素和注釋復(fù)習(xí)總結(jié)示例
- JSP FusionCharts Free顯示圖表 具體實現(xiàn)
- 網(wǎng)頁模板:關(guān)于jsp頁面使用jstl的異常分析
- JSP頁面中文傳遞參數(shù)使用escape編碼
- 基于jsp:included的使用與jsp:param亂碼的解決方法
- Java Web項目中連接Access數(shù)據(jù)庫的配置方法
- JDBC連接Access數(shù)據(jù)庫的幾種方式介紹
- 網(wǎng)站圖片路徑的問題:絕對路徑/虛擬路徑
- (jsp/html)網(wǎng)頁上嵌入播放器(常用播放器代碼整理)
- jsp下顯示中文文件名及絕對路徑下的圖片解決方法
- 相關(guān)鏈接:
- 教程說明:
JSP教程-使用Stripes進行Java Web開發(fā)
。
