<?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; 标签</title>
	<atom:link href="http://www.yeeach.com/tag/%e6%a0%87%e7%ad%be/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标签中select框缺省selected实现</title>
		<link>http://www.yeeach.com/2008/05/22/struts2-doubleselect%e6%a0%87%e7%ad%be%e4%b8%adselect%e6%a1%86%e7%bc%ba%e7%9c%81selected%e5%ae%9e%e7%8e%b0/</link>
		<comments>http://www.yeeach.com/2008/05/22/struts2-doubleselect%e6%a0%87%e7%ad%be%e4%b8%adselect%e6%a1%86%e7%bc%ba%e7%9c%81selected%e5%ae%9e%e7%8e%b0/#comments</comments>
		<pubDate>Thu, 22 May 2008 05:49:09 +0000</pubDate>
		<dc:creator>chuanliang</dc:creator>
				<category><![CDATA[技术相关]]></category>
		<category><![CDATA[doubleselect]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[struts2]]></category>
		<category><![CDATA[标签]]></category>

		<guid isPermaLink="false">http://www.yeeach.com/2008/05/22/struts2-doubleselect%e6%a0%87%e7%ad%be%e4%b8%adselect%e6%a1%86%e7%bc%ba%e7%9c%81selected%e5%ae%9e%e7%8e%b0/</guid>
		<description><![CDATA[&#160;&#160;&#160; 在项目中，省市下拉框联动采用的是Struts2的doubleselect标签，需要根据业务需求实现两个下拉框动态的缺省值（selected）。 业务场景： &#160;&#160;&#160; 在代理商管理中，增加代理商时候选择代理商所属的省市，然后增加代理商的销售人员，但代理商销售人员销售产品，如果客户在客户库中没有相关信息，需要增加客户，此时侯应当缺省根据代理商所属的省市信息，在增加客户时候，客户所在省市的缺省selected的值应当为代理商所在的省市信息。 &#160; 主要实现逻辑如下： &#160;&#160;&#160; 采用doubleselect标签的value和doublevalue属性,在action中定义两个select框缺省值参数（例子中是defaultItem、doubleDefaultItem）的get、set方法，在action方法中根据业务逻辑（在增加客户时候，客户所在省市缺省为销售员所在省市）调用set方法设定两个select框的缺省值，然后在页面通过value和doublevalue方法获取设定的缺省值。 实现样例如下： 1. Action package com.mobilesoft.esales.webapp.action; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import org.apache.log4j.Logger; public class DoubleListAction extends BaseAction { private static final Logger logger = Logger.getLogger(DoubleListAction.class); private String defaultItem; private String doubleDefaultItem; public String execute() { return SUCCESS; &#160;&#160;&#160; } public String doubleSelectTest(){ &#160;&#160;&#160;&#160;&#160;&#160; Map map=new [...]]]></description>
			<content:encoded><![CDATA[<p>&nbsp;&nbsp;&nbsp; 在项目中，省市下拉框联动采用的是Struts2的doubleselect标签，需要根据业务需求实现两个下拉框动态的缺省值（selected）。
<p><b>业务场景：</b>
<p>&nbsp;&nbsp;&nbsp; 在代理商管理中，增加代理商时候选择代理商所属的省市，然后增加代理商的销售人员，但代理商销售人员销售产品，如果客户在客户库中没有相关信息，需要增加客户，此时侯应当缺省根据代理商所属的省市信息，在增加客户时候，客户所在省市的缺省selected的值应当为代理商所在的省市信息。
<p>&nbsp;
<p><b>主要实现逻辑如下：</b>
<p>&nbsp;&nbsp;&nbsp; 采用doubleselect标签的value和doublevalue属性,在action中定义两个select框缺省值参数（例子中是defaultItem、doubleDefaultItem）的get、set方法，在action方法中根据业务逻辑（在增加客户时候，客户所在省市缺省为销售员所在省市）调用set方法设定两个select框的缺省值，然后在页面通过value和doublevalue方法获取设定的缺省值。
<p>实现样例如下：<br />
<h3><b>1. </b>Action</h3>
<p>package com.mobilesoft.esales.webapp.action;
<p><b>import</b> java.util.ArrayList;
<p><b>import</b> java.util.HashMap;
<p><b>import</b> java.util.Map;
<p><b>import</b> org.apache.log4j.Logger;
<p><b>public</b> <b>class</b> DoubleListAction <b>extends</b> BaseAction {
<p><b>private</b> <b>static</b> <b>final</b> Logger <i>logger</i> = Logger.<i>getLogger</i>(DoubleListAction.<b>class</b>);
<p><b>private</b> String defaultItem;
<p><b>private</b> String doubleDefaultItem;
<p><b>public</b> String execute() {
<p><b>return</b> <i>SUCCESS</i>;
<p>&nbsp;&nbsp;&nbsp; }
<p><b>public</b> String doubleSelectTest(){
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Map map=<b>new</b> HashMap();
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ArrayList list1=<b>new</b> ArrayList();
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list1.add(&#8220;11&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list1.add(&#8220;12&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list1.add(&#8220;13&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.put(&#8220;1&#8243;, list1);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ArrayList list2=<b>new</b> ArrayList();
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list2.add(&#8220;21&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list2.add(&#8220;22&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list2.add(&#8220;23&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.put(&#8220;2&#8243;, list2);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ArrayList list3=<b>new</b> ArrayList();
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list3.add(&#8220;31&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list3.add(&#8220;32&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list3.add(&#8220;33&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.put(&#8220;3&#8243;, list3);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setDefaultItem(&#8220;2&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; setDoubleDefaultItem(&#8220;23&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getRequest().setAttribute(&#8220;defaultItem&#8221;, getDefaultItem());
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getRequest().setAttribute(&#8220;doubleDefaultItem&#8221;, getDoubleDefaultItem());
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getRequest().setAttribute(&#8220;map&#8221;, map);
<p><b>return</b> <i>SUCCESS</i>;
<p>&nbsp;&nbsp;&nbsp; }
<p><b>public</b> String getDefaultItem() {
<p><b>return</b> defaultItem;
<p>&nbsp;&nbsp;&nbsp; }
<p><b>public</b> <b>void</b> setDefaultItem(String defaultItem) {
<p><b>this</b>.defaultItem = defaultItem;
<p>&nbsp;&nbsp;&nbsp; }
<p><b>public</b> String getDoubleDefaultItem() {
<p><b>return</b> doubleDefaultItem;
<p>&nbsp;&nbsp;&nbsp; }
<p><b>public</b> <b>void</b> setDoubleDefaultItem(String doubleDefaultItem) {
<p><b>this</b>.doubleDefaultItem = doubleDefaultItem;
<p>&nbsp;&nbsp;&nbsp; }
<p>}<br />
<h3><b>2. </b>doubleselect.jsp</h3>
<p>&lt;%@ taglib prefix=&#8221;s&#8221; uri=&#8221;/struts-tags&#8221; %&gt;
<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>&lt;<b>html</b>&gt;
<p>&lt;<b>head</b>&gt;
<p>&lt;<b>title</b>&gt;Struts 2 Cool Tags &#8211; &amp;lt;s:doubeselect/ &amp;gt;&lt;/<b>title</b>&gt;
<p>&lt;<b>s</b>:<b>head</b> /&gt;
<p>&lt;/<b>head</b>&gt;
<p>&lt;<b>body</b>&gt;
<p>&lt;<b>h2</b>&gt;Doubleselect 缺省值selected使用数据演示：&lt;/<b>h2</b>&gt;
<p>&lt;<b>s</b>:<b>form</b> name=&#8221;form1&#8243;&gt;
<p>&lt;<b>s</b>:doubleselect label=&#8221;缺省值测试&#8221;
<p>&nbsp;&nbsp;&nbsp; list=&#8221;#request.map.keySet()&#8221;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doubleList=&#8221;#request.map[top]&#8221;
<p>name=&#8221;doubleselect1&#8243;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doubleName=&#8221;doubleselect2&#8243;
<p>value=&#8221;#request.defaultItem&#8221;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doubleValue=&#8221;#request.doubleDefaultItem&#8221;
<p>&nbsp;&nbsp;&nbsp; formName=&#8221;form1&#8243;
<p>/&gt;
<p>&lt;/<b>s</b>:<b>form</b>&gt;
<p>&lt;/<b>body</b>&gt;
<p>&lt;/<b>html</b>&gt;<br />
<h3><b>3. </b>struts.xml</h3>
<p>&lt;action name=&#8221;doubleSelectTest&#8221; method=&#8221;doubleSelectTest&#8221; class=&#8221;com.mobilesoft.esales.webapp.action.DoubleListAction&#8221;&gt;
<p>&lt;result name=&#8221;success&#8221;&gt;test/doubleselect.jsp&lt;/result&gt;
<p>&lt;/action&gt;
<p>&nbsp;</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:6fae0b05-be83-4497-a9d7-7a77bca53c6b" 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/doubleselect" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/doubleselect');" rel="tag">doubleselect</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/java" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/java');" rel="tag">java</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/05/22/struts2-doubleselect%e6%a0%87%e7%ad%be%e4%b8%adselect%e6%a1%86%e7%bc%ba%e7%9c%81selected%e5%ae%9e%e7%8e%b0/" >Permalink</a> |
	  <a href="http://www.yeeach.com/2008/05/22/struts2-doubleselect%e6%a0%87%e7%ad%be%e4%b8%adselect%e6%a1%86%e7%bc%ba%e7%9c%81selected%e5%ae%9e%e7%8e%b0/#comments" >One comment</a></p>
	<p>Add to <a href="http://del.icio.us/post?url=http://www.yeeach.com/2008/05/22/struts2-doubleselect%e6%a0%87%e7%ad%be%e4%b8%adselect%e6%a1%86%e7%bc%ba%e7%9c%81selected%e5%ae%9e%e7%8e%b0/&amp;title=Struts2 doubleselect标签中select框缺省selected实现" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://del.icio.us/post?url=http://www.yeeach.com/2008/05/22/struts2-doubleselect%e6%a0%87%e7%ad%be%e4%b8%adselect%e6%a1%86%e7%bc%ba%e7%9c%81selected%e5%ae%9e%e7%8e%b0/&amp;title=Struts2 doubleselect标签中select框缺省selected实现');">del.icio.us</a></p>
	<p>Search blogs linking this post with <a href="http://www.technorati.com/search/http://www.yeeach.com/2008/05/22/struts2-doubleselect%e6%a0%87%e7%ad%be%e4%b8%adselect%e6%a1%86%e7%bc%ba%e7%9c%81selected%e5%ae%9e%e7%8e%b0/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.technorati.com/search/http://www.yeeach.com/2008/05/22/struts2-doubleselect%e6%a0%87%e7%ad%be%e4%b8%adselect%e6%a1%86%e7%bc%ba%e7%9c%81selected%e5%ae%9e%e7%8e%b0/');" 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/05/22/struts2-doubleselect%e6%a0%87%e7%ad%be%e4%b8%adselect%e6%a1%86%e7%bc%ba%e7%9c%81selected%e5%ae%9e%e7%8e%b0/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Struts2 中下拉框中采用树形结构实现</title>
		<link>http://www.yeeach.com/2008/04/03/struts2-%e4%b8%ad%e4%b8%8b%e6%8b%89%e6%a1%86%e4%b8%ad%e9%87%87%e7%94%a8%e6%a0%91%e5%bd%a2%e7%bb%93%e6%9e%84%e5%ae%9e%e7%8e%b0/</link>
		<comments>http://www.yeeach.com/2008/04/03/struts2-%e4%b8%ad%e4%b8%8b%e6%8b%89%e6%a1%86%e4%b8%ad%e9%87%87%e7%94%a8%e6%a0%91%e5%bd%a2%e7%bb%93%e6%9e%84%e5%ae%9e%e7%8e%b0/#comments</comments>
		<pubDate>Thu, 03 Apr 2008 03:53:26 +0000</pubDate>
		<dc:creator>chuanliang</dc:creator>
				<category><![CDATA[技术相关]]></category>
		<category><![CDATA[struts2]]></category>
		<category><![CDATA[tree]]></category>
		<category><![CDATA[标签]]></category>
		<category><![CDATA[树形结构]]></category>

		<guid isPermaLink="false">http://www.yeeach.com/2008/04/03/struts2-%e4%b8%ad%e4%b8%8b%e6%8b%89%e6%a1%86%e4%b8%ad%e9%87%87%e7%94%a8%e6%a0%91%e5%bd%a2%e7%bb%93%e6%9e%84%e5%ae%9e%e7%8e%b0/</guid>
		<description><![CDATA[　　在项目中，有大量的诸如“产品类型”这样的下拉选择框，为了保证项目后期的可维护性，除了相对固化的类别可以在代码中直接写死外，这些下拉选择框应当尽量从系统的数据字典表中进行动态读取和展现。但在展现时候存在一个问题，如果分类存在多级时候，一种方案是采用几个下拉框进行级联操作，也即所谓的DoubleSelect，但这种情况只适用与两级级联菜单的情况，在处理上也不具有通用性。例如典型的需求： 对于产品类别，结构如下： 产品类别（顶级节点：root,类型：product_type）: 　&#124;-娱乐（产品大类1:product_type1,类型:product_type） 　　　&#124;-音乐（产品分类11,product_type11） 　　　　　&#124;-流行音乐（子分类111,product_type111） 　　　　　&#124;-摇滚音乐（子分类112,product_type112） 　　　&#124;-产品分类12 　&#124;-商务（产品大类2） &#160; 1、数据库存储策略 &#160; 鉴于此，在项目中，对于这样的需求的实现方法如下： 对于一种类别（例如对于产品类别product_type）的子类别在oss_category(类别表)中存储方案如下： 1、在oss_category表中插入一条记录用于标识“产品类别”对应的顶级节点，其 category_id=1,parent_id=-1,category_type=”product_type”,category_name=”root” 2、在oss_category表中插入一条记录用于标识“product_type11”2级节点，其 category_id=2,parent_id=1,category_type=”product_type”,category_name=”product_type1” 3、在oss_category表中插入一条记录用于标识“product_type11”3级节点，其 category_id=3,parent_id=2,category_type=”product_type”,category_name=”product_type11” 整个数据库脚本如下： CREATE TABLE `oss_category` ( `category_id` int(11) NOT NULL auto_increment, `parent_id` int(11) default &#8216;-1&#8242;, `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` [...]]]></description>
			<content:encoded><![CDATA[<p>　　在项目中，有大量的诸如“产品类型”这样的下拉选择框，为了保证项目后期的可维护性，除了相对固化的类别可以在代码中直接写死外，这些下拉选择框应当尽量从系统的数据字典表中进行动态读取和展现。但在展现时候存在一个问题，如果分类存在多级时候，一种方案是采用几个下拉框进行级联操作，也即所谓的DoubleSelect，但这种情况只适用与两级级联菜单的情况，在处理上也不具有通用性。例如典型的需求：
<p>对于产品类别，结构如下：
<p>产品类别（顶级节点：root,类型：product_type）:
<p>　|-娱乐（产品大类1:product_type1,类型:product_type）
<p>　　　|-音乐（产品分类11,product_type11）
<p>　　　　　|-流行音乐（子分类111,product_type111）
<p>　　　　　|-摇滚音乐（子分类112,product_type112）
<p>　　　|-产品分类12
<p>　|-商务（产品大类2）
<p>&nbsp;
<p><a></a><br />
<h3>1、数据库存储策略</h3>
<h5>
</h5>
<p>&nbsp;
<p>鉴于此，在项目中，对于这样的需求的实现方法如下：
<p>对于一种类别（例如对于产品类别product_type）的子类别在oss_category(类别表)中存储方案如下：
<p>1、在oss_category表中插入一条记录用于标识“产品类别”对应的顶级节点，其
<p>category_id=1,parent_id=-1,category_type=”product_type”,category_name=”root”
<p>2、在oss_category表中插入一条记录用于标识“product_type11”2级节点，其
<p>category_id=2,parent_id=1,category_type=”product_type”,category_name=”product_type1”
<p>3、在oss_category表中插入一条记录用于标识“product_type11”3级节点，其
<p>category_id=3,parent_id=2,category_type=”product_type”,category_name=”product_type11”
<p>整个数据库脚本如下：
<p>CREATE TABLE `oss_category` (
<p>`category_id` int(11) NOT NULL auto_increment,
<p>`parent_id` int(11) default &#8216;-1&#8242;,
<p>`level` smallint(6) default NULL,
<p>`is_leaf` tinyint(1) default NULL,
<p>`category_title` varchar(100) default NULL,
<p>`category_name` varchar(100) default NULL,
<p>`category_code` varchar(100) default NULL,
<p>`category_type` varchar(30) default NULL,
<p>`image` varchar(255) default NULL,
<p>`status` varchar(20) default NULL,
<p>`creator` varchar(50) default NULL,
<p>`create_date` datetime default NULL,
<p>`modify_user` varchar(50) default NULL,
<p>`modify_date` datetime default NULL,
<p>`description` text,
<p>PRIMARY KEY(`category_id`)
<p>) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=gbk;
<p>INSERT INTO `oss_category` VALUES (&#8217;1&#8242;, &#8216;-1&#8242;, &#8217;1&#8242;, &#8217;0&#8242;, &#8216;root&#8217;, &#8216;root&#8217;, &#8216;root&#8217;, &#8216;product_type&#8217;, null, &#8217;1&#8242;, null, null, null, null, null);
<p>INSERT INTO `oss_category` VALUES (&#8217;2&#8242;, &#8217;1&#8242;, &#8217;2&#8242;, &#8217;0&#8242;, &#8216;&lt;input type=\&#8217;checkbox\&#8217; name=\&#8217;product_type1\&#8217;id=\&#8217;product_type1\&#8217;/&gt;&lt;b&gt;product_type1&lt;/b&gt;&#8217;, &#8216;product_type1&#8242;, &#8216;product_type1&#8242;, &#8216;product_type&#8217;, null, &#8217;1&#8242;, null, null, null, null, null);
<p>INSERT INTO `oss_category` VALUES (&#8217;3&#8242;, &#8217;1&#8242;, &#8217;2&#8242;, &#8217;0&#8242;, &#8216;&lt;input type=\&#8217;checkbox\&#8217; name=\&#8217;product_type2\&#8217; id=\&#8217;product_type2\&#8217;class=\&#8217;treeCheckBox\&#8217;/&gt;&lt;b&gt;product_typ&#8217;, &#8216;product_type2&#8242;, &#8216;product_type2&#8242;, &#8216;product_type&#8217;, null, &#8217;1&#8242;, null, null, null, null, null);
<p>INSERT INTO `oss_category` VALUES (&#8217;4&#8242;, &#8217;3&#8242;, &#8217;3&#8242;, &#8217;0&#8242;, &#8216;&lt;input type=\&#8217;checkbox\&#8217; name=\&#8217;product_type21\&#8217;id=\&#8217;product_type21\&#8217;/&gt;&lt;b&gt;product_type21&lt;/b&gt;&#8217;, &#8216;product_type21&#8242;, &#8216;product_type21&#8242;, &#8216;product_type&#8217;, null, &#8217;1&#8242;, null, null, null, null, null);
<p>INSERT INTO `oss_category` VALUES (&#8217;5&#8242;, &#8217;2&#8242;, &#8217;3&#8242;, &#8217;0&#8242;, &#8216;&lt;input type=\&#8217;checkbox\&#8217; name=\&#8217;product_type11\&#8217;id=\&#8217;product_type11\&#8217;/&gt;&lt;b&gt;product_type11&lt;/b&gt;&#8217;, &#8216;product_type11&#8242;, &#8216;product_type11&#8242;, &#8216;product_type&#8217;, null, &#8217;1&#8242;, null, null, null, null, null);
<p>INSERT INTO `oss_category` VALUES (&#8217;6&#8242;, &#8217;5&#8242;, &#8217;4&#8242;, &#8217;1&#8242;, &#8216;&lt;input type=\&#8217;checkbox\&#8217; name=\&#8217;product_type111\&#8217;id=\&#8217;product_type111\&#8217;/&gt;&lt;b&gt;product_type111&lt;/b&gt;&#8217;, &#8216;product_type111&#8242;, &#8216;product_type111&#8242;, &#8216;product_type&#8217;, null, &#8217;1&#8242;, null, null, null, null, null);
<p>INSERT INTO `oss_category` VALUES (&#8217;7&#8242;, &#8217;3&#8242;, &#8217;2&#8242;, &#8217;0&#8242;, &#8216;&lt;input type=\&#8217;checkbox\&#8217; name=\&#8217;product_type22\&#8217; id=\&#8217;product_type22\&#8217;/&gt;&lt;b&gt;product_type22&lt;/b&gt;&#8217;, &#8216;product_type22&#8242;, &#8216;product_type22&#8242;, &#8216;product_type&#8217;, null, &#8217;1&#8242;, null, null, null, null, null);
<p>INSERT INTO `oss_category` VALUES (&#8217;8&#8242;, &#8217;2&#8242;, &#8217;3&#8242;, &#8217;0&#8242;, &#8216;&lt;input type=\&#8217;checkbox\&#8217; name=\&#8217;product_type12\&#8217;id=\&#8217;product_type12\&#8217;/&gt;&lt;b&gt;product_type12&lt;/b&gt;&#8217;, &#8216;product_type12&#8242;, &#8216;product_type12&#8242;, &#8216;product_type&#8217;, null, &#8217;1&#8242;, null, null, null, null, null);
<p>INSERT INTO `oss_category` VALUES (&#8217;9&#8242;, &#8217;4&#8242;, &#8217;4&#8242;, &#8217;1&#8242;, &#8216;&lt;input type=\&#8217;checkbox\&#8217; name=\&#8217;product_type211\&#8217;id=\&#8217;product_type211\&#8217;/&gt;&lt;b&gt;product_type211&lt;/b&gt;&#8217;, &#8216;product_type211&#8242;, &#8216;product_type211&#8242;, &#8216;product_type&#8217;, null, &#8217;1&#8242;, null, null, null, null, null);
<p>INSERT INTO `oss_category` VALUES (&#8217;10&#8242;, &#8217;7&#8242;, &#8217;4&#8242;, &#8217;1&#8242;, &#8216;&lt;input type=\&#8217;checkbox\&#8217; name=\&#8217;product_type221\&#8217;id=\&#8217;product_type221\&#8217;/&gt;&lt;b&gt;product_type221&lt;/b&gt;&#8217;, &#8216;product_type221&#8242;, &#8216;product_type221&#8242;, &#8216;product_type&#8217;, null, &#8217;1&#8242;, null, null, null, null, null);
<p><a></a><br />
<h3>2、下拉框展现树形结构策略</h3>
<h5>
<p><a href="http://192.168.1.88/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/Java/Struts2%26webwork/Struts2_%E4%B8%AD%E4%B8%8B%E6%8B%89%E6%A1%86%E4%B8%AD%E9%87%87%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E5%AE%9E%E7%8E%B0#" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://192.168.1.88/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/Java/Struts2%26webwork/Struts2_%E4%B8%AD%E4%B8%8B%E6%8B%89%E6%A1%86%E4%B8%AD%E9%87%87%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E5%AE%9E%E7%8E%B0#');"><img alt="编辑段落" src="http://192.168.1.88/skins/common/icons/icon-trans.gif"></a></h5>
<p>为了保证跨浏览器的兼容性，不采用任何控件来实现在下拉框中展现树形结构，而采用最为原始的拼凑出如下形式的select 框
<p>&lt;select&gt;
<p>&lt;option value=&#8221;1&#8243;&gt;1&lt;/option&gt;
<p>&lt;option value=&#8221;11&#8243;&gt;&amp;nbsp;&amp;nbsp;|-11&lt;/option&gt;
<p>&lt;option value=&#8221;12&#8243;&gt;&amp;nbsp;&amp;nbsp;|-12&lt;/option&gt;
<p>&lt;option value=&#8221;2&#8243;&gt;2&lt;/option&gt;
<p>&lt;option value=&#8221;21&#8243;&gt;&amp;nbsp;&amp;nbsp;|-21&lt;/option&gt;
<p>&lt;option value=&#8221;22&#8243;&gt;&amp;nbsp;&amp;nbsp;|-22&lt;/option&gt;
<p>&lt;/select&gt;
<p>也即用&amp;nbsp;来实现缩进来达到树形结构的效果，在实现上只需要在程序中拼凑出这样的字符串到界面展现即可。
<p>在Struts2中，采用标签展现结果时候，注意property的选项escape=”false”,让Struts2不要对字符串进行转义。
<p>&lt;s:property value=&#8221;#request.selectResult&#8221; escape=&#8221;false&#8221;/&gt;
<p><a></a><br />
<h3>3、代码实现</h3>
<h5>
<p><a href="http://192.168.1.88/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/Java/Struts2%26webwork/Struts2_%E4%B8%AD%E4%B8%8B%E6%8B%89%E6%A1%86%E4%B8%AD%E9%87%87%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E5%AE%9E%E7%8E%B0#" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://192.168.1.88/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/Java/Struts2%26webwork/Struts2_%E4%B8%AD%E4%B8%8B%E6%8B%89%E6%A1%86%E4%B8%AD%E9%87%87%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E5%AE%9E%E7%8E%B0#');"><img alt="编辑段落" src="http://192.168.1.88/skins/common/icons/icon-trans.gif"></a></h5>
<p>代码基本上沿用了原来的树形结构的代码，由于原来与OssCategory及ossCategoryDAO存在冲突，拷贝OssCategory.hbm.xml为Tree.hbm.xml。
<p><a></a><br />
<h4>3.1、Model层</h4>
<h6>
<p><a href="http://192.168.1.88/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/Java/Struts2%26webwork/Struts2_%E4%B8%AD%E4%B8%8B%E6%8B%89%E6%A1%86%E4%B8%AD%E9%87%87%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E5%AE%9E%E7%8E%B0#" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://192.168.1.88/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/Java/Struts2%26webwork/Struts2_%E4%B8%AD%E4%B8%8B%E6%8B%89%E6%A1%86%E4%B8%AD%E9%87%87%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E5%AE%9E%E7%8E%B0#');"><img alt="编辑段落" src="http://192.168.1.88/skins/common/icons/icon-trans.gif"></a></h6>
<p>package com.mobilesoft.framework.tree.model;
<p>import java.util.Date;
<p>import java.util.List;
<p>import java.util.Set;
<p>import com.mobilesoft.framework.common.model.BaseObject;
<p>/**
<p>* OssCategory entity.
<p>*
<p>* @author MyEclipse Persistence Tools
<p>*/
<p>public class Tree extends BaseObject
<p>implements java.io.Serializable {
<p>// Fields
<p>private Integer categoryId;
<p>private Integer parentId;
<p>private Short level;
<p>private Byte isLeaf;
<p>private String categoryTitle;
<p>private String categoryName;
<p>private String categoryCode;
<p>private String categoryType;
<p>private String image;
<p>private String status;
<p>private String creator;
<p>private Date createDate;
<p>private String modifyUser;
<p>private Date modifyDate;
<p>private String description;
<p>private Tree[] childCategories;
<p>// Constructors
<p>/** default constructor */
<p>public Tree() {
<p>}
<p>/** full constructor */
<p>public Tree(Integer parentId, Short level, Byte isLeaf,
<p>String categoryTitle, String categoryName, String categoryCode,
<p>String categoryType, String image, String status, String creator,
<p>Date createDate, String modifyUser, Date modifyDate,
<p>String description) {
<p>this.parentId = parentId;
<p>this.level = level;
<p>this.isLeaf = isLeaf;
<p>this.categoryTitle = categoryTitle;
<p>this.categoryName = categoryName;
<p>this.categoryCode = categoryCode;
<p>this.categoryType = categoryType;
<p>this.image = image;
<p>this.status = status;
<p>this.creator = creator;
<p>this.createDate = createDate;
<p>this.modifyUser = modifyUser;
<p>this.modifyDate = modifyDate;
<p>this.description = description;
<p>}
<p>// Property accessors
<p>public Integer getCategoryId() {
<p>return this.categoryId;
<p>}
<p>public void setCategoryId(Integer categoryId) {
<p>this.categoryId = categoryId;
<p>}
<p>public Integer getParentId() {
<p>return this.parentId;
<p>}
<p>public void setParentId(Integer parentId) {
<p>this.parentId = parentId;
<p>}
<p>public Short getLevel() {
<p>return this.level;
<p>}
<p>public void setLevel(Short level) {
<p>this.level = level;
<p>}
<p>public Byte getIsLeaf() {
<p>return this.isLeaf;
<p>}
<p>public void setIsLeaf(Byte isLeaf) {
<p>this.isLeaf = isLeaf;
<p>}
<p>public String getCategoryTitle() {
<p>return this.categoryTitle;
<p>}
<p>public void setCategoryTitle(String categoryTitle) {
<p>this.categoryTitle = categoryTitle;
<p>}
<p>public String getCategoryName() {
<p>return this.categoryName;
<p>}
<p>public void setCategoryName(String categoryName) {
<p>this.categoryName = categoryName;
<p>}
<p>public String getCategoryCode() {
<p>return this.categoryCode;
<p>}
<p>public void setCategoryCode(String categoryCode) {
<p>this.categoryCode = categoryCode;
<p>}
<p>public String getCategoryType() {
<p>return this.categoryType;
<p>}
<p>public void setCategoryType(String categoryType) {
<p>this.categoryType = categoryType;
<p>}
<p>public String getImage() {
<p>return this.image;
<p>}
<p>public void setImage(String image) {
<p>this.image = image;
<p>}
<p>public String getStatus() {
<p>return this.status;
<p>}
<p>public void setStatus(String status) {
<p>this.status = status;
<p>}
<p>public String getCreator() {
<p>return this.creator;
<p>}
<p>public void setCreator(String creator) {
<p>this.creator = creator;
<p>}
<p>public Date getCreateDate() {
<p>return this.createDate;
<p>}
<p>public void setCreateDate(Date createDate) {
<p>this.createDate = createDate;
<p>}
<p>public String getModifyUser() {
<p>return this.modifyUser;
<p>}
<p>public void setModifyUser(String modifyUser) {
<p>this.modifyUser = modifyUser;
<p>}
<p>public Date getModifyDate() {
<p>return this.modifyDate;
<p>}
<p>public void setModifyDate(Date modifyDate) {
<p>this.modifyDate = modifyDate;
<p>}
<p>public String getDescription() {
<p>return this.description;
<p>}
<p>public void setDescription(String description) {
<p>this.description = description;
<p>}
<p>public Tree[] getChildCategories() {
<p>return childCategories;
<p>}
<p>public void setChildCategories(Tree[] childCategories) {
<p>this.childCategories = childCategories;
<p>}
<p>}
<p><a></a><br />
<h4>3.2、DAO层</h4>
<h6>
<p><a href="http://192.168.1.88/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/Java/Struts2%26webwork/Struts2_%E4%B8%AD%E4%B8%8B%E6%8B%89%E6%A1%86%E4%B8%AD%E9%87%87%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E5%AE%9E%E7%8E%B0#" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://192.168.1.88/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/Java/Struts2%26webwork/Struts2_%E4%B8%AD%E4%B8%8B%E6%8B%89%E6%A1%86%E4%B8%AD%E9%87%87%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E5%AE%9E%E7%8E%B0#');"><img alt="编辑段落" src="http://192.168.1.88/skins/common/icons/icon-trans.gif"></a></h6>
<p>package com.mobilesoft.framework.tree.dao.hibernate;
<p>import org.apache.log4j.Logger;
<p>import java.util.ArrayList;
<p>import java.util.Iterator;
<p>import java.util.List;
<p>import org.apache.commons.logging.Log;
<p>import org.apache.commons.logging.LogFactory;
<p>import org.hibernate.LockMode;
<p>import org.springframework.context.ApplicationContext;
<p>import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
<p>import com.mobilesoft.framework.tree.model.Tree;
<p>/**
<p>* A data access object (DAO) providing persistence and search support for
<p>* Tree entities. Transaction control of the save(), update() and
<p>* delete() operations can directly support Spring container-managed
<p>* transactions or they can be augmented to handle user-managed Spring
<p>* transactions. Each of these methods provides additional information for how
<p>* to configure it for the desired type of transaction control.
<p>*
<p>* @see com.mobilesoft.esales.model.Tree
<p>* @author MyEclipse Persistence Tools
<p>*/
<p>public class TreeDAO extends HibernateDaoSupport {
<p>/**
<p>* Logger for this class
<p>*/
<p>private static final Logger logger = Logger.getLogger(TreeDAO.class);
<p>private static final Log log = LogFactory.getLog(TreeDAO.class);
<p>// property constants
<p>public static final String PARENT_ID = &#8220;parentId&#8221;;
<p>public static final String LEVEL = &#8220;level&#8221;;
<p>public static final String IS_LEAF = &#8220;isLeaf&#8221;;
<p>public static final String tree_TITLE = &#8220;categoryTitle&#8221;;
<p>public static final String tree_NAME = &#8220;categoryName&#8221;;
<p>public static final String tree_CODE = &#8220;categoryCode&#8221;;
<p>public static final String tree_TYPE = &#8220;categoryType&#8221;;
<p>public static final String IMAGE = &#8220;image&#8221;;
<p>public static final String STATUS = &#8220;status&#8221;;
<p>public static final String CREATOR = &#8220;creator&#8221;;
<p>public static final String MODIFY_USER = &#8220;modifyUser&#8221;;
<p>public static final String DESCRIPTION = &#8220;description&#8221;;
<p>public String delimiter;
<p>protected void initDao() {
<p>// do nothing
<p>}
<p>/*
<p>省略掉其他方法
<p>*/
<p>public static TreeDAO getFromApplicationContext(
<p>ApplicationContext ctx) {
<p>return (TreeDAO) ctx.getBean(&#8220;treeDAO&#8221;);
<p>}
<p>public Tree[] getAlltree() {
<p>ArrayList&lt;Tree&gt; resultList=new ArrayList&lt;Tree&gt;();
<p>String queryString=&#8221;from Tree as tree where tree.parentId=1&#8243;;
<p>List&lt;Tree&gt; queryList =getHibernateTemplate().find(queryString);
<p>Iterator iterator=queryList.iterator();
<p>while(iterator.hasNext()){
<p>Tree tree=(Tree)iterator.next();
<p>Tree[] childrenArray=getChildCategoriesById(tree.getCategoryId());
<p>logger.debug(&#8220;getAlltree() &#8211; Tree[] childrenList=&#8221; + childrenArray.length);
<p>tree.setChildCategories(childrenArray);
<p>resultList.add(tree);
<p>}
<p>Tree[] resultArray=(Tree[])resultList.toArray(new Tree[resultList.size()]);
<p>return resultArray;
<p>}
<p>public String getChildrenByType(String type,boolean includeRoot,String delimiter ){
<p>this.delimiter=delimiter;
<p>StringBuffer resultBuffer=new StringBuffer();
<p>resultBuffer.append(&#8220;&lt;select&gt;&#8221;);
<p>StringBuffer queryBuffer=new StringBuffer(&#8220;from Tree as tree where tree.categoryType=&#8217;&#8221;);
<p>queryBuffer.append(type);
<p>queryBuffer.append(&#8220;&#8216; order by tree.categoryId asc &#8220;);
<p>logger.fatal(queryBuffer);
<p>List&lt;Tree&gt; queryList =getHibernateTemplate().find(queryBuffer.toString());
<p>if(queryList.size()&gt;0){
<p>Tree[] treeArray=(Tree[])queryList.toArray(new Tree[queryList.size()]);
<p>int start;
<p>if(includeRoot)
<p>start=0;
<p>else
<p>start=1;
<p>resultBuffer.append(&#8220;&lt;option value=&#8217;&#8221;);
<p>resultBuffer.append(treeArray[start].getCategoryId());
<p>resultBuffer.append(&#8220;&#8216;&gt;&#8221;);
<p>resultBuffer.append(treeArray[start].getCategoryName());
<p>resultBuffer.append(&#8220;&lt;/option&gt;&#8221;);
<p>String childrenStr=getChildCategories4Select(treeArray[start].getCategoryId(),treeArray[start].getLevel());
<p>logger.debug(&#8220;getChildrenByType( String ) &#8211; start String=&#8221; + start +&#8221;,level is :&#8221;+treeArray[start].getLevel());
<p>resultBuffer.append(childrenStr);
<p>logger.fatal(&#8220;getChildrenByType(String) &#8211; StringBuffer resultBuffer11111=&#8221; + resultBuffer);
<p>resultBuffer.append(&#8220;&lt;/select&gt;&#8221;);
<p>return resultBuffer.toString();
<p>}else{
<p>return &#8220;&lt;/select&gt;&#8221;;
<p>}
<p>}
<p>public Tree[] getChildCategoriesById(int treeId) {
<p>String queryString=&#8221;from Tree as tree where tree.parentId=&#8221;+treeId;
<p>List&lt;Tree&gt; queryList =getHibernateTemplate().find(queryString);
<p>logger.debug(&#8220;getChildCategoriesById(int) &#8211; List&lt;Tree&gt; queryList=&#8221; + queryList.size());
<p>ArrayList&lt;Tree&gt; resultList=new ArrayList&lt;Tree&gt;();
<p>Iterator iterator=queryList.iterator();
<p>while(iterator.hasNext()){
<p>Tree tree=(Tree)iterator.next();
<p>Tree[] childrenList=getChildCategoriesById(tree.getCategoryId());
<p>logger.debug(&#8220;getChildCategoriesById(int) &#8211; Tree[] childrenList=&#8221; + childrenList+&#8221;parentid is &#8220;+treeId);
<p>tree.setChildCategories(childrenList);
<p>resultList.add(tree);
<p>}
<p>Tree[] resultArray=(Tree[])resultList.toArray(new Tree[resultList.size()]);
<p>return resultArray;
<p>}
<p>/*
<p>* @return 要拼凑出如下形式的select 框
<p>* &lt;select&gt;
<p>* &lt;option value=&#8221;1&#8243;&gt;1&lt;/option&gt;
<p>* &lt;option value=&#8221;11&#8243;&gt;&amp;nbsp;&amp;nbsp;|-11&lt;/option&gt;
<p>* &lt;option value=&#8221;12&#8243;&gt;&amp;nbsp;&amp;nbsp;|-12&lt;/option&gt;
<p>* &lt;option value=&#8221;2&#8243;&gt;2&lt;/option&gt;
<p>* &lt;option value=&#8221;21&#8243;&gt;&amp;nbsp;&amp;nbsp;|-21&lt;/option&gt;
<p>* &lt;option value=&#8221;22&#8243;&gt;&amp;nbsp;&amp;nbsp;|-22&lt;/option&gt;
<p>* &lt;/select&gt;
<p>*
<p>* @param treeId节点的id号
<p>* @param rootLevel所在类别子树根节点在整棵树中的层级
<p>*/
<p>public String getChildCategories4Select(int treeId,int rootLevel) {
<p>StringBuffer childBuffer=new StringBuffer();
<p>String queryString=&#8221;from Tree as tree where tree.parentId=&#8221;+treeId;
<p>List&lt;Tree&gt; queryList =getHibernateTemplate().find(queryString);
<p>logger.debug(&#8220;getChildCategories4Select(int,int) &#8211; List&lt;Tree&gt; queryList=&#8221; + queryList.size());
<p>ArrayList&lt;Tree&gt; resultList=new ArrayList&lt;Tree&gt;();
<p>Iterator iterator=queryList.iterator();
<p>while(iterator.hasNext()){
<p>Tree tree=(Tree)iterator.next();
<p>int childLevel=tree.getLevel();
<p>childBuffer.append(&#8220;&lt;option value=&#8217;&#8221;);
<p>childBuffer.append(tree.getCategoryId());
<p>childBuffer.append(&#8221; &#8216;&gt;&#8221;);
<p>for(int i=0;i&lt;=childLevel-rootLevel;i++)
<p>childBuffer.append(&#8220;&amp;nbsp;&amp;nbsp;&#8221;);
<p>childBuffer.append(this.delimiter+tree.getCategoryName());
<p>childBuffer.append(&#8220;&lt;/option&gt;&#8221;);
<p>String childrenStr=getChildCategories4Select(tree.getCategoryId(),rootLevel);
<p>childBuffer.append(childrenStr);
<p>logger.debug(&#8220;getChildCategories4Select(int,int) &#8211; childBuffer=&#8221; + childBuffer);
<p>}
<p>return childBuffer.toString();
<p>}
<p>}
<p><a></a><br />
<h4>3.3、Service层</h4>
<h6>
<p><a href="http://192.168.1.88/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/Java/Struts2%26webwork/Struts2_%E4%B8%AD%E4%B8%8B%E6%8B%89%E6%A1%86%E4%B8%AD%E9%87%87%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E5%AE%9E%E7%8E%B0#" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://192.168.1.88/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/Java/Struts2%26webwork/Struts2_%E4%B8%AD%E4%B8%8B%E6%8B%89%E6%A1%86%E4%B8%AD%E9%87%87%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E5%AE%9E%E7%8E%B0#');"><img alt="编辑段落" src="http://192.168.1.88/skins/common/icons/icon-trans.gif"></a></h6>
<p><strong>TreeService</strong><strong>.java</strong>
<p>package com.mobilesoft.framework.tree.service;
<p>import java.util.List;
<p>import java.util.Set;
<p>import com.mobilesoft.framework.tree.model.Tree;
<p>public interface TreeService {
<p>/**
<p>* @return 获取下级子节点
<p>*/
<p>//public Set getChildren(int rootId);
<p>/**
<p>* @return 递归指定级别的所有子节点
<p>*
<p>*/
<p>//public Set getChildrenByLevel(int rootId,int level);
<p>/**
<p>* 用于获取数据字典中指定类别的所有类型的节点，
<p>* 类别表节点的树形结构
<p>* |&#8211; ROOT 根类别（-1）
<p>* 　|&#8211;类别类型：套餐类别 bundle_type
<p>* 　　|&#8211;3 套餐类别1
<p>* 　　|&#8211;4 套餐类别2
<p>*　|&#8211;类别类型：产品类别 product_type
<p>* 　　|&#8211;产品大类1
<p>*　　　　|&#8211;产品大类11
<p>*　　　　　|&#8212;产品大类别111
<p>*　　　　　|&#8212;产品大类别112
<p>*　　　　|&#8211;产品大类12
<p>* @return 获取指定类型的所有子节点
<p>* 在实现上，对于诸如”产品类别“等下拉框可能为树形结构的元素，
<p>* 为了避免由于浏览器兼容性问题，在形式上是树形结构，
<p>* 实际上就是从字典表（目前树形结构仍然采用oss_category作为字典表）动态取出数据，然后拼凑成字符串形式展现，例如：
<p>* &lt;select&gt;
<p>* &lt;option value=&#8221;1&#8243;&gt;1&lt;/option&gt;
<p>*&lt;option value=&#8221;11&#8243;&gt;&amp;nbsp;&amp;nbsp;|-11&lt;/option&gt;
<p>*&lt;option value=&#8221;12&#8243;&gt;&amp;nbsp;&amp;nbsp;|-12&lt;/option&gt;
<p>*&lt;option value=&#8221;2&#8243;&gt;2&lt;/option&gt;
<p>*&lt;option value=&#8221;21&#8243;&gt;&amp;nbsp;&amp;nbsp;|-21&lt;/option&gt;
<p>*&lt;option value=&#8221;22&#8243;&gt;&amp;nbsp;&amp;nbsp;|-22&lt;/option&gt;
<p>*&lt;/select&gt;
<p>* @param type:节点的类型
<p>* @param levle:节点相对于所属类型的节点的级别 -1表示获取所属类型的根节点的所有级别的子节点
<p>*/
<p>public String getChildrenByType( String type);
<p>public String getChildrenByType( String type,boolean includeRoot);
<p>public String getChildrenByType( String type,boolean includeRoot,String delimiter);
<p>/**
<p>* @return 获取指定根节点的所有子节点
<p>*/
<p>public Tree[]getAllTree();
<p>}
<p><strong>TreeServiceImpl</strong><strong>.java</strong>
<p>package com.mobilesoft.framework.tree.service.impl;
<p>import java.util.List;
<p>import java.util.Set;
<p>import com.mobilesoft.framework.tree.dao.hibernate.TreeDAO;
<p>import com.mobilesoft.framework.tree.model.Tree;
<p>import com.mobilesoft.framework.tree.service.TreeService;
<p>public class TreeServiceImpl implements TreeService {
<p>TreeDAO treeDAO;
<p>String delimiter;
<p>public Set getChildren(int rootId) {
<p>// TODO Auto-generated method stub
<p>return null;
<p>}
<p>public Set getLevelChildren(int rootId, int level) {
<p>// TODO Auto-generated method stub
<p>return null;
<p>}
<p>public String getChildrenByType( String type){
<p>return treeDAO.getChildrenByType(type,true,this.delimiter);
<p>}
<p>public String getChildrenByType( String type,boolean includeRoot){
<p>return treeDAO.getChildrenByType(type,includeRoot,this.delimiter);
<p>}
<p>public String getChildrenByType( String type,boolean includeRoot,String delimiter){
<p>return treeDAO.getChildrenByType(type,includeRoot,delimiter);
<p>}
<p>public Tree[]getAllTree(){
<p>return treeDAO.getAlltree();
<p>}
<p>public TreeDAO gettreeDAO() {
<p>return treeDAO;
<p>}
<p>public void settreeDAO(TreeDAO treeDAO) {
<p>this.treeDAO = treeDAO;
<p>}
<p>public String getDelimiter() {
<p>return delimiter;
<p>}
<p>public void setDelimiter(String delimiter) {
<p>this.delimiter = delimiter;
<p>}
<p>}
<p><a></a><br />
<h3>3.4、调用方法</h3>
<h6>
<p><a href="http://192.168.1.88/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/Java/Struts2%26webwork/Struts2_%E4%B8%AD%E4%B8%8B%E6%8B%89%E6%A1%86%E4%B8%AD%E9%87%87%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E5%AE%9E%E7%8E%B0#" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://192.168.1.88/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/Java/Struts2%26webwork/Struts2_%E4%B8%AD%E4%B8%8B%E6%8B%89%E6%A1%86%E4%B8%AD%E9%87%87%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E5%AE%9E%E7%8E%B0#');"><img alt="编辑段落" src="http://192.168.1.88/skins/common/icons/icon-trans.gif"></a></h6>
<p>以Action中为例：
<p>private TreeService treeService;
<p><strong>public</strong> String getChildrenByType(){
<p>String selectResult=treeService.getChildrenByType(&#8220;product_type&#8221;);
<p>getRequest().setAttribute(&#8220;selectResult&#8221;, selectResult);
<p><strong>return</strong><em>SUCCESS</em>;
<p>}
<p><strong>public</strong> TreeService getTreeService() {
<p><strong>return</strong>treeService;
<p>}
<p><strong>public</strong><strong>void</strong> setTreeService(TreeService treeService) {
<p><strong>this</strong>.treeService = treeService;
<p>}
<p>注意：getChildrenByType方法有三个重载（overload）方法，
<p>public String getChildrenByType( String type);
<p>public String getChildrenByType( String type,boolean includeRoot);
<p>public String getChildrenByType( String type,boolean includeRoot,String delimiter);
<p>但实际上最后还是调用的是getChildrenByType( String type,boolean includeRoot,String delimiter)，
<p>参数说明：
<p>type: 类别的类型，例如product_type
<p>includeRoot：是否包含所在类别的根节点，例如查询product_type是否，是否需要导出所在类别的root节点
<p>delimiter：在下拉框选择时候，分隔符类型，缺省为“|-”,可以在applicationContext-service.xml中修改或调用时候传递参数。<strong></strong>
<p><a></a><br />
<h4>3.5、配置文件</h4>
<h6>
<p><a href="http://192.168.1.88/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/Java/Struts2%26webwork/Struts2_%E4%B8%AD%E4%B8%8B%E6%8B%89%E6%A1%86%E4%B8%AD%E9%87%87%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E5%AE%9E%E7%8E%B0#" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://192.168.1.88/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%87%E6%A1%A3/Java/Struts2%26webwork/Struts2_%E4%B8%AD%E4%B8%8B%E6%8B%89%E6%A1%86%E4%B8%AD%E9%87%87%E7%94%A8%E6%A0%91%E5%BD%A2%E7%BB%93%E6%9E%84%E5%AE%9E%E7%8E%B0#');"><img alt="编辑段落" src="http://192.168.1.88/skins/common/icons/icon-trans.gif"></a></h6>
<p><strong>applicationContext-resources.xml</strong>
<p>&lt;property name=&#8221;mappingResources&#8221;&gt;
<p>&lt;list&gt;
<p>&lt;value&gt;com/mobilesoft/framework/tree/model/Tree.hbm.xml&lt;/value&gt;
<p>&lt;/list&gt;
<p>&lt;/property&gt;
<p><strong>applicationContext-dao.xml</strong>
<p>&lt;bean id=&#8221;treeDAO&#8221;
<p>class=&#8221;com.mobilesoft.framework.tree.dao.hibernate.TreeDAO&#8221;&gt;
<p>&lt;property name=&#8221;sessionFactory&#8221;&gt;
<p>&lt;ref bean=&#8221;sessionFactory&#8221; /&gt;
<p>&lt;/property&gt;
<p>&lt;/bean&gt;
<p><strong>applicationContext-service.xml</strong>
<p>&lt;bean id=&#8221;treeService&#8221;
<p>class=&#8221;com.mobilesoft.framework.tree.service.impl.TreeServiceImpl&#8221;&gt;
<p>&lt;property name=&#8221;treeDAO&#8221;&gt;
<p>&lt;ref bean=&#8221;treeDAO&#8221; /&gt;
<p>&lt;/property&gt;
<p>&lt;property name=&#8221;delimiter&#8221; value=&#8221;|-&#8221;/&gt;
<p>&lt;/bean&gt;
<p><strong>action-servlet.xml</strong>
<p>&lt;bean id=&#8221;treeAction&#8221; scope=&#8221;prototype&#8221;
<p>class=&#8221;com.mobilesoft.esales.webapp.action.TreeAction&#8221;&gt;
<p>&lt;property name=&#8221;treeService&#8221;&gt;
<p>&lt;ref bean=&#8221;treeService&#8221; /&gt;
<p>&lt;/property&gt;
<p>&lt;/bean&gt;
<p><strong>struts.xml</strong>
<p>&lt;action name=&#8221;treeAction&#8221; method=&#8221;execute&#8221; class=&#8221;treeAction&#8221;&gt;
<p>&lt;result name=&#8221;success&#8221;&gt;test/treetest.jsp&lt;/result&gt;
<p>&lt;/action&gt;
<p>&nbsp;</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:f6a88463-ad89-4437-b092-de31864521d3" 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%91%e5%bd%a2%e7%bb%93%e6%9e%84" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/%e6%a0%91%e5%bd%a2%e7%bb%93%e6%9e%84');" rel="tag">树形结构</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></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/03/struts2-%e4%b8%ad%e4%b8%8b%e6%8b%89%e6%a1%86%e4%b8%ad%e9%87%87%e7%94%a8%e6%a0%91%e5%bd%a2%e7%bb%93%e6%9e%84%e5%ae%9e%e7%8e%b0/" >Permalink</a> |
	  <a href="http://www.yeeach.com/2008/04/03/struts2-%e4%b8%ad%e4%b8%8b%e6%8b%89%e6%a1%86%e4%b8%ad%e9%87%87%e7%94%a8%e6%a0%91%e5%bd%a2%e7%bb%93%e6%9e%84%e5%ae%9e%e7%8e%b0/#comments" >No comment</a></p>
	<p>Add to <a href="http://del.icio.us/post?url=http://www.yeeach.com/2008/04/03/struts2-%e4%b8%ad%e4%b8%8b%e6%8b%89%e6%a1%86%e4%b8%ad%e9%87%87%e7%94%a8%e6%a0%91%e5%bd%a2%e7%bb%93%e6%9e%84%e5%ae%9e%e7%8e%b0/&amp;title=Struts2 中下拉框中采用树形结构实现" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://del.icio.us/post?url=http://www.yeeach.com/2008/04/03/struts2-%e4%b8%ad%e4%b8%8b%e6%8b%89%e6%a1%86%e4%b8%ad%e9%87%87%e7%94%a8%e6%a0%91%e5%bd%a2%e7%bb%93%e6%9e%84%e5%ae%9e%e7%8e%b0/&amp;title=Struts2 中下拉框中采用树形结构实现');">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/03/struts2-%e4%b8%ad%e4%b8%8b%e6%8b%89%e6%a1%86%e4%b8%ad%e9%87%87%e7%94%a8%e6%a0%91%e5%bd%a2%e7%bb%93%e6%9e%84%e5%ae%9e%e7%8e%b0/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.technorati.com/search/http://www.yeeach.com/2008/04/03/struts2-%e4%b8%ad%e4%b8%8b%e6%8b%89%e6%a1%86%e4%b8%ad%e9%87%87%e7%94%a8%e6%a0%91%e5%bd%a2%e7%bb%93%e6%9e%84%e5%ae%9e%e7%8e%b0/');" 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/03/struts2-%e4%b8%ad%e4%b8%8b%e6%8b%89%e6%a1%86%e4%b8%ad%e9%87%87%e7%94%a8%e6%a0%91%e5%bd%a2%e7%bb%93%e6%9e%84%e5%ae%9e%e7%8e%b0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Struts2 OptionTransferSelect标签使用</title>
		<link>http://www.yeeach.com/2008/04/02/struts2-optiontransferselect%e6%a0%87%e7%ad%be%e4%bd%bf%e7%94%a8/</link>
		<comments>http://www.yeeach.com/2008/04/02/struts2-optiontransferselect%e6%a0%87%e7%ad%be%e4%bd%bf%e7%94%a8/#comments</comments>
		<pubDate>Wed, 02 Apr 2008 12:27:09 +0000</pubDate>
		<dc:creator>chuanliang</dc:creator>
				<category><![CDATA[技术相关]]></category>
		<category><![CDATA[optiontransferselect]]></category>
		<category><![CDATA[struts2]]></category>
		<category><![CDATA[标签]]></category>

		<guid isPermaLink="false">http://www.yeeach.com/2008/04/02/struts2-optiontransferselect%e6%a0%87%e7%ad%be%e4%bd%bf%e7%94%a8/</guid>
		<description><![CDATA[&#160; 有时候需要在两个Select框中双向挪动数据，此种在Struts2叫OptionTransferSelect，效果如下： 1. Action层 TransferSelect.java package com.mobilesoft.esales.webapp.action; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; public class TransferSelect extends BaseAction { private static final Logger logger = Logger.getLogger(DoubleListAction.class); &#160;&#160;&#160; String[] leftRoles; &#160;&#160;&#160; String[] rightRoles; public String execute(){&#160;&#160;&#160; return SUCCESS; &#160;&#160;&#160; } public String transferSelect(){ &#160;&#160;&#160;&#160;&#160;&#160; ArrayList&#60;Roles&#62; leftList=new ArrayList&#60;Roles&#62; ();&#160;&#160;&#160;&#160;&#160; &#160;&#160;&#160;&#160;&#160;&#160; Roles [...]]]></description>
			<content:encoded><![CDATA[<p>&nbsp;</p>
<p>有时候需要在两个Select框中双向挪动数据，此种在Struts2叫OptionTransferSelect，效果如下：
<p><a href="http://www.yeeach.com/wp-content/uploads/2008/04/windowslivewriterstruts2optiontransferselect-11d55optiontransferselect-21.png" ><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="382" alt="optiontransferselect" src="http://www.yeeach.com/wp-content/uploads/2008/04/windowslivewriterstruts2optiontransferselect-11d55optiontransferselect-thumb1.png" width="432" border="0"></a><br />
<h3><b>1. </b>Action层</h3>
<p>TransferSelect.java
<p><b>package</b> com.mobilesoft.esales.webapp.action;
<p><b>import</b> java.util.ArrayList;
<p><b>import</b> java.util.Iterator;
<p><b>import</b> java.util.List;
<p><b>import</b> java.util.Map;
<p><b>import</b> java.util.Set;
<p><b>import</b> org.apache.log4j.Logger;
<p><b>public</b> <b>class</b> TransferSelect <b>extends</b> BaseAction {
<p><b>private</b> <b>static</b> <b>final</b> Logger <i>logger</i> = Logger.<i>getLogger</i>(DoubleListAction.<b>class</b>);
<p>&nbsp;&nbsp;&nbsp; String[] leftRoles;
<p>&nbsp;&nbsp;&nbsp; String[] rightRoles;
<p><b>public</b> String execute(){&nbsp;&nbsp;&nbsp;
<p><b>return</b> <i>SUCCESS</i>;
<p>&nbsp;&nbsp;&nbsp; }
<p><b>public</b> String transferSelect(){
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ArrayList&lt;Roles&gt; leftList=<b>new</b> ArrayList&lt;Roles&gt; ();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Roles leftRoles1=<b>new</b> Roles();
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leftRoles1.setRoleId(1);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leftRoles1.setRoleName(&#8220;角色1&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Roles leftRoles2=<b>new</b> Roles();
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leftRoles2.setRoleId(2);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leftRoles2.setRoleName(&#8220;角色2&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Roles leftRoles3=<b>new</b> Roles();
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leftRoles3.setRoleId(3);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leftRoles3.setRoleName(&#8220;角色3&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Roles leftRoles4=<b>new</b> Roles();
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leftRoles4.setRoleId(4);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leftRoles4.setRoleName(&#8220;角色4&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leftList.add(leftRoles1);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leftList.add(leftRoles2);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leftList.add(leftRoles3);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leftList.add(leftRoles4);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ArrayList&lt;Roles&gt;&nbsp; rightList=<b>new</b> ArrayList();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Roles rightRoles1=<b>new</b> Roles();
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rightRoles1.setRoleId(1);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rightRoles1.setRoleName(&#8220;角色5&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Roles rightRoles2=<b>new</b> Roles();
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rightRoles2.setRoleId(2);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rightRoles2.setRoleName(&#8220;角色6&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Roles rightRoles3=<b>new</b> Roles();
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rightRoles3.setRoleId(3);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rightRoles3.setRoleName(&#8220;角色7&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Roles rightRoles4=<b>new</b> Roles();
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rightRoles4.setRoleId(4);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rightRoles4.setRoleName(&#8220;角色8&#8243;);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rightList.add(rightRoles1);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rightList.add(rightRoles2);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rightList.add(rightRoles3);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rightList.add(rightRoles4);&nbsp;&nbsp;&nbsp;&nbsp;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getRequest().setAttribute(&#8220;rightList&#8221;, rightList);
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getRequest().setAttribute(&#8220;leftList&#8221;, leftList);
<p><b>return</b> <i>SUCCESS</i>;
<p>&nbsp;&nbsp;&nbsp; }
<p><b>public</b> String transferSelectPost(){
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Map map=getRequest().getParameterMap();
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Set set=map.entrySet();
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Iterator iterator=set.iterator();
<p><b>while</b>(iterator.hasNext()){
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Map.Entry mapEntry=(Map.Entry)iterator.next();
<p><b>if</b>(mapEntry.getValue() <b>instanceof</b> String[]){
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String[] selectValues=(String[])mapEntry.getValue();
<p><b>for</b>(<b>int</b> i=0;i&lt;selectValues.length;i++){
<p><i>logger</i>.fatal(&#8220;For map test，The key is: &#8220;+mapEntry.getKey()+&#8221;,value is :&#8221;+selectValues[i]);&nbsp;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
<p><b>for</b>(<b>int</b> i=0;i&lt;leftRoles.length;i++){
<p><i>logger</i>.fatal(&#8220;For Array test,The leftRoles roleName is: &#8220;+leftRoles[i]);&nbsp;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
<p><b>for</b>(<b>int</b> i=0;i&lt;rightRoles.length;i++){
<p><i>logger</i>.fatal(&#8220;For Array test,The rightRoles roleName is: &#8220;+rightRoles[i]);&nbsp;&nbsp;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getRequest().setAttribute(&#8220;map&#8221;, map);
<p><b>return</b> <i>SUCCESS</i>;
<p>&nbsp;&nbsp;&nbsp; }
<p><b>public</b> <b>void</b> setLeftRoles(String[] leftRoles) {
<p><b>this</b>.leftRoles = leftRoles;
<p>&nbsp;&nbsp;&nbsp; }
<p><b>public</b> <b>void</b> setRightRoles(String[] rightRoles) {
<p><b>this</b>.rightRoles = rightRoles;
<p>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;
<p>}
<p><strong>Roles.java</strong>
<p>package com.mobilesoft.esales.webapp.action;
<p>public class Roles {<br />&nbsp;&nbsp;&nbsp; private Integer roleId;<br />&nbsp;&nbsp;&nbsp; private String roleName;<br />&nbsp;&nbsp;&nbsp; public Roles(){<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; public Integer getRoleId() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return roleId;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; public void setRoleId(Integer roleId) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.roleId = roleId;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; public String getRoleName() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return roleName;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; public void setRoleName(String roleName) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.roleName = roleName;<br />&nbsp;&nbsp;&nbsp; }<br />}<br />
<h3><b>2. </b>Web层</h3>
<p><b>transferselect.jsp</b>
<p>&lt;%@ taglib prefix=&#8221;s&#8221; uri=&#8221;/struts-tags&#8221; %&gt;
<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>&lt;<b>html</b>&gt;
<p>&lt;<b>head</b>&gt;
<p>&lt;<b>title</b>&gt;Struts 2 Cool Tags &#8211; OptionTransferSelect&lt;/<b>title</b>&gt;
<p>&lt;<b>s</b>:<b>head</b> theme=&#8221;ajax&#8221;/&gt;
<p>&lt;/<b>head</b>&gt;
<p>&lt;<b>body</b>&gt;
<p>&lt;<b>h2</b>&gt;用户角色授权&lt;/<b>h2</b>&gt;
<p>&lt;<b>s</b>:<b>form</b> action=&#8221;transferSelectPost&#8221; name=&#8221;form1&#8243; &gt;
<p>&lt;<b>s</b> <img src='http://www.yeeach.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> ptiontransferselect
<p>label=&#8221;测试-Action数据&#8221;
<p>name=&#8221;leftRoles&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; leftTitle=&#8221;用户已授权角色&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; list=&#8221;#request.leftList&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; listKey=&#8221;roleId&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; listValue=&#8221;roleName&#8221;
<p>multiple=&#8221;true&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; headerKey=&#8221;headerKey&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; headerValue=&#8221;&#8212; 请选择用户角色 &#8212;&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; emptyOption=&#8221;false&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; allowUpDownOnLeft=&#8221;false&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cssStyle=&#8221;width:200px;height:300px;&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rightTitle=&#8221;用户未授权的角色&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doubleList=&#8221;#request.rightList&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doubleListKey=&#8221;roleId&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doubleListValue=&#8221;roleName&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doubleName=&#8221;rightRoles&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doubleHeaderKey=&#8221;doubleHeaderKey&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doubleHeaderValue=&#8221;&#8212; 请选择用户角色 &#8212;&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doubleEmptyOption=&#8221;false&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doubleMultiple=&#8221;true&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; allowUpDownOnRight=&#8221;false&#8221;
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doubleCssStyle=&#8221;width:200px;height:300px;&#8221;
<p>/&gt;
<p>&lt;<b>s</b>:submit align=&#8221;left&#8221;/&gt;
<p>&lt;/<b>s</b>:<b>form</b>&gt;
<p>&lt;/<b>body</b>&gt;
<p>&lt;/<b>html</b>&gt;
<p><b>transferselectpost.jsp</b>
<p><b></b>
<p>&lt;%@ taglib prefix=&#8221;s&#8221; uri=&#8221;/struts-tags&#8221; %&gt;
<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>&lt;<b>html</b>&gt;
<p>&lt;<b>head</b>&gt;
<p>&lt;<b>title</b>&gt;Struts 2 Cool Tags &#8211; OptionTransferSelect&lt;/<b>title</b>&gt;
<p>&lt;<b>s</b>:<b>head</b> /&gt;
<p>&lt;/<b>head</b>&gt;
<p>&lt;<b>body</b>&gt;
<p>&lt;<b>h2</b>&gt;选择结果&lt;/<b>h2</b>&gt;
<p>&lt;<b>s</b>:<b>form</b> action=&#8221;transferSelect&#8221; name=&#8221;form1&#8243; &gt;
<p>&lt;<b>s</b>:iterator value=&#8221;#request.map&#8221; status=&#8221;mystatus&#8221;&gt;
<p>&lt;<b>tr</b>&gt;
<p>&lt;<b>td</b>&gt;
<p>&lt;<b>s</b>:property value=&#8221;key&#8221; /&gt;:&lt;<b>s</b>:property value=&#8221;value&#8221; /&gt;,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<p>&lt;/<b>td</b>&gt;
<p>&lt;/<b>tr</b>&gt;
<p>&lt;/<b>s</b>:iterator&gt;
<p>&lt;<b>s</b>:submit align=&#8221;left&#8221;/&gt;
<p>&lt;/<b>s</b>:<b>form</b>&gt;
<p>&lt;/<b>body</b>&gt;
<p>&lt;/<b>html</b>&gt;<br />
<h3><b>3. </b>struts.xml</h3>
<p>&lt;action name=&#8221;transferSelect&#8221; method=&#8221;transferSelect&#8221; class=&#8221;com.mobilesoft.esales.webapp.action.TransferSelect&#8221;&gt;
<p>&lt;result name=&#8221;success&#8221;&gt;test/transferselect.jsp&lt;/result&gt;
<p>&lt;/action&gt;
<p>&lt;action name=&#8221;transferSelectPost&#8221; method=&#8221;transferSelectPost&#8221; class=&#8221;com.mobilesoft.esales.webapp.action.TransferSelect&#8221;&gt;
<p>&lt;result name=&#8221;success&#8221;&gt;test/transferselectpost.jsp&lt;/result&gt;
<p>&lt;/action&gt;
<p>&nbsp;</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:00bf265e-d0af-4813-bf4d-3162e158f3c2" 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/optiontransferselect" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/optiontransferselect');" rel="tag">optiontransferselect</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></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/02/struts2-optiontransferselect%e6%a0%87%e7%ad%be%e4%bd%bf%e7%94%a8/" >Permalink</a> |
	  <a href="http://www.yeeach.com/2008/04/02/struts2-optiontransferselect%e6%a0%87%e7%ad%be%e4%bd%bf%e7%94%a8/#comments" >One comment</a></p>
	<p>Add to <a href="http://del.icio.us/post?url=http://www.yeeach.com/2008/04/02/struts2-optiontransferselect%e6%a0%87%e7%ad%be%e4%bd%bf%e7%94%a8/&amp;title=Struts2 OptionTransferSelect标签使用" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://del.icio.us/post?url=http://www.yeeach.com/2008/04/02/struts2-optiontransferselect%e6%a0%87%e7%ad%be%e4%bd%bf%e7%94%a8/&amp;title=Struts2 OptionTransferSelect标签使用');">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-optiontransferselect%e6%a0%87%e7%ad%be%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-optiontransferselect%e6%a0%87%e7%ad%be%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-optiontransferselect%e6%a0%87%e7%ad%be%e4%bd%bf%e7%94%a8/feed/</wfw:commentRss>
		<slash:comments>1</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>如何添加 WordPress 2.3 标签到你使用的主题</title>
		<link>http://www.yeeach.com/2007/10/06/%e5%a6%82%e4%bd%95%e6%b7%bb%e5%8a%a0-wordpress-23-%e6%a0%87%e7%ad%be%e5%88%b0%e4%bd%a0%e4%bd%bf%e7%94%a8%e7%9a%84%e4%b8%bb%e9%a2%98/</link>
		<comments>http://www.yeeach.com/2007/10/06/%e5%a6%82%e4%bd%95%e6%b7%bb%e5%8a%a0-wordpress-23-%e6%a0%87%e7%ad%be%e5%88%b0%e4%bd%a0%e4%bd%bf%e7%94%a8%e7%9a%84%e4%b8%bb%e9%a2%98/#comments</comments>
		<pubDate>Sat, 06 Oct 2007 07:21:49 +0000</pubDate>
		<dc:creator>chuan liang</dc:creator>
				<category><![CDATA[技术相关]]></category>
		<category><![CDATA[tags]]></category>
		<category><![CDATA[themes]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[标签]]></category>
		<category><![CDATA[主题]]></category>

		<guid isPermaLink="false">http://www.yeeach.com/2007/10/06/%e5%a6%82%e4%bd%95%e6%b7%bb%e5%8a%a0-wordpress-23-%e6%a0%87%e7%ad%be%e5%88%b0%e4%bd%a0%e4%bd%bf%e7%94%a8%e7%9a%84%e4%b8%bb%e9%a2%98/</guid>
		<description><![CDATA[http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme/ http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme-part-2/ http://wordpresschina.org/how-to-add-wordpress-23-tags-to-your-current-theme-9/ WordPress 2.3 应当于 9月 24日发布。很多博客已经想要尽快升级，因为新版本增加了一个非常有利于搜索引擎优化的工具：标签。虽然其它插件来支持标签，显然很多博客并不去用。我知道我就不用。【译者注：我也没用。】 Ultimate Tag Warrior 是目前为止最好的标签插件。我在家里的计算机上安装测试过。不幸的是，这个插件文件在一个压缩包内，看起来就不容易安装，因此很多人都不使用。UTW 也很难配置，有很多选项并没有解释清楚。这个插件有几十个选项要填写，不经过测试你根本不知道效果是什么样，因此我要选择一个标签，就花费了不止一个小时的时间。 WordPress 2.3 改变了这一切。有了内置的插件支持和插件云功能，再也不需要难以配置的插件。WordPress 提供两个简单的接口函数来供任何主题调用。经过这次升级，标签将很快传遍全世界。 不幸的是，这意味着如果你要在你的主题里使用这个功能，必须要进行更新。如果你通过 WordPress 主题站下载的主题，基本没有办法知道你使用的主题的作者是否曾升级。毕竟，到现在很多还有很多主题都不支持 Widget 呢，那可是很容易实现，也是对很多 WordPress 博客用户来说都是必须的功能。【译者注：潜台词，更何况刚刚加入的标签，不知道何年何月才能支持。】 如果你付费平直一个主题，那么在你的主题设计者对你的主题升级之前，你还要等多久呢？要花费你多少钱呢？你的主题设计者还在做这行的生意么？ 幸运的是，你可以自己更新你的主题 也不是什么难事。在你进行任何改变之前，我建议你复制一份你使用的主题文件。如果升级中出现任何错误，你无法找到错误的话，你可以删除主题，用你备份的文件来替代。只要备份 WordPress\WP-CONTENT\Theme\themename 目录即可。 【译者注：这里有个错误，目录位置应为 wordpress\wp-content\themes\themename 。另外，本文介绍的仅仅是主题的更新。在你升级 WordPress 2.3 之前，请务必进行全面备份！】 既然你阅读本文，我就假设你对于主题内部的工作并不熟悉。我将简单地介绍下 The Loop (循环)，然后解释如何将标签集成到你的主题里。 The Loop 是指你的博客里控制显示信息的 PHP 代码。如果你有兴趣看看纯粹的代码是让 WordPress 工作的话，我这里有一个完整的未加样式的 WordPress 主题 skeleton 。如果你打开 INDEX.PHP 文件，你就会看到 WordPress 使用 PHP [...]]]></description>
			<content:encoded><![CDATA[<p><a title="http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme/" href="http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme/');">http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme/</a></p>
<p><a title="http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme-part-2/" href="http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme-part-2/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme-part-2/');">http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme-part-2/</a></p>
<p><a title="http://wordpresschina.org/how-to-add-wordpress-23-tags-to-your-current-theme-9/" href="http://wordpresschina.org/how-to-add-wordpress-23-tags-to-your-current-theme-9/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://wordpresschina.org/how-to-add-wordpress-23-tags-to-your-current-theme-9/');">http://wordpresschina.org/how-to-add-wordpress-23-tags-to-your-current-theme-9/</a></p>
<p>WordPress 2.3 应当于 9月 24日发布。很多博客已经想要尽快升级，因为新版本增加了一个非常有利于搜索引擎优化的工具：标签。虽然其它插件来支持标签，显然很多博客并不去用。我知道我就不用。【译者注：我也没用。】
<p>Ultimate Tag Warrior 是目前为止最好的标签插件。我在家里的计算机上安装测试过。不幸的是，这个插件文件在一个压缩包内，看起来就不容易安装，因此很多人都不使用。UTW 也很难配置，有很多选项并没有解释清楚。这个插件有几十个选项要填写，不经过测试你根本不知道效果是什么样，因此我要选择一个标签，就花费了不止一个小时的时间。
<p>WordPress 2.3 改变了这一切。有了内置的插件支持和插件云功能，再也不需要难以配置的插件。WordPress 提供两个简单的接口函数来供任何主题调用。经过这次升级，标签将很快传遍全世界。
<p>不幸的是，这意味着如果你要在你的主题里使用这个功能，必须要进行更新。如果你通过 WordPress 主题站下载的主题，基本没有办法知道你使用的主题的作者是否曾升级。毕竟，到现在很多还有很多主题都不支持 Widget 呢，那可是很容易实现，也是对很多 WordPress 博客用户来说都是必须的功能。【译者注：潜台词，更何况刚刚加入的标签，不知道何年何月才能支持。】
<p>如果你付费平直一个主题，那么在你的主题设计者对你的主题升级之前，你还要等多久呢？要花费你多少钱呢？你的主题设计者还在做这行的生意么？<br />
<h5>幸运的是，你可以自己更新你的主题</h5>
<p>也不是什么难事。在你进行任何改变之前，我建议你复制一份你使用的主题文件。如果升级中出现任何错误，你无法找到错误的话，你可以删除主题，用你备份的文件来替代。只要备份 WordPress\WP-CONTENT\Theme\themename 目录即可。
<p>【译者注：这里有个错误，目录位置应为 wordpress\wp-content\themes\themename 。另外，本文介绍的仅仅是主题的更新。在你升级 WordPress 2.3 之前，请<a href="http://jiangzhanyong.com/2007/05/backup-you-blog-308.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://jiangzhanyong.com/2007/05/backup-you-blog-308.html');">务必进行全面备份</a>！】
<p>既然你阅读本文，我就假设你对于主题内部的工作并不熟悉。我将简单地介绍下 The Loop (循环)，然后解释如何将标签集成到你的主题里。
<p>The Loop 是指你的博客里控制显示信息的 PHP 代码。如果你有兴趣看看纯粹的代码是让 WordPress 工作的话，我这里有一个<a href="http://richgilchrest.com/images/WP-Theme-Skeleton.zip" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://richgilchrest.com/images/WP-Theme-Skeleton.zip');">完整的未加样式的 WordPress 主题 skeleton</a> 。如果你打开 INDEX.PHP 文件，你就会看到 WordPress 使用 PHP 命令来读取和显示信息，包括标题，作者，日期，和评论数目。主题的作者通过 The Loop 来设置布局，相关的样式信息，这样原本纯粹的信息显示就变成了华丽的、格式漂亮的博客页面，包括了颜色，图片和很好的设计结构。
<p>The Loop 代码看起来是这样的：
<ol>
<li>&lt;?php while( have_posts() ) : the_post(); ?&gt;
<li>&lt;div class=&#8221;post&#8221; id=&#8221;post-&lt;?php the_ID(); ?&gt;&#8221;&gt;
<li>&lt;h2&gt;&lt;a href=&#8221;&lt;?php the_permalink() ?&gt;&#8221; rel=&#8221;bookmark&#8221; title=&#8221;Permanent Link to &lt;?php the_title(); ?&gt;&#8221;&gt;
<li>&lt;?php the_title(); ?&gt;&lt;/a&gt;&lt;/h2&gt;
<li>&lt;?php the_category( &#8216;, &#8216; ); ?&gt; &lt;?php the_author(); ?&gt; &lt;?php the_time(&#8216;F jS, Y&#8217;); ?&gt;
<li>&lt;?php edit_post_link(&#8216;Edit&#8217;,&#8217; &#8216;,&#8221;); ?&gt; &lt;br/&gt; &lt;?php comments_popup_link(&#8216;No Comments&#8217;, &#8217;1 Comment&#8217;, &#8216;% Comments&#8217;); ?&gt;
<li>&lt;?php the_content(); ?&gt;
<li>&lt;/div&gt;
<li>&lt;?php endwhile; ?&gt;</li>
</ol>
<h5>添加标签只需要在 The Loop 内添加一行命令</h5>
<p>找到你的 \Wordpress\WP-CONTENT\Themes\themename 目录，你将看到这两个文件：
<p>INDEX.PHP
<p>SINGLE.PHP
<p>这个 INDEX 文件是 WordPress 主要页面。当有人访问你的博客主页的时候，这个页面被加载。这个文件调用 header（页眉），footer（页脚），和 sidebar（侧边拦）文件。它还包含 The Loop。这是我们要添加标签调用函数的地方。插入标签显示函数到你的文章只需要在 The Loop 内添加一个命令：
<ol>
<li>&lt;?php the_tags(‘before’, ’separator’, ‘after’); ?&gt;</li>
</ol>
<p>Before，Separator 和 After 分别用你希望在标签行里显示的文字代替。如果你想要在文章内容后面、“Pervious”链接前面显示标签，只要将上面这行代码复制到紧挨下面这行语句后面即可：
<ol>
<li>&lt;?php the_content(); ?&gt;</li>
</ol>
<p>你也可以将这句放到别的地方。在下面的截屏，我将命令添加到了评论后面。WordPress 的接口函数都有很容易理解的名字，因此你很容易就能理解每句代码。
<p>添加标签前：
<p><img alt="WordPress Tags" src="http://wordpresschina.org/images/w-20070926-taglesson1.png">
<p>添加标签后：
<p><img alt="WordPress Tags" src="http://wordpresschina.org/images/w-20070926-taglesson2.png">
<p>SINGLE.PHP （通常）是同 INDEX.PHP 文件是一样的，只不过它只显示特定文章，并不需要执行 Loop （循环）。除非你的主题对独立文章和主页使用不同的样式。因此，你也应该将标签放到 Single.php 完全相同的地方。只需找到和 INDEX.PHP 文件内相同的代码，将标签放上即可。<br />
<h5>标签云</h5>
<p>标签云功能也已添加（到 WordPress 2.3 中）。有些类似于 Flickr 风格，最流行的标签，显示的字体越大。标签云显示你的博客使用全部标签，而不是某篇文章使用的标签，因此，添加一个 Widget 或到页脚比放到 Loop（循环） 内更好。下面的例子仅仅为了示范，将标签云放在了一篇文章后面：
<p><img alt="WordPress Tags" src="http://wordpresschina.org/images/w-20070926-taglesson3.png">
<p>如果你想要创建一个包括标签云的侧边拦 Widget ，你要先安装 Executable PHP Widget 或类似功能的插件，允许你在 Widget 内运行 PHP 代码。插件激活之后，打开你的 Widget 菜单，添加一个 PHP 代码的 Widget。可以随便起个名字，然后再主窗口添加如下代码：
<ol>
<li>&lt;?php wp_tag_cloud(&#8216;smallest=8&amp;largest=36&amp;&#8217;); ?&gt;</li>
</ol>
<p>这个标签云将显示你的博客使用的全部标签，按照名字排序，使用最少的标签 8pt字体，使用最多的标签 36pt 的字体。<a href="http://codex.wordpress.org/Template_Tags/wp_tag_cloud" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://codex.wordpress.org/Template_Tags/wp_tag_cloud');">更多定义标签云的细节可以访问这里</a>。
<p>如果你想要在页脚添加标签云，你需要编辑 WordPress\WP-CONTENT\Themes\themename\FOOTER.PHP 。和 index 文件一样，你只需要添加代码到合适的位置即可。放在页脚的时候，比放在 index 内变化稍微多一些，因此我无法精确地告诉你放在什么地方。像前面所说，WordPress 的接口函数很容易理解，因此，想把代码放到什么地方，就放什么地方。如果放错了，你可以很容易地撤销、重新放置。
<p>一点也不难吧，是不是？我希望我已经帮你准备好使用 WordPress 2.3 这个很棒的功能。差不多所有的搜索引擎优化专家都推荐使用标签。标签添加到 WordPress 2.3 之后，不再只是之前那些使用插件的用户，每个用户都将从中受益。
<p>补充：<a href="http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme-part-2/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme-part-2/');">如何添加 WordPress 2.3 标签到你的主题第二部分</a>，回答了下面网友提出的一些问题。
<p>原文出处: <a href="http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme/');">http://richgilchrest.com/how-to-add-wordpress-23-tags-to-your-current-theme/</a>
<p>中文翻译: <a href="http://wordpresschina.org/how-to-add-wordpress-23-tags-to-your-current-theme-9/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://wordpresschina.org/how-to-add-wordpress-23-tags-to-your-current-theme-9/');">http://wordpresschina.org/how-to-add-wordpress-23-tags-to-your-current-theme-9/</a>
<p>&nbsp;</p>
<p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:1d8fd253-b0a5-4a06-bc9e-8b579136047b" style="padding-right: 0px; display: inline; padding-left: 0px; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati 标签:  		<a href="http://technorati.com/tags/wordpress/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/wordpress/');" rel="tag">wordpress</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/%e4%b8%bb%e9%a2%98/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/%e4%b8%bb%e9%a2%98/');" rel="tag">主题</a> 		,  		<a href="http://technorati.com/tags/themes/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/themes/');" rel="tag">themes</a> 		,  		<a href="http://technorati.com/tags/tags/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://technorati.com/tags/tags/');" rel="tag">tags</a> 		</div></p>
	<p></p>
	<hr noshade style="margin:0;height:1px" />
	<p>&copy; chuan liang for <a href="http://www.yeeach.com" >出家如初，成佛有余</a>, 2007. |
	  <a href="http://www.yeeach.com/2007/10/06/%e5%a6%82%e4%bd%95%e6%b7%bb%e5%8a%a0-wordpress-23-%e6%a0%87%e7%ad%be%e5%88%b0%e4%bd%a0%e4%bd%bf%e7%94%a8%e7%9a%84%e4%b8%bb%e9%a2%98/" >Permalink</a> |
	  <a href="http://www.yeeach.com/2007/10/06/%e5%a6%82%e4%bd%95%e6%b7%bb%e5%8a%a0-wordpress-23-%e6%a0%87%e7%ad%be%e5%88%b0%e4%bd%a0%e4%bd%bf%e7%94%a8%e7%9a%84%e4%b8%bb%e9%a2%98/#comments" >No comment</a></p>
	<p>Add to <a href="http://del.icio.us/post?url=http://www.yeeach.com/2007/10/06/%e5%a6%82%e4%bd%95%e6%b7%bb%e5%8a%a0-wordpress-23-%e6%a0%87%e7%ad%be%e5%88%b0%e4%bd%a0%e4%bd%bf%e7%94%a8%e7%9a%84%e4%b8%bb%e9%a2%98/&amp;title=如何添加 WordPress 2.3 标签到你使用的主题" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://del.icio.us/post?url=http://www.yeeach.com/2007/10/06/%e5%a6%82%e4%bd%95%e6%b7%bb%e5%8a%a0-wordpress-23-%e6%a0%87%e7%ad%be%e5%88%b0%e4%bd%a0%e4%bd%bf%e7%94%a8%e7%9a%84%e4%b8%bb%e9%a2%98/&amp;title=如何添加 WordPress 2.3 标签到你使用的主题');">del.icio.us</a></p>
	<p>Search blogs linking this post with <a href="http://www.technorati.com/search/http://www.yeeach.com/2007/10/06/%e5%a6%82%e4%bd%95%e6%b7%bb%e5%8a%a0-wordpress-23-%e6%a0%87%e7%ad%be%e5%88%b0%e4%bd%a0%e4%bd%bf%e7%94%a8%e7%9a%84%e4%b8%bb%e9%a2%98/" onclick="javascript:pageTracker._trackPageview('/outbound/article/http://www.technorati.com/search/http://www.yeeach.com/2007/10/06/%e5%a6%82%e4%bd%95%e6%b7%bb%e5%8a%a0-wordpress-23-%e6%a0%87%e7%ad%be%e5%88%b0%e4%bd%a0%e4%bd%bf%e7%94%a8%e7%9a%84%e4%b8%bb%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/2007/10/06/%e5%a6%82%e4%bd%95%e6%b7%bb%e5%8a%a0-wordpress-23-%e6%a0%87%e7%ad%be%e5%88%b0%e4%bd%a0%e4%bd%bf%e7%94%a8%e7%9a%84%e4%b8%bb%e9%a2%98/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
