微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Struts2、Spring、Hibernate整合ExtJS

SSHExtTree

百度文库提供下载:

开标题就知道是Struts、Spring、Hibernate、ExtJS的Tree实例文档,其中包括Filter功能的checkNodeTree、comboBoxCheckNodeTree、comboBoxTree这三种扩展的tree。不错,如果你不了解Struts、Spring、Hibernate、ExtJS,也不要紧。跟着我做,做出这个例子应该木有问题。

生产环境:

System:Windows

WebBrowser:IE6+、Firefox3+

JavaEE Server:tomcat5.0.2.8、tomcat6

IDE:eclipse、MyEclipse6.1+

Database:Ms SQLServer2000、2005

开发依赖库版本:

ExtJS:lib 2.1

Struts: 2.1.4

Hibernate:3.2

Spring:2.0

Email:

Blog:

如果你具备上面的环境后,下面就可以跟着我一步步的完成这个SSHExtTree的示例。

1、 添加Hibernate支持,这里我用MyEclipse的工具直接添加jar包链接数据库配置文件,这一步如果你熟悉可以跳过。

A、 首先你选择你的MyEclipse中的MyEclipse Database Explorer这个视图

clip_image001

B、 进入视图后,点击new

clip_image002

C、 进入new视图后,你就可以添加你的DB的链接数据库的种类、端口、地址、数据库名称

clip_image003

我上面选择的是Mssql2005

Connect URL:jdbc:jtds:sqlserver://localhost:1433/jc2009_gdszz

jc2009_gdszz是数据库名称,是建科院的数据库

用户名密码就是你链接数据库密码

注意的是你还要添加你的链接数据库的driver,我这里用jdts驱动

上面的完成后,你可以点击Test Driver就可以测试你的链接对不对。如果对的话就会出现上面的successfully!

D、 继续Next你可以选择第三个单选按钮,就是下面的1。然后点击Add按钮选择你的数据库。这样后面链接数据库的时候就不会出现其他的数据库了;点击Finish

clip_image004

E、 下面开始链接数据库

clip_image005

上面的sql_2005就是我们刚才建的数据库链接了。右键sql_2005,然后点击Open connection,就可以链接到你的数据库

F、 然后展开数据库,选择dbo展开,选择table。你就看到你的数据库中的表了

clip_image006

至此数据链接创建成功,下面我们添加Hibernate的支持

G、 下面切换到MyEclipse JavaEE视图,如果你喜欢Java视图也可以。这里用MyEclipse JavaEE视图。

clip_image007

然后右键点击你建好的SSHExtTree这个WebProject

clip_image009

选择MyEclipse,选择Add Hibernate

H、进入添加Hibernate支持的视图后,选择Hibernate3.2;然后记得选择添加jar包到你的工程lib中

clip_image010

I、 继续Next,选择New。我喜欢单独的Hibernate配置文件,如果你不喜欢你可以在Spring中添加配置。

clip_image011

J、 点击Next,进入选择数据库链接的视图,当然是选择我们刚才创建的sql_2005这个视图了。

clip_image012

记得选择你的数据库方言,数据库方言对于不同的数据库是不同的。

K、 点击Next你就可以看到创建SessionFactory,我们用Spring就不要这个了。点击Finish;就可以看到配置文件hibernate.cfg.xml

我们还得添加2条:

sql">true

sql">true

这个在调试程序的时候有用,可以格式化输入sql语句

综上所述,上面的主要完成的就是添加Hibernate的jar包数据库链接配置文件。你也可以手动添加Hibernate的数据库配置文件jar包。那样就不需要上面的步骤。

2、 下面我们添加Spring的支持,请跟着我做

A、 右键SSHExtTree项目,选择MyEclipse然后选择Add Spring

clip_image014

B、 点击后你可以看到Spring的支持了,Spring选择2.0的版本。然后就是选择你要的jar包

clip_image015

C、 我们选择完后,继续下一步Next

clip_image016

D、 继续下一步Next

clip_image017

上面的SessionFactory Bean id就是你的applicationContext.xml这个文件中的SessionFactory的bean的id。在后面我们需要为其他使用Hibernate模版的文件件注入sessionFactory。至此Spring的支持添加完毕,现在我们需要配置Spring的Aop管理我们的事务。

E、 首先修改applicationContext.xml为applicationContext-common.xml,然后我们添加aop、tx的命名空间。你也可以手动添加,如果你不记得Sping的aop、tx的命名空间,请跟着我做。

F、 右键我们的Project,选择New然后选择xml basic template

clip_image019

G、 进入页面后,直接next。选择第二项

clip_image020

H、进入后,看下面的选择schema文件

clip_image021

先选择aop2.0,点击next

I、 进入视图后你可以看到

clip_image022

选择p,点击Edit 也就是1处。然后将改成aop。然后点击Add

J、 进入视图后,你就可以继续选择tx这个命名空间的schame

clip_image023

K、 点击ok后,你可以选择刚才的tx。然后点击edit。为它添加xsd

clip_image024

将ns name复制粘贴到Location Hint中,然后在后面添加/spring-tx-2.0.xsd

完了后,点击Finish。

然后copy里面的内容到刚才的applicationContext-common.xml中,内容如下:

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="http://www.springframework.org/schema/aop

http://www.springframework.org/schema/aop/spring-aop-2.0.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-2.0.xsd ">

刚才这么多步骤就是要这些文件内容

最后common文件的的头部就是这样的内容

display='none'; document.getElementById('Code_Closed_Text_69495').style.display='none'; document.getElementById('Code_Open_Image_69495').style.display='inline'; document.getElementById('Code_Open_Text_69495').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_69495" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_69495').style.display='none'; getElementById('Code_Closed_Image_69495').style.display='inline'; getElementById('Code_Closed_Text_69495').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_69495"> = := := := :=spring-beans-2.0.xsd"

L、 下面配置事务的传播特性

Hibernate的事务管理机制

display='none'; document.getElementById('Code_Closed_Text_21081').style.display='none'; document.getElementById('Code_Open_Image_21081').style.display='inline'; document.getElementById('Code_Open_Text_21081').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_21081" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_21081').style.display='none'; getElementById('Code_Closed_Image_21081').style.display='inline'; getElementById('Code_Closed_Text_21081').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_21081"> = = = =

上面的配置注入了sessionFactory,property中的name是HibernateTransactionManager中的setSessionFactory这个setter方法,后面的ref是上面的bean的引用。

事务的传播特性

display='none'; document.getElementById('Code_Closed_Text_725834').style.display='none'; document.getElementById('Code_Open_Image_725834').style.display='inline'; document.getElementById('Code_Open_Text_725834').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_725834" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_725834').style.display='none'; getElementById('Code_Closed_Image_725834').style.display='inline'; getElementById('Code_Closed_Text_725834').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_725834"> : = -= : : = =required" : = =required" : = =required" : = =required" : = -= : :

配置哪些方法参与事务的管理,add*代码addXXX开头的方法,后面的propagation是事务的传播特性、级别,最后的*代表所有方法,对于查询方法read-only只读就可以了。查询不需要参与事务。

配置在哪里启用事务,哪些包或类、方法参与事务管理:

display='none'; document.getElementById('Code_Closed_Text_858858').style.display='none'; document.getElementById('Code_Open_Image_858858').style.display='inline'; document.getElementById('Code_Open_Text_858858').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_858858" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_858858').style.display='none'; getElementById('Code_Closed_Image_858858').style.display='inline'; getElementById('Code_Closed_Text_858858').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_858858"> :fig :pointcut = = : -= pointcut-= :fig

上面的pointcut称作切面,expression是表达式(关于表达式更多内容可以参考spring官方文档)

execution(* com.hhh.biz.impl.*.*(..))前面的execution是固定的,括号里面的内容

一个*代表任意返回值,com.hhh.biz.impl代表包。在这一层的包被纳入到事务的管理,impl.*代表impl下面的所有的class,impl.*.*代表class中所有方法,impl.*.*(..)代表的是方法的任意个参数。这个表达的是事务管理到com.hhh.biz.impl下所有类的方法的任意返回值、任意参数

advice-ref是上面配置的事务的传播特性,pointcut-ref是上面的切面配置至此关键的配置就完毕了。

综上所述,上面的主要是完成用IDE添加Spring的jar包配置文件,如果你不想用上面的方式,也可以手动添加jar包。然后将xml配置文件的的头部、命名空间等信息贴到建好的xml中也是可行的。

3、 下面我们将手动添加Struts2.x的jar和配置Struts2.x的运行环境

A、 你需要添加以下jar包

commons-logging-api-1[1].1.1.jar

freemarker-2[1].3.10.jar

ognl-2[1].6.11.jar

struts2-core-2.0.11.jar

xwork-2[1].0.2.jar

由于和Spring整合,这里还有添加strtus和spring的插件包struts2-spring-plugin-2.0.14.jar

B、 下面开始配置struts的核心控制器

在web.xml中添加如下配置:

display='none'; document.getElementById('Code_Closed_Text_87579').style.display='none'; document.getElementById('Code_Open_Image_87579').style.display='inline'; document.getElementById('Code_Open_Text_87579').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_87579" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_87579').style.display='none'; getElementById('Code_Closed_Image_87579').style.display='inline'; getElementById('Code_Closed_Text_87579').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_87579"> -struts2-name -org.apache.struts2.dispatcher.Filterdispatcher-class - -struts2-name -/*-pattern -mapping

这样struts2的web.xml配置就完成了

C、 下面开始添加struts的Action配置文件,这个文件名称就是struts.xml。不要随便更改,这个是认的名称。如果你想用其他的名称,请在web.xml中的核心控制器中配置param参数设置配置文件名称

内容如下:

display='none'; document.getElementById('Code_Closed_Text_452619').style.display='none'; document.getElementById('Code_Open_Image_452619').style.display='inline'; document.getElementById('Code_Open_Text_452619').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_452619" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_452619').style.display='none'; getElementById('Code_Closed_Image_452619').style.display='inline'; getElementById('Code_Closed_Text_452619').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_452619">xml version="1.0" encoding="UTF-8" !DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"

这样struts的配置就完成了

4、 整合ssh框架,首先还是web.xml配置。

Spring提供了编码过滤器,我们在web.xml添加编码过滤器的配置。

display='none'; document.getElementById('Code_Closed_Text_381961').style.display='none'; document.getElementById('Code_Open_Image_381961').style.display='inline'; document.getElementById('Code_Open_Text_381961').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_381961" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_381961').style.display='none'; getElementById('Code_Closed_Image_381961').style.display='inline'; getElementById('Code_Closed_Text_381961').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码 display: none" id="Code_Open_Text_381961"> -characterEncodingFilter-name -org.springframework.web.filter.CharacterEncodingFilter-class -aram aram-encodingaram-name aram-UTF-8aram-value -param - -characterEncodingFilter-name -/*-pattern -mapping

配置加载Spring配置的路径

display='none'; document.getElementById('Code_Closed_Text_125305').style.display='none'; document.getElementById('Code_Open_Image_125305').style.display='inline'; document.getElementById('Code_Open_Text_125305').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_125305" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_125305').style.display='none'; getElementById('Code_Closed_Image_125305').style.display='inline'; getElementById('Code_Closed_Text_125305').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_125305">-aram aram-contextConfigLocationaram-name aram-classpath*:applicationContext-*.xmlaram-value -param

配置加载Spring上下文的的监听器

display='none'; document.getElementById('Code_Closed_Text_102698').style.display='none'; document.getElementById('Code_Open_Image_102698').style.display='inline'; document.getElementById('Code_Open_Text_102698').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_102698" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_102698').style.display='none'; getElementById('Code_Closed_Image_102698').style.display='inline'; getElementById('Code_Closed_Text_102698').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_102698"> >org.springframework.web.context.ContextLoaderListener>

至此配置基本完成,下面发布到tomcat中。看看是否有误错误,没有错误请求index.jsp看看。成功了就继续;

请求发现出现了java.lang.classNotFoundException: org.springframework.web.context.ContextLoaderListener这个异常信息,发现在添加jar包的时候没有把spring-web这个选中。那就手动添加spring-web.jar

这个jar包就ok了。启动发现没有错误,范围index.jsp也成功了。

5、 下面通过用MyEclipse Database Explorer生成JavaBeans、hbm.xml配置文件

我们这里写Tree,只需用一张Tree的表就可以了。

首先看下这张表的结构,代码如下:

clip_image025

NodeId是主键,PID引用NodeID,PID是应用的父节点。也就是说当前数据的PID指向的数据的id就是它的父元素。

假如要查NodeID=1的子元素,那就差些PID=1的就是它的子元素的。

A、右键击sort表格,选择reverse

clip_image026

这里就选sort这个表,然后右键。选择Hibernate Reverse Engineering就可以生产JavaBeans、hbm.xml映射文件了。

B、选择browser,选择package

clip_image028

C、选择create POJO DB<->Table,然后点击Finish

clip_image029

文件生成

clip_image030

6、 编写ExtJS的Tree需要的树形结构的JavaBeans和完成Tree数据查询接口和实现代码

Tree JavaBeans

display='none'; document.getElementById('Code_Closed_Text_232069').style.display='none'; document.getElementById('Code_Open_Image_232069').style.display='inline'; document.getElementById('Code_Open_Text_232069').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_232069" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_232069').style.display='none'; getElementById('Code_Closed_Image_232069').style.display='inline'; getElementById('Code_Closed_Text_232069').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_232069"> Tree { String id; String text; leaf; Integer nodelevel; String nodeId; String pid; List children = ArrayList();
<span style="color: #008000"&gt;//setter/getter</span>

<span style="color: #0000ff"&gt;public</span> Tree(){
}

<span style="color: #0000ff"&gt;public</span> Tree(String text,String id,String nodeId,String pid,Integer nodelevel) {
    <span style="color: #0000ff"&gt;this</span>.id = id;
    <span style="color: #0000ff"&gt;this</span>.text = text;
    <span style="color: #0000ff"&gt;this</span>.pid = pid;
    <span style="color: #0000ff"&gt;this</span>.nodeId = nodeId;
    <span style="color: #0000ff"&gt;this</span>.nodelevel = nodelevel;
    <span style="color: #0000ff"&gt;if</span> (nodelevel < 3) {
        <span style="color: #0000ff"&gt;this</span>.leaf = <span style="color: #0000ff"&gt;false</span>;
    } <span style="color: #0000ff"&gt;else</span> {
        <span style="color: #0000ff"&gt;this</span>.leaf = <span style="color: #0000ff"&gt;true</span>;
    }
}</span></pre></div>

上面的text、leaf、children三个元素是ExtJS的Tree的固定属性。如果不按照这个格式创建JavaBeans,那么Tree将不能顺利加载。

BaseDao接口

display='none'; document.getElementById('Code_Closed_Text_184847').style.display='none'; document.getElementById('Code_Open_Image_184847').style.display='inline'; document.getElementById('Code_Open_Text_184847').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_184847" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_184847').style.display='none'; getElementById('Code_Closed_Image_184847').style.display='inline'; getElementById('Code_Closed_Text_184847').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_184847"> BaseDao { 查询 * @createDate Dec 25,2010 6:19:22 PM * @param hql * @return * @throws Exception */ List getList(String hql) Exception; }

BaseDaoImpl上面接口的实现也很简单,就是继承HibernateDaoSupport完成查询

display='none'; document.getElementById('Code_Closed_Text_337715').style.display='none'; document.getElementById('Code_Open_Image_337715').style.display='inline'; document.getElementById('Code_Open_Text_337715').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_337715" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_337715').style.display='none'; getElementById('Code_Closed_Image_337715').style.display='inline'; getElementById('Code_Closed_Text_337715').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_337715"> function: 通过hql语句查询List集合 * @createDate 2010-8-2 下午05:51:05 * @param hql 查询hql语句 * @return List * @throws Exception */ @SuppressWarnings("") List getList(String hql) Exception { List list = ; { list = (List) .getHibernateTemplate().find(hql); } (Exception e) { RuntimeException(e); } list; }

编写TreeDao接口

display='none'; document.getElementById('Code_Closed_Text_331884').style.display='none'; document.getElementById('Code_Open_Image_331884').style.display='inline'; document.getElementById('Code_Open_Text_331884').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_331884" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_331884').style.display='none'; getElementById('Code_Closed_Image_331884').style.display='inline'; getElementById('Code_Closed_Text_331884').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_331884"> TreeDao { List getTreeListByParentId(T entity) Exception; }

TreeDaoImpl上面接口实现

display='none'; document.getElementById('Code_Closed_Text_799498').style.display='none'; document.getElementById('Code_Open_Image_799498').style.display='inline'; document.getElementById('Code_Open_Text_799498').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_799498" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_799498').style.display='none'; getElementById('Code_Closed_Image_799498').style.display='inline'; getElementById('Code_Closed_Text_799498').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_799498"> TreeDaoImpl Tree> TreeDao {
<span style="color: #0000ff"&gt;private</span> BaseDao<T> dao;

<span style="color: #0000ff"&gt;public</span> <span style="color: #0000ff"&gt;void</span> setDao(BaseDao<T> dao) {
    <span style="color: #0000ff"&gt;this</span>.dao = dao;
}

<span style="color: #0000ff"&gt;public</span> List<T> getTreeListByParentId(T entity) <span style="color: #0000ff"&gt;throws</span> Exception {
    String hql = "<span style="color: #8b0000"&gt;select new com.hhh.entity.Tree(categoryname,id,nodeId,pid,nodelevel) from SsSort where isshow = 1</span>";
    <span style="color: #0000ff"&gt;if</span> (entity == <span style="color: #0000ff"&gt;null</span> || entity.getNodeId() == <span style="color: #0000ff"&gt;null</span> || "<span style="color: #8b0000"&gt;</span>".equals(entity.getNodeId())) {
        hql += "<span style="color: #8b0000"&gt; and pid is null</span>";
    } <span style="color: #0000ff"&gt;else</span> {
        hql += "<span style="color: #8b0000"&gt; and pid = '</span>" + entity.getNodeId() + "<span style="color: #8b0000"&gt;'</span>";
    }
    <span style="color: #0000ff"&gt;return</span> dao.getList(hql);
}

}

上面的hql查询语句是将SsSort(Ss_sort table)这个对象的查询到的数据封装在Tree这个对象中。

现在看看服务层biz接口和实现

display='none'; document.getElementById('Code_Closed_Text_109460').style.display='none'; document.getElementById('Code_Open_Image_109460').style.display='inline'; document.getElementById('Code_Open_Text_109460').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_109460" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_109460').style.display='none'; getElementById('Code_Closed_Image_109460').style.display='inline'; getElementById('Code_Closed_Text_109460').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_109460"> TreeBiz Tree> {
<span style="color: #008000"&gt;/**
 * 通过sort对象去<a href="/tag/chaxun/" target="_blank" class="keywords">查询</a>子结点list
 * @createDate 2010-8-10 下午02:51:55
 * @p<a href="/tag/ara/" target="_blank" class="keywords">ara</a>m <T> 操作对象类型
 * @p<a href="/tag/ara/" target="_blank" class="keywords">ara</a>m entity <a href="/tag/chaxun/" target="_blank" class="keywords">查询</a>数据封装条件
 * @return 返回sort对象所有的list集合
 * @throws Exception
 */</span>
<span style="color: #0000ff"&gt;public</span> List<T> getTreeListByParentId(T entity) <span style="color: #0000ff"&gt;throws</span> Exception;

<span style="color: #008000"&gt;/**
 * 通过entity对象<a href="/tag/chaxun/" target="_blank" class="keywords">查询</a>子对象进行递归变量查找
 * @createDate 2010-8-11 下午01:04:02
 * @p<a href="/tag/ara/" target="_blank" class="keywords">ara</a>m <T> <a href="/tag/chaxun/" target="_blank" class="keywords">查询</a>对象类型
 * @p<a href="/tag/ara/" target="_blank" class="keywords">ara</a>m entity <a href="/tag/chaxun/" target="_blank" class="keywords">查询</a>对象
 * @throws Exception
 */</span>
<span style="color: #0000ff"&gt;public</span> <span style="color: #0000ff"&gt;void</span> getTreeByParentId2Recursion(T entity) <span style="color: #0000ff"&gt;throws</span> Exception;

}

看看实现的代码

display='none'; document.getElementById('Code_Closed_Text_254120').style.display='none'; document.getElementById('Code_Open_Image_254120').style.display='inline'; document.getElementById('Code_Open_Text_254120').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_254120" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_254120').style.display='none'; getElementById('Code_Closed_Image_254120').style.display='inline'; getElementById('Code_Closed_Text_254120').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_254120"> com.hhh.biz.impl;

<span style="color: #0000ff">import java.util.List;
<span style="color: #0000ff">import com.hhh.biz.TreeBiz;
<span style="color: #0000ff">import com.hhh.dao.TreeDao;
<span style="color: #0000ff">import com.hhh.entity.Tree;

<span style="color: #0000ff">public <span style="color: #0000ff">class TreeBizImpl<T <span style="color: #0000ff">extends Tree> <span style="color: #0000ff">implements TreeBiz {
<span style="color: #0000ff">private TreeDao dao;

<span style="color: #0000ff"&gt;public</span> <span style="color: #0000ff"&gt;void</span> setDao(TreeDao<T> dao) {
    <span style="color: #0000ff"&gt;this</span>.dao = dao;
}

<span style="color: #0000ff"&gt;public</span> List<T> getTreeListByParentId(T entity) <span style="color: #0000ff"&gt;throws</span> Exception {
    <span style="color: #0000ff"&gt;return</span> dao.getTreeListByParentId(entity);
}

<span style="color: #008000"&gt;/**
 * @see com.hhh.biz.TreeBiz#getTreeByParentId2Recursion(com.hhh.entity.Tree)
 * 这是<a href="/tag/yige/" target="_blank" class="keywords">一个</a>递归<a href="/tag/chaxun/" target="_blank" class="keywords">查询</a>,如果你一下看不明白递归的<a href="/tag/daima/" target="_blank" class="keywords">代码</a>,可以参考getSortByParentI<a href="/tag/d2l/" target="_blank" class="keywords">d2l</a>eaf<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>
 * 然后将循环中相同的<a href="/tag/daima/" target="_blank" class="keywords">代码</a>改造成递归即可
 * @createDate Dec 25,2010 7:07:26 PM
 */</span>
@SuppressWarnings("<span style="color: #8b0000"&gt;unchecked</span>")
<span style="color: #0000ff"&gt;public</span> <span style="color: #0000ff"&gt;void</span> getTreeByParentId2Recursion(T entity) <span style="color: #0000ff"&gt;throws</span> Exception {
    List<T> child =  dao.getTreeListByParentId(entity);
    <span style="color: #0000ff"&gt;if</span> (child.size() > 0) {
        <span style="color: #0000ff"&gt;for</span> (T s : child) {
            <span style="color: #0000ff"&gt;this</span>.getTreeByParentId2Recursion(s);
        }
        entity.setChildren((List<Tree>)child);
    } <span style="color: #0000ff"&gt;else</span> {
        entity.setLeaf(<span style="color: #0000ff"&gt;true</span>);
    }
}

<span style="color: #0000ff"&gt;public</span> <span style="color: #0000ff"&gt;void</span> getTreeByParentI<a href="/tag/d2l/" target="_blank" class="keywords">d2l</a>eaf(T entity) <span style="color: #0000ff"&gt;throws</span> Exception {
    List<T> child =  dao.getTreeListByParentId(entity);
    <span style="color: #0000ff"&gt;if</span> (child.size() > 0) {
        <span style="color: #0000ff"&gt;for</span> (T s : child) {
            List<T> child2 = dao.getTreeListByParentId(s);
            <span style="color: #0000ff"&gt;if</span> (child2.size() > 0) {
                <span style="color: #0000ff"&gt;for</span> (T s2 : child2) {
                    List<T> child3 = dao.getTreeListByParentId(s2);
                    <span style="color: #0000ff"&gt;if</span> (child3.size() > 0) {
                        <span style="color: #0000ff"&gt;for</span> (T s3 : child3) {
                            List<T> child4 = dao.getTreeListByParentId(s3);
                            <span style="color: #0000ff"&gt;if</span> (child4.size() == 0) {
                                s3.setLeaf(<span style="color: #0000ff"&gt;true</span>);
                            } <span style="color: #0000ff"&gt;else</span> {
                                s3.setLeaf(<span style="color: #0000ff"&gt;false</span>);
                            }
                            s2.getChildren().add(s3);
                        }
                    } <span style="color: #0000ff"&gt;else</span> {
                        s2.setLeaf(<span style="color: #0000ff"&gt;true</span>);
                    }
                    s.getChildren().add(s2);
                }
            } <span style="color: #0000ff"&gt;else</span> {
                s.setLeaf(<span style="color: #0000ff"&gt;true</span>);
            }
            entity.getChildren().add(s);
        }
    } <span style="color: #0000ff"&gt;else</span> {
        entity.setLeaf(<span style="color: #0000ff"&gt;true</span>);
    }
}

}

上的查询getTreeByParentId2Recursion用到了递归方法,如果你对递归的代码不是很明白就看看下面的查询getTreeByParentId2leaf代码

7、 下面编写Action代码,action中需要用到json-lib这个jar包,这个jar的主要作用就是将Java对象序列化成json格式的字符串对象。

需要添加如下jar包

ezmorph-1.0.3.jar

json-lib-2.3-jdk15.jar

commons-lang.jar

commons-collections-3.2.jar

commons-beanutils.jar

display='none'; document.getElementById('Code_Closed_Text_382856').style.display='none'; document.getElementById('Code_Open_Image_382856').style.display='inline'; document.getElementById('Code_Open_Text_382856').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_382856" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_382856').style.display='none'; getElementById('Code_Closed_Image_382856').style.display='inline'; getElementById('Code_Closed_Text_382856').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_382856">public class TreeAction extends ActionSupport {
private static final long serialVersionUID = -3795544890686836966L;

private TreeBiz<span style="color: #0000ff"&gt;<</span><span style="color: #800000"&gt;Tree</span><span style="color: #0000ff"&gt;></span> biz;
private String data;
private Tree tree = new Tree();

public void setBiz(TreeBiz<span style="color: #0000ff"&gt;<</span><span style="color: #800000"&gt;Tree</span><span style="color: #0000ff"&gt;></span> biz) {
    this.biz = biz;
}

@Override
public String execute() throws Exception {
    biz.getTreeByParentId2Recursion(tree);
    data = JSONArray.fromObject(tree.getChildren()).toString();
    return SUCCESS;
}

}

上面的代码很简单,看看action中的execute代码。JSONArray.fromObject这个主要就是将一个数值序列化成json的字符串。

看看xml配置文件的配置:

display='none'; document.getElementById('Code_Closed_Text_532615').style.display='none'; document.getElementById('Code_Open_Image_532615').style.display='inline'; document.getElementById('Code_Open_Text_532615').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_532615" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_532615').style.display='none'; getElementById('Code_Closed_Image_532615').style.display='inline'; getElementById('Code_Closed_Text_532615').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_532615"> = = = = = = /data.jsp

首先看看struts配置文件中的constant元素,它是设置struts的国际化编码的,然后就是package这个包,它相当于java类在package是区分配置的空间,其实package还有一个属性就是namespace命名空间。后面的extends是继承struts-default的认配置。

action就是配置的class Action的配置,上面的Action就通过这里的配置。name就是我们访问action的路径,class就是Action的classpath。这里用了spring的继承,所有class和spring配置的bean的id或name对应的。result是Action跳转的视图配置。

Spring的beans的配置:

display='none'; document.getElementById('Code_Closed_Text_975674').style.display='none'; document.getElementById('Code_Open_Image_975674').style.display='inline'; document.getElementById('Code_Open_Text_975674').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_975674" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_975674').style.display='none'; getElementById('Code_Closed_Image_975674').style.display='inline'; getElementById('Code_Closed_Text_975674').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_975674"> = := :=spring-beans-2.0.xsd"
<span style="color: #0000ff"&gt;<</span><span style="color: #800000"&gt;bean</span> <span style="color: #ff0000"&gt;id</span>=<span style="color: #0000ff"&gt;"baseDao"</span> <span style="color: #ff0000"&gt;class</span>=<span style="color: #0000ff"&gt;"com.hhh.dao.impl.BaseDaoImpl"</span><span style="color: #0000ff"&gt;></span>
    <span style="color: #0000ff"&gt;<</span><span style="color: #800000"&gt;property</span> <span style="color: #ff0000"&gt;name</span>=<span style="color: #0000ff"&gt;"sessionFactory"</span> <span style="color: #ff0000"&gt;ref</span>=<span style="color: #0000ff"&gt;"sessionFactory"</span><span style="color: #0000ff"&gt;/></span>
<span style="color: #0000ff"&gt;</</span><span style="color: #800000"&gt;bean</span><span style="color: #0000ff"&gt;></span>

<span style="color: #0000ff"&gt;<</span><span style="color: #800000"&gt;bean</span> <span style="color: #ff0000"&gt;id</span>=<span style="color: #0000ff"&gt;"treeDao"</span> <span style="color: #ff0000"&gt;class</span>=<span style="color: #0000ff"&gt;"com.hhh.dao.impl.TreeDaoImpl"</span><span style="color: #0000ff"&gt;></span>
    <span style="color: #0000ff"&gt;<</span><span style="color: #800000"&gt;property</span> <span style="color: #ff0000"&gt;name</span>=<span style="color: #0000ff"&gt;"dao"</span> <span style="color: #ff0000"&gt;ref</span>=<span style="color: #0000ff"&gt;"baseDao"</span><span style="color: #0000ff"&gt;/></span>
<span style="color: #0000ff"&gt;</</span><span style="color: #800000"&gt;bean</span><span style="color: #0000ff"&gt;></span>

<span style="color: #0000ff"&gt;<</span><span style="color: #800000"&gt;bean</span> <span style="color: #ff0000"&gt;id</span>=<span style="color: #0000ff"&gt;"treeBiz"</span> <span style="color: #ff0000"&gt;class</span>=<span style="color: #0000ff"&gt;"com.hhh.biz.impl.TreeBizImpl"</span><span style="color: #0000ff"&gt;></span>
    <span style="color: #0000ff"&gt;<</span><span style="color: #800000"&gt;property</span> <span style="color: #ff0000"&gt;name</span>=<span style="color: #0000ff"&gt;"dao"</span> <span style="color: #ff0000"&gt;ref</span>=<span style="color: #0000ff"&gt;"treeDao"</span><span style="color: #0000ff"&gt;/></span>
<span style="color: #0000ff"&gt;</</span><span style="color: #800000"&gt;bean</span><span style="color: #0000ff"&gt;></span>

<span style="color: #0000ff"></<span style="color: #800000">beans<span style="color: #0000ff">>

Spring的action的配置:

display='none'; document.getElementById('Code_Closed_Text_93113').style.display='none'; document.getElementById('Code_Open_Image_93113').style.display='inline'; document.getElementById('Code_Open_Text_93113').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_93113" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_93113').style.display='none'; getElementById('Code_Closed_Image_93113').style.display='inline'; getElementById('Code_Closed_Text_93113').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_93113">" xmlns:xsi="" xsi:schemaLocation=" http:spring-beans-2.0.xsd"> " =""> ="" ref=""/>

这里是id=treeAction就是和上面struts配置文件中的action配置的class对应的。

这里这样配置能够起作用是struts2-spring-plugin-2.0.14.jar这个jar包

8、 发布启动当前工程发现有如下错误

org.hibernate.MappingException: Association references unmapped class: com.hhh.entity.SsSortSubject

我们删掉SsSort.hbm.xml这个配置文件中的

我们不需要这个配置

如果出现这个java.lang.NoClassDefFoundError: org/objectweb/asm/CodeVisitor异常就删掉cglib这个jar包,这是cglib中需要asm这个依赖。这里我们不要cglib

如果发布成功,启动没有错误。然后在浏览器中输入:

看看是否输出json格式的字符串。如果输出是正常的内容,没有异常。那么后台的代码就编写成功。

9、 下面开始编写客户端的代码,添加ext2的js库。

编写客户端tree的代码:

上面就是一颗树,带点击和选中事件的tree。我们还可以给它额外添加些辅助功能,让它可以查询树节点,点击展开、收缩、刷新等功能。

首先添加这些工具条,toolbar

完善工具条上面的handler事件的方法

看看tree的入口函数和导入的js文件

启动项目,在浏览器中请求:

可以看到如下界面:

clip_image032

查询的地方输入检测,就可以查询到相关带检测的项目:

clip_image034

点击一个节点就可以得到它的id或text

clip_image036

下拉列表选择节点树

效果图:

clip_image037

有了上面写的tree,现在写comboBoxCheckNodeTree。需要用到扩展的comboBox的js文件。Ext.ux.ComboBoxCheckTree.js这个是插件,进扩展的comboBox的js库。直接引入即可。下面编写comboBox的js:

display='none'; document.getElementById('Code_Closed_Text_752234').style.display='none'; document.getElementById('Code_Open_Image_752234').style.display='inline'; document.getElementById('Code_Open_Text_752234').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_752234" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_752234').style.display='none'; getElementById('Code_Closed_Image_752234').style.display='inline'; getElementById('Code_Closed_Text_752234').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_752234">Box * @createDate: Sep 5,2010 3:22:35 PM * @class Ext.hoo.tree.ComboBoxCheckNodeTree * @extends Ext.ux.ComboBoxCheckTree */ Ext.ns(""); Ext.hoo.tree.ComboBoxCheckNodeTree = Ext.extend(Ext.ux.ComboBoxCheckTree,{ : () { Ext.hoo.tree.ComboBoxCheckNodeTree.superclass..call(,{ renderTo: Ext.get('show'), height: 150, 默认叶子节点 tree: { xtype: 'treepanel',height: 100,checkModel: 'cascade', onlyLeafCheckable: , animate: ,rootVisible: ,loader: Ext.tree.TreeLoader({ dataUrl: Ext.hoo.tree.ComboBoxCheckNodeTree.TREE_DATA_URL,baseAttrs: { uiProvider: Ext.ux.TreeCheckNodeUI } }),root: Ext.tree.AsyncTreeNode({ expanded: ,id: "" }) } }); .on("",.onFieldChange,); },onFieldChange: (field) { (field.getValue() + "" + .getValue() + "" + .getRawValue()); } });

Ext.hoo.tree.ComboBoxCheckNodeTree.TREE_DATA_URL = "<span style="color: #8b0000">tree.action";

Ext.onReady(<span style="color: #0000ff">function () {
Ext.BLANK_IMAGE_URL = "<span style="color: #8b0000">ext2/resources/images/default/s.gif";
<span style="color: #0000ff">new Ext.hoo.tree.ComboBoxCheckNodeTree();
});

代码比较简单,上面常用的属性也作注释说明。这个comboBoxTree可以用作多选比较好,当然单选也可以。

下拉列表树

效果图:

clip_image038

不带checkBox的tree,一般用于单选模式。看代码

display='none'; document.getElementById('Code_Closed_Text_481390').style.display='none'; document.getElementById('Code_Open_Image_481390').style.display='inline'; document.getElementById('Code_Open_Text_481390').style.display='inline';" align="top" src="/res/2019/02-14/22/1c53668bcee393edac0d7b3b3daff1ae.gif" width="11" height="16">display: none" id="Code_Open_Image_481390" onclick="this.style.display='none'; document.getElementById('Code_Open_Text_481390').style.display='none'; getElementById('Code_Closed_Image_481390').style.display='inline'; getElementById('Code_Closed_Text_481390').style.display='inline';" align="top" src="/res/2019/02-14/22/405b18b4b6584ae338e0f6ecaf736533.gif" width="11" height="16">代码display: none" id="Code_Open_Text_481390">Box的tree的comboBox * @createDate: Sep 5,2010 3:22:35 PM * @class Ext.hoo.tree.ComboBoTree * @extends Ext.ux.ComboBoxCheckTree */ Ext.ns(""); Ext.hoo.tree.ComboBoTree = Ext.extend(Ext.ux.ComboBoxTree,{ : () { Ext.hoo.tree.ComboBoTree.superclass..call(,{ renderTo: Ext.get('basicTree'), 默认) selectNodeModel: "", hiddenName: "",tree: { xtype: 'treepanel',animate: ,loader: Ext.tree.TreeLoader({ dataUrl: Ext.hoo.tree.ComboBoTree.TREE_DATA_URL }),id: "" }) },listeners: { select: (field) { (field.getValue() + "" + .getValue() + "" + .getRawValue() + "" + .getNode().text); } } }); } });

Ext.hoo.tree.ComboBoTree.TREE_DATA_URL = "<span style="color: #8b0000">tree.action";

Ext.onReady(<span style="color: #0000ff">function () {
Ext.BLANK_IMAGE_URL = "<span style="color: #8b0000">ext2/resources/images/default/s.gif";
<span style="color: #0000ff">new Ext.hoo.tree.ComboBoTree();
});

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐