熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> JSP教程 >> 正文

利用Stripes實現Java Web開發

2013-11-15 12:11:23  來源: JSP教程 

  Stripes是一個以讓程序員的web開發簡單而高效為准則來設計的基於動作的開源Java web框架本文將介紹Stripes與其它如Struts之類基於動作的框架的區別和其提供的一些存在於Ruby on Rails之中的簡單性

  Stripes是一個以讓程序員的web開發簡單而高效為准則來設計的基於動作的開源Java web框架傳統的Java web開發著眼於借去耦(Decoupling)來實現其靈活性但導致多個的配置文件額外的對象和其他資源的分散這些困難造成相當多的程序員的更高的學習時間和低下的效率其結果是有些Java程序員被一些非Java的框架所吸引去了Ruby on Rails或者Django一些Java web框架如Stripes正在開始從這些非Java框架中汲取其成功經驗簡單而高效的開發本文將介紹Stripes與其它如Struts之類基於動作的框架的區別和其提供的一些存在於Ruby on Rails之中的簡單性 
  其流程基本上就是一個MVC框架Stripes和其他的基於動作的框架的一個主要的區別是沒有一個外部的配置文件我們隨後將看到Stripes用annotation和約定而非配置來提高產出和減少雜亂

  編寫你的第一個Stripe動作(Action)

  讓我們現在就開始通過創建Hello World例程來了解Stripes框架和理解其運作HelloWorldAction類將提示用戶輸入姓氏和名字然後在另一個View裡面顯示首先我們來編寫controller類

  
public class HelloWorldAction implements ActionBean
{
 @ValidateNestedProperties(
 {
  @Validate(field = "firstName" required = true on = {"hello"})
  @Validate(field = "age" required = true minvalue = on = {"hello"})
 })
 private Person person;
 private ActionBeanContext context;
 @DefaultHandler public Resolution index()
 {
  return new ForwardResolution("Hellojsp");
 }
 public Resolution hello()
 {
  return new ForwardResolution("SayHellojsp");
 }
 public void setPerson(String person) {thisperson = person;}
 public String getPerson() { return person;}
 public void setContext(ActionBeanContext c) {thiscontext = c; }
 public ActionBeanContext getContext() {return context; }}

  Controller類是一個實現了Stripes特有接口ActionBean的POJO(Plain Old Java Object譯注讀破粥)所有的Stripes動作類都要實現這一接口以讓StripesDispatcher servlet在運行服務時為其注入一個ActionBeanContext對象ActionBeanContext對象可以讓你存取的對象如requestresponse和servlet context等servlet API大多數時候在Stripes應用中是不用讀取這些底層API對象的

  ActionBeanContext類還提供當前動作的狀態並可以添加信息消息和錯誤消息到當前動作中ActionBeanContext的變量和其讀寫方法可以放在一個基類裡面因為所有的Stripes動作都要實現之

  Controller類的其他部分對於任何Java程序員來說都是很面熟的有一個Person對象和其讀寫方法是用來讀寫用戶的姓名給view的雖然這僅僅是一個簡單的嵌套對象Stripes可以通過Java集合泛型支持和下標化的屬性來實現更復雜完善的數據捆綁因為Stripes可以處理復雜數據捆綁你的領域對象(Domain Object)可以在其他需要它們的層重用例如通過Stripes你可以很容易的收集一個領域對象的信息然後用其他的POJO框架如Hibernate或者EJB來對其進行持久化

  Person對象變量上有一個Stripes驗證annotation用來保證用戶在激活hello方法的時候已經輸入了姓名如果用戶沒有輸入這兩個必需的變量原始頁會被返回並顯示一個相關的錯誤消息該驗證只有在hello事件被申請的時候才會被激活因為annotation的屬性中指定了(on = {"hello"})Stripes還會使用實用默認法則根據驗證方法和變量名稱產生一個錯誤信息例如如果Person類的firstName變量在提交的時候沒有提供用戶將看到

  Person First Name is a required field

  這條消息是通過將PersonfirstName進行刻讀化處理後得到的如果有必要這些錯誤消息可以被重載來提供更多的客戶自定義功能

  另外還有一個Integer類型的變量age是Person對象的一個屬性Stripes首先試圖對request中命為personage的parameter轉換為Integer類型並將其捆綁到Person對象上在Person對象的age變量被付值以後Stripes將驗證該Integer值是否小於如果用戶輸入了一個字符串而非整數用戶得到這個消息

  The value (Mark) entered in field Person Age must be a valid number

  若是用戶輸入了一個小於的整數用戶將看到這個消息

  The minimum allowed value for Age is

  同樣地我們沒有必要為這些錯誤消息提供任何外部的配置文件Annotation提供的驗證與你的變量在同一個位置上使得程序員定位驗證理解驗證的內容和對驗證進行維護變動更容易

  這個Stripes動作還有兩個可被激活的方法(稱為事件)事件是ActionBean類中有如下特征的方法

  public Resolution eventName

  請注意index方法被標注為@DefaultHandler annotation因為在本動作中有多個事件其中一個必須被指定為默認事件如果調用本動作的URL沒有指定哪個事件Stripes則查找標注有@DefaultHandler annotation的事件並執行

  顯示層(View)

  現在讓我們給Hello World例程加上顯示層的邏輯Stripes默認支持JSP為顯示層的標准技術不過你也可以用其他的顯示層技術比如FreeMaker除了Stripes的tag庫以外沒有什麼新的東西要學Hellojsp是初始的顯示可以讓用戶輸入和提交姓名

  
<%@ taglib prefix="stripes" uri="%>

<stripes:errors/>
<stripes:form beanclass="com myco web stripes action example HelloWorldAction"> Say hello t <br> First name:
<stripes:text name="personfirstName"/> <br> Age:<stripes:text name="personage"/><br>
<stripes:submit name="hello" value="Say Hello"/>
</stripes:form>

  這個JSP易讀易維護而Stripes用於form和input的tag跟對應的HTML代碼非常相似stripes:form tag包含一個beanclass屬性其值為我們前面定義的controller類的完整類名我們可以用stripes:form中的action屬性來替換beanclass屬性但是beanclass屬性可以讓你在以後對Stripes動作進行重構的時候更加方便如果你要用在stripes:form tag中使用action屬性方法如下

  
<stripes:form action="/example/HelloWorldaction">

  有一個stripes:input tag指定了一個名為personfirstName屬性其作用是將其儲存的輸入值付給controller的Person對象的firstName變量中最後stripes:submit tag指定一個name屬性來告訴Stripes的HelloWorldAction類使用哪一個事件

  我們現在已經完成了提交姓名的值給HelloWorldAction剩下的就是在另一個view中將其反饋給用戶了

  
<%@ taglib prefix="stripes" uri="%>

<stripes:errors/>
<h>Hello {actionBeanpersonfirstName} your age is {actionBeanpersonage} </h> <p/>
<stripes:link beanclass="commycowebstripesaction exampleHelloWorldAction"> Say Hello Again
</stripes:link>

  本JSP將自己通過一個對動作的引用讀取person的姓名信息並顯示為達到這一目的Stripes自動在request的屬性中添加一個名為actionBean動作對象以供JSTL存取最後我們用了一個strips:link tag來建立一個返回HelloWorldAction地鏈接從而可以讓我們輸入不同的姓名我們以可以通過如下辦法顯式地創建一個指向index事件的stripes:link

  
<stripes:link beanclass="commycowebstripesaction exampleHelloWorldAction" event="index">
Say Hello Again
</stripes:link>

  因為我們已經用annotation把index方法標記為@DefaultHandlerStripes無須event屬性也知道要執行哪一個方法

  用約定不用配置文件

  我們現在有了Java組件我們該做配置了把動作映射的一個URL上並將其連接到我們的兩個view上面去等一下!我們在用Stripes我們不需要外部配置文件!

  雖然這聽來好像好得不像是真的但這的確是Stripes的一項最具生產效率的功能Stripes使用約定而非配置文件來映射動作到URL上我們也無須使用一個外部配置文件來把view映射到一個個標記名字上這意味著程序員不用再為了一個標記名字——比方說SUCCESS——的實際來源而在配置文件中跳來跳去了沒有必要在Java和view組件的外部進行配線因而導致更好地維護性和更高的生產率

  Stripes是如何提供隱式的URL映射而無需在外部配置每一個動作或者而外的annotation呢?這個可以從Stripes在webxml中的配置以及它是如何通過實用默認法建立URL映射來解釋首先我們來看看Servlet過濾器StripesFilter其在webxml中的默認配置如下

  <filter>
<displayname>Stripes Filter</displayname>
<filtername>StripesFilter</filtername>
<filterclass> netsourceforgestripescontrollerStripesFilter </filterclass>
<initparam>
<paramname>ActionResolverUrlFilters</paramname>
<paramvalue>/WEBINF/classes</paramvalue>
</initparam>
</filter>

  當Servlet容器啟動的時候StripesFilter對其initparam元素執行初始化其中最重要的initparam元素就是ActionResolverUrlFilters參數這個參數告訴Stripes到哪裡查找跟Stripes有關的類這個例子裡面Stripes將查找/WEBINF/classes目錄下的所有實現ActionBean接口的類每一個被找到的類和其綁定的URL都將被加入一個Map中

  讓我們來看看Stripes是如何處理我們的HelloWorldAction動作為例子吧因為HelloWorldAction類位於/WEBINF/classes目錄下所以會被認為是一個Stripes servlet在我們的例子當中其完整類名是commycowebstripesactionexampleHelloWorldAction隨後其完整類名將按照如下法則被翻譯成一個URL綁定

  . 將含有wwwwebstripes和action的部分及其以前的內容刪掉在我們的例子有三個上述單詞所以我們得到了exampleHelloWorldAction

  . 如果類名中包涵帶Action或Bean的尾巴刪掉因為我們的類名以Action結尾我們得到了exampleHelloWorld

  . 將替換為/我們得到了example/HelloWorld

  . 最後添加上一個尾綴(默認是action)從而完成了URL綁定最後的結果是example/HelloWorldaction

  現在Stripes找到了ActionBean類並為其創建了一個URL綁定然後存放在一個javautilMap<String Class<? extends ActionBean>>之中其中key參數是URL綁定value參數是實現ActionBean的類名下面是我們的例子中的Map

  URL綁定/example/HelloWorldaction
  ActionBean類commycowebstripesactionexampleHelloWorldAction

  我們要看的第二個組件是Stripes如何把URL綁定翻譯成你正在做的這個ActionBean類這是Stripes調度servlet的職責在webxml中的配置如下

  
<servlet>
<servletname>StripesDispatcher</servletname>
<servletclass>
netsourceforgestripescontrollerDispatcherServlet </servletclass>
<loadonstartup></loadonstartup>
</servlet>
<servletmapping>
<servletname>StripesDispatcher</servletname>
<urlpattern>*action</urlpattern>
</servletmapping>

  StripesDispatcher的一個職責就是將URL解析為Stripes的ActionBean類當用戶激活URL 的時候Stripes調度servlet將在URL映射表中查詢並找到commycowebstripesactionexampleHelloWorldAction類並實例化產生該類的一個實例最後index方法被激活因為在annotation中它被定義為默認局柄而在該URL中並沒有指定一個事件

  如果我們想要直接執行HelloWorldAction中的hello方法怎麼辦?應該象下面這個URL這樣把事件的名字放在request的參數中

  請注意我們沒有給hello這個request參數名指定任何值在這個情況下StripesDispatcher會把hello這個這個request參數名和HelloWorldAction類中個一個帶有public Resolution hello()簽名的函數識別並映射該方法名城在初始化的時候為了性能而緩存在另一個Map中

  我們已經看到Stripes的基礎以及如果創建簡單的動作和一些該框架是如何運作的細節通過在webxml中的初始化我們能夠避免用多個單獨的XML配置文件來把我們的顯示層組建寫在一起這很重要原因如下首先如果你需要任何改動你可以看到一個URL就立即知道你該查看哪一個類其次我們不需要任何單獨的工具來在你的配置文件過大而且不可管理的時候幫助你通過消除掉配置文件我們不再需要給框架一大堆的metadata最後我們不再需要為一個獨立的用來描述我們的組件是如果相互關聯的文件來一刻不停維護了

  Ajax

  要不要更高級的功能?那我們就來看看Stripes是怎麼處理Ajax的我們將把先前的Hello World例程改成使用Ajax調用Stripes動作本例子的源代碼可以在本文資源中找到首先我們對Hellojsp作改動使其引用Prototype JavaScript函數庫我們還要為Ajax調用增加一個JavaScript函數並更改提交按鈕為其添加一個onclick事件

  
<%@ taglib prefix="stripes" uri="%>

<script src="{pageContextrequestcontextPath}/js/prototypejs" type="text/javascript">
</script>
<script type="text/javascript">
function sayHelloAjax(){
 var myAjax = new AjaxUpdater(hello "<stripes:url beanclass="com myco web stripes action example HelloWorldAction" event="sayHelloAjax"/>" { method: get parameters: Formserialize(helloForm) });
 }
 </script>
 
 <stripes:errors/>
 <stripes:form beanclass="com myco web stripes action example HelloWorldAction" id="helloForm">
 Say hello t
  <br> First name:
  <stripes:text name="personfirstName"/><br>
  Age:<stripes:text name="personage"/><br>
  <stripes:button name="helloAjax" value="Say Hello" onclick="sayHelloAjax()"/>
   <div id="hello"></div>
 </stripes:form>

  stripes:button有一個onclick事件將會調用HelloWorldAction類中的sayHelloAjax方法並將其結果返回在一個叫hello的div tag中下面是我們要在HelloWorldAction中介紹的一個新方法

  
public Resolution sayHelloAjax()
{
 return new ForwardResolution("SayHelloAjaxjsp");
}

  這個方法沒有多少工作因為Stripes已經承擔了姓名內容的綁定因此本方法唯一的責任就是轉發到一個叫SayHelloAjaxjsp的頁面片斷上去該葉面片段的內容如下

  
<h>Hello {actionBeanpersonfirstName} your age is {actionBeanpersonage}!</h

  Spring整合

  Stripes還內置了對Spring支持你可以自動地將Spring bean諸如到你的動作中按照Stripes的風格除了Spring上下文配置文件以外不需要任何外部配置文件如果我們Spring的配置文件如下

  
<bean id="personService" parent="abstractTxDefinition">
<property name="target">
<bean class="commycoserviceimplPersonServiceImpl"/>
</property>
</bean>

  要把person服務注入到一個Stripes動作中得增加一個跟Spring bean的名字一致的屬性和setterStripes提供了@SpringBean annotation來查詢正確的Spring bean以注入到動作之中下面是我們要在動作類中包含的例子

  
private PersonService personService;
@SpringBeanpublic void setBlogService(BlogService blogService)
{
thisblogService = blogService;
}

  本文無法囊括Stripes的所有高級功能但是Stripes有非常完整的文檔Stripes還包含了一個與Tiles類似但無需外部配置文件的layout管理器另外攔截器還可以用於生命周期事件的各處文件上載等等等等

  結論

  Stripes是一個既強大又簡單的Java web框架Stripes利用了Java 的annotation和泛型功能從而使得Java程序員避免維護外部配置文件並增加工作效率Stripes可以簡化困難的web開發工作並使得簡單的工作更加簡單!
 


From:http://tw.wingwit.com/Article/program/Java/JSP/201311/20456.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.