欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
Java Web Framework綜述

Java Web Framework綜述

0.簡(jiǎn)介

本文介紹Java Web Framework的基本工作原理,和一些常用的開(kāi)源Web MVC Framework(Struts, Web Work, Tapestry, Echo, JSF, Maverick, Spring MVC, Turbine, Cocoon, Barracuda)。

Web開(kāi)發(fā)的最重要的基本功是HTTP;Java Web開(kāi)發(fā)的最重要的基本功是Servlet Specification。HTTPServlet Specification對于Web ServerWeb Framework的開(kāi)發(fā)實(shí)現來(lái)說(shuō),是至關(guān)重要的協(xié)議規范。

應用和剖析開(kāi)源Web Framework,既有助于深入掌握HTTP & Servlet Specification, 也有助于了解一些現代的B/S Web框架設計思想,如MVC,事件處理機制,頁(yè)面組件,IoC,AOP等。在這個(gè)現代化的大潮中,即使Servlet規范本身也不能免俗,不斷引入Filter、Listener等現代框架設計模式。同是Sun公司出品的JSF更是如此。

關(guān)于MVC模型、項目簡(jiǎn)介、配置文件、入門(mén)示例等基礎知識,網(wǎng)上已經(jīng)有大量的重復資料信息,本文不再贅述。

文中會(huì )提到一些相關(guān)的開(kāi)源項目,和一些編程思想,如有需要,可以用相關(guān)的關(guān)鍵字在網(wǎng)上搜索,獲取基本的背景知識。

本文力圖言簡(jiǎn)意賅,突出重點(diǎn)。著(zhù)重描述其他資料沒(méi)有提到、或很少提到的較重要內容,如運行原理、主流用法,相關(guān)知識,關(guān)鍵特性等。

1. Java Web程序工作原理

TomcatServer.xml文件中定義了網(wǎng)絡(luò )請求路徑到主機本地文件路徑的映射。比如,<context path="/yourapp" docBase="yourapp_dir/webapp"/>

 

我們來(lái)看一下,一個(gè)HTTP Request-Response Cycle的處理過(guò)程。

HTTP Request URL一般分為三段:host, context, path。

http://yourhost/yourapp/en/index.html這個(gè)URL,分為host=yourhost, context=yourapp, path=en/index.html三段。其中,Context部分由request.getContext()獲得,path部分由request.getServletPath()獲得(返回結果是“/en/index.html”)。

yourhost主機上運行的Tomcat Web Server接收到這個(gè)URL,根據Context定義,把yourapp這個(gè)網(wǎng)絡(luò )路徑映射為yourapp_dir/webapp,并在此目錄下定位en/index.html這個(gè)文件,返回到客戶(hù)端。

 

如果我們這個(gè)URL更換為http://yourhost/yourapp/en/index.jsp,這個(gè)時(shí)候Tomcat會(huì )試圖把yourapp_dir/webapp/en/index.jsp文件編譯成Servlet,并調用運行這個(gè)Servlet。

我們再把這個(gè)URL更換為http://yourhost/yourapp/en/index.do。

注意,戲劇化的事情就發(fā)生在這個(gè)時(shí)候,Servlet規范中最重要的類(lèi)RequestDispatcher登場(chǎng)了。RequestDispatcher根據WEB-INF/web.xml配置文件的定義,調用對應的Servlet來(lái)處理en/index.do這個(gè)路徑。

假設web.xml里面有這樣的定義。

  <servlet>

    <servlet-name>DispatchServlet</servlet-name>

    <servlet-class>yourapp.DispatchServlet</servlet-class>

  </servlet>

  <servlet-mapping>

    <servlet-name>DispatchServlet</servlet-name>

    <url-pattern>*.do</url-pattern>

  </servlet-mapping>

那么,RequestDispatcher會(huì )調用yourapp.DispatchServlet類(lèi)處理這個(gè)路徑。

如果web.xml沒(méi)有定義對應en/index.do這個(gè)路徑的Servlet,那么Tomcat返回“您請求的資源不存在”。

RequestDispatcher用于Web Server中,也可以用于應用程序中進(jìn)行處理轉向,資源定位。比如,我們在處理en/index.do的代碼中調用,

request.getRequestDispatcher(“cn/index.jsp”).forward(request, response), 就可以轉交另外的資源cn/index.jsp來(lái)處理。

 

幾乎所有的Web Framework都需要定義自己的Dispatch作用的Servlet,并調用RequestDispatcher進(jìn)行轉向處理。

閱讀Web Framework源代碼,有兩條主要線(xiàn)索,(1)根據web.xml找到對應的Servlet類(lèi);(2)搜索包含“RequestDispatcher”詞的代碼文件。

 

我們看到,request, response  這兩個(gè)參數,被RequestDispatcher在各種Servlet之間傳來(lái)傳去(JSP也是Servlet)。所以,requestsetAttribute()getAttribute()方法是Servlet之間傳送數據的主要方式。

MVC結構中,一般的處理流程如下:

處理HTTP Request的基本單位一般稱(chēng)為Action,是一個(gè)比Servlet輕量得多的接口定義,通常只有一兩個(gè)方法,如execute(perform), validate等。

我們知道,URL->Servlet映射,定義在Web.xml配置文件里,但MVC框架通常會(huì )有另外一個(gè)定義URL-> Action映射的配置文件。

入口Dispatcher Servlet根據URL -> Action的映射關(guān)系,把請求轉發(fā)給Action。

Action獲得輸入參數,調用商業(yè)邏輯,并把結果數據和View標識給(Model & View)返回給Dispatcher Servlet。

Dispatcher Servlet根據這個(gè)View 標識,定位相應的View Template Path,把處理轉交給ViewJSP +TagLib, Velocity, Free Marker, XSL等)。

View一般通過(guò)request.getAttribute()獲得結果數據,并顯示到客戶(hù)端。至于是誰(shuí)把結果數據設置到request.attribute里面,有兩種可能:ActionDispatcher Servlet。

2. Struts

http://struts.apache.org/

Struts是目前用戶(hù)群最大、開(kāi)發(fā)廠(chǎng)商支持最多的開(kāi)源Web Framework。

Struts勞苦功高,為普及MVC框架作出了不可磨滅的貢獻。顯赫的聲望,趨于老化的厚重結構,令Struts成為很多現代Web Framework參照、挑戰的目標。

 

Struts應用主要包括3件事情: 配置struts-config.xml文件,實(shí)現Action類(lèi),實(shí)現View;還有一些高級擴展用法。下面分別講述。

 

1. 配置struts-config.xml文件:

Struts支持多級配置文件,具體用法和限制,詳見(jiàn)Struts文檔。這里只討論struts-config.xml主流配置的內容。:-)

 

(1) URL PathAction的映射。

<action path="/LogonSubmit" type="app.LogonAction" ... />

 

Struts的入口ServletActionServlet。

ActionServlet需要此信息把URL Path調用對應的Action類(lèi)處理。

Struts運行期間,一個(gè)URL Path,只存在一個(gè)對應的Struts Action實(shí)例。所有的該URL Path的請求,都經(jīng)過(guò)這同一個(gè)Struts Action實(shí)例處理。所以Struts Action必須線(xiàn)程安全。

想想看,其實(shí)這個(gè)要求并不過(guò)分,Action只是一個(gè)處理程序,不應該保存跨HTTP請求的狀態(tài)數據,按理來(lái)說(shuō),也應該做成線(xiàn)程安全的。

 

(2) Template NameView Template Path的映射。

<forward name="success" path="/pages/Welcome.jsp"/>

 

Action類(lèi)返回一個(gè)Template Name,ActionServlet根據這個(gè)Template Name獲得對應的View Template Path,然后調用

request.getRequestDispatcher(“View Template Path”),把處理轉向路徑對應的Servlet。在這個(gè)例子中,是轉向/pages/Welcome.jsp編譯后的Servlet。

 

我們來(lái)看一個(gè)一個(gè)Velocity的例子。

<include name="success" path="/pages/Welcome.vm"/>

web.xml的定義如下

<servlet>

  <servlet-name>velocity</servlet-name>

<servlet-class>org.apache.velocity.tools.view.servlet.VelocityViewServlet</servlet-class>

</servlet>

<servlet-mapping>

  <servlet-name>velocity</servlet-name>

  <url-pattern>*.vm</url-pattern>

</servlet-mapping>

 

這時(shí),request.getRequestDispatcher(“/pages/Welcome.vm”)會(huì )調用VelocityViewServlet,由VelocityViewServlet負責裝并驅動(dòng)運行/pages/Welcome.vm這個(gè)模板文件。

這里面有一個(gè)問(wèn)題,如果調用的是DispatchRequester.include()方法,那么如何才能把pages/Welcome.vm傳給VelocityViewServlet呢?

如前所說(shuō),RequestDispatcher傳遞的參數只有兩個(gè),requestresponse。那么只能通過(guò)request attribute。正是為了解決這個(gè)問(wèn)題,Servlet2.3規范之后,加入了javax.servlet.include.servlet_path這個(gè)屬性。

參見(jiàn)VelocityViewServlet的代碼(velocity-tool開(kāi)源項目)

// If we get here from RequestDispatcher.include(), getServletPath()

// will return the original (wrong) URI requested.  The following special

// attribute holds the correct path.  See section 8.3 of the Servlet

// 2.3 specification.

String path = (String)request.getAttribute("javax.servlet.include.servlet_path");

 

從這里我們可以看出,為什么通曉Servlet Specification對于通曉Web Framework至關(guān)重要。

 

(3) Form Bean的定義

<form-bean name="logonForm" type="app.LogonForm"/>
Struts Form Bean需要繼承ActionForm類(lèi)。

Form Bean類(lèi),主要有三個(gè)作用:

[1]根據bean的定義,利用reflection機制,自動(dòng)把request參數轉化為需要的數據類(lèi)型,填入到bean的屬性當中。ActionForm類(lèi)名中雖然有Form這個(gè)詞,但不僅能夠獲取Form提交后的HTTP Post參數,也可以獲取URL后綴的HTTP Get參數。

[2]輸入驗證。用戶(hù)可以配置validation.xml,定義各屬性的驗證規則。

[3]當作View Object來(lái)用。用戶(hù)需要熟練掌握Struts HTML TagLib的用法,才能把Form Bean的屬性正確顯示出來(lái)。

 

(4)其他定義。詳見(jiàn)Struts文檔。不再贅述。

 

2.實(shí)現Action。

Action類(lèi)從Form Bean或直接從request中獲得輸入參數,調用商業(yè)邏輯,把結果數據(也許會(huì )包裝成View Object),用request.setAttribute()放到request中,最后返回一個(gè)用ForwardMapping類(lèi)包裝的Template Name。

 

3.實(shí)現View。

Struts View的標準實(shí)現方法是JSP + Struts TagLib,其中最重要的就是Struts HTML TagLib。

html:form tag則是整個(gè)HTML Tag的核心,其它的如html:input, html:selecttag,都包含在html:form tag里面。

html:form tag用來(lái)映射Form Bean(也可以通過(guò)適當定義,映射其他的bean,但使用上會(huì )有很多麻煩)。html:form tag包含的其他Struts html tag用來(lái)映射Form Bean的屬性。

 

Struts Bean TagLib的用法比較臃腫,一般情況下可以用JSTL代替。當然,如果需要用到bean:message tag實(shí)現國際化,那又另當別論。

Struts Tile TagLib用于頁(yè)面布局。開(kāi)源Portal項目Liferay使用了Struts Tile TagLib做為布局控制。

 

4.高級擴展用法

用戶(hù)可以重載Struts的一些控制類(lèi),引入自己的一些定制類(lèi)。詳見(jiàn)Struts文檔。

本文不是Struts專(zhuān)題,只講述最重要的主流用法,其它邊邊角角的,不再贅述。

3. WebWork

http://www.opensymphony.com/webwork/

WebWork由于靈活的可插拔特性,受到很多資深程序員的歡迎。似乎很有可能大肆流行起來(lái)。

WebWork項目建立在XWork項目上。入口ServletWebWork項目中定義的ServletDispatcher,而ActionXWork項目中定義。

XWork Action接口的execute()方法沒(méi)有參數,不像Struts Action那樣接受request, response參數,所以XWork Action能夠脫離Web環(huán)境被直接調用,便于單元測試。

這里引入了一個(gè)問(wèn)題。沒(méi)有了request參數,那么XWork Action如何獲得request parameters作為輸入數據?又通過(guò)什么橋梁(Strutsrequest.setAttribute)把結果數據傳送到View層?

Web Work中,只能通過(guò)Action本身的getter, setter屬性來(lái)傳送輸入參數和輸出結果。

比如,我們有這樣一個(gè)實(shí)現了XWork Action接口的類(lèi),

YourAction implements Action{

  int productId = null;

  String productName = null;

 

  public void setProductId(int productId){this.productId = productId;}

  public String getProductName(){return productName;}

 

  public String execute(){

      productName = findNameById(productId);

      return “success”;

  }

}

這個(gè)類(lèi)里面的productId將接受request輸入參數,productName是輸出到頁(yè)面顯示的結果。

比如,這樣的請求,http://yourhost/yourapp/MyAction.action?productId=1

Web Work會(huì )把1填到YourActionproductId里面,然后執行execute()方法,JSP里的語(yǔ)句<ww:property value=“productName”>會(huì )把YourActionproductName顯示在頁(yè)面上。

 

如果一個(gè)Web Framework采用了這種屏蔽Actionrequest, response參數的設計方式,一般也同時(shí)會(huì )采用這種Action和輸入輸出數據結合成一體的解決方式。類(lèi)似的情形也存在于TapestryMaverick中,后面會(huì )講到。

WebWork ServletDispatcher接收到HTTP Request的時(shí)候,首先把所有相關(guān)的信息(包括request, response, session, servlet config, servelt context, 所有request參數)等存放到AcationContext中,然后根據Interceptor配置信息,生成一個(gè)YourAction的動(dòng)態(tài)代理類(lèi)對象。實(shí)際上運行的正是這個(gè)代理對象,如同Servlet Filter的工作機制一般,所有注入的Interceptor方法會(huì )先于Actio方法運行。

我們來(lái)看一下ActionInterceptor的地位:Action沒(méi)有參數,無(wú)法獲得ActionContext;而Interceptor接受的ActionInvoication參數擁有包括ActionContext在內的所有重要信息。

這種權力分配的不平等,注定了Action的作用非常有限,只限于調用商業(yè)邏輯,然后返回一個(gè)成功與否標志。所有與外部Web世界打交道、協(xié)調內部工作流程的重擔,都責無(wú)旁貸地落在Interceptor的肩上。

我們可以設想一個(gè)極端的例子。我們聲明一批不做任何事情的空Action,我們只是需要它們的空殼類(lèi)名;我們制作一批對應的Interceptor,所有的轉發(fā)控制、商業(yè)邏輯都在Interceptor上實(shí)現,然后把Interceptor都注入到對應的空Action。這在理論上是完全可行的。

Web海洋的包圍中,Action可少,Interceptor不可少。Action是一個(gè)孤島,如果沒(méi)有外來(lái)盟友Interceptor的協(xié)助,只能在自己的小范圍內獨立作戰(比如Unit Test),而對整體大局的作戰目標無(wú)法產(chǎn)生影響。

下面我們來(lái)看一下Action是如何在Interceptor的全程監管下工作的。

 

WebWork中,我們需要如下配置XWork.xml。

<xwork>

<!-- Include webwork defaults (from WebWork-2.1 JAR). -->

<include file="webwork-default.xml" />

 

<!-- Configuration for the default package. -->

<package name="default" extends="webwork-default">

    <!-- Default interceptor stack. -->

    <default-interceptor-ref name=" defaultStack" />

 

    <!-- Action: YourAction. -->

    <action name="youraction" class="yourapp.YourAction">

        <result name="success" type="dispatcher">

YourAction.jsp

</result>

</action>

</package>

</xwork>

 

webwork-default.xml里面的相關(guān)定義如下:

<interceptors>

<interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/>

 

<interceptor name="static-params" class="com.opensymphony.xwork.interceptor.

StaticParametersInterceptor"/>

<interceptor name="params" class="com.opensymphony.xwork.interceptor.ParametersInterceptor

"/>

<interceptor name="conversionError" class="com.opensymphony.webwork.interceptor.

WebWorkConversionErrorInterceptor"/>

<interceptor-stack name="defaultStack">

    <interceptor-ref name="static-params"/>

    <interceptor-ref name="params"/>

    <interceptor-ref name="conversionError"/>

</interceptor-stack>

</interceptors>

 

從上述的配置信息中可以看出,YourAction執行execute()方法的前后,會(huì )被

defaultStack所定義的三個(gè)Intercepter截獲。這些Interceptor的任務(wù)之一就是把輸入參數設置到Action的對應屬性當中。

如果我們需要加入對YourAction的屬性的驗證功能,只要把上述定義中的validation Interceptor加入到defaultStack中就可以了。當然,實(shí)際工作還沒(méi)有這么簡(jiǎn)單,一般來(lái)說(shuō),還要為每個(gè)進(jìn)行屬性驗證的Action的都配置一份validation.xml。

XWork Interceptor能夠在PackageAction級別上,進(jìn)行截獲處理。

Servlet Filter能夠在URL Patten級別上,進(jìn)行截獲處理。雖然實(shí)際上,Servlet Filter截獲的是Servlet,但某些情況下,可以達到和截獲一批Action的同樣效果。

比如,在Web Work中,我們可以為所有admin packageAction,加入一個(gè)Interceptor,當檢查到當前Session的用戶(hù)沒(méi)有admin權限時(shí),統一返回一個(gè)警告頁(yè)面:您沒(méi)有足夠的權限執行這個(gè)操作。

我們看到也可以為所有URL Pattern為“admin/*.action”的URL定義一個(gè)Servlet Filter,當檢查到當前Session的用戶(hù)沒(méi)有admin權限時(shí),統一返回一個(gè)警告頁(yè)面:您沒(méi)有足夠的權限執行這個(gè)操作。

 

WebWorkInterceptor配置是相當靈活的,相當于對Action實(shí)現了AOP。Interceptor相當于Aspect,基類(lèi)AroundInterceptorbefore(), after()方法相當于Advice。

另外,XWork也提供了從XML配置文件裝配Component的機制,相當于實(shí)現了對于ComponentIoC。

提到AOPIoC,順便多講兩句。Spring AOP能夠截獲所有Interface,不限于某個(gè)特定接口;Spring框架支持所有類(lèi)型的IoC,不限于某種特定類(lèi)型。

 

要知道,AOP, IoC可是現在最時(shí)髦的東西,一定不要錯過(guò)啊。:D

相關(guān)概念導讀(如果需要,請用如下關(guān)鍵字搜索網(wǎng)絡(luò )):

AOP -- Aspect Oriented Programming -- 面向方面編程。

IoC – Inversion of Control --控制反轉

Dynamic Proxy -- 動(dòng)態(tài)代理,JDK1.4引入的特性。還可以進(jìn)一步參考CGLib, ASM等開(kāi)源項目。

 

WebWork直接支持所有主流View -- XSL,Velocity, FreeMarker,JSP。WebWork還提供了自己的TagLib。“直接支持”的意思是說(shuō),不用像Struts那樣,使用Velocity的時(shí)候,還需要引入輔助橋梁Velocity-tool。

WebWork中用到一種功能和XPath類(lèi)似的對象尋徑語(yǔ)言ONGL,是一個(gè)開(kāi)源項目。ONGL同樣用在下面要介紹的Tapestry項目中。

Opensymphony下還有一個(gè)SiteMesh項目,通過(guò)Servlet Filter機制控制布局??梢院?/span>WebWork組合使用。

 

4. Tapestry

http://jakarta.apache.org/tapestry/

Tapestry近來(lái)突然火了起來(lái),令我感到吃驚。也許是JSF帶來(lái)的Page Component風(fēng)潮令人們開(kāi)始關(guān)注和追逐Tapestry。

Tapestry的重要思想之一就是Page Component。

前面講到,XWork能夠自動(dòng)把request參數映射到Action的屬性當中。Tapestry走得更遠,甚至能夠根據request參數,映射到ActionTapestry里面稱(chēng)為Page)的方法,并把request參數映射為Page方法需要的參數,進(jìn)行正確的調用。就這樣,Tapestry不僅把輸入輸出數據,而且把事件方法也綁定到了Page上面。

Tapestry框架中,Action的概念已經(jīng)非常模糊,而換成了Page的概念。而Tapestry Page是擁有屬性和事件的頁(yè)面組件,其中的事件處理部相當于Action的職責,而屬性部分起著(zhù)Model的作用。

除了使用Page和其它的Tapestry頁(yè)面組件,用戶(hù)也可以自定義頁(yè)面組件。

 

這種頁(yè)面組件/屬性事件的編程模型,受到一些程序員的歡迎。當然,這種編程模型并不是沒(méi)有代價(jià)的,每個(gè)Tapestry模板文件都需要一個(gè)對應的.page文件。這些.page文件定義了頁(yè)面組件的屬性、事件、Validator等信息。

 

我們來(lái)看一下B/S結構中,組件的屬性、事件和HTTP Request綁定的基本原理。一個(gè)能夠發(fā)出請求的頁(yè)面組件(比如LinkButton),在輸出自己的HTML的時(shí)候,需要輸出一些特殊的信息來(lái)標志本組件的屬性/事件,這樣下次HTTP Request來(lái)的時(shí)候,會(huì )把這些信息帶回來(lái),以便Web Framework加以辨認識別,發(fā)給正確的Page Component處理。

這些特殊信息通常包含在URL參數或Hidden Input里面,必要的時(shí)候,還需要生成一些Java Script。Tapestry,Echo,JSF都是這種原理。

Tapestry的例子如下:

<a href="#" jwcid="@DirectLink" parameters="ognl:currentItem.itemId" listener="ognl:listeners.showItem">

JSFTagLib實(shí)現頁(yè)面組件,也提供了類(lèi)似的CommandLinkCommandButton Tag。其中對應Tapestry listenerTag屬性是action。后面會(huì )講解。

 

Tapestry的模板標簽是HTML標簽的擴展,具有良好的“所見(jiàn)即所得”特性,能夠直接在瀏覽器中正確顯示,這也是Tapestry的一個(gè)亮點(diǎn)。

5. Echo

http://sourceforge.net/projects/echo

Echo提供了一套類(lèi)似Swing的頁(yè)面組件,直接生成HTML。

從程序員的角度看來(lái),用Echo編寫(xiě)Web程序,和用Swing編寫(xiě)Applet一樣,屬于純面向組件事件編程,編程模型也以Event/Listener結構為主體。

Echo沒(méi)有Dispatcher Servlet,也沒(méi)有定義URL->Action映射的配置文件。

EchoAction就是實(shí)現了ActionListener接口(參數為ActionEvent)的Servlet(繼承EchoServer類(lèi))。

所以,Echo直接由Web Server根據web.xml配置的URL -> Servlet的映射,進(jìn)行轉發(fā)控制。

 

Echo也沒(méi)有明顯的View層,Echo在頁(yè)面組件方面走得更遠,所有的HTMLJavaScript都由框架生成。你不必(也沒(méi)有辦法)寫(xiě)HTML,只需要(也只能)在Java代碼中按照類(lèi)似Swing編程方式,生成或操作用戶(hù)界面。用戶(hù)也可以定制自己的Echo組件。

EchoUI Component的實(shí)現,采用了兩個(gè)重要的模式。一個(gè)是PeerComponent -> ComponentPeer)模式,一個(gè)是UI Component -> Renderer模式。

雖然EchoAPI更類(lèi)似于Swing,但實(shí)現上卻采用更接近于AWTPeer模式。每個(gè)Component類(lèi)(代表抽象的組件,比如Button),都有一個(gè)對應的ComponentPeer類(lèi)(代表實(shí)際的組件,比如windows桌面的Button,Linux桌面的Button,HTML Button等)。

先別急,這個(gè)事情還沒(méi)有完。雖然ComponentPeer落實(shí)到了具體的界面控件,但是它還是舍不得顯示自己,進(jìn)一步把顯示工作交給一個(gè)Renderer來(lái)執行。

比如,在Echo里面,Button類(lèi)對應一個(gè)ButtonUI(繼承了ComponentPeer)類(lèi),而這個(gè)ButtonUI類(lèi)會(huì )把最終顯示交給ButtonRender來(lái)處理。

據說(shuō)多了這么一步,能夠讓顯示控制更加靈活豐富。比如,同一個(gè)Renderer可以處理不同的UI Component,同一個(gè)UI Component也可以交給不同的Renderer處理。

JSF的頁(yè)面組件也采用了UI Component -> Renderer模式,后面會(huì )講到。

6. JSF

http://java.sun.com/j2ee/javaserverfaces/index.jsp

http://wwws.sun.com/software/communitysource/jsf/download.html download source

 

JSF的中心思想也是頁(yè)面組件/屬性事件。一般來(lái)說(shuō),JSF的頁(yè)面組件是一個(gè)三件套{ UI Component, Tag, Renderer}。

UI Component有可能對應Model,Event,Listener。Tag包含componentTyperendererType兩個(gè)屬性,用來(lái)選擇對應的的UI ComponentRenderer。

JSF的應用核心無(wú)疑是JSF TagLib。JSF TagLib包含了對應所有重要HTML元素的Tag,而且Input Tag可以直接包含Validator Tag或者Validator屬性,來(lái)定義驗證手段。

 

我們通過(guò)JSF攜帶的cardemo例子,來(lái)看JSF的處理流程。

(1) carDetail.jsp有如下內容:

<h:commandButton action="#{carstore.buyCurrentCar}" value="#{bundle.buy}" />

可以看到,這個(gè)buttonsubmit actioncarstore.buyCurrentCar方法綁定在一起。我們在Tapestry里面曾經(jīng)看到過(guò)類(lèi)似的情景。

 

(2) carstorefaces-config.cml中定義:

  <managed-bean>

    <managed-bean-name> carstore </managed-bean-name>

    <managed-bean-class> carstore.CarStore </managed-bean-class>

    <managed-bean-scope> session </managed-bean-scope>

  </managed-bean>

 

(3) carstore.CarStore類(lèi)中的buyCurrentCar方法如下:

    public String buyCurrentCar() {

        getCurrentModel().getCurrentPrice();

        return "confirmChoices";

    }

 

(4) confirmChoices轉向在faces-config.cml中定義:

  <navigation-rule>

    <from-view-id>/carDetail.jsp</from-view-id>

    <navigation-case>

      <description>

        Any action that returns "confirmChoices" on carDetail.jsp should

        cause navigation to confirmChoices.jsp

      </description>

      <from-outcome>confirmChoices</from-outcome>

      <to-view-id>/confirmChoices.jsp</to-view-id>

    </navigation-case>

  </navigation-rule>

 

(5)于是轉到頁(yè)面confirmChoices.jsp。

 

除了Interceptor之外,JSF幾乎包含了現代Web Framework應該具備的所有特性:頁(yè)面組件,屬性事件,IoC (ManagedBean),Component -> Renderer,類(lèi)似于Swing ComponentModel-Event-Listener。

也許設計者認為,眾多龐雜的模式能夠保證JSF成為一個(gè)成功的框架。Portal開(kāi)源項目eXo就是建立在JSF框架上。

 

可以看出這樣一個(gè)趨勢,現代Web Framework認為B/S結構的無(wú)狀態(tài)特性和HTML界面是對編程來(lái)說(shuō)是需要極力掩蓋的一個(gè)缺陷,所以盡量模擬C/S結構的組件和事件機制,以吸引更多的程序員。

7. Maverick

http://mav.sourceforge.net/

Maverick是一個(gè)輕量而完備的MVC Model 2框架。MaverickAction不叫Action,直截了當的稱(chēng)作Controller。

Controller只接受一個(gè)ControllerContext參數。request,response, servlet config, servelt context等輸入信息都包裝在ControllerContext里面,而且Model也通過(guò)ControllerContextmodel屬性返回。整個(gè)編程結構清晰而明快,令人贊賞。

但這個(gè)世界上難有十全十美的事情,由于ControllerContext只有一個(gè)model屬性可以傳遞數據,程序員必須把所有需要的數據都打包在一個(gè)對象里面設置到model屬性里。這種麻煩自然而然會(huì )導致這樣的可能用法,直接把Controller本身設置為model,這又回到了Controller(Action)Model一體的老路。

 

前面講到,WebWork也把所有的輸入信息都包裝在ActionContext里面,但Action并沒(méi)有權力獲取。而在Maverick中,Controller對于ControllerContext擁有全權的控制,兩者地位不可同日而語(yǔ)。當然,由于參數ControllerContext包含request,reponse之類(lèi)信息,這也意味著(zhù),Maverick Controller不能像WebWork Action那樣脫離Web環(huán)境獨立運行。

當然,這也并不意味著(zhù)任何結構性缺陷。程序的結構由你自己控制,你完全可以把需要Unit Test的那部分從Web環(huán)境脫離開(kāi)來(lái),放到Business層。

如同WebWork,Maverick直接支持所有的主流View。Maverick的配置文件采Struts, Cocoon兩家之長(cháng),URL -> Action -> View映射的主體結構類(lèi)似于Struts,而View定義部分對Transform的支持則類(lèi)似于Cocoon。如:

<command name="friends">

<controller class="org.infohazard.friendbook.ctl.Friends"/>

<view name="success" path="friends.jsp">

        <transform path="trimInside.jsp"/>

</view>

</command>

8. Spring MVC

http://www.springframework.com/

Spring MVC是我見(jiàn)過(guò)的結構最清晰的MVC Model 2實(shí)現。

Action不叫Action,準確地稱(chēng)做Controller;Controller接收request, response參數,干脆利落地返回ModelAndView(其中的Model不是Object類(lèi)型,而是Map類(lèi)型)。

其它的Web Framework中, Action返回值一般都只是一個(gè)View Name;Model則需要通過(guò)其它的途徑(如request.attribute,Context參數,或Action本身的屬性數據)傳遞上去。

 

Spring以一招IoC名滿(mǎn)天下,其AOP也方興未艾。“Spring出品,必屬精品”的觀(guān)念已經(jīng)深入人心。我這里多說(shuō)也無(wú)益,強烈建議讀者去閱讀Spring Doc & Sample & Code本身。

9. Turbine

http://jakarta.apache.org/turbine/

Turbine是一個(gè)提供了完善權限控制的堅實(shí)框架(Fulcrum子項目是其基石)。Turbine的個(gè)人用戶(hù)不多,但不少公司用戶(hù)選擇Turbine作為框架,開(kāi)發(fā)一些嚴肅的應用(我并沒(méi)有說(shuō),用其它框架開(kāi)發(fā)的應用就不嚴肅^_^)。Portal開(kāi)源項目JetSpeed建立在Turbine上。

TurbineRunData來(lái)傳遞輸入輸出數據。如同MaverickControllerContext,RunData是整個(gè)Turbine框架的數據交換中心。除了request, response等基本信息,RunData直接包括了User/ACL等權限控制相關(guān)的屬性和方法,另外還包括Action NameTarget Template Name等定位屬性。

ModuleTurbine里面除了RunData之外的又一個(gè)核心類(lèi),是Turbine框架的基本構件,ActionModule,Screen也是Module。Turbine提供了LoginUserLogoutUser兩個(gè)Action作為整個(gè)系統的出入口。而其余流量的權限控制則由類(lèi)似于Servlet Filter機制的Pipeline控制。

Turbine Pipeline的編程模型和Servlet Filter一模一樣:Turbine PipelineValve就相當于Servlet Filter,而ValveContext則相當于Filter Chain。還有更相近的例子,Tomcat源代碼里面也有ValveValueContext兩個(gè)類(lèi),不僅編程模型一樣,而且名字也一樣。

 

權限控制貫穿于Turbine框架的始終。要用好Turbine,首先要通曉子項目Fulcrum Security部分的權限實(shí)現模型。

Fulcrum Security的權限實(shí)體包括四個(gè)-- User, Group, Role, Permission。

實(shí)體之間包含{Role,Permission}{ Group, User, Role}兩組關(guān)系。

{Role,Permission}是多對多的關(guān)系,一個(gè)Role可以具有各種Permission;{ Group, User, Role}之間是多對多的關(guān)系,一個(gè)Group可包含多個(gè)User,并可以給User分配不同的Role。

權限模型的實(shí)現同樣采用Peer模式,Entity -> EntityPeer, Entity -> ManagerPeer。

EntityEntityManger代表抽象的模型概念,而EntityPeerManagerPeer代表具體的實(shí)現。

用戶(hù)可以根據模型,提供不同的實(shí)現,比如,用內存結構中實(shí)現,用數據表結構實(shí)現,與Windows NT權限驗證機制結合,與OSWorkflow的權限控制模型結合,等等。其中,用數據表結構實(shí)現,又可以選擇用Torque實(shí)現,或者用Hibernate實(shí)現。(TorqueTurbineO/R Mapping子項目)

 

例如,Falcrum.property配置文件包含如下Security相關(guān)選項:

# -------------------------------------------------------------------

#  S E C U R I T Y  S E R V I C E

# -------------------------------------------------------------------

services.SecurityService.user.class=org.apache.fulcrum.security.impl.db.entity.TurbineUser

services.SecurityService.user.manager=org.apache.fulcrum.security.impl.db.DBUserManager

services.SecurityService.secure.passwords.algorithm=SHA

# -------------------------------------------------------------------

#  D A T A B A S E  S E R V I C E

# -------------------------------------------------------------------

services.DatabaseService.database.newapp.driver=org.gjt.mm.mysql.Driver

services.DatabaseService.database.newapp.url=jdbc:mysql://127.0.0.1/newapp

services.DatabaseService.database.newapp.username=turbine

services.DatabaseService.database.newapp.password=turbine

 

這說(shuō)明,權限控制實(shí)現由數據庫提供,需要根據權限模型創(chuàng )建如下數據表:

TURBINE_USER,TURBINE_ROLE,TURBINE_GROUP,

TURBINE_PERMISSION,TURBINE_ROLE_PERMISSION,

TURBINE_USER_GROUP_ROLE。

 

10. Cocoon

http://cocoon.apache.org

Cocoon項目是一個(gè)叫好不叫做的框架。采用XML + XSLT Pipeline機制,Java程序只需要輸出XML數據,Cocoon框架調用XSL文件把XML數據轉換成HTML、WML等文件。

Cocoon強大靈活的XSL Pipeline配置功能,XSLT的內容/顯示分離的承諾,一直吸引了不少程序員fans。怎奈天不從人愿,由于復雜度、速度瓶頸、XSL學(xué)習難度等問(wèn)題的限制,Cocoon一直主要限于網(wǎng)站發(fā)布出版領(lǐng)域,向CMSPortal方向不斷發(fā)展。另外,Cocoon開(kāi)發(fā)了XSP腳本和Cocoon Form技術(shù)。

Cocoonsitemap.xmap配置文件比較復雜,與其它的Web Framework差別很大。

主體Pipelines配置部分采用Pattern Match的方式,很像XSL語(yǔ)法,也可以類(lèi)比于Web.xml里面Servlet Mapping的定義。比如,一個(gè)典型的URL->Action的映射定義看起來(lái)是這個(gè)樣子:

<map:pipelines>

<map:pipeline>

<map:match pattern="*-dept.html">

  <map:act set="process">

    <map:parameter name="descriptor"

                   value="context://docs/department-form.xml"/>

    <map:parameter name="form-descriptor"

                   value="context://docs/department-form.xml"/>

    <map:generate type="serverpages" src="docs/confirm-dept.xsp"/>

    <map:transform src="stylesheets/apache.xsl"/>

    <map:serialize/>

  </map:act>

  <map:generate type="serverpages" src="docs/{1}-dept.xsp"/>

  <map:transform src="stylesheets/apache.xsl"/>

  <map:serialize/>

</map:match>

</map:pipeline>

</map:pipelines>

11. Barracuda

http://barracudamvc.org/Barracuda/index.html

Barracuda是一個(gè)HTML DOM Component + Event/Listener結構的框架。

根據模板文件或配置文件生成靜態(tài)Java類(lèi),并在代碼中使用這些生成類(lèi),是Barracuda的一大特色。

Barracuda需要用XMLC項目把所有的HTMLWML模板文件,靜態(tài)編譯成DOM結構的Java類(lèi),作為頁(yè)面組件。XMLC會(huì )根據HTML元素的id定義,生成相應DOM結點(diǎn)的簡(jiǎn)便操作方法。

 

Barracuda的事件類(lèi)也需要用Barracuda Event Builder工具把event.xml編譯成Java類(lèi),引入到工程中。Barracuda直接用Java類(lèi)的繼承關(guān)系映射事件之間的父子層次關(guān)系。比如,ChildEventParentEvent的子類(lèi)。

Barracuda的事件分為兩類(lèi):Request EventsControl Events)和Response EventsView Events)。

 

Barracuda事件處理過(guò)程很像Windows系統消息隊列的處理機制。

(1) Barracuda根據HTTP Request生成Request Event,放入到事件隊列中。

(2) EventDispatcher檢查事件隊列是否為空,如果為空,結束。如果非空,按照先進(jìn)先出的方式,從事件隊列中取出一個(gè)事件,根據這個(gè)事件的類(lèi)型,選擇并調用最合適的EventListener,參數Event Context包含事件隊列。

 “根據事件類(lèi)型,選擇最合適的EventListener對象”的過(guò)程是這樣的:比如,

EventDispatcher從時(shí)間隊列里取出來(lái)一個(gè)事件,類(lèi)型是ChildEvent;Barracuda首先尋找注冊了監聽(tīng)ChildEventEventListener,如果找不到,再上溯到ChildEvent的父類(lèi)ParentEvent,看哪些EventListenerParentEvent感興趣。

詳細過(guò)程參見(jiàn)BarracudaDefaultEventDispatcher類(lèi)。

(3) EventListener根據Event Context包含的request信息,調用商業(yè)邏輯,獲得結果數據,然后根據不同情況,把新的事件加入到Event Context的事件隊列中。

(4) 控制交還給EventDispatcher,回到第(2)步。

 

The End.

Enjoy.

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Java開(kāi)源Web開(kāi)發(fā)框架分類(lèi)列表
jetspeed velocity turbine的整合
深入整體分析Spring MVC framework
SSH(Struts,Spring,Hibernate)和SSM(SpringMVC,Spring,MyBatis)的區別
struts2訪(fǎng)問(wèn)request、session和application對象
Struts2 權限驗證
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久