<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Java Study Center  
    日歷
    <2008年9月>
    31123456
    78910111213
    14151617181920
    21222324252627
    2829301234
    567891011
    統(tǒng)計(jì)
    • 隨筆 - 40
    • 文章 - 3
    • 評(píng)論 - 0
    • 引用 - 0

    導(dǎo)航

    常用鏈接

    留言簿(1)

    隨筆檔案(40)

    文章檔案(3)

    搜索

    •  

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

     

    在上一篇文章《Struts 2與AJAX(第一部分)》,我已經(jīng)簡(jiǎn)單地介紹了<s:tree />的一些用法,接下來(lái)我將繼續(xù)深入講解<s:tree />的使用和通過(guò)DWR實(shí)現(xiàn)AJAX校驗(yàn)。

    更多<s:tree />

    在Struts 2的showcase中有兩個(gè)<s:tree />的例子,分別是靜態(tài)樹(shù)與動(dòng)態(tài)樹(shù)。所謂的靜態(tài)樹(shù)即是在編寫(xiě)JSP代碼時(shí)通過(guò)<s:treenode />生成樹(shù)節(jié)點(diǎn)。我的上一篇文章的例子就是一個(gè)典型的靜態(tài)樹(shù)。而動(dòng)態(tài)樹(shù)則是在程序運(yùn)行期間,Struts 2 運(yùn)行時(shí)(Runtime)根據(jù)程序中的數(shù)據(jù)動(dòng)態(tài)創(chuàng)建樹(shù)節(jié)點(diǎn)。雖然在兩個(gè)例子中<s:tree />的theme屬性都為“ajax”,但是從嚴(yán)格意義上來(lái)說(shuō),這兩種樹(shù)都不屬于AJAX樹(shù),因?yàn)樗鼈兌际窃谳敵鲰?yè)面時(shí)將全部節(jié)點(diǎn)加載到其中,而不是在父節(jié)點(diǎn)展開(kāi)時(shí)通過(guò)XHR(XMLHttpRequest)獲取節(jié)點(diǎn)數(shù)據(jù)。

    動(dòng)態(tài)樹(shù)

    下面我們先看一下動(dòng)態(tài)樹(shù)的例子,接著再一步步地將其改造為名副其實(shí)的AJAX 樹(shù)。下例將會(huì)把WEB應(yīng)用程序的目錄樹(shù)展現(xiàn)在JSP頁(yè)面中。因此,我需要先包裝一下java.io.File 類(lèi),代碼如下:

    package tutorial;

    import java.io.File;

    public class FileWrapper {
       
    private File file;

       
    public FileWrapper(String path) {
           file
    = new File(path);
       }

       
       
    public FileWrapper(File file) {
           
    this.file = file;
       }

       
       
    public String getId() {
           
    return "file_" + file.hashCode();
       }

       
       
    public String getName() {
           
    return file.getName();
       }

       
       
    public String getAbsolutePath() {
           
    return file.getAbsolutePath();
       }

       
       
    public FileWrapper[] getChildren() {
           File[] files
    = file.listFiles();
           
    if(files != null && files.length > 0) {
               
    int length = files.length;
               FileWrapper[] wrappers
    = new FileWrapper[length];
               
    for(int i = 0; i < length; ++i) {
                   wrappers[i]
    = new FileWrapper(files[i]);
               }

               
    return wrappers;
           }

           
    return new FileWrapper[0];
       }

    }
    清單1 src/tutorial/FileWrapper.java

    之所以需要對(duì)File類(lèi)進(jìn)行如此包裝,是因?yàn)?lt;s:tree />用于動(dòng)態(tài)樹(shù)時(shí),rootNode、nodeIdProperty、nodeTitleProperty 和 childCollectionProperty等屬性都必填的。

    然后是Action類(lèi)的代碼如下:

    package tutorial;

    import javax.servlet.http.HttpServletRequest;

    import org.apache.struts2.interceptor.ServletRequestAware;

    import com.opensymphony.xwork2.ActionSupport;

    public class DynamicTreeAction extends ActionSupport implements ServletRequestAware {
       
    private static final long serialVersionUID = 1128593047269036737L;
       
       
    private HttpServletRequest request;
       
    private FileWrapper root;

       
    public void setServletRequest(HttpServletRequest request) {    
           
    this.request = request;
       }

       
       
    public FileWrapper getRoot() {
           
    return root;
       }

       
       @Override
       
    public String execute() {
           root
    = new FileWrapper(request.getSession().getServletContext().getRealPath("/"));        
           
    return SUCCESS;
       }

    }
    清單2 src/tutorial/DynamicTreeAction.java

    上述代碼取得WEB應(yīng)用程序的根目錄的絕對(duì)路徑后,初始化FileWrapper對(duì)象root。該對(duì)象將為JSP頁(yè)面的<s:tree />的根節(jié)點(diǎn)。如下代碼所示:

    <%@ page language="java" contentType="text/html; charset=utf-8"
        pageEncoding
    ="utf-8"%>
    <%@ taglib prefix="s" uri="/struts-tags"%>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
       
    <head>
           
    <title>Struts 2 AJAX - More Tree</title>
           
    <s:head theme="ajax" debug="true" />
           
    <script type="text/javascript">
           
    /* <![CDATA[ */
               
    function treeNodeSelected(arg) {
                    alert(arg.source.title
    + ' selected');
                }
                
               
    function treeNodeExpanded(arg) {
                    alert(arg.source.title
    + ' expanded');
                }
                
               
    function treeNodeCollapsed(arg) {
                    alert(arg.source.title
    + ' collapsed');
                }
                
                dojo.addOnLoad(
    function() {                
                   
    var t = dojo.widget.byId('appFiles');
                    dojo.event.topic.subscribe(t.eventNames.expand, treeNodeExpanded);                
                    dojo.event.topic.subscribe(t.eventNames.collapse, treeNodeCollapsed);
                    
                   
    var s = t.selector;                
                    dojo.event.connect(s, 'select', 'treeNodeSelected');
                });
           
    /* ]]> */    
           
    </script>
       
    </head>
       
    <body>
           
    <h2>
                Dynamic Tree Example
           
    </h2>
           
    <div style="float:left; margin-right: 50px;">
               
    <s:tree id="appFiles" theme="ajax" rootNode="root"
                    nodeTitleProperty
    ="name" nodeIdProperty="id"
                    childCollectionProperty
    ="children" />
           
    </div>
       
    </body>
    </html>
    清單3 WebContent/Tree.jsp

    因?yàn)?lt;s:tree />的treeCollapsedTopic和treeExpandedTopic屬性都沒(méi)有起作用,所以如果我們想要監(jiān)聽(tīng)這兩個(gè)事件,就必須使用上述代碼的方法。

    最后是struts.xml配置文件:

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

    <!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd"
    >

    <struts>
       
    <package name="Struts2_AJAX_DEMO" extends="struts-default">
           
    <action name="DynamicTree" class="tutorial.DynamicTreeAction">
               
    <result>Tree.jsp</result>
           
    </action>
       
    </package>
    </struts>
    清單4 src/struts.xml

    發(fā)布運(yùn)行應(yīng)用程序,在瀏覽器地址欄中鍵入http://localhost:8080/Struts2_Ajax2/DynamicTree.action,有如下圖所示頁(yè)面:


    圖1 動(dòng)態(tài)樹(shù)示例

    AJAX 樹(shù)

    正如我在文章開(kāi)頭所說(shuō),Struts 2所提供的靜態(tài)樹(shù)和動(dòng)態(tài)樹(shù)都不是嚴(yán)格意義上的AJAX樹(shù)。下面就讓我們來(lái)實(shí)現(xiàn)一個(gè)如假包換的AJAX樹(shù)。首先要說(shuō)明的是,Struts 2的<s:tree />默認(rèn)是不支持這種按需加載數(shù)據(jù)的AJAX樹(shù)。不過(guò)因?yàn)樗腔贒ojo的樹(shù)控件(Widget)所以要擴(kuò)展也很方便。

    Dojo 通過(guò)名為“TreeRPCController”的控件實(shí)現(xiàn) AJAX 樹(shù),它會(huì)監(jiān)聽(tīng)被控制樹(shù)的事件。當(dāng)發(fā)生展開(kāi)節(jié)點(diǎn)的事件時(shí),TreeRPCController就會(huì)向URL發(fā)送XHR請(qǐng)求,該URL由TreeRPCController的RPCUrl 屬性定義。XHR請(qǐng)求格式類(lèi)似如下格式:

    http://localhost:8080/Struts2_Ajax2/AjaxTree.action?action=getChildren&data={"node":{"widgetId":"file_226092423","objectId":"C:\\Program Files\\Tomcat 5.5\\webapps\\Struts2_Ajax2","index":0,"isFolder":true},"tree":{"widgetId":"appFiles","objectId":""}}&dojo.preventCache=1182913465392
    清單5 XHR樣本

    顯而易見(jiàn),請(qǐng)求中包含三個(gè)參數(shù),分別是action為“getChildren”(固定值),data一個(gè)包含當(dāng)前節(jié)點(diǎn)與樹(shù)信息的JSON串和dojo.preventCache隨機(jī)串,用于緩存不同節(jié)點(diǎn)的請(qǐng)求響應(yīng)(父節(jié)點(diǎn)只會(huì)在第一次被展開(kāi)時(shí)到服務(wù)器端加載數(shù)據(jù),之后都是從瀏覽器的緩存中讀取數(shù)據(jù),可以提高應(yīng)用程序性能)。

    首先我要先寫(xiě)一個(gè)加載樹(shù)節(jié)點(diǎn)數(shù)據(jù)的Action類(lèi),代碼如下:

    package tutorial;

    import java.util.Map;

    import com.googlecode.jsonplugin.JSONExeption;
    import com.googlecode.jsonplugin.JSONUtil;

    public class AjaxTreeAction extends DynamicTreeAction {
       
    private static final long serialVersionUID = 3970019751740942311L;

       
    private String action;
       
    private String data;
       
    private FileWrapper[] wrappers;

       
    public void setAction(String action) {
           
    this.action = action;
       }

       
       
    public void setData(String data) {
           
    this.data = data;
       }


       
    public FileWrapper[] getWrappers() {
           
    return wrappers;
       }


       @Override
       
    public String execute() {
           
    if("getChildren".equals(action)) {
               
    try {
                   Object o
    = JSONUtil.deserialize(data);
                   String path
    = ((Map) ((Map) o).get("node")).get("objectId").toString();
                   wrappers
    = new FileWrapper(path).getChildren();
               }
    catch (JSONExeption e) {
                   e.printStackTrace();
               }

               
    return "ajax";
           }
       
           
    return super.execute();
       }

    }
    清單6 src/tutorial/AjaxTreeAction.java

    上述代碼可能需要解釋一下:

    1. action屬性對(duì)應(yīng)于XHR中的action,如果它為“getChildren”時(shí),則需要進(jìn)行加載子節(jié)點(diǎn)操作。否則,會(huì)讀取樹(shù)的根節(jié)點(diǎn),并返回JSP頁(yè)面;
    2. 通過(guò)上面XHR的分析,大家可以知道data是代表樹(shù)和當(dāng)前節(jié)點(diǎn)的JSON串,故應(yīng)將其反串行化為Map對(duì)象,并將其 objectId屬性取出。通常情況下,Dojo樹(shù)的objectId屬性代表服務(wù)器端的對(duì)象的標(biāo)識(shí),在本例中為文件夾的絕對(duì)路徑;
    3. wrappers屬性表示當(dāng)前文件夾下的文件數(shù)組,它被傳送到Freemarker頁(yè)面,翻譯為Dojo樹(shù)節(jié)點(diǎn)數(shù)組的JSON串。

    下面是Freemarker頁(yè)面的代碼:

    [
    <#list wrappers as r>
        { "title": "${r.name}", "isFolder":
    <#if r.children?size gt 0>true<#else>false</#if>, "id": "${r.id}", "objectId": "${r.absolutePath?js_string}" }<#if r_has_next>,</#if>
    </#list>
    ]
    清單7 WebContent/AjaxTree.ftl

    以上代碼中<#list></#lsit>的寫(xiě)法是Freemarker中遍歷集合的寫(xiě)法;而<#if r.children?size gt 0>判斷“r”對(duì)象的children屬性是否為空;r.absolutePath?js_string 就是將“r”的absolutePath屬性的值輸出為Javascript 的字串符形式;<#if r_has_next></#if>判斷集合是否有下一項(xiàng)數(shù)據(jù)。如果希望更詳細(xì)地了解Freemarker的使用,請(qǐng)參考該手冊(cè)

    接下來(lái),讓我們看看Action的配置代碼片段:

            <action name="AjaxTree" class="tutorial.AjaxTreeAction">
               
    <result>AjaxTree.jsp</result>
               
    <result name="ajax" type="freemarker">AjaxTree.ftl</result>
           
    </action>
    清單8 src/struts.xml配置片段

    最后是JSP頁(yè)面代碼:

    <%@ page language="java" contentType="text/html; charset=utf-8"
        pageEncoding
    ="utf-8"%>
    <%@ taglib prefix="s" uri="/struts-tags"%>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
       
    <head>
           
    <title>Struts 2 AJAX - More Tree</title>
           
    <s:head theme="ajax" debug="true" />
           
    <script type="text/javascript">
           
    /* <![CDATA[ */
               
    function treeNodeSelected(arg) {
                    alert(arg.source.title
    + ' selected');
                }
                    
                dojo.addOnLoad(
    function() {                
                   
    var t = dojo.widget.byId('appFiles');                
                   
    var s = t.selector;                
                    dojo.event.connect(s, 'select', 'treeNodeSelected');
                });    
           
    /* ]]> */    
           
    </script>
       
    </head>
       
    <body>
           
    <h2>
                AJAX Tree Example
           
    </h2>
           
    <div style="float:left; margin-right: 50px;">
               
    <script type="text/javascript">
               
    /* <![CDATA[ */
                    dojo.require(
    "dojo.lang.*");
                    dojo.require(
    "dojo.widget.*");
                    dojo.require(
    "dojo.widget.Tree");
                    dojo.require(
    "dojo.widget.TreeRPCController");                
                 
    /* ]]> */
                 
    </script>             
               
    <div dojoType="TreeRPCController" widgetId="treeController"
                    DNDcontroller
    ="create" RPCUrl="<s:url />"></div>
               
    <div dojoType="Tree" widgetId="appFiles" toggle="fade" controller="treeController">
                   
    <div dojoType="TreeNode" title='<s:property value="root.name" />'
                        widgetId='
    <s:property value="root.id" />'
                        isFolder='
    <s:property value="root.children.length > 0" />'
                        objectId='
    <s:property value="root.absolutePath" />'>
                   
    </div>
               
    </div>
           
    </div>
       
    </body>
    </html>
    清單9 WebContent/AjaxTree.jsp

    由于上面所提及的原因,我在上述的代碼中并沒(méi)有使用<s:tree />標(biāo)志,而是使用了Dojo的寫(xiě)法——?jiǎng)?chuàng)建 widgetId 為“treeController”的 TreeRPCController 并將設(shè)為樹(shù)的控制器。

    發(fā)布運(yùn)行應(yīng)用程序,在瀏覽器地址欄中鍵入http://localhost:8080/Struts2_Ajax2/AjaxTree.action,點(diǎn)開(kāi)某個(gè)節(jié)點(diǎn),在節(jié)點(diǎn)加載的過(guò)程中,加號(hào)圖標(biāo)變成時(shí)鐘狀圖標(biāo),如下圖所示頁(yè)面:


    圖2 AJAX樹(shù)示例

    自定義<s:tree />的AJAX的主題(theme)

    Struts 2的標(biāo)志過(guò)人之外在于它允許開(kāi)發(fā)人員自定義標(biāo)志的頁(yè)面輸出。要做到這一點(diǎn),你所需要做的只是創(chuàng)建一個(gè)自定義的theme并將其應(yīng)用到相應(yīng)標(biāo)志。下面就讓我自定義一個(gè)真正的AJAX的<s:tree/>的theme。

    首先,你的源文件的根目錄下新建包“template.realajax”。

    然后,在上一步所建的包中新建“tree.ftl”文件,內(nèi)容如下:

    <script type="text/javascript">
    /* <![CDATA[ */
        dojo.require(
    "dojo.lang.*");
        dojo.require(
    "dojo.widget.*");
        dojo.require(
    "dojo.widget.Tree");
        dojo.require(
    "dojo.widget.TreeRPCController");    <#-- Added by Max -->            
    /* ]]> */
    </script>    
    <#-- Added by Max -->             
    <div dojoType="TreeRPCController" 
         widgetId
    ="${parameters.id?html}_controller"
         DNDcontroller
    ="create" 
         RPCUrl
    ="<@s.url />">
    </div>
    <#-- End -->    
    <div dojoType="Tree"   
        <#if parameters.blankIconSrc?exists
    >
        gridIconSrcT="
    <@s.url value='${parameters.blankIconSrc}' encode="false" includeParams='none'/>"
       
    </#if>
       
    <#if parameters.gridIconSrcL?exists>
        gridIconSrcL="
    <@s.url value='${parameters.gridIconSrcL}' encode="false" includeParams='none'/>"
       
    </#if>
       
    <#if parameters.gridIconSrcV?exists>
        gridIconSrcV="
    <@s.url value='${parameters.gridIconSrcV}' encode="false" includeParams='none'/>"
       
    </#if>
       
    <#if parameters.gridIconSrcP?exists>
        gridIconSrcP="
    <@s.url value='${parameters.gridIconSrcP}' encode="false" includeParams='none'/>"
       
    </#if>
       
    <#if parameters.gridIconSrcC?exists>
        gridIconSrcC="
    <@s.url value='${parameters.gridIconSrcC}' encode="false" includeParams='none'/>"
       
    </#if>
       
    <#if parameters.gridIconSrcX?exists>
        gridIconSrcX="
    <@s.url value='${parameters.gridIconSrcX}' encode="false" includeParams='none'/>"
       
    </#if>
       
    <#if parameters.gridIconSrcY?exists>
        gridIconSrcY="
    <@s.url value='${parameters.gridIconSrcY}' encode="false" includeParams='none'/>"
       
    </#if>
       
    <#if parameters.gridIconSrcZ?exists>
        gridIconSrcZ="
    <@s.url value='${parameters.gridIconSrcZ}' encode="false" includeParams='none'/>"
       
    </#if>
       
    <#if parameters.expandIconSrcPlus?exists>
        expandIconSrcPlus="
    <@s.url value='${parameters.expandIconSrcPlus}' includeParams='none'/>"
       
    </#if>
       
    <#if parameters.expandIconSrcMinus?exists>
        expandIconSrcMinus="
    <@s.url value='${parameters.expandIconSrcMinus?html}' includeParams='none'/>"
       
    </#if>
       
    <#if parameters.iconWidth?exists>
        iconWidth="
    <@s.url value='${parameters.iconWidth?html}' encode="false" includeParams='none'/>"
       
    </#if>
       
    <#if parameters.iconHeight?exists>
        iconHeight="
    <@s.url value='${parameters.iconHeight?html}' encode="false" includeParams='none'/>"
       
    </#if>
       
    <#if parameters.toggleDuration?exists>
        toggleDuration=${parameters.toggleDuration?c}
       
    </#if>
       
    <#if parameters.templateCssPath?exists>
        templateCssPath="
    <@s.url value='${parameters.templateCssPath}' encode="false" includeParams='none'/>"
       
    </#if>
       
    <#if parameters.showGrid?exists>
        showGrid="${parameters.showGrid?default(true)?string}"
       
    </#if>
       
    <#if parameters.showRootGrid?exists>
        showRootGrid="${parameters.showRootGrid?default(true)?string}"
       
    </#if>
       
    <#if parameters.id?exists>
        id="${parameters.id?html}"
       
    </#if>
       
    <#if parameters.treeSelectedTopic?exists>
        publishSelectionTopic="${parameters.treeSelectedTopic?html}"
       
    </#if>
       
    <#if parameters.treeExpandedTopic?exists>
        publishExpandedTopic="${parameters.treeExpandedTopic?html}"
       
    </#if>
       
    <#if parameters.treeCollapsedTopic?exists>
        publishCollapsedTopic="${parameters.treeCollapsedTopic?html}"
       
    </#if>
       
    <#if parameters.toggle?exists>
        toggle="${parameters.toggle?html}"
       
    </#if>
        controller="${parameters.id?html}_controller"
    <#-- Added by Max -->    
        >
       
    <#if parameters.label?exists>
       
    <div dojoType="TreeNode" title="${parameters.label?html}"
        <#if parameters.nodeIdProperty?exists
    >
        id="${stack.findValue(parameters.nodeIdProperty)}"
       
    <#else>
        id="${parameters.id}_root"
       
    </#if>
        >
       
    <#elseif parameters.rootNode?exists>
        ${stack.push(parameters.rootNode)}
       
    <#-- Edited by Max -->    
       
    <div dojoType="TreeNode" 
                 title
    ="${stack.findValue(parameters.nodeTitleProperty)}"
                 widgetId
    ="${stack.findValue(parameters.nodeIdProperty)}"
                 isFolder
    ="<#if stack.findValue(parameters.childCollectionProperty)?size gt 0>true<#else>false</#if>"
                 objectId
    ="${stack.findValue(parameters.nameValue)}">
           
    </div>
       
    <#-- End -->        
       
    <#assign oldNode = stack.pop()/> <#-- pop the node off of the stack, but don't show it -->
       
    </#if>    
    清單10 src/template/realajax/tree.ftl

    對(duì)上述稍作解釋?zhuān)鲜龃a主要在原版的src/template/ajax/tree.ftl的基礎(chǔ)上添加了TreeRPCController的控件,并只輸出根節(jié)點(diǎn)。由于<s:tree />沒(méi)有類(lèi)似nodeObjectIdProperty的屬性,所以我用了value屬性表示objectId對(duì)應(yīng)的屬性名稱(chēng)。

    接著新建tree-close.ftl文件,內(nèi)容和原版的一樣,如下所示:

    <#if parameters.label?exists></div></#if></div>
    清單11 src/template/realajax/tree-close.ftl

    再下來(lái)就應(yīng)該是將theme應(yīng)用到<s:tree />,如下代碼所示:

    <%@ page language="java" contentType="text/html; charset=utf-8"
        pageEncoding
    ="utf-8"%>
    <%@ taglib prefix="s" uri="/struts-tags"%>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
       
    <head>
           
    <title>Struts 2 AJAX - More Tree</title>
           
    <s:head theme="ajax" debug="true" />
           
    <script type="text/javascript">
           
    /* <![CDATA[ */
               
    function treeNodeSelected(arg) {
                    alert(arg.source.title
    + ' selected');
                }
                    
                dojo.addOnLoad(
    function() {                
                   
    var t = dojo.widget.byId('appFiles');                
                   
    var s = t.selector;                
                    dojo.event.connect(s, 'select', 'treeNodeSelected');
                });    
           
    /* ]]> */    
           
    </script>
       
    </head>
       
    <body>
           
    <h2>
                AJAX Tree Example
           
    </h2>
           
    <div style="float:left; margin-right: 50px;">
               
    <s:tree id="appFiles" theme="realajax" rootNode="root"
                    nodeTitleProperty
    ="name" nodeIdProperty="id"
                    childCollectionProperty
    ="children" value="absolutePath" />
           
    </div>
       
    </body>
    </html>
    清單12 WebContent/AjaxTreeTheme.jsp

    上述代碼中<s:tree />的用法,除了theme改為“realajax”和多了value="absolutePath"外,幾乎和靜態(tài)樹(shù)中的一樣。

    為了不影響前一個(gè)例子,我們?yōu)樵揓SP文件配置類(lèi)型相同的Action,如下代碼所示:

            <action name="AjaxTreeTheme" class="tutorial.AjaxTreeAction">
               
    <result>AjaxTreeTheme.jsp</result>
               
    <result name="ajax" type="freemarker">AjaxTree.ftl</result>
           
    </action>
    清單13 src/struts.xml配置片段

    發(fā)布運(yùn)行應(yīng)用程序,在瀏覽器地址欄中鍵入http://localhost:8080/Struts2_Ajax2/AjaxTreeTheme.action,結(jié)果如圖2所示。

    總結(jié)

    通過(guò)上述例子,大家知道Struts 2 的AJAX 標(biāo)志是基于Dojo控件開(kāi)發(fā)的,所以如果大家希望熟練地使用這些標(biāo)志,最好去了解一下Dojo。

    本來(lái)還打算介紹一下Struts 2與DWR,不過(guò)看看文章的篇幅似乎足夠自成一篇了,因此DWR相關(guān)的內(nèi)容要留待下文繼續(xù)了。

    posted on 2008-09-17 15:40 綠茶_鄭州 閱讀(106) 評(píng)論(0)  編輯  收藏

    只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


    網(wǎng)站導(dǎo)航:
     
     
    Copyright © 綠茶_鄭州 Powered by: 博客園 模板提供:滬江博客
    主站蜘蛛池模板: 精品无码无人网站免费视频| 亚洲国产精品一区第二页| 亚洲午夜电影在线观看高清| a级在线观看免费| 中文字幕亚洲不卡在线亚瑟| 国产精品亚洲五月天高清| 毛片免费观看网址| 亚洲国产综合在线| 99re视频精品全部免费| 亚洲AV无码不卡无码| 中文日本免费高清| 国产亚洲色视频在线| 无码 免费 国产在线观看91| 国产极品粉嫩泬免费观看| 亚洲乱码日产精品一二三| 毛片a级毛片免费观看免下载| 亚洲一级毛片免观看| 亚洲精品在线免费观看| 亚洲一区二区三区电影| 亚洲免费精彩视频在线观看| 亚洲AV乱码一区二区三区林ゆな| 伊人久久大香线蕉免费视频| 亚洲色欲色欲www在线丝| 成人免费一区二区三区| 亚洲综合网站色欲色欲| 男女一进一出抽搐免费视频| 国产成人精品久久亚洲高清不卡 | 一级做a爰片久久毛片免费看| 亚洲成?Ⅴ人在线观看无码| 国产亚洲美女精品久久| 免费v片在线观看无遮挡| 美女被爆羞羞网站免费| 又大又硬又爽免费视频| 免费福利在线观看| 亚洲伊人久久成综合人影院| 国产免费人成视频尤勿视频| 亚洲中文字幕久久精品无码喷水| 国产视频精品免费视频| 国产亚洲AV无码AV男人的天堂| 在线观看特色大片免费网站| 亚洲国产一区二区三区青草影视|