<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>出家如初，成佛有余&#187; dojo</title>
	<atom:link href="http://www.yeeach.com/tag/dojo/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.yeeach.com</link>
	<description>专注电子商务领域，关注无线互联网，关注新媒体；Yeeach.com用于记录我技术生涯的点滴</description>
	<lastBuildDate>Sun, 25 Jul 2010 10:30:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Struts2 DoubleSelect标签的使用</title>
		<link>http://www.yeeach.com/2008/04/02/struts2-doubleselect%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/</link>
		<comments>http://www.yeeach.com/2008/04/02/struts2-doubleselect%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/#comments</comments>
		<pubDate>Tue, 01 Apr 2008 17:21:04 +0000</pubDate>
		<dc:creator>chuanliang</dc:creator>
				<category><![CDATA[技术相关]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[doubleselect]]></category>
		<category><![CDATA[struts2]]></category>
		<category><![CDATA[tag]]></category>

		<guid isPermaLink="false">http://www.yeeach.com/2008/04/02/struts2-doubleselect%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/</guid>
		<description><![CDATA[Struts2本身提供了级联下拉选择框标签，这对简化诸如省份/城市这样的典型需求的操作是大有好处的，同时也有利于架构的统一，没有必要引入一大堆的javascript代码，使用方法如下： 1、Action层 DoubleListAction.java package com.mobilesoft.esales.webapp.action; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import com.mobilesoft.framework.tree.model.FileWrapper; import com.mobilesoft.framework.tree.model.OssCategory; import com.mobilesoft.framework.tree.service.TreeService; public class DoubleListAction extends BaseAction { /** * Logger for this class */ private static final Logger logger = Logger.getLogger(DoubleListAction.class); public String execute() { Map map=new HashMap(); ArrayList list1=new ArrayList(); list1.add("11"); list1.add("12"); [...]]]></description>
			<content:encoded><![CDATA[<p>Struts2本身提供了级联下拉选择框标签，这对简化诸如省份/城市这样的典型需求的操作是大有好处的，同时也有利于架构的统一，没有必要引入一大堆的javascript代码，使用方法如下：</p>
<h3>1、Action层</h3>
<p>DoubleListAction.java</p>
<pre class="csharpcode">package com.mobilesoft.esales.webapp.action;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import com.mobilesoft.framework.tree.model.FileWrapper;
import com.mobilesoft.framework.tree.model.OssCategory;
import com.mobilesoft.framework.tree.service.TreeService;

<span class="kwrd">public</span> <span class="kwrd">class</span> DoubleListAction extends BaseAction {
    <span class="rem">/**</span>
<span class="rem">     * Logger for this class</span>
<span class="rem">     */</span>
    <span class="kwrd">private</span> <span class="kwrd">static</span> final Logger logger = Logger.getLogger(DoubleListAction.<span class="kwrd">class</span>);

    <span class="kwrd">public</span> String execute() {
        Map map=<span class="kwrd">new</span> HashMap();
        ArrayList list1=<span class="kwrd">new</span> ArrayList();
        list1.add(<span class="str">"11"</span>);
        list1.add(<span class="str">"12"</span>);
        list1.add(<span class="str">"13"</span>);
        map.put(<span class="str">"1"</span>, list1);
        ArrayList list2=<span class="kwrd">new</span> ArrayList();
        list2.add(<span class="str">"21"</span>);
        list2.add(<span class="str">"22"</span>);
        list2.add(<span class="str">"23"</span>);
        map.put(<span class="str">"2"</span>, list2);
        ArrayList list3=<span class="kwrd">new</span> ArrayList();
        list3.add(<span class="str">"31"</span>);
        list3.add(<span class="str">"32"</span>);
        list3.add(<span class="str">"33"</span>);
        map.put(<span class="str">"3"</span>, list3);
        getRequest().setAttribute(<span class="str">"map"</span>, map);
        <span class="kwrd">return</span> SUCCESS;
    }

    <span class="kwrd">public</span> String doubleSelectTest(){
        Map map=<span class="kwrd">new</span> HashMap();
        ArrayList list1=<span class="kwrd">new</span> ArrayList();
        list1.add(<span class="str">"11"</span>);
        list1.add(<span class="str">"12"</span>);
        list1.add(<span class="str">"13"</span>);
        map.put(<span class="str">"1"</span>, list1);
        ArrayList list2=<span class="kwrd">new</span> ArrayList();
        list2.add(<span class="str">"21"</span>);
        list2.add(<span class="str">"22"</span>);
        list2.add(<span class="str">"23"</span>);
        map.put(<span class="str">"2"</span>, list2);
        ArrayList list3=<span class="kwrd">new</span> ArrayList();
        list3.add(<span class="str">"31"</span>);
        list3.add(<span class="str">"32"</span>);
        list3.add(<span class="str">"33"</span>);
        map.put(<span class="str">"3"</span>, list3);
        getRequest().setAttribute(<span class="str">"map"</span>, map);
        <span class="kwrd">return</span> SUCCESS;
    }
    <span class="kwrd">public</span> String doubleSelectPost(){

        Map map=getRequest().getParameterMap();
        Set set=map.entrySet();
        Iterator iterator=set.iterator();
        <span class="kwrd">while</span>(iterator.hasNext()){
            Map.Entry mapEntry=(Map.Entry)iterator.next();
            logger.fatal(<span class="str">"The key is: "</span>+mapEntry.getKey()+<span class="str">",value is :"</span>+mapEntry.getValue());
        }
        getRequest().setAttribute(<span class="str">"map"</span>, map);
        <span class="kwrd">return</span> SUCCESS;
    }

}</pre>
<h3>2、页面</h3>
<p>doubleslect.jsp</p>
<pre class="csharpcode"><span class="asp">&lt;%@ taglib prefix="s" uri="/struts-tags" %&gt;</span>
<span class="asp">&lt;%@ page language="java" errorPage="/error.jsp" pageEncoding="GBK" contentType="text/html;charset=GBK" %&gt;</span>
<span class="kwrd">&lt;</span><span class="html">html</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">head</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">title</span><span class="kwrd">&gt;</span>Struts 2 Cool Tags - <span class="attr">&lt;</span>s:doubeselect/ <span class="attr">&gt;</span><span class="kwrd">&lt;/</span><span class="html">title</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">s:head</span> <span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">head</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">body</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">h2</span><span class="kwrd">&gt;</span>Doubleselect Tag Example<span class="kwrd">&lt;/</span><span class="html">h2</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">s:form</span> <span class="attr">action</span><span class="kwrd">="doubleSelectPost"</span> <span class="attr">name</span><span class="kwrd">="form1"</span><span class="kwrd">&gt;</span>
Doubleselect演示1
<span class="kwrd">&lt;</span><span class="html">s:set</span> <span class="attr">name</span><span class="kwrd">="technology"</span>
     <span class="attr">value</span><span class="kwrd">="#{
         'Java': {'Spring', 'Hibernate', 'Struts 2'},
         '.Net': {'Linq', ' ASP.NET 2.0'},
         'Database': {'Oracle', 'SQL Server', 'DB2', 'MySQL'}
         }"</span> <span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;</span><span class="html">s:doubleselect</span> <span class="attr">label</span><span class="kwrd">="技术选择"</span>
<span class="attr">list</span><span class="kwrd">="#technology.keySet()"</span>
<span class="attr">name</span><span class="kwrd">="doubleselect1"</span>
<span class="attr">doubleName</span><span class="kwrd">="techdetail"</span>
<span class="attr">formName</span><span class="kwrd">="form1"</span>
<span class="attr">doubleList</span><span class="kwrd">="#technology[top]"</span> <span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;</span><span class="html">br</span><span class="kwrd">/&gt;&lt;</span><span class="html">br</span><span class="kwrd">/&gt;</span>
Doubleselect演示数据演示2：
<span class="kwrd">&lt;</span><span class="html">s:set</span> <span class="attr">name</span><span class="kwrd">="mymap"</span> <span class="attr">value</span><span class="kwrd">="#request.map"</span><span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;</span><span class="html">s:doubleselect</span> <span class="attr">list</span><span class="kwrd">="#request.map.keySet()"</span>
                <span class="attr">doubleName</span><span class="kwrd">="mymap1"</span>
                <span class="attr">name</span><span class="kwrd">="doubleselect2"</span>
                <span class="attr">formName</span><span class="kwrd">="form1"</span>
                <span class="attr">doubleList</span><span class="kwrd">="#request.map[top]"</span>
                <span class="attr">label</span><span class="kwrd">="Map Test"</span> <span class="kwrd">/&gt;</span>

<span class="kwrd">&lt;</span><span class="html">s:submit</span><span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">s:form</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">body</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">html</span><span class="kwrd">&gt;</span></pre>
<style type="text/css">.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } </style>
<p>doubleselectpost.jsp</p>
<pre class="csharpcode">&lt;%@ taglib prefix=<span class="str">"s"</span> uri=<span class="str">"/struts-tags"</span> %&gt;
&lt;%@ page language=<span class="str">"java"</span> errorPage=<span class="str">"/error.jsp"</span> pageEncoding=<span class="str">"GBK"</span> contentType=<span class="str">"text/html;charset=GBK"</span> %&gt;
&lt;html&gt;
&lt;head&gt;
    &lt;title&gt;Struts 2 Cool Tags - &lt;s:doubeselect/ &gt;&lt;/title&gt;
    &lt;s:head /&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;h2&gt;Doubleselect Tag Example&lt;/h2&gt;
&lt;s:form name=<span class="str">"form1"</span>&gt;
&lt;table border=<span class="str">"0"</span> cellspacing=<span class="str">"0"</span> cellpadding=<span class="str">"1"</span>&gt;
&lt;tr&gt;
  &lt;th&gt;参数值&lt;/th&gt;
&lt;/tr&gt;
&lt;s:iterator <span class="kwrd">value</span>=<span class="str">"#request.map.keySet()"</span> status=<span class="str">"keys"</span>&gt;
    &lt;tr&gt;
        &lt;td&gt;&lt;s:property/&gt;&lt;/td&gt;
    &lt;/tr&gt;
&lt;/s:iterator&gt;
&lt;/s:form&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<style type="text/css">.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } </style>
<h3>3、struts.xml配置文件</h3>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">action</span> <span class="attr">name</span><span class="kwrd">="doubleSelectTest"</span> <span class="attr">method</span><span class="kwrd">="doubleSelectTest"</span> <span class="attr">class</span><span class="kwrd">="com.mobilesoft.esales.webapp.action.DoubleListAction"</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">result</span> <span class="attr">name</span><span class="kwrd">="success"</span><span class="kwrd">&gt;</span>test/doubleselect.jsp<span class="kwrd">&lt;/</span><span class="html">result</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">action</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">action</span> <span class="attr">name</span><span class="kwrd">="doubleSelectPost"</span> <span class="attr">method</span><span class="kwrd">="doubleSelectPost"</span> <span class="attr">class</span><span class="kwrd">="com.mobilesoft.esales.webapp.action.DoubleListAction"</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">result</span> <span class="attr">name</span><span class="kwrd">="success"</span><span class="kwrd">&gt;</span>test/doubleselectpost.jsp<span class="kwrd">&lt;/</span><span class="html">result</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">action</span><span class="kwrd">&gt;</span></pre>
<style type="text/css">.csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } </style>
<h3>4、级联下拉框间的换行&lt;br &gt;问题</h3>
<p>缺省情况下，两个级联下拉框间是换行的，Struts2采用Freemarker来做模板，可以通过修改模板来定制标签缺省的树形。参看“Struts2中Datetimepicker控件的中文问题”中的方法，也即：</p>
<ul>
<li>修改struts.mxl，增加如下内容。</li>
</ul>
<p>&lt;constant name=&#8221;struts.serve.static&#8221; value=&#8221;false&#8221; /&gt;</p>
<p>&lt;constant name=&#8221;struts.ui.templateDir&#8221; value=&#8221;struts&#8221; /&gt;</p>
<p>注意在struts2-core-2.0.11.jar/org/apache/struts2/default.properties中有几个与Freemarker对应的配置参数：</p>
<p>struts.ui.theme=xhtml<br />
struts.ui.templateDir=template<br />
#sets the default  template type. Either ftl, vm, or jsp<br />
struts.ui.templateSuffix=ftl</p>
<ul>
<li>覆盖缺省的静态文件</li>
</ul>
<p>在resource目录（与WEB-INF同级或WEB-INF下）创建struts目录,并：</p>
<p>解压struts2-core-2.0.11.jar:/org/apache/struts2/static/ to /struts/</p>
<p>解压struts2-core-2.0.11.jar:/template/simple/ to /struts/simple/</p>
<p>解压struts2-core-2.0.11.jar:/template/xhtml/ to /struts/xhtml/</p>
<p>解压struts2-core-2.0.11.jar:/template/css_xhtml/ to /struts/css_xhtml/</p>
<p>解压struts2-core-2.0.11.jar:/template/ajax/ to /struts/ajax/</p>
<p>解压struts2-core-2.0.11.jar:/template/archive/ to /struts/archive</p>
<p>最后的目录结构如下：</p>
<p>struts/<br />
- ajax/<br />
- archive/<br />
- css_xhtml/<br />
- dojo/<br />
- nls/<br />
- src/<br />
- animation/<br />
- &#8230;<br />
- xml/<br />
- struts/<br />
- widget/<br />
- widgets/<br />
- niftycorners/<br />
- simple/<br />
- xhtml/</p>
<ul>
<li>修改doubleselect的模板doubleselect.ftl</li>
</ul>
<p>修改struts/simple/doubleselect.ftl去除其中的&lt;br /&gt;</p>
<p class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:1e6fd078-b61f-4efd-b862-acab2cd95a65" style="margin: 0px; padding: 0px; display: inline">Technorati 标签: <a href="http://technorati.com/tags/struts2" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/struts2');" rel="tag">struts2</a>,<a href="http://technorati.com/tags/doubleselect" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/doubleselect');" rel="tag">doubleselect</a>,<a href="http://technorati.com/tags/tag" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/tag');" rel="tag">tag</a>,<a href="http://technorati.com/tags/dojo" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/dojo');" rel="tag">dojo</a></p>
	<p></p>
	<hr noshade style="margin:0;height:1px" />
	<p>&copy; chuanliang for <a href="http://www.yeeach.com" >出家如初，成佛有余</a>, 2008. |
	  <a href="http://www.yeeach.com/2008/04/02/struts2-doubleselect%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/" >Permalink</a> |
	  <a href="http://www.yeeach.com/2008/04/02/struts2-doubleselect%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/#comments" >6 comments</a></p>
	<p>Add to <a href="http://del.icio.us/post?url=http://www.yeeach.com/2008/04/02/struts2-doubleselect%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/&amp;title=Struts2 DoubleSelect标签的使用" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://del.icio.us/post?url=http://www.yeeach.com/2008/04/02/struts2-doubleselect%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/&amp;title=Struts2 DoubleSelect标签的使用');">del.icio.us</a></p>
	<p>Search blogs linking this post with <a href="http://www.technorati.com/search/http://www.yeeach.com/2008/04/02/struts2-doubleselect%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.technorati.com/search/http://www.yeeach.com/2008/04/02/struts2-doubleselect%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/');" title="Search on Technorati">Technorati</a></p>
	<p>Want more on these topics ? Browse the archive of posts filed under <a href="http://www.yeeach.com/category/%e6%8a%80%e6%9c%af-%e8%bd%af%e4%bb%b6/"  title="查看 技术相关 的全部文章" rel="category tag">技术相关</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.yeeach.com/2008/04/02/struts2-doubleselect%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Struts2 Tree标签的使用</title>
		<link>http://www.yeeach.com/2008/04/01/struts2-tree%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/</link>
		<comments>http://www.yeeach.com/2008/04/01/struts2-tree%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/#comments</comments>
		<pubDate>Tue, 01 Apr 2008 03:06:16 +0000</pubDate>
		<dc:creator>chuanliang</dc:creator>
				<category><![CDATA[技术相关]]></category>
		<category><![CDATA[checkbox]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[struts2]]></category>
		<category><![CDATA[tree]]></category>
		<category><![CDATA[标签]]></category>

		<guid isPermaLink="false">http://www.yeeach.com/2008/04/01/struts2-tree%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/</guid>
		<description><![CDATA[　　在项目中有很多地方使用了树形结构，主要有几个地方：素材和软件等软件资源表，人员权限的权限资源表、人员权限的角色，套餐及产品包，现以类别表为例，说明树形结构的数据库存储、利用Struts2 中dojo的Tree标签来完成前端展现。 1、 数据库结构 CREATE TABLE `oss_category` ( `category_id` int(11) NOT NULL auto_increment, `parent_id` int(11) default '-1', `level` smallint(6) default NULL , `is_leaf` tinyint(1) default NULL, `category_title` varchar(100) default NULL, `category_name` varchar(100) default NULL, `category_code` varchar(100) default NULL, `category_type` varchar(30) default NULL, `image` varchar(255) default NULL, `status` varchar(20) default NULL, `creator` varchar(50) default NULL, `create_date` [...]]]></description>
			<content:encoded><![CDATA[<p>　　在项目中有很多地方使用了树形结构，主要有几个地方：素材和软件等软件资源表，人员权限的权限资源表、人员权限的角色，套餐及产品包，现以类别表为例，说明树形结构的数据库存储、利用Struts2 中dojo的Tree标签来完成前端展现。</p>
<h3>1、 数据库结构</h3>
<pre class="csharpcode"><span class="kwrd">CREATE</span> <span class="kwrd">TABLE</span> `oss_category` (
  `category_id` <span class="kwrd">int</span>(11) <span class="kwrd">NOT</span> <span class="kwrd">NULL</span> auto_increment,
  `parent_id` <span class="kwrd">int</span>(11) <span class="kwrd">default</span> <span class="str">'-1'</span>,
  `<span class="kwrd">level</span>` <span class="kwrd">smallint</span>(6) <span class="kwrd">default</span> <span class="kwrd">NULL</span> ,
  `is_leaf` tinyint(1) <span class="kwrd">default</span> <span class="kwrd">NULL</span>,
  `category_title` <span class="kwrd">varchar</span>(100) <span class="kwrd">default</span> <span class="kwrd">NULL</span>,
  `category_name` <span class="kwrd">varchar</span>(100) <span class="kwrd">default</span> <span class="kwrd">NULL</span>,
  `category_code` <span class="kwrd">varchar</span>(100) <span class="kwrd">default</span> <span class="kwrd">NULL</span>,
  `category_type` <span class="kwrd">varchar</span>(30) <span class="kwrd">default</span> <span class="kwrd">NULL</span>,
  `image` <span class="kwrd">varchar</span>(255) <span class="kwrd">default</span> <span class="kwrd">NULL</span>,
  `status` <span class="kwrd">varchar</span>(20) <span class="kwrd">default</span> <span class="kwrd">NULL</span>,
  `creator` <span class="kwrd">varchar</span>(50) <span class="kwrd">default</span> <span class="kwrd">NULL</span>,
  `create_date` datetime <span class="kwrd">default</span> <span class="kwrd">NULL</span>,
  `modify_user` <span class="kwrd">varchar</span>(50) <span class="kwrd">default</span> <span class="kwrd">NULL</span>,
  `modify_date` datetime <span class="kwrd">default</span> <span class="kwrd">NULL</span>,
  `description` text,
  <span class="kwrd">PRIMARY</span> <span class="kwrd">KEY</span>  (`category_id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 <span class="kwrd">DEFAULT</span> CHARSET=gbk;</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<p>测试数据：
<pre class="csharpcode">INSERT <span class="kwrd">INTO</span> `oss_category` <span class="kwrd">VALUES</span> (<span class="str">'1'</span>, <span class="str">'-1'</span>, <span class="str">'1'</span>, <span class="str">'0'</span>, <span class="str">'root'</span>, <span class="str">'root'</span>, <span class="str">'root'</span>, <span class="str">'product_type'</span>, <span class="kwrd">null</span>, <span class="str">'1'</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>);
INSERT <span class="kwrd">INTO</span> `oss_category` <span class="kwrd">VALUES</span> (<span class="str">'2'</span>, <span class="str">'1'</span>, <span class="str">'2'</span>, <span class="str">'0'</span>, <span class="str">'&lt;input type=\'</span>checkbox\<span class="str">' name=\'</span>product_type1\<span class="str">'  id=\'</span>product_type1\<span class="str">'  /&gt;&lt;b&gt;product_type1&lt;/b&gt;'</span>, <span class="str">'product_type1'</span>, <span class="str">'product_type1'</span>, <span class="str">'product_type'</span>, <span class="kwrd">null</span>, <span class="str">'1'</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>);
INSERT <span class="kwrd">INTO</span> `oss_category` <span class="kwrd">VALUES</span> (<span class="str">'3'</span>, <span class="str">'1'</span>, <span class="str">'2'</span>, <span class="str">'0'</span>, <span class="str">'&lt;input type=\'</span>checkbox\<span class="str">' name=\'</span>product_type2\<span class="str">' id=\'</span>product_type2\<span class="str">'  class=\'</span>treeCheckBox\<span class="str">'/&gt;&lt;b&gt;product_typ'</span>, <span class="str">'product_type2'</span>, <span class="str">'product_type2'</span>, <span class="str">'product_type'</span>, <span class="kwrd">null</span>, <span class="str">'1'</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>);
INSERT <span class="kwrd">INTO</span> `oss_category` <span class="kwrd">VALUES</span> (<span class="str">'4'</span>, <span class="str">'3'</span>, <span class="str">'3'</span>, <span class="str">'0'</span>, <span class="str">'&lt;input type=\'</span>checkbox\<span class="str">' name=\'</span>product_type21\<span class="str">'  id=\'</span>product_type21\<span class="str">'  /&gt;&lt;b&gt;product_type21&lt;/b&gt;'</span>, <span class="str">'product_type21'</span>, <span class="str">'product_type21'</span>, <span class="str">'product_type'</span>, <span class="kwrd">null</span>, <span class="str">'1'</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>);
INSERT <span class="kwrd">INTO</span> `oss_category` <span class="kwrd">VALUES</span> (<span class="str">'5'</span>, <span class="str">'2'</span>, <span class="str">'3'</span>, <span class="str">'0'</span>, <span class="str">'&lt;input type=\'</span>checkbox\<span class="str">' name=\'</span>product_type11\<span class="str">'  id=\'</span>product_type11\<span class="str">'  /&gt;&lt;b&gt;product_type11&lt;/b&gt;'</span>, <span class="str">'product_type11'</span>, <span class="str">'product_type11'</span>, <span class="str">'product_type'</span>, <span class="kwrd">null</span>, <span class="str">'1'</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>);
INSERT <span class="kwrd">INTO</span> `oss_category` <span class="kwrd">VALUES</span> (<span class="str">'6'</span>, <span class="str">'5'</span>, <span class="str">'4'</span>, <span class="str">'1'</span>, <span class="str">'&lt;input type=\'</span>checkbox\<span class="str">' name=\'</span>product_type111\<span class="str">'  id=\'</span>product_type111\<span class="str">'  /&gt;&lt;b&gt;product_type111&lt;/b&gt;'</span>, <span class="str">'product_type111'</span>, <span class="str">'product_type111'</span>, <span class="str">'product_type'</span>, <span class="kwrd">null</span>, <span class="str">'1'</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>);
INSERT <span class="kwrd">INTO</span> `oss_category` <span class="kwrd">VALUES</span> (<span class="str">'7'</span>, <span class="str">'3'</span>, <span class="str">'2'</span>, <span class="str">'0'</span>, <span class="str">'&lt;input type=\'</span>checkbox\<span class="str">' name=\'</span>product_type22\<span class="str">'  id=\'</span>product_type22\<span class="str">'  /&gt;&lt;b&gt;product_type22&lt;/b&gt;'</span>, <span class="str">'product_type22'</span>, <span class="str">'product_type22'</span>, <span class="str">'product_type'</span>, <span class="kwrd">null</span>, <span class="str">'1'</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>);
INSERT <span class="kwrd">INTO</span> `oss_category` <span class="kwrd">VALUES</span> (<span class="str">'8'</span>, <span class="str">'2'</span>, <span class="str">'3'</span>, <span class="str">'0'</span>, <span class="str">'&lt;input type=\'</span>checkbox\<span class="str">' name=\'</span>product_type12\<span class="str">'  id=\'</span>product_type12\<span class="str">'  /&gt;&lt;b&gt;product_type12&lt;/b&gt;'</span>, <span class="str">'product_type12'</span>, <span class="str">'product_type12'</span>, <span class="str">'product_type'</span>, <span class="kwrd">null</span>, <span class="str">'1'</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>);
INSERT <span class="kwrd">INTO</span> `oss_category` <span class="kwrd">VALUES</span> (<span class="str">'9'</span>, <span class="str">'4'</span>, <span class="str">'4'</span>, <span class="str">'1'</span>, <span class="str">'&lt;input type=\'</span>checkbox\<span class="str">' name=\'</span>product_type211\<span class="str">'  id=\'</span>product_type211\<span class="str">'  /&gt;&lt;b&gt;product_type211&lt;/b&gt;'</span>, <span class="str">'product_type211'</span>, <span class="str">'product_type211'</span>, <span class="str">'product_type'</span>, <span class="kwrd">null</span>, <span class="str">'1'</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>);
INSERT <span class="kwrd">INTO</span> `oss_category` <span class="kwrd">VALUES</span> (<span class="str">'10'</span>, <span class="str">'7'</span>, <span class="str">'4'</span>, <span class="str">'1'</span>, <span class="str">'&lt;input type=\'</span>checkbox\<span class="str">' name=\'</span>product_type221\<span class="str">'  id=\'</span>product_type221\<span class="str">'  /&gt;&lt;b&gt;product_type221&lt;/b&gt;'</span>, <span class="str">'product_type221'</span>, <span class="str">'product_type221'</span>, <span class="str">'product_type'</span>, <span class="kwrd">null</span>, <span class="str">'1'</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>, <span class="kwrd">null</span>);
</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<h3>&nbsp;</h3>
<h3>注意：</h3>
<ul>
<li>为了支持在树形结构的节点前有checkbox框，需要在树形结构的title（对应s:tree中的nodeTitleProperty）前增加checkbox树形，因此在数据库中category_title字段的格式采用如上的形式，例如：</li>
</ul>
<p>&lt;input type=&#8217;checkbox&#8217; name=&#8217;product_type1&#8242;&nbsp; id=&#8217;product_type1&#8242;&nbsp; /&gt;&lt;b&gt;product_type1&lt;/b&gt;</p>
<ul>
<li>对于有序的树形结构，为了标识left和right，可以增加ordering字段，或者采用类似嵌套树的结构，例如</li>
</ul>
<pre class="csharpcode"><span class="kwrd">CREATE</span> <span class="kwrd">TABLE</span> nested_category (
 category_id <span class="kwrd">INT</span> AUTO_INCREMENT <span class="kwrd">PRIMARY</span> <span class="kwrd">KEY</span>,
 name <span class="kwrd">VARCHAR</span>(20) <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>,
 lft <span class="kwrd">INT</span> <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>,
 rgt <span class="kwrd">INT</span> <span class="kwrd">NOT</span> <span class="kwrd">NULL</span>
);</pre>
<pre class="csharpcode">但采用嵌套树的方式，在变动一个节点时候需要对相关的节点进行更新，不是很适合。但效率较高。可以参看：</pre>
<pre class="csharpcode"><a href="http://dev.mysql.com/tech-resources/articles/hierarchical-data.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://dev.mysql.com/tech-resources/articles/hierarchical-data.html');">http://dev.mysql.com/tech-resources/articles/hierarchical-data.html</a></pre>
<pre class="csharpcode"><a href="http://www.sitepoint.com/print/hierarchical-data-database" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.sitepoint.com/print/hierarchical-data-database');">http://www.sitepoint.com/print/hierarchical-data-database</a></pre>
<ul>
<li>
<pre class="csharpcode">mysql对树形结构没有原生的支持，Oracle和DB2可以支持，Oracle通过CONNECT BY，DB2通过With方式。</pre>
</li>
</ul>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<h3>2、Model层 </h3>
<p>OssCategory.java</p>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<p>直接用myeclipse生成后，增加了如下内容： </p>
<pre class="csharpcode">    <span class="kwrd">private</span> OssCategory[] childCategories;
    <span class="kwrd">private</span> OssCategory parentCategory;

    <span class="kwrd">public</span> OssCategory[] getChildCategories() {
        <span class="kwrd">return</span> childCategories;
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> setChildCategories(OssCategory[] childCategories) {
        <span class="kwrd">this</span>.childCategories = childCategories;
    }

    <span class="kwrd">public</span> OssCategory getParentCategory() {
        <span class="kwrd">return</span> parentCategory;
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> setParentCategory(OssCategory parentCategory) {
        <span class="kwrd">this</span>.parentCategory = parentCategory;
    }</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<h1>3、DAO层</h1>
<p>OssCategoryDAO.java</p>
<p>直接用myeclipse生成，没有调优，增加如下内容：</p>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<pre class="csharpcode">    <span class="kwrd">public</span> OssCategory[] getAllCategory() {
        ArrayList&lt;OssCategory&gt; resultList=<span class="kwrd">new</span> ArrayList&lt;OssCategory&gt;();
        String queryString=<span class="str">"from OssCategory as category where category.parentId=1"</span>;
        List&lt;OssCategory&gt; queryList =getHibernateTemplate().find(queryString);
        Iterator iterator=queryList.iterator();
        <span class="kwrd">while</span>(iterator.hasNext()){
            OssCategory ossCategory=(OssCategory)iterator.next();
            OssCategory[] childrenArray=getChildCategoriesById(ossCategory.getCategoryId());
            logger.debug(<span class="str">"getAllCategory() - OssCategory[] childrenList="</span> + childrenArray.length);
            ossCategory.setChildCategories(childrenArray);
            resultList.add(ossCategory);

        }

        OssCategory[] resultArray=(OssCategory[])resultList.toArray(<span class="kwrd">new</span> OssCategory[resultList.size()]);
        <span class="kwrd">return</span> resultArray;

    }

    <span class="kwrd">public</span> OssCategory[] getChildCategoriesById(<span class="kwrd">int</span> categoryId) {
        String queryString=<span class="str">"from OssCategory as category where category.parentId="</span>+categoryId;
        List&lt;OssCategory&gt; queryList =getHibernateTemplate().find(queryString);
        logger.debug(<span class="str">"getChildCategoriesById(int) - List&lt;OssCategory&gt; queryList="</span> + queryList.size());
        ArrayList&lt;OssCategory&gt; resultList=<span class="kwrd">new</span> ArrayList&lt;OssCategory&gt;();
        Iterator iterator=queryList.iterator();
        <span class="kwrd">while</span>(iterator.hasNext()){
            OssCategory ossCategory=(OssCategory)iterator.next();
            OssCategory[] childrenList=getChildCategoriesById(ossCategory.getCategoryId());
            logger.debug(<span class="str">"getChildCategoriesById(int) - OssCategory[] childrenList="</span> + childrenList+<span class="str">"parentid is "</span>+categoryId); <span class="rem">//$NON-NLS-1$</span>
            ossCategory.setChildCategories(childrenList);
            resultList.add(ossCategory);

        }
        OssCategory[] resultArray=(OssCategory[])resultList.toArray(<span class="kwrd">new</span> OssCategory[resultList.size()]);
        <span class="kwrd">return</span> resultArray;
    }</pre>
<pre class="csharpcode">注意：</pre>
<ul>
<li>
<pre class="csharpcode">　getAllCategory和getChildCategoriesById采用了递归调用方式，应该可以一次性取出指定节点的所有子节点到结果集合List，然后对List在内存中进行遍历，但比较麻烦，先采用此种方式。</pre>
<li>
<pre class="csharpcode"> struts2的tree应该支持List，而不一定要采用数组方式，只不过没有测试</pre>
</li>
</ul>
<pre class="csharpcode">&nbsp;</pre>
<h3>4、Service层</h3>
<p>TreeService.java</p>
<p>有些方法尚未实现</p>
<pre class="csharpcode">package com.mobilesoft.framework.tree.service;

import java.util.List;
import java.util.Set;

import com.mobilesoft.framework.tree.model.OssCategory;

<span class="kwrd">public</span> <span class="kwrd">interface</span> TreeService {

    <span class="rem">/**</span>
<span class="rem">     * @return 获取下级子节点</span>
<span class="rem">     */</span>
  <span class="rem">//  public Set getChildren(int rootId);</span>

    <span class="rem">/**</span>
<span class="rem">     * @return 递归指定级别的所有子节点</span>
<span class="rem">     *      </span>
<span class="rem">     */</span>
  <span class="rem">//  public Set getChildrenByLevel(int rootId,int level);</span>

    <span class="rem">/**</span>
<span class="rem">     * @return 获取指定类型的所有子节点</span>
<span class="rem">     * @param type:节点的类型</span>
<span class="rem">     * @param levle:节点相对于所属类型的节点的级别 -1表示获取所属类型的根节点的所有级别的子节点</span>
<span class="rem">     */</span>
 <span class="rem">//   public Set getChildrenByType( String type,int level);</span>

    <span class="rem">/**</span>
<span class="rem">     * @return 获取指定根节点的所有子节点</span>
<span class="rem">     */</span>
    <span class="kwrd">public</span> OssCategory[]  getAllCategory();

}</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<p>TreeServiceImpl.java</p>
<p>&nbsp;</p>
<pre class="csharpcode">package com.mobilesoft.framework.tree.service.impl;

import java.util.List;
import java.util.Set;

import com.mobilesoft.framework.tree.dao.hibernate.OssCategoryDAO;
import com.mobilesoft.framework.tree.model.OssCategory;
import com.mobilesoft.framework.tree.service.TreeService;

<span class="kwrd">public</span> <span class="kwrd">class</span> TreeServiceImpl implements TreeService {
    OssCategoryDAO ossCategoryDAO;
    <span class="kwrd">public</span> Set getChildren(<span class="kwrd">int</span> rootId) {
        <span class="rem">// TODO Auto-generated method stub</span>
        <span class="kwrd">return</span> <span class="kwrd">null</span>;
    }

    <span class="kwrd">public</span> Set getLevelChildren(<span class="kwrd">int</span> rootId, <span class="kwrd">int</span> level) {
        <span class="rem">// TODO Auto-generated method stub</span>
        <span class="kwrd">return</span> <span class="kwrd">null</span>;
    }

    <span class="kwrd">public</span> OssCategory[]   getAllCategory(){
        <span class="kwrd">return</span> ossCategoryDAO.getAllCategory();
    }
    <span class="kwrd">public</span> OssCategoryDAO getOssCategoryDAO() {
        <span class="kwrd">return</span> ossCategoryDAO;
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> setOssCategoryDAO(OssCategoryDAO ossCategoryDAO) {
        <span class="kwrd">this</span>.ossCategoryDAO = ossCategoryDAO;
    }

}
</pre>
<p><style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
</p>
<h3>5、Action层</h3>
<pre class="csharpcode">package com.mobilesoft.esales.webapp.action;

import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import com.mobilesoft.framework.tree.model.FileWrapper;
import com.mobilesoft.framework.tree.model.OssCategory;
import com.mobilesoft.framework.tree.service.TreeService;

<span class="kwrd">public</span> <span class="kwrd">class</span> TreeAction extends BaseAction {
    <span class="rem">/**</span>
<span class="rem">     * Logger for this class</span>
<span class="rem">     */</span>
    <span class="kwrd">private</span> <span class="kwrd">static</span> final Logger logger = Logger.getLogger(TreeAction.<span class="kwrd">class</span>);

    <span class="kwrd">private</span> OssCategory root;
    <span class="kwrd">private</span> TreeService treeService;
    <span class="kwrd">private</span> FileWrapper fileroot;

    <span class="kwrd">public</span> String execute() {
        root = <span class="kwrd">new</span> OssCategory();
        root.setCategoryId(<span class="kwrd">new</span> Integer(1));
        root.setParentId(-1);
        root.setCategoryTitle(<span class="str">"Root"</span>);
        root.setCategoryName(<span class="str">"Root"</span>);
        OssCategory[] childCategories = treeService.getAllCategory();

        root.setChildCategories(childCategories);
        visitTree(childCategories);
        getRequest().setAttribute(<span class="str">"root"</span>, root);
        <span class="rem">// fileroot = new FileWrapper(getSession().getServletContext().getRealPath("/"));</span>
        <span class="kwrd">return</span> SUCCESS;
    }

    <span class="kwrd">public</span> String treeWithCheckbox() {
        Map map = getRequest().getParameterMap();
        logger.fatal(<span class="str">"the tree map"</span>);
        Set set = map.entrySet();
        Iterator iterator = set.iterator();
        <span class="kwrd">while</span> (iterator.hasNext()) {
            Map.Entry entry = (Map.Entry) iterator.next();

            logger.fatal(<span class="str">"the tree key is: "</span> + entry.getKey() + <span class="str">" ,and value is: "</span>
                    + entry.getValue());
        }

        <span class="kwrd">return</span> SUCCESS;
    }

    <span class="kwrd">public</span> TreeService getTreeService() {
        <span class="kwrd">return</span> treeService;
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> setTreeService(TreeService treeService) {
        <span class="kwrd">this</span>.treeService = treeService;
    }

    <span class="kwrd">public</span> OssCategory getRoot() {
        <span class="kwrd">return</span> root;
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> setRoot(OssCategory root) {
        <span class="kwrd">this</span>.root = root;
    }

    <span class="kwrd">public</span> <span class="kwrd">void</span> visitTree(OssCategory[] tree) {

        <span class="kwrd">for</span> (<span class="kwrd">int</span> i = 0; i &lt; tree.length; i++) {
            OssCategory node = (OssCategory) tree[i];
            logger.fatal(<span class="str">"visitTree:The treenode parentid is :"</span>
                    + node.getParentId() + <span class="str">" ,treenode id is "</span>
                    + node.getCategoryId() + <span class="str">",and the treenode name is "</span>
                    + node.getCategoryName());
            visitTree(node.getChildCategories());
        }

    }
}
</pre>
<p><style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
</p>
<h3>6、页面</h3>
<p>treetest.jsp</p>
<pre class="csharpcode"><span class="asp">&lt;%@ taglib prefix="s" uri="/struts-tags" %&gt;</span>
<span class="asp">&lt;%@ page language="java" errorPage="/error.jsp" pageEncoding="GBK" contentType="text/html;charset=GBK" %&gt;</span>
<span class="kwrd">&lt;</span><span class="html">html</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">head</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">title</span><span class="kwrd">&gt;</span>tag list<span class="kwrd">&lt;/</span><span class="html">title</span><span class="kwrd">&gt;</span>
    <span class="asp">&lt;%@ include file="/common/meta.jsp" %&gt;</span>

<span class="kwrd">&lt;</span><span class="html">style</span><span class="kwrd">&gt;</span>
    .treeCheckBox {
        height: 14px;
        margin: 0px;
        padding: 0px;
        border: 1px;
        vertical-align: middle;
    }
<span class="kwrd">&lt;/</span><span class="html">style</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">s:head</span> <span class="attr">theme</span><span class="kwrd">="ajax"</span> <span class="attr">debug</span><span class="kwrd">="true"</span> <span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">head</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">body</span> <span class="kwrd">&gt;</span>

<span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">="text/javascript"</span><span class="kwrd">&gt;</span>
<span class="kwrd">function</span> treeNodeSelected(arg) {
    <span class="rem">//alert("id["+arg.source.widgetId+"], name["+ arg.source.title+ "] selected");</span>
}

<span class="kwrd">function</span> treeNodeExpanded(arg) {
    <span class="rem">//alert("id["+arg.source.widgetId+"], name["+ arg.source.title+ "] expanded");</span>
}

<span class="kwrd">function</span> treeNodeCollapsed(arg) {
    <span class="rem">//alert("id["+arg.source.widgetId+"], name["+ arg.source.title+ "] collapsed");</span>
}

dojo.addOnLoad(<span class="kwrd">function</span>() {
    <span class="kwrd">var</span> t = dojo.widget.byId(<span class="str">'root'</span>);
    dojo.<span class="kwrd">event</span>.topic.subscribe(t.eventNames.expand, treeNodeExpanded);
    dojo.<span class="kwrd">event</span>.topic.subscribe(t.eventNames.collapse, treeNodeCollapsed);

    <span class="kwrd">var</span> s = t.selector;   

});

<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>

<span class="kwrd">&lt;</span><span class="html">s:form</span> <span class="attr">name</span><span class="kwrd">="form1"</span> <span class="attr">action</span><span class="kwrd">="treeWithCheckbox"</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">div</span> <span class="attr">style</span><span class="kwrd">="float:left; margin-right: 50px;"</span> <span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">s:tree</span>
    <span class="attr">theme</span><span class="kwrd">="ajax"</span>
    <span class="attr">id</span><span class="kwrd">="root"</span>
    <span class="attr">rootNode</span><span class="kwrd">="#request.root"</span>
    <span class="attr">childCollectionProperty</span><span class="kwrd">="childCategories"</span>
    <span class="attr">nodeIdProperty</span><span class="kwrd">="categoryId"</span>
    <span class="attr">nodeTitleProperty</span><span class="kwrd">="categoryTitle"</span>
    <span class="attr">treeSelectedTopic</span><span class="kwrd">="treeSelected"</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">s:tree</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">div</span><span class="kwrd">&gt;</span>     

<span class="kwrd">&lt;</span><span class="html">div</span> <span class="attr">style</span><span class="kwrd">="float:left; margin-right: 50px;"</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">s:submit</span><span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">div</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">s:form</span><span class="kwrd">&gt;</span>

<span class="kwrd">&lt;/</span><span class="html">body</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">html</span><span class="kwrd">&gt;</span></pre>
<pre class="csharpcode"><span class="kwrd"></span>&nbsp;</pre>
<p><span class="kwrd"><strong><font size="3">注意：</font></strong></span></p>
<ul>
<li><span class="kwrd">在s:tree中不能使用label标签，使用后树形结构出不来。</span>
<li>childCollectionProperty=&#8221;childCategories&#8221;对应Category.java中的
<pre class="csharpcode"><span class="kwrd">private</span> OssCategory[] childCategories;

<span class="kwrd">public</span> OssCategory[] getChildCategories() {
    <span class="kwrd">return</span> childCategories;
} 

<span class="kwrd">public</span> <span class="kwrd">void</span> setChildCategories(OssCategory[] childCategories) {
    <span class="kwrd">this</span>.childCategories = childCategories;
}
</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<li>
<p>nodeIdProperty=&#8221;categoryId&#8221;和nodeTitleProperty=&#8221;categoryTitle&#8221; 对应OssCategory[] childCategories中每一个Category的categoryId和categoryTitle</p>
<li>
<p>rootNode=&#8221;#request.root&#8221;，采用rootNode=&#8221;root&#8221;方式好像取不到数据，按理说应该可以通过ognl自动调用getRoot方法得到</p>
<li>
<p>结果提交后，根据对应checkbox的name的on属性来判断是否选中，因此在数据库中对节点的命名需要有一定规则，以便方便选择</p>
</li>
</ul>
<p><strong><font size="3">尚需要完善的地方：</font></strong> </p>
<ul>
<li>增加对下拉框树形结构实现的支持，以处理项目中大量诸如产品类型、资源类型等类型。</li>
</ul>
<p>在实现上，为了避免由于浏览器兼容性问题，在形式上是树形结构，实际上就是从字典表（目前树形结构仍然采用oss_category作为字典表）动态取出数据，然后拼凑成字符串形式展现，例如：
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">select</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">option</span> <span class="attr">value</span><span class="kwrd">="1"</span><span class="kwrd">&gt;</span>1<span class="kwrd">&lt;/</span><span class="html">option</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">option</span> <span class="attr">value</span><span class="kwrd">="11"</span><span class="kwrd">&gt;</span><span class="attr">&amp;nbsp;</span><span class="attr">&amp;nbsp;</span>|-11<span class="kwrd">&lt;/</span><span class="html">option</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">option</span> <span class="attr">value</span><span class="kwrd">="12"</span><span class="kwrd">&gt;</span><span class="attr">&amp;nbsp;</span><span class="attr">&amp;nbsp;</span>|-12<span class="kwrd">&lt;/</span><span class="html">option</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">option</span> <span class="attr">value</span><span class="kwrd">="2"</span><span class="kwrd">&gt;</span>2<span class="kwrd">&lt;/</span><span class="html">option</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">option</span> <span class="attr">value</span><span class="kwrd">="21"</span><span class="kwrd">&gt;</span><span class="attr">&amp;nbsp;</span><span class="attr">&amp;nbsp;</span>|-21<span class="kwrd">&lt;/</span><span class="html">option</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">option</span> <span class="attr">value</span><span class="kwrd">="22"</span><span class="kwrd">&gt;</span><span class="attr">&amp;nbsp;</span><span class="attr">&amp;nbsp;</span>|-22<span class="kwrd">&lt;/</span><span class="html">option</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">select</span><span class="kwrd">&gt;</span></pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<ul>
<li>进一步优化递归算法，一次性从数据库取出需要的数据，在内存中完成树形结构的构造，避免对数据库的查询，在目前情况下，采用递归方式问题也不大。
<li>由于Struts2.0采用dojo来实现其标签，尽管dojo与jquery相比较很重，但由于与Struts2.0较好支持，在架构统一上和使用上还是较为方便的，因此有空需要研究一下dojo库。</li>
</ul>
<p><style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
</p>
<h3>7、参考资料</h3>
<p><a title="http://www.ajaxtree.com/" href="http://www.ajaxtree.com/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.ajaxtree.com/');">http://www.ajaxtree.com/</a></p>
<p><a title="http://struts.apache.org/2.x/docs/tree.html" href="http://struts.apache.org/2.x/docs/tree.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://struts.apache.org/2.x/docs/tree.html');">http://struts.apache.org/2.x/docs/tree.html</a></p>
<p><a title="http://ait.web.psi.ch/js/dojo/tests/widget/tree/" href="http://ait.web.psi.ch/js/dojo/tests/widget/tree/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://ait.web.psi.ch/js/dojo/tests/widget/tree/');">http://ait.web.psi.ch/js/dojo/tests/widget/tree/</a></p>
<p><a title="http://exjava.spaces.live.com/blog/cns!A43FBDAF9245A0BC!199.entry" href="http://exjava.spaces.live.com/blog/cns!A43FBDAF9245A0BC!199.entry" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://exjava.spaces.live.com/blog/cns!A43FBDAF9245A0BC!199.entry');">http://exjava.spaces.live.com/blog/cns!A43FBDAF9245A0BC!199.entry</a></p>
<p><a title="http://www.stack.be/~roel/blog/archives/the-dojo-tree-control-for-beginners-part-1/" href="http://www.stack.be/~roel/blog/archives/the-dojo-tree-control-for-beginners-part-1/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.stack.be/~roel/blog/archives/the-dojo-tree-control-for-beginners-part-1/');">http://www.stack.be/~roel/blog/archives/the-dojo-tree-control-for-beginners-part-1/</a></p>
<p><a title="http://www.stack.be/~roel/blog/archives/the-dojo-tree-control-for-beginners-part-2" href="http://www.stack.be/~roel/blog/archives/the-dojo-tree-control-for-beginners-part-2" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.stack.be/~roel/blog/archives/the-dojo-tree-control-for-beginners-part-2');">http://www.stack.be/~roel/blog/archives/the-dojo-tree-control-for-beginners-part-2</a></p>
<p><a title="http://www.codepencil.com/index.php/struts2-dojo-dynamic-tree/" href="http://www.codepencil.com/index.php/struts2-dojo-dynamic-tree/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.codepencil.com/index.php/struts2-dojo-dynamic-tree/');">http://www.codepencil.com/index.php/struts2-dojo-dynamic-tree/</a></p>
<p><a title="http://dojotoolkit.org/book/dojo-book-0-9/part-2-dijit/advanced-editing-and-display/tree" href="http://dojotoolkit.org/book/dojo-book-0-9/part-2-dijit/advanced-editing-and-display/tree" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://dojotoolkit.org/book/dojo-book-0-9/part-2-dijit/advanced-editing-and-display/tree');">http://dojotoolkit.org/book/dojo-book-0-9/part-2-dijit/advanced-editing-and-display/tree</a></p>
<p>&nbsp;</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:db0b9ee1-db3c-4d64-aa7f-77a5adcf42c5" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati 标签: <a href="http://technorati.com/tags/struts2" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/struts2');" rel="tag">struts2</a>,<a href="http://technorati.com/tags/tree" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/tree');" rel="tag">tree</a>,<a href="http://technorati.com/tags/%e6%a0%87%e7%ad%be" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/%e6%a0%87%e7%ad%be');" rel="tag">标签</a>,<a href="http://technorati.com/tags/dojo" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/dojo');" rel="tag">dojo</a>,<a href="http://technorati.com/tags/checkbox" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/checkbox');" rel="tag">checkbox</a></div>
	<p></p>
	<hr noshade style="margin:0;height:1px" />
	<p>&copy; chuanliang for <a href="http://www.yeeach.com" >出家如初，成佛有余</a>, 2008. |
	  <a href="http://www.yeeach.com/2008/04/01/struts2-tree%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/" >Permalink</a> |
	  <a href="http://www.yeeach.com/2008/04/01/struts2-tree%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/#comments" >6 comments</a></p>
	<p>Add to <a href="http://del.icio.us/post?url=http://www.yeeach.com/2008/04/01/struts2-tree%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/&amp;title=Struts2 Tree标签的使用" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://del.icio.us/post?url=http://www.yeeach.com/2008/04/01/struts2-tree%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/&amp;title=Struts2 Tree标签的使用');">del.icio.us</a></p>
	<p>Search blogs linking this post with <a href="http://www.technorati.com/search/http://www.yeeach.com/2008/04/01/struts2-tree%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.technorati.com/search/http://www.yeeach.com/2008/04/01/struts2-tree%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/');" title="Search on Technorati">Technorati</a></p>
	<p>Want more on these topics ? Browse the archive of posts filed under <a href="http://www.yeeach.com/category/%e6%8a%80%e6%9c%af-%e8%bd%af%e4%bb%b6/"  title="查看 技术相关 的全部文章" rel="category tag">技术相关</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.yeeach.com/2008/04/01/struts2-tree%e6%a0%87%e7%ad%be%e7%9a%84%e4%bd%bf%e7%94%a8/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Struts2中Datetimepicker控件的中文问题</title>
		<link>http://www.yeeach.com/2008/03/30/struts2%e4%b8%addatetimepicker%e6%8e%a7%e4%bb%b6%e7%9a%84%e4%b8%ad%e6%96%87%e9%97%ae%e9%a2%98/</link>
		<comments>http://www.yeeach.com/2008/03/30/struts2%e4%b8%addatetimepicker%e6%8e%a7%e4%bb%b6%e7%9a%84%e4%b8%ad%e6%96%87%e9%97%ae%e9%a2%98/#comments</comments>
		<pubDate>Sun, 30 Mar 2008 01:26:16 +0000</pubDate>
		<dc:creator>chuanliang</dc:creator>
				<category><![CDATA[技术相关]]></category>
		<category><![CDATA[datetimepicker]]></category>
		<category><![CDATA[dojo]]></category>
		<category><![CDATA[struts.serve.static]]></category>
		<category><![CDATA[struts2]]></category>

		<guid isPermaLink="false">http://www.yeeach.com/2008/03/30/struts2%e4%b8%addatetimepicker%e6%8e%a7%e4%bb%b6%e7%9a%84%e4%b8%ad%e6%96%87%e9%97%ae%e9%a2%98/</guid>
		<description><![CDATA[为了与现有数据库字符集GBK统一，在Struts2中采用GBK作为缺省的编码方式，与此对应的编码相关的配置： 1、JVM中缺省字符集 &#160;&#160;&#160; 或者在环境变量中配置JAVA_OPTS=%JAVA_OPT%;-Dfile.encoding=GBK -Duser.language=zh_CN&#160;&#160;&#160; 或者在Tomcat的启动脚本中配置JAVA_OPTS=%JAVA_OPT%;-Dfile.encoding=GBK -Duser.language=zh_CN 2、Tomcat的URIEncoding ,处理GET方式的乱码问题 在server.xml中配置： &#60;Connector port="8080" maxHttpHeaderSize="8192" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="GBK" 3、Struts2的Locale配置 在Struts.xml中配置&#160;&#160;&#160; &#60;constant name=&#8221;struts.locale&#8221; value=&#8221;zh_CN&#8221; /&#62;&#160;&#160;&#160; &#60;constant name=&#8221;struts.i18n.encoding&#8221; value=&#8221;GBK&#8221; /&#62; 4、采用Spring的过滤器对POST页面编码 &#60;filter&#62;&#160;&#160;&#160; &#60;filter-name&#62;encodingFilter&#60;/filter-name&#62;&#160;&#160;&#160; &#60;filter-class&#62;&#160;&#160;&#160;&#160;&#160;&#160;&#160; org.springframework.web.filter.CharacterEncodingFilter&#60;/filter-class&#62;&#160;&#160;&#160; &#60;init-param&#62;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#60;param-name&#62;encoding&#60;/param-name&#62;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#60;param-value&#62;GBK&#60;/param-value&#62;&#160;&#160;&#160; &#60;/init-param&#62;&#160;&#160;&#160; &#60;init-param&#62;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#60;param-name&#62;forceEncoding&#60;/param-name&#62;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#60;param-value&#62;true&#60;/param-value&#62;&#160;&#160;&#160; &#60;/init-param&#62;&#60;/filter&#62; &#8230; &#60;filter-mapping&#62;&#160;&#160;&#160; &#60;filter-name&#62;encodingFilter&#60;/filter-name&#62;&#160;&#160;&#160; &#60;url-pattern&#62;/*&#60;/url-pattern&#62;&#60;/filter-mapping&#62; 5、页面统一编码为GBK 在common/meta.jsp中 &#60;meta http-equiv=&#8221;Cache-Control&#8221; content=&#8221;no-store&#8221;/&#62;&#60;!&#8211; HTTP [...]]]></description>
			<content:encoded><![CDATA[<p>为了与现有数据库字符集GBK统一，在Struts2中采用GBK作为缺省的编码方式，与此对应的编码相关的配置：<br /> <br />
<h3>1、JVM中缺省字符集</h3>
<p>&nbsp;&nbsp;&nbsp; 或者在环境变量中配置JAVA_OPTS=%JAVA_OPT%;-Dfile.encoding=GBK -Duser.language=zh_CN<br />&nbsp;&nbsp;&nbsp; 或者在Tomcat的启动脚本中配置JAVA_OPTS=%JAVA_OPT%;-Dfile.encoding=GBK -Duser.language=zh_CN</p>
<h3>2、Tomcat的URIEncoding ,处理GET方式的乱码问题</h3>
<p>在server.xml中配置：</p>
<pre>&lt;Connector port="8080" maxHttpHeaderSize="8192"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               connectionTimeout="20000" disableUploadTimeout="true"
               URIEncoding="GBK"</pre>
<h3>3、Struts2的Locale配置</h3>
<p>在Struts.xml中配置<br />&nbsp;&nbsp;&nbsp; &lt;constant name=&#8221;struts.locale&#8221; value=&#8221;zh_CN&#8221; /&gt;<br />&nbsp;&nbsp;&nbsp; &lt;constant name=&#8221;struts.i18n.encoding&#8221; value=&#8221;GBK&#8221; /&gt;</p>
<h3>4、采用Spring的过滤器对POST页面编码</h3>
<p>&lt;filter&gt;<br />&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;encodingFilter&lt;/filter-name&gt;<br />&nbsp;&nbsp;&nbsp; &lt;filter-class&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.springframework.web.filter.CharacterEncodingFilter&lt;/filter-class&gt;<br />&nbsp;&nbsp;&nbsp; &lt;init-param&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;encoding&lt;/param-name&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;GBK&lt;/param-value&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/init-param&gt;<br />&nbsp;&nbsp;&nbsp; &lt;init-param&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;forceEncoding&lt;/param-name&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;true&lt;/param-value&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/init-param&gt;<br />&lt;/filter&gt; </p>
<p>&#8230;</p>
<p>&lt;filter-mapping&gt;<br />&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;encodingFilter&lt;/filter-name&gt;<br />&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;/*&lt;/url-pattern&gt;<br />&lt;/filter-mapping&gt; </p>
<h3>5、页面统一编码为GBK</h3>
<p>在common/meta.jsp中 </p>
<p>&lt;meta http-equiv=&#8221;Cache-Control&#8221; content=&#8221;no-store&#8221;/&gt;<br />&lt;!&#8211; HTTP 1.0 &#8211;&gt;<br />&lt;meta http-equiv=&#8221;Pragma&#8221; content=&#8221;no-cache&#8221;/&gt;<br />&lt;!&#8211; Prevents caching at the Proxy Server &#8211;&gt;<br />&lt;meta http-equiv=&#8221;Expires&#8221; content=&#8221;0&#8243;/&gt;<br />&lt;meta http-equiv=&#8221;Content-Type&#8221; content=&#8221;text/html; charset=GBK&#8221;/&gt;<br />&lt;meta name=&#8221;generator&#8221; content=&#8221;Mobile-soft.cn&#8221; /&gt; <br />&lt;meta http-equiv=&#8221;keywords&#8221; content=&#8221;mobile,payment,telecommunication,internet&#8221;&gt;<br />&lt;meta http-equiv=&#8221;description&#8221; content=&#8221;mobile-soft&#8221;&gt;<br />同时在各页面中包含meta.jsp页面及设定pageEncoding：</p>
<p>&lt;%@ include file=&#8221;/common/meta.jsp&#8221; %&gt;</p>
<p>&lt;%@ page language=&#8221;java&#8221; errorPage=&#8221;/error.jsp&#8221; pageEncoding=&#8221;GBK&#8221; contentType=&#8221;text/html;charset=GBK&#8221; %&gt;</p>
<h3>6、数据库编码</h3>
<p>数据库建库时候字符集编码采用GBK</p>
<p>在applicationContext-resources.xml中，mysql的配置</p>
<p>&nbsp;&nbsp;&nbsp; &lt;bean id=&#8221;dataSource&#8221; class=&#8221;org.apache.commons.dbcp.BasicDataSource&#8221;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; destroy-method=&#8221;close&#8221;&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name=&#8221;driverClassName&#8221; value=&#8221;com.mysql.jdbc.Driver&#8221;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name=&#8221;url&#8221;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value=&#8221;jdbc:mysql://localhost/mysql?useUnicode=true&amp;amp;characterEncoding=gbk&#8221;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name=&#8221;username&#8221; value=&#8221;root&#8221;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name=&#8221;password&#8221; value=&#8221;"/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name=&#8221;maxActive&#8221; value=&#8221;100&#8243;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name=&#8221;maxIdle&#8221; value=&#8221;30&#8243;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name=&#8221;maxWait&#8221; value=&#8221;1000&#8243;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name=&#8221;defaultAutoCommit&#8221; value=&#8221;true&#8221;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name=&#8221;removeAbandoned&#8221; value=&#8221;true&#8221;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name=&#8221;removeAbandonedTimeout&#8221; value=&#8221;60&#8243;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name=&#8221;validationQuery&#8221; value=&#8221;SELECT 1&#8243;/&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name=&#8221;testOnBorrow&#8221; value=&#8221;true&#8221;/&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/bean&gt; </p>
<p>&nbsp;&nbsp;&nbsp; 采用以上步骤基本上搞定了乱码问题，但在使用Struts2的datetimepicker控件时候出现了乱码问题，Struts2的javascript标签库缺省是采用庞大的dojo库（为何不采用jquery这样清爽的javascript库），因此怀疑是dojo的i18n问题，解决步骤如下： </p>
<h3>1、修改struts.serve.static的缺省配置</h3>
<p>修改struts.mxl，增加如下内容。 </p>
<p>&lt;constant name=&#8221;struts.serve.static&#8221; value=&#8221;false&#8221; /&gt; </p>
<p>在struts2-core-2.0.11.jar/org/apache/struts2/default.properties中,struts.serve.static缺省值为true，也即从struts2-core-2.0.11.jar查找Struts2的静态文件，这参数的命名太晦涩。 </p>
<p>### Used by FilterDispatcher<br />### If true then Struts serves static content from inside its jar. <br />### If false then the static content must be available at &lt;context_path&gt;/struts<br />struts.serve.static=true </p>
<p>注意这里的&lt;context_path&gt;/struts实际指的就是jsp页面所在目录。</p>
<h3>2、覆盖缺省的静态文件</h3>
<p>&nbsp;&nbsp;&nbsp; 在resource目录（与WEB-INF同级或WEB-INF下）创建struts目录,并： </p>
<p>&nbsp;&nbsp;&nbsp; 解压struts2-core-2.0.11.jar:/org/apache/struts2/static/ to /struts/ </p>
<p>&nbsp;&nbsp;&nbsp; 解压struts2-core-2.0.11.jar:/template/simple/dojoRequire.js to /struts/simple/ </p>
<p>&nbsp;&nbsp;&nbsp; 解压struts2-core-2.0.11.jar:/template/xhtml/styles.css to /struts/xhtml/ </p>
<p>&nbsp;&nbsp;&nbsp; 解压struts2-core-2.0.11.jar:/template/xhtml/validation.js to /struts/xhtml/ </p>
<p>&nbsp;&nbsp;&nbsp; 解压struts2-core-2.0.11.jar:/template/css_xhtml/styles.css to /struts/css_xhtml/ </p>
<p>&nbsp;&nbsp;&nbsp; 解压struts2-core-2.0.11.jar:/template/css_xhtml/validation.js to /struts/css_xhtml/ </p>
<p>&nbsp;&nbsp;&nbsp; 解压struts2-core-2.0.11.jar:/template/ajax/dojoRequire.js to /struts/ajax/ </p>
<p>&nbsp;&nbsp;&nbsp; 解压struts2-core-2.0.11.jar:/template/ajax/validation.js to /struts/ajax/ </p>
<p>&nbsp;&nbsp;&nbsp; 注意：以上所说的解压并不是把整个包都解压，只是把需要的内容勇winrar直接拽出来，对于struts2-core-2.0.11.jar包还是保持原状，不要做任何改动，以方便后期的升级。</p>
<h3>3、修改js文件的编码方式</h3>
<p>&nbsp;&nbsp;&nbsp; 用记事本打开struts/dojo/src/i18n/calendar/nls/zh/gregorian.js并以ASSI格式另存为gregorian.js </p>
<p>&nbsp;&nbsp;&nbsp; 用记事本打开struts/dojo/src/i18n/calendar/nls/zh/gregorianExtras.js并以ASSI格式另存为gregorianExtras.js </p>
<p>&nbsp;&nbsp;&nbsp; 用记事本打开struts/dojo/src/i18n/calendar/nls/zh-cn/gregorian.js并以ASSI格式另存为gregorian.js </p>
<p>&nbsp; 以上几个文件，原来的格式是UTF-8的 </p>
<h3>4、页面实例</h3>
<p>&lt;%@ taglib prefix=&#8221;s&#8221; uri=&#8221;/struts-tags&#8221; %&gt;<br />&lt;%@ page language=&#8221;java&#8221; errorPage=&#8221;/error.jsp&#8221; pageEncoding=&#8221;GBK&#8221; contentType=&#8221;text/html;charset=GBK&#8221; %&gt;<br />&lt;html&gt;<br />&lt;head&gt;</p>
<p>　&lt;title&gt;tag list&lt;/title&gt;</p>
<p>　&lt;%@ include file=&#8221;/common/meta.jsp&#8221; %&gt;</p>
<p>　&lt;s:head/&gt;</p>
<p>&lt;/head&gt;<br />&lt;body&gt;<br />　&lt;s:form name=&#8221;form1&#8243; action=&#8221;test2&#8243;&gt;<br />　&lt;s:datetimepicker name=&#8221;start_date&#8221; language=&#8221;zh-cn&#8221;&nbsp; label=&#8221;计费开始时间&#8221; displayFormat=&#8221;yyyy-MM-dd&#8221; /&gt;<br />　&lt;s:submit/&gt;<br />&lt;/s:form&gt; </p>
<p>&lt;/body&gt;<br />&lt;/html&gt;</p>
<p>注意这里language为zh-cn（也可以为zh），而不是zh_CN，这与java中不同。dojo官方在<a href="http://dojo.jot.com/InternationalizationOverview" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://dojo.jot.com/InternationalizationOverview');">Internationalization (i18n)</a>文档中强调： </p>
<h4><em>Locale </em></h4>
<p><em>dojo.locale</em> </p>
<p><em>The locale is a short string, defined by the host environment, which conforms to </em><a href="http://www.ietf.org/rfc/rfc3066.txt" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.ietf.org/rfc/rfc3066.txt');"><em>RFC 3066</em></a><em> used in the HTML specification. It consists of short identifiers, typically two characters long which are case-insensitive. Note that Dojo uses dash separators, not underscores like Java (e.g. &#8220;en-us&#8221;, not &#8220;en_US&#8221;). Typically country codes are used in the optional second identifier, and additional variants may be specified. For example, Japanese is &#8220;ja&#8221;; Japanese in Japan is &#8220;ja-jp&#8221;. Notice that the lower case is intentional &#8212; while Dojo will often convert all locales to lowercase to normalize them, it is the lowercase that must be used when defining your resources. </em></p>
<p><em>The locale in the browser is typically set during install and is not easily configurable. Note that this is not the same locale in the preferences dialog which can be used to accompany HTTP requests; there is unfortunately no way to access that locale from the client without a server round-trip. </em></p>
<p><em>The locale Dojo uses on a page may be overridden by setting djConfig.locale. This may be done to accomodate applications with a known user profile or server pages which do manual assembly and assume a certain locale. You may also set djConfig.extraLocale to load localizations in addition to your own, in case you want to specify a particular translation or have multiple languages appear on your page.</em> </p>
<h5>5、参考文档</h5>
<p><a title="http://cwiki.apache.org/S2WIKI/creating-a-custom-dojo-profile-for-struts-20x.html" href="http://cwiki.apache.org/S2WIKI/creating-a-custom-dojo-profile-for-struts-20x.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://cwiki.apache.org/S2WIKI/creating-a-custom-dojo-profile-for-struts-20x.html');">http://cwiki.apache.org/S2WIKI/creating-a-custom-dojo-profile-for-struts-20x.html</a> </p>
<p><a title="http://dojo.jot.com/InternationalizationOverview" href="http://dojo.jot.com/InternationalizationOverview" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://dojo.jot.com/InternationalizationOverview');">http://dojo.jot.com/InternationalizationOverview</a> </p>
<p><a title="http://cwiki.apache.org/WW/datetimepicker.html" href="http://cwiki.apache.org/WW/datetimepicker.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://cwiki.apache.org/WW/datetimepicker.html');">http://cwiki.apache.org/WW/datetimepicker.html</a> </p>
<p>&nbsp;</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:713a5503-59b5-426c-b7e0-9a88b86b5f57" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati 标签: <a href="http://technorati.com/tags/struts2" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/struts2');" rel="tag">struts2</a>,<a href="http://technorati.com/tags/dojo" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/dojo');" rel="tag">dojo</a>,<a href="http://technorati.com/tags/datetimepicker" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/datetimepicker');" rel="tag">datetimepicker</a>,<a href="http://technorati.com/tags/struts.serve.static" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/struts.serve.static');" rel="tag">struts.serve.static</a></div>
	<p></p>
	<hr noshade style="margin:0;height:1px" />
	<p>&copy; chuanliang for <a href="http://www.yeeach.com" >出家如初，成佛有余</a>, 2008. |
	  <a href="http://www.yeeach.com/2008/03/30/struts2%e4%b8%addatetimepicker%e6%8e%a7%e4%bb%b6%e7%9a%84%e4%b8%ad%e6%96%87%e9%97%ae%e9%a2%98/" >Permalink</a> |
	  <a href="http://www.yeeach.com/2008/03/30/struts2%e4%b8%addatetimepicker%e6%8e%a7%e4%bb%b6%e7%9a%84%e4%b8%ad%e6%96%87%e9%97%ae%e9%a2%98/#comments" >3 comments</a></p>
	<p>Add to <a href="http://del.icio.us/post?url=http://www.yeeach.com/2008/03/30/struts2%e4%b8%addatetimepicker%e6%8e%a7%e4%bb%b6%e7%9a%84%e4%b8%ad%e6%96%87%e9%97%ae%e9%a2%98/&amp;title=Struts2中Datetimepicker控件的中文问题" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://del.icio.us/post?url=http://www.yeeach.com/2008/03/30/struts2%e4%b8%addatetimepicker%e6%8e%a7%e4%bb%b6%e7%9a%84%e4%b8%ad%e6%96%87%e9%97%ae%e9%a2%98/&amp;title=Struts2中Datetimepicker控件的中文问题');">del.icio.us</a></p>
	<p>Search blogs linking this post with <a href="http://www.technorati.com/search/http://www.yeeach.com/2008/03/30/struts2%e4%b8%addatetimepicker%e6%8e%a7%e4%bb%b6%e7%9a%84%e4%b8%ad%e6%96%87%e9%97%ae%e9%a2%98/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.technorati.com/search/http://www.yeeach.com/2008/03/30/struts2%e4%b8%addatetimepicker%e6%8e%a7%e4%bb%b6%e7%9a%84%e4%b8%ad%e6%96%87%e9%97%ae%e9%a2%98/');" title="Search on Technorati">Technorati</a></p>
	<p>Want more on these topics ? Browse the archive of posts filed under <a href="http://www.yeeach.com/category/%e6%8a%80%e6%9c%af-%e8%bd%af%e4%bb%b6/"  title="查看 技术相关 的全部文章" rel="category tag">技术相关</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.yeeach.com/2008/03/30/struts2%e4%b8%addatetimepicker%e6%8e%a7%e4%bb%b6%e7%9a%84%e4%b8%ad%e6%96%87%e9%97%ae%e9%a2%98/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
