六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

使用Java技術在Cocoon中完成商業邏輯

[摘要]如果你對Apache Cocoon有了解或者以涉足,你可能對在Cocoon中如何使用Java更好 的實現特定的邏輯有所疑惑。這篇文章將給您介紹如何使用XSP(Extensible Server Page) 和Action。同時還有示例和設計原則。 你可能聽到了一些來自Apache的關于Cocoon...
如果你對Apache Cocoon有了解或者以涉足,你可能對在Cocoon中如何使用Java更好
的實現特定的邏輯有所疑惑。這篇文章將給您介紹如何使用XSP(Extensible Server Page)
和Action。同時還有示例和設計原則。

你可能聽到了一些來自Apache的關于Cocoon的聲音。現在,在經歷了三年的發展后,
Cocoon已經逐漸的從一個簡單的實現XSL (Extensible Stylesheet Language) 轉換
的servlet成長為一個飽滿的Web應用框架。

Cocoon是用Java開發的,一般做為servlet運行在象Tomcat這樣的servlet容器中。


在這篇文章里,我們將介紹到兩種辦法來在基于Cocoon的應用中使用Java實現商業邏輯。

首先,讓我們來總的了解一下Cocoon。

Cocoon正式的定義是一個XML發布引擎,我們可以理解Cocoon為一個用來產生、轉換、處理
和輸出數據的框架。也可以理解Cocoon是一個從多種數據源接收數據再應用不同的處理,最
后將數據以想要的格式輸出的機器。

我們也可以定義Cocoon是一個數據流機器。也就是說,當你使用Cocoon時,你定義數據的路
徑或者流程來產生Web應用的頁面。


下面是Cocoon主要的一些基本的原理:

1、Cocoon把所有的數據做為SAX (Simple API for XML) 事件來處理,任何非XML的數據都要
轉變成XML描述。

2、生成器(能生成SAX事件)的組件負責處理輸入數據

3、序列化器負責處理輸出數據,將數據輸出到客戶端(瀏覽器、文件等)。

4、開發人員組合生成器、序列化器和其它組件構成管道。所有的管道都在一個叫做站點地圖的
文件中定義。

5、通過URI (Uniform Resource Identifier)來匹配管道,但URI是與物理資源脫離的。


第5點需要說明一下:

對于傳統的Web server,URI一般映射到物理資源。
例如,這個URI http://localhost/index.html 在Apache server將映射到一個叫index.html的
HTML文件。

在Cocoon中,URIs 和 物理資源可以是沒有任何絕對的相互關系的。你可以自由的設計URI來幫
助用戶更好的瀏覽你的站點。最后,你可以更好的組織你的文件讓其容易管理和維護。

為了更好的了解Cocoon的處理模型,可以看一個簡單的管道。

下面這個例子定義了一個叫index.html的頁面。這個管道位于叫sitemap.xmap站點地圖中:

<map:match pattern="index.html">
<map:generate type="file" src="content/mainfile.xml"/>
<map:transform type="xslt" src="content/stylesheets/mainstyle.xsl"/>
<map:serialize type="html"/>
</map:match>


這個管道有三步:

首先是一個生成器組件FileGenerator從XML文件"content/mainfile.xml "讀取數據。
(FileGenerator實際上已經提前在地圖中定義,可以通過"type"屬性來引用。Cocoon中所有的
管道組件都是通過它們的type屬性來引用的。)

接著進行轉換,轉換器TraxTransformer將XSL stylesheet應用到引入的數據。

最后,序列化器HTMLSerializer將數據寫到客戶端的瀏覽器。


你可能疑惑,上面所說的和Java開發有什么聯系呢?

我們把Cocoon的應用分成三個部分:

1、數據的收集層 Data Collection (Generation)

2、數據的處理和轉換層 Data Processing&Transforming

3、數據的輸出層 Data Output(Serialization)

那么,Java開發在Cocoon的處理轉換層是非常重要的。Cocoon的轉換和處理層是基于Cocoon的
應用的核心,通過這一層對輸入數據的處理,邏輯的應用,你就可以得到所期望的輸出。


在Cocoon中,你可以有下面四種實現邏輯的方法:

1、使用轉換器(Transformer)組件:他們按照你給定的規則轉換傳入的數據。典型的例子
便是TraxTransformer。


2、通過不同的 request、session、URI來選擇不同的組件做出正確的處理。

3、使用已有的或者自己實現的Action。

4、使用混合了Java代碼和內容的XSP。


這篇文章介紹最后兩種辦法:XSP 和 Action。XSP 和 Action的開發都是在servlet context內。
確切的說,兩種組件(實際上是所有的組件)都要存取request, response, session, 和
context對象。在某些方面,你要實現的大量的邏輯都會與這些對象相互作用。


XSP

XSP是Cocoon項目的創新。你可以把它和JSP相比較,因為它們都是混合邏輯和內容而且JSP的
taglib和XSP的logicsheet也很相似。

XSP位于管道的起點,實際上它被Cocoon轉換成生成器(Generator)來給管道中其余的組件提
供數據。

讓我們看下面這個叫 sample1.xsp 簡單的示例:

<?xml version="1.0"?>

<xsp:page language="java" xmlns:xsp="http://apache.org/xsp">

<xsp:logic>
Date now = new Date();
String msg = "Boo!";
</xsp:logic>

<content>
<title>Welcome to Cocoon</title>

<paragraph>

This is an XSP. You can see how we it contain both logic
(inside the <xsp:logic> tags) and content. In the logic block
above, we created a Date object whose value is <xsp:expr>now</xsp:expr>.
Oh, we also had a special message for you: <xsp:expr>msg</xsp:expr>

</paragraph>
</content>

</xsp:page>

首先注意這個文檔的根標記是<xsp:page>。

<xsp:page language="java" xmlns:xsp="http://apache.org/xsp">

這個標記定義XSP的language(可以是Java或者JavaScript)和用到的邏輯單的namespace。

接著是我們定義了兩個Java變量的<xsp:logic>塊。

這些<xsp:logic>塊可以有多個,可以出現在你希望的任何地方,而且可以包含各種Java代碼。

最后,是我們自己的內容,從用戶自己的跟標簽開始,在上面的示例中是<content>。在內容部分里,
我們可以用<xsp:expr>這個標簽得到在前面定義的變量。

記住,一個XSP實際上就是一個生成器Generator。Cocoon將其轉換成Java源文件然后編譯、執行它。
(如果想看XSP轉換成的Java源文件,到你的servlet容器的工作路徑下去找。例如,
如果你使用Tomcat 4.0.4,那么路徑就是下面這樣:
$CATALINA_HOME/work/Standalone/localhost/cocoon/cocoon-files/org/apache/cocoon/www.)

XSP執行后產生的XML數據被傳遞給管道其余的組件。


看下面這個管道實例:

<map:pipeline match="*.xsp">
<map:generate type="serverpages" src="examples/{1}.xsp"/>
<map:serialize type="xml"/>
</map:pipeline>


這里,我們使用一個指定的生成器 ServerPagesGenerator,來處理我們簡單的XSP。返回給客戶
端未加修飾的XML。

注意例子中使用了特別的 {1} 變量引用:它代替值在管道開始處的通配符指示的值。也就是說,
如果我們在瀏覽器中打開我們的Web應用中的sample1.xsp,那么 {1}的值便是sample1。

記住,同多數Cocoon組件一樣,XSP訪問request, response, session, 和 context 對象。這些
對象實際上是HttpServletRequest, HttpServletResponse, HttpSession, 和
HttpServletContext的封裝,Cocoon正式版本提供了大量的存取這些對象的方法。


XSP在從數據庫讀取數據的時候特別有用。

數據庫數據自然地以行和列組織,所以數據庫數據很容易轉換到XML。然而,JDBC
(Java Database Connectivity)沒有適合地代碼完成向XML的轉換。

XSP可以讓我們在讀取數據時很容易,這要感謝ESQL 邏輯單。ESQL 邏輯單除了隱藏了詳細
的JDBC代碼,還允許將行和列放入到特定的標簽中。同時ESQL 邏輯單也可以執行嵌套查詢
和執行更新命令。

下面,我們舉個XSP應用的例子:

假如我們想將一些Cocoon的資源(名稱和URL)存儲到數據庫。


首先,我們定義存放資源的數據表,然后當用戶通過關鍵字搜索時,我們使用XSP來找到相應
的行,將數據顯示給用戶。

隨后,我們構建一個表單來增加新的列。


表的定義和插入的數據如下面所示。我們這里使用的數據庫是MySQL,如果您使用的是其它的
數據庫,要注意做相應的改動。這個例子中,必須要有配置好數據庫連接池。

表結構如下:

use test;

create table Resources (
ResourceURL varchar(255) not null,
ResourceName varchar(64) not null
);

插入一些資源數據:

insert into Resources values
(&acute;;http://xml.apache.org/cocoon&acute;;, &acute;Cocoon Home Page&acute;);

insert into Resources values
(&acute;;http://www.galatea.com/flashguides/cocoon-tips-2.xml&acute;;, &acute;Cocoon 2.0 Tips and Tricks&acute;);



表建好后并且Cocoon也正確的配置過后,我們就可以寫下面這個XSP例子:

<?xml version="1.0"?>

<xsp:page language="java"
xmlns:xsp="http://apache.org/xsp"
xmlns:esql="http://apache.org/cocoon/SQL/v2">

<xsp:logic>
String keyword = request.getParameter("value");
</xsp:logic>

<content>
<title>Search results</title>
<esql:connection>
<esql:pool>resources</esql:pool>
<esql:execute-query>
<esql:query>
select * from Resources
where ResourceName like &acute;%<xsp:expr>keyword</xsp:expr>%&acute;
</esql:query>
<esql:results>
<resources>
<esql:row-results>
<resource>
<esql:get-columns/>
</resource>
</esql:row-results>
</ resources >
</esql:results>
</esql:execute-query>
</esql:connection>

</content>
</xsp:page>



注意在<xsp:page>標簽中聲明的名稱空間(namespace)。任何時候,在XSP中使用邏輯單的時候,
必須要聲明其名稱空間(namespace)。你可以在Cocoon webapp路徑下的WEB-INF/cocoon.xconf找
到邏輯單的定義。XSP 名稱空間的聲明就是要說明這是個XSP邏輯單。

實際上,所有的XSP至少要實現XSP邏輯單。在XSP被轉換成Java源文件之前,其中的邏輯單
(實際上僅是XSL文件)會先做XSLT處理轉換成Java代碼。因此,在上面的例子中的所有的
ESQL標簽都會轉換成了我們所熟悉的JDBC代碼。但是并不是所有的標簽都可以變成JDBC代碼,
注意上面示例中的<esql:pool>塊,它涉及到了在WEB-INF/cocoon.xconf文件中定義的數據庫
連接池。上面程序中使用的連接池叫做"resources" ,當然你可以使用你所喜歡的定義。

注意,我們這里使用<resources> 這個標簽將結果集包了起來而且每行的數據都放到<resource>標
簽里。這樣我們就可以很容易的編寫樣式表來將XML轉換成其它瀏覽器可以理解的格式。我們沒有
為表的列定義任何標簽,通過使用<esql:get-columns/>,Cocoon會將每一列的值放到自動以相應
的列名定義的標簽里面。


現在,讓我注意一下例子中的SQL查詢語句,正如你所看到的,這條SQL是動態生成的。當用戶
通過GETs 或者 POSTs提交數據到這個XSP后,在XSP的頂部,我們將request參數的值賦給
了keyword變量,然后根據keyword組成SQL語句。


既然這個例子很簡單,讓我們把它變復雜一點,加入Email功能,可以在用戶提供Email地址后,
將查詢結果發送給用戶。

XSP示例如下:

<?xml version="1.0"?>

<xsp:page language="java"
xmlns:xsp="http://apache.org/xsp"
xmlns:esql="http://apache.org/cocoon/SQL/v2"
xmlns:sendmail="http://apache.org/cocoon/sendmail/1.0"
xmlns:xsp-request="http://apache.org/xsp/request/2.0"
>

<content>

<xsp:logic>
String keyword = <xsp-request:get-parameter name="value"/>;
String emailAddr = <xsp-request:get-parameter name="email"/>;
String emailBody = "";
</xsp:logic>

<title>Search results</title>
<esql:connection>
<esql:pool>resources</esql:pool>
<esql:execute-query>
<esql:query>
select * from Resources where ResourceName like
&acute;%<xsp:expr>keyword</xsp:expr>%&acute; order by ResourceName
</esql:query>
<esql:results>
<resources>
<esql:row-results>
<resource>
<xsp:logic>
emailBody += <esql:get-string column="ResourceName"/>;
emailBody += ", " + <esql:get-string column="ResourceURL"/> + "\n";
</xsp:logic>
<esql:get-columns/>
</resource>
</esql:row-results>
</resources>
</esql:results>
</esql:execute-query>
</esql:connection>

<xsp:logic>
if (emailAddr != null) {
<sendmail:send-mail>
<sendmail:charset>ISO-8859-1</sendmail:charset>
<sendmail:smtphost>MY_SMTP_HOST</sendmail:smtphost>
<sendmail:from>MY_FROM_ADDRESS</sendmail:from>
<sendmail:to><xsp:expr>emailAddr</xsp:expr></sendmail:to>
<sendmail:subject>Cocoon Search Results</sendmail:subject>
<sendmail:body><xsp:expr>emailBody</xsp:expr></sendmail:body>
</sendmail:send-mail>
}
</xsp:logic>

</content>
</xsp:page>


來自sendmail邏輯單的幾個標簽讓我們擁有了發送EMAIL的能力。在這個例子中,我們將查詢結果
的每一行相加賦值給emailBody變量做為郵件的正文。當用戶通過request參數提供一個EMAIL地址,
我們就可以發送EMAIL了。當然這需要您提前設定好SMTP服務器和FROM地址。

Cocoon知道根據sendmail邏輯單來處理在sendmail名稱空間里的標簽,因為這個名稱空間已經
在<xsp:page>標簽中已經聲明。查看示例中的聲明,你會看到xsp-request這個名稱空間。
xsp-request邏輯單提供了Request常用方法的封裝。雖然在XSP中直接訪問request對象和
使用xsp-request邏輯單沒有什么功能上的區別,但是,理論上使用logicsheet的標簽比直
接的JAVA代碼更優美。

在運行這個例子之前,你必須要先在cocoon.xconf文件中設置sendmail邏輯單,Cocoon的配置
文件都在Web application 的 WEB-INF目錄下。用你熟悉的編輯器打開cocoon.xconf文件,
找到<target-language name="java">標簽。在這個塊內,你會發現所有其它邏輯單的定義。
在最后一個邏輯單(SOAP邏輯單)后加入下面的內容:

<builtin-logicsheet>
<parameter name="prefix" value="mail"/>
<parameter name="uri" value="http://apache.org/cocoon/sendmail/1.0"/>
<parameter name="href"
value="resource://org/apache/cocoon/components/language/markup/xsp/java/sendmail.xsl"/>
</builtin-logicsheet>


這個定義將http://apache.org.cocoon/sendmail/1.0名稱空間和已經包括在Cocoon JAR中
的sendmail.xsl樣式表聯合起來。

要使用sendmail邏輯單的功能,Cocoon必須要 mail.jar 和 activation.jar這兩個JAR。
如果您使用的Server是Tomcat4.x的話,那么它們位于$CATALINA_HOME/common/lib。



Actions


Action功能很強大,你可以將它放到管道的任何地方。Action可以認為是小的自包含的機器,
它獲取某些輸入數據,做一些處理,然后返回HashMap對象。不同于Cocoon中的Generators,
Transformers, Serializers組件,Action不對實際的XML內容做任何事情,它主要在管道中
實現一些邏輯。


學習Action包括要對管道參數做些了解,有時管道的組件必須交流數據。當然,XML內容會通
過SAX事件傳遞;但是,我們所說的是管道組件本身的功能需要的值。

管道參數有兩種:input 和 output。Input參數是由緊跟在組件聲明后面的一個或者多個
<map:parameter>標簽來定義的。它們為組件提供一個或者多個值來影響其操作。

Matcher和Action這兩個組件可以為它們后面的組件提供能存取的Output變量。
這些output參數放在HashMap對象里,可以通過key名稱(如:{1})來引用。
所有的管道都至少有一個由管道開始處的Matcher提供的HashMap。我們在管道中使用這個
HashMap對象,使用{1}可以取得HashMap中Key為1的值。


Cocoon本身包含一些內置的Action。其中有一個是依靠數據庫來鑒別用戶的Action。當我們
想保護Cocoon中的某些頁面,只允許授權的用戶訪問時,可以將用戶的ID和密碼存儲到數據
庫里,然后使用DatabaseAuthenticationAction來做登錄確認。
這個DatabaseAuthenticationAction要求我們提供一個XML描述文件來說明要使用哪個表和哪
些列。下面是這個描述文件的示例:


<?xml version="1.0" encoding="UTF-8"?>

<auth-descriptor>
<connection>resources</connection>
<table name="Users">
<select dbcol="USER_NAME" request-param="userid" to-session="userid"/>
<select dbcol="USER_PASSWORD" request-param="userpwd"/>
</table>
</auth-descriptor>


上面這個文件說明用戶認證Action將使用resources連接池和User表,request提交的userid參數
和userpwd參數將與User表中的USER_NAME和USER_PASSWORD列來比較,如果成功確認,將參
數userid寫到session里。

當你在管道中使用一個Action時,它必須先在站點地圖中的<map:components>塊中的
<map:actions>塊中定義。如下:

<map:components>
<!-- all other component definitions go here -->
<map:actions>
<map:action name="authenticator"
src="org.apache.cocoon.acting.DatabaseAuthenticatorAction"/>
<!-- other actions definitions go here -->
</map:actions>
</map:components>

一旦定義過后,就可以使用這個Action來負責我們要保護的區域。下面為要保護的區域定
義了三個管道:


<map:match pattern="protected/login.html">
<map:read mime-type="text/html" src="secret/login.html"/>
</map:match>

<map:match pattern="protected/login">
<map:act type="authenticator">
<map:parameter name="descriptor" value=" secret/auth-info.xml"/>
<map:redirect-to uri="index.html"/>
</map:act>

<map:redirect-to uri="login.html"/>
</map:match>

<map:match pattern="protected/*">
<map:match type="sessionstate" pattern="*">
<map:parameter name="attribute-name" value="userid"/>

<map:match pattern="protected/*.html">
<map:read mime-type="text/html" src=" secret/*.html"/>
</map:match>

<map:match pattern="protected/*.xsp">
<map:generate type="serverpages" src=" secret/{1}.xsp"/>
<map:serialize type="xml"/>
</map:match>
</map:match>

<map:redirect-to uri="login.html"/>
</map:match>


第一個管道簡單的提供了一個登錄的表單,是個HTML文件,不需要轉換。第二個管道處理
從login.html提交的實際的登錄動作。第三個來處理我們要保護的內容。

下面我們做詳細的論述:

DatabaseAuthenticationAction依靠描述文件來驗證登錄。但是,我們如何知道驗證是否
成功呢?對于Action,如果它們返回了有效的HashMap,那么在<map:act>塊里的部分將執
行。如果返回null值,那么塊下面的部分將執行。也就是說,按照上面管道的定義,我們
有兩種可能的結果,即:如果認證通過,我們就可以到達受保護的區域,如果失敗將返回
到Login頁面。

在 protected/* 管道有幾個嵌套的Matcher,第二個的type是sessionstate,這個Matcher
實際上是WildcardSessionAttributeMatcher,在這里用來讀取session里的userid的值。

在這個例子中,我們知道DatabaseAuthenticationAction設置了一個叫userid的session屬
性,我們通過檢測userid屬性來判斷用戶是否登錄成功,如果它不存在,則轉向到login頁面。

在Cocoon已經有一個DatabaseAddAction可用來插入數據,但為了更好的理解Action,我們
將寫一個自己的Action用來將新的Resource記錄插入到Resources表中。

我們假想你已經編寫了一個HTML頁面,可用來POST兩個變量name和url到管道。我們的
Action將從Request對象中找回name和url參數,將其插入到表中,最后返回一個HashMap對象。

下面是程序代碼:

package test;

import org.apache.avalon.excalibur.datasource.DataSourceComponent;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.ComponentSelector;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.avalon.framework.component.Composable;
import org.apache.avalon.framework.activity.Disposable;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Session;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.acting.AbstractAction;

import java.sql.Connection;
import java.sql.Statement;
import java.sql.SQLException;

import java.util.HashMap;
import java.util.Map;

public class AddResourceAction extends AbstractAction
implements ThreadSafe, Composable, Disposable
{
protected ComponentSelector dbselector;
protected ComponentManager manager;

public void compose(ComponentManager manager) throws ComponentException {
this.dbselector =
(ComponentSelector) manager.lookup(DataSourceComponent.ROLE + "Selector");

}

protected final DataSourceComponent getDataSource(String pool)
throws ComponentException {
return (DataSourceComponent) this.dbselector.select(pool);
}

public Map act( Redirector redirector, SourceResolver resolver,
Map objectModel, String
source, Parameters param )
throws Exception
{
Request req = ObjectModelHelper.getRequest(objectModel);
Session ses = req.getSession(true);

String poolName = param.getParameter("pool");

String resourceName = req.getParameter("name");
String resourceUrl = req.getParameter("url");

if (poolName == null) {
getLogger().error("Missing a pool name");
return null;
}

if (resourceName == null resourceUrl == null) {
getLogger().error("Missing input parameters");
return null;
}

Map map = new HashMap();

DataSourceComponent dataSource = getDataSource(poolName);
Connection conn = null;
boolean status = false;

try {
conn = dataSource.getConnection();
Statement stmt = conn.createStatement();
String cmd = "insert into Resources values (&acute;" +
resourceName + "&acute;, &acute;" +
resourceUrl + "&acute;)";
stmt.executeUpdate(cmd);

map.put("resource-name", resourceName);
map.put("resource-url", resourceUrl);

getLogger().debug("Resources insert completed by user " +
ses.getId());

status = true;
stmt.close();
} catch (Exception e) {
getLogger().error("Stmt failed: ", e);
} finally {
try {
if (conn != null) conn.close();
} catch (SQLException sqe) {
getLogger().warn("Error closing the datasource", sqe);
}
}

if (!status) return null;
return(map);
}

public void dispose() {
this.manager.release(dbselector);
}
}

這兒有大量的東西需要消化,特別是如果你不熟悉Cocoon的結構。我們一步步的來說明。

首先,Cocoon action的主方法是 act(),當在管道中使用Action時Cocoon將調用這個方法。
在這個示例中,act()得到Request參數、從連接池中得到數據庫連接,執行插入,然后填充
HashMap對象,并將其返回。

在Act方法的開始是從ObjectModelHelper組件中取得Request對象,然后得到兩個參數。這個
Action需要另外一個參數,pool;它將告訴我們使用哪個連接池。如果這個參數沒有,那么
Action將返回null而且將錯誤寫到日志里。有了pool的名稱,我們就可以從連接池得到數據
庫的連接。Avalon的Excalibur組件用來負責Cocoon的連接池。如果你不熟悉Avalon,可以
訪問這里http://jakarta.apache.org/avalon/ 。

代碼中的insert statement是直接的JDBC語法。在插入成功后,會將成功的信息寫到日志里。
對于日志,如果按上面Action的寫法,所有的日志信息都寫到你的Web Application的
WEB-INF/logs/sitemap.log文件。

最后,我們將兩個輸入參數寫到了Map對象,雖然它們都在Request對象中,這樣做是多余的,
但我們這樣做是為了示例Map對象的用法。

看一下這個Action在站點地圖中的定義。我們必須首先在站點地圖的<map:components>區定
義這個Action。

<map:components>
<!-- all other component definitions go here -->
<map:actions>
<map:action name="authenticator"
src="org.apache.cocoon.acting.DatabaseAuthenticatorAction"/>
<map:action name="add-resource" src="test.AddResourceAction"
logger="sitemap.action.AddResourceAction"/>
<!-- other actions definitions go here -->
</map:actions>
</map:components>


在管道中使用這個Action:


<map:match pattern="addresource">
<map:act type="add-resource">
<map:parameter name="pool" value="resources"/>
<map:read mime-type="text/html" src="examples/confirmation.html"/>
</map:act>

<map:read mime-type="text/html" src="examples/addresource.html"/>
</map:match>

可以看到,在<map:act> 行的下面,緊跟著的<map:parameter>標簽為Action提供"pool"參數。
一切順利的話,Action將返回一個Map對象,confirmation頁面將被顯示。


在瀏覽器中打開http://localhost:8080/cocoon/addresource,你會看到一個輸入表單。
表單提交后,如果插入成功,將顯示confirmation頁面,如果出現錯誤,將再次返回到表單
頁面。查看WEB-INF/logs/sitemap.log,錯誤信息會告訴你出現了什么錯誤。


如何有效的使用XSP和Action?


XSP和Action是在Cocoon中實現邏輯的兩種不同的辦法。選擇哪一種更適合呢?

XSP在取數據或者創建結構化的數據方面是很有用的。Action被證明在控制數據流程
(并不產生或者影響數據)的邏輯實現上很有用。我們上面看到的用戶驗證和數據庫
操作便是這樣的兩個例子。

然而,有一點需要說明的問題:XSP會將邏輯和內容混合。而Cocoon的一個基本的原則
就是邏輯、內容、表示的分離。

在使用XSP的時候,我們提出以下幾點建議:

首先,盡可能的使用邏輯單,邏輯單會很好的將Java代碼隱藏。

第二,盡量使用Cocoon的提供的功能,如:在做數據庫的Select的時候,我們也可以用
SqlTransformer來實現。

第三,在決策方面的邏輯盡可能的使用Selector, Matcher或Action組件。

最后,當無法避免在你的XSP中插入Java邏輯的話,盡可能的讓<xsp:logic>小,而且不要
把它們散布到各種你的標簽中。



主站蜘蛛池模板: 亚洲日韩视频免费观看 | 婷婷六月综合 | 五月天婷婷亚洲 | 天堂网在线播放 | 色橹橹欧美在线观看视频高清 | 日本精品视频在线 | 日韩欧美国产成人 | 亚洲精品91 | 五月婷婷在线观看视频 | 欧美在线观看网站 | 日韩不卡手机视频在线观看 | 伊人手机在线观看 | 青春草在线视频免费 | 日韩毛片在线视频 | 四虎国产精品免费久久影院 | 青青草中文字幕 | 手机在线日韩高清理论片 | 午夜激情视频 | 午夜影视在线 | 日韩小视频在线 | 亚洲一区www | 日本大片在线观看 | 午夜色站| 天堂8在线官网 | 青青草原视频在线 | 污在线观看视频 | 婷婷综合影院 | 日比免费视频 | 日本免费中文字幕在线看 | 五月激情综合丁香色婷婷 | 日本高清视频一区二区三区 | 色宅男中文字幕亚洲专区 | 天天摸天天操 | 日本视频高清 | 婷婷激情六月 | 五月天婷婷亚洲 | 四虎影院欧美 | 欧美亚洲综合另类 | 天天躁狠狠躁狠狠躁夜夜躁 | 天天草夜夜 | 亚洲狠狠婷婷综合久久久久图片 |