您的位置:首页 > 编程语言 > Java开发

myBatis3,spring3,struts2.2整合

2011-08-04 08:47 387 查看
开发环境:

System:Windows

WebBrowser:IE6+、Firefox3+

JavaEEServer:tomcat5.0.2.8、tomcat6

IDE:eclipse、MyEclipse8

Database:MySQL

开发依赖库:

JavaEE5、Spring3.0.5、Mybatis3.0.4、myBatis-spring-1.0、Struts2.2.3、junit4.8.2、ext2.2.2

Email:hoojo_@126.com

Blog:http://blog.csdn.net/IBM_hoojo

http://hoojo.cnblogs.com/

上次介绍过Spring3、SpringMVC、MyBatis3整合,在线博文:/article/4791843.html

一、准备工作

1、下载jar包

Struts2jar下载:

http://labs.renren.com/apache-mirror//struts/library/struts-2.2.3-lib.zip

Spring3jar下载:

http://ebr.springsource.com/repository/app/library/version/detail?name=org.springframework.spring&version=3.0.5.RELEASE

MyBatis3jar下载:http://www.mybatis.org/java.html

2、添加的jar包如下:

二、Spring、MyBatis整合

1、需要的jar文件如下:

2、在src目录中加入mybatis.xml,内容如下:

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEconfigurationPUBLIC"-//mybatis.org//DTDConfig3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

<!--别名-->

<typeAliases>

<typeAliastype="com.hoo.entity.Account"alias="account"/>

</typeAliases>

</configuration>

上面的配置文件中,可以加入一些公共、常用的MyBatis方面的全局配置。如handler、objectFactory、plugin、以及mappers的映射路径(由于在applicationContext-common中的SqlSessionFactoryBean有配置mapper的location,这里就不需要配置)等。这个类的文件名称和下面的applicationContext-common.xml中的configLocation中的值对应,不是随便写的。

3、在src目录中添加applicationContext-common.xml中加入内容如下:

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

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

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

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

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

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

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

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

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

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

<!--配置DataSource数据源-->

<beanid="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">

<propertyname="driverClassName"value="com.mysql.jdbc.Driver"/>

<propertyname="url"value="jdbc:mysql://10.0.0.131:3306/ash2"/>

<propertyname="username"value="dev"/>

<propertyname="password"value="dev"/>

</bean>

<!--配置SqlSessionFactoryBean-->

<beanid="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean">

<propertyname="dataSource"ref="dataSource"/>

<propertyname="configLocation"value="classpath:mybatis.xml"/>

<!--mapper和resultmap配置路径-->

<propertyname="mapperLocations">

<list>

<!--表示在com.hoo.resultmap包或以下所有目录中,以-resultmap.xml结尾所有文件-->

<value>classpath:com/hoo/resultmap/**/*-resultmap.xml</value>

<value>classpath:com/hoo/entity/*-resultmap.xml</value>

<value>classpath:com/hoo/mapper/**/*-mapper.xml</value>

</list>

</property>

</bean>

<!--配置事务管理器,注意这里的dataSource和SqlSessionFactoryBean的dataSource要一致,不然事务就没有作用了-->

<beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<propertyname="dataSource"ref="dataSource"/>

</bean>

<!--配置事务的传播特性-->

<beanid="baseTransactionProxy"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"abstract="true">

<propertyname="transactionManager"ref="transactionManager"/>

<propertyname="transactionAttributes">

<props>

<propkey="add*">PROPAGATION_REQUIRED</prop>

<propkey="edit*">PROPAGATION_REQUIRED</prop>

<propkey="remove*">PROPAGATION_REQUIRED</prop>

<propkey="insert*">PROPAGATION_REQUIRED</prop>

<propkey="update*">PROPAGATION_REQUIRED</prop>

<propkey="del*">PROPAGATION_REQUIRED</prop>

<propkey="*">readOnly</prop>

</props>

</property>

</bean>

<!--通过扫描的模式,扫描目录在com/hoo/mapper目录下,所有的mapper都继承SqlMapper接口的接口,这样一个bean就可以了-->

<beanclass="org.mybatis.spring.mapper.MapperScannerConfigurer">

<propertyname="basePackage"value="com.hoo.mapper"/>

<propertyname="markerInterface"value="com.hoo.mapper.SqlMapper"/>

</bean>

</beans>

DataSource,这里的是采用jdbc的dataSource;

SqlSessionFactory,是MyBatis团队提供整合Spring的SqlSession工厂Bean用它可以完成Spring和MyBatis的整合。SqlSessionFactoryBean需要注入DataSource,配置myBatis配置文件的location,以及配置mapper.xml和resultMap.xml文件的路径,可以用通配符模式配置。其实mapper里面是可以存放resultMap的内容的。由于resultMap文件的内容是和JavaBean及数据库表对象进行映射的。一般一张表、一个JavaBean(Model)对应一个resultMap文件。将resultMap独立出来提供可读性、维护性。

TransactionManager,事务管理器是采用jdbc的管理器。需要注入DataSource数据源,这里注入的数据源和SqlSessionFactory是同一个数据源。如果不同的数据源,事务将无法起到作用。

baseTransactionProxy,事务的传播特性才有spring提供的TransactionProxyFactoryBean这个事务代理工厂的拦截器类来完成。其他的暂时还没有可以支持事务配置的传播特性和隔离级别的方法,关于这里你可以参考:/article/4791844.html

MapperScannerConfigurer是MyBatis的mapper接口的扫描器,通过这个配置可以完成对指定basePackage报下的类进行扫描,如果这些类有继承SqlMapper这个类的,将会是MyBatis的接口。不需要单独配置mapper,而完成注入。

4、在src目录添加applicationContext-beans.xml这个文件,文件内容如下:

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

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

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

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

http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!--注解探测器-->

<context:component-scanbase-package="com.hoo"/>

</beans>

这里面可以完成一下Action、Bean的注入配置

5、JavaBean(Model、Entity)相关类、及resultMap.xml文件内容

Bean

packagecom.hoo.entity;

importjava.io.Serializable;

importjava.util.Date;

publicclassAccountimplementsSerializable{

privatestaticfinallongserialVersionUID=-7970848646314840509L;

privateIntegeraccountId;

privateStringusername;

privateStringpassword;

privateDatecreateTime;

publicAccount(){

super();

}

//getter、setter

@Override

publicStringtoString(){

returnthis.accountId+"#"+this.username+"#"+this.password+"#"+this.createTime;

}

}

account-resultMap.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mappernamespace="accountMap">

<resultMaptype="com.hoo.entity.Account"id="accountResultMap">

<idproperty="accountId"column="account_id"/>

<resultproperty="username"column="username"/>

<resultproperty="password"column="password"/>

<resultproperty="createTime"column="create_time"/>

</resultMap>

</mapper>

resultMap的type属性和对应的classpath对应,id会在mapper.xml文件中用到。下面的属性property是JavaBean的属性,column和数据库的字段对应。

6、上面的applicationContext-common.xml中配置了SqlMapper,下面是SqlMapper代码,就一个空接口

packagecom.hoo.mapper;

/**

*<b>function:</b>所有的Mapper继承这个接口

*@authorhoojo

*@createDate2011-4-12下午04:00:31

*@fileSqlMapper.java

*@packagecom.hoo.mapper

*@projectMyBatisForSpring

*@bloghttp://blog.csdn.net/IBM_hoojo

*@emailhoojo_@126.com

*@version1.0

*/

publicinterfaceSqlMapper{

}

7、定制我们自己的增删改查(CRUD)组件,接口如下

packagecom.hoo.mapper;

importjava.util.List;

importorg.springframework.dao.DataAccessException;

/**

*<b>function:</b>BaseSqlMapper继承SqlMapper,对Mapper进行接口封装,提供常用的增删改查组件;

*也可以对该接口进行扩展和封装

*@authorhoojo

*@createDate2011-4-14上午11:36:41

*@fileBaseSqlMapper.java

*@packagecom.hoo.mapper

*@projectMyBatisForSpring

*@bloghttp://blog.csdn.net/IBM_hoojo

*@emailhoojo_@126.com

*@version1.0

*/

publicinterfaceBaseSqlMapper<T>extendsSqlMapper{

publicvoidadd(Tentity)throwsDataAccessException;

publicvoidedit(Tentity)throwsDataAccessException;

publicvoidremvoe(Tentity)throwsDataAccessException;

publicTget(Tentity)throwsDataAccessException;

publicList<T>getList(Tentity)throwsDataAccessException;

}

当然实际开发中,增删改查组件一定不止这几个方法。这里只是随便挪列几个方法做一个示例。实际中可以根据需求进行添加方法,这里添加的方法可以用一个mapper.xml进行实现,然后注入这个mapper即可完成操作。也可以定义其他的mapper,如AccountMapper继承这个接口。然后为AccountMapper提供实现也是可以的。

8、下面看看AccountMapper接口

packagecom.hoo.mapper;

importjava.util.List;

importcom.hoo.entity.Account;

/**

*<b>function:</b>继承SqlMapper,MyBatis数据操作接口;此接口无需实现类

*@authorhoojo

*@createDate2010-12-21下午05:21:20

*@fileAccountMapper.java

*@packagecom.hoo.mapper

*@projectMyBatis

*@bloghttp://blog.csdn.net/IBM_hoojo

*@emailhoojo_@126.com

*@version1.0

*/

publicinterfaceAccountMapper<TextendsAccount>extendsBaseSqlMapper<T>{

publicList<T>getAllAccount();

}

上面的AccountMapper继承了BaseSqlMapper,并且提供了自己所需要的方法。下面实现这个Mapper中和父接口的方法。

account-mapper.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEmapperPUBLIC"-//mybatis.org//DTDMapper3.0//EN"

"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--namespace和定义的Mapper接口对应,并实现其中的方法-->

<mappernamespace="com.hoo.mapper.AccountMapper">

<selectid="getList"parameterType="com.hoo.entity.Account"resultType="list"resultMap="accountResultMap">

select*fromaccountwhereusernamelike'%'#{username}'%'

</select>

<selectid="getAllAccount"resultType="list"resultMap="accountResultMap">

select*fromaccount

</select>

<!--accountResultMap是account-resultmap.xml中定义的resultmap-->

<selectid="get"parameterType="account"resultType="com.hoo.entity.Account"resultMap="accountResultMap">

<![CDATA[

select*fromaccountwhereaccount_id=#{accountId}

]]>

</select>

<!--自动生成id策略-->

<insertid="add"useGeneratedKeys="true"keyProperty="account_id"parameterType="account">

insertintoaccount(account_id,username,password)

values(#{accountId},#{username},#{password})

</insert>

<updateid="edit"parameterType="account">

updateaccountset

username=#{username},

password=#{password}

whereaccount_id=#{accountId}

</update>

<deleteid="remove"parameterType="account">

deletefromaccountwhereaccount_id=#{accountId}

</delete>

</mapper>

mapper的namespace和接口的classpath对应,里面的sql语句的id和方法名称对应。这样就完成了AccountMapper的实现。

9、下面来测试下AccountMapper的功能,代码如下:

packagecom.hoo.mapper;

importjava.util.List;

importjavax.inject.Inject;

importorg.springframework.test.context.ContextConfiguration;

importorg.springframework.test.context.junit38.AbstractJUnit38SpringContextTests;

importcom.hoo.entity.Account;

/**

*<b>function:</b>AccountMapperJUnit测试类

*@authorhoojo

*@createDate2011-4-12下午04:21:50

*@fileAccountMapperTest.java

*@packagecom.hoo.mapper

*@projectMyBatisForSpring

*@bloghttp://blog.csdn.net/IBM_hoojo

*@emailhoojo_@126.com

*@version1.0

*/

@ContextConfiguration("classpath:applicationContext-*.xml")

publicclassAccountMapperTestextendsAbstractJUnit38SpringContextTests{

@Inject

privateAccountMapper<Account>mapper;

publicvoidtestGetAccount(){

Accountacc=newAccount();

acc.setAccountId(28);

System.out.println(mapper.get(acc));

}

publicvoidtestAdd(){

Accountaccount=newAccount();

account.setUsername("lisi@155.com");

account.setPassword("abc");

mapper.add(account);

}

publicvoidtestEditAccount(){

Accountacc=newAccount();

acc.setAccountId(28);

acc=mapper.get(acc);

System.out.println(acc);

acc.setUsername("Zhangsan22");

acc.setPassword("123123");

mapper.edit(acc);

System.out.println(mapper.get(acc));

}

publicvoidtestRemoveAccount(){

Accountacc=newAccount();

acc.setAccountId(28);

mapper.remvoe(acc);

System.out.println(mapper.get(acc));

}

publicvoidtestAccountList(){

List<Account>acc=mapper.getAllAccount();

System.out.println(acc.size());

System.out.println(acc);

}

publicvoidtestList(){

Accountacc=newAccount();

acc.setUsername("@qq.com");

List<Account>list=mapper.getList(acc);

System.out.println(list.size());

System.out.println(list);

}

}

运行上面的方法,没有错误基本上就算完成了Mapper的功能了。

10、下面来写一个数据库操作的基类Dao,代码如下:

packagecom.hoo.dao;

importjava.util.List;

importcom.hoo.mapper.BaseSqlMapper;

/**

*<b>function:</b>

*@authorhoojo

*@createDate2011-4-14上午11:30:09

*@fileBaseMapperDao.java

*@packagecom.hoo.dao

*@projectMyBatisForSpring

*@bloghttp://blog.csdn.net/IBM_hoojo

*@emailhoojo_@126.com

*@version1.0

*/

publicinterfaceBaseMapperDao<T>{

@SuppressWarnings("unchecked")

publicvoidsetMapperClass(Class<?extendsBaseSqlMapper>mapperClass);

publicBaseSqlMapper<T>getMapper();

publicbooleanadd(Tentity)throwsException;

publicbooleanedit(Tentity)throwsException;

publicbooleanremove(Tentity)throwsException;

publicTget(Tentity)throwsException;

publicList<T>getAll(Tentity)throwsException;

}

这个Dao定义了BaseSqlMapper中的方法,还提供了一个setMapperClass的方法。目的是在使用这个dao的时候,需要设置一个Mapper的class。且这个Mapper必须要是BaseSqlMapper或它的子类。所有的dao都可以用BaseMapperDao来完成CRUD操作即可,当BaseMapperDao的方法不够用的情况下,可以在接口中提供SqlSession、SqlSessionTemplate方法,让底层人员自己扩展所需要的方法。这里的dao和mapper好像有点冗余,因为dao和mapper完成的功能都是类似或是相同的。但是你可以在dao中,同时调用不同的mapper,来完成当前模块的dao所需要的功能。

11、看看BaseMapperDao的实现代码

packagecom.hoo.dao.impl;

importjava.util.List;

importjavax.inject.Inject;

importorg.apache.ibatis.session.SqlSessionFactory;

importorg.mybatis.spring.SqlSessionTemplate;

importorg.springframework.stereotype.Repository;

importcom.hoo.dao.BaseMapperDao;

importcom.hoo.mapper.BaseSqlMapper;

/**

*<b>function:</b>运用SqlSessionTemplate封装Dao常用增删改方法,可以进行扩展

*@authorhoojo

*@createDate2011-4-14下午12:22:07

*@fileBaseMapperDaoImpl.java

*@packagecom.hoo.dao.impl

*@projectMyBatisForSpring

*@bloghttp://blog.csdn.net/IBM_hoojo

*@emailhoojo_@126.com

*@version1.0

*/

@SuppressWarnings("unchecked")

@Repository

publicclassBaseMapperDaoImpl<T>extendsSqlSessionTemplateimplementsBaseMapperDao<T>{

@Inject

publicBaseMapperDaoImpl(SqlSessionFactorysqlSessionFactory){

super(sqlSessionFactory);

}

privateClass<?extendsBaseSqlMapper>mapperClass;

publicvoidsetMapperClass(Class<?extendsBaseSqlMapper>mapperClass){

this.mapperClass=mapperClass;

}

publicBaseSqlMapper<T>getMapper(){

returnthis.getMapper(mapperClass);

}

publicbooleanadd(Tentity)throwsException{

booleanflag=false;

try{

this.getMapper().add(entity);

flag=true;

}catch(Exceptione){

flag=false;

throwe;

}

returnflag;

}

publicbooleanedit(Tentity)throwsException{

booleanflag=false;

try{

this.getMapper().edit(entity);

flag=true;

}catch(Exceptione){

flag=false;

throwe;

}

returnflag;

}

publicTget(Tentity)throwsException{

returnthis.getMapper().get(entity);

}

publicList<T>getAll()throwsException{

returnthis.getMapper().getList(null);

}

publicbooleanremove(Tentity)throwsException{

booleanflag=false;

try{

this.getMapper().remvoe(entity);

flag=true;

}catch(Exceptione){

flag=false;

throwe;

}

returnflag;

}

}

这个实现类继承了SqlSessionTemplate,并且要注入SqlSessionFactory。提供的setMapperClass方法需要设置其BaseSqlMapper或它的子类。

好了,至此基本的CRUD的mapper和dao就算完成了。现在我们可以定义我们自己的业务模块,调用公共组件来完成增删改查操作。

12、下面测试下这个BaseMapperDao功能

packagecom.hoo.dao;

importjavax.inject.Inject;

importorg.junit.Before;

importorg.springframework.test.context.ContextConfiguration;

importorg.springframework.test.context.junit38.AbstractJUnit38SpringContextTests;

importcom.hoo.entity.Account;

importcom.hoo.mapper.AccountMapper;

/**

*<b>function:</b>

*@authorhoojo

*@createDate2011-4-14下午01:08:49

*@fileBaseMapperDaoImplTest.java

*@packagecom.hoo.dao

*@projectMyBatisForSpring

*@bloghttp://blog.csdn.net/IBM_hoojo

*@emailhoojo_@126.com

*@version1.0

*/

@ContextConfiguration("classpath:applicationContext-*.xml")

publicclassBaseMapperDaoImplTestextendsAbstractJUnit38SpringContextTests{

@Inject

privateBaseMapperDao<Account>dao;

@Before

publicvoidinit(){

System.out.println(dao);

dao.setMapperClass(AccountMapper.class);

}

publicvoidtestGet()throwsException{

init();

Accountacc=newAccount();

acc.setAccountId(28);

System.out.println(dao.get(acc));

}

publicvoidtestAdd()throwsException{

init();

Accountaccount=newAccount();

account.setUsername("temp@156.com");

account.setPassword("abc");

System.out.println(dao.add(account));

}

}

13、下面定义AccountDao接口

packagecom.hoo.dao;

importjava.util.List;

importorg.springframework.dao.DataAccessException;

/**

*<b>function:</b>Account数据库操作dao接口

*@authorhoojo

*@createDate2011-4-13上午10:21:38

*@fileAccountDao.java

*@packagecom.hoo.dao

*@projectMyBatisForSpring

*@bloghttp://blog.csdn.net/IBM_hoojo

*@emailhoojo_@126.com

*@version1.0

*/

publicinterfaceAccountDao<T>{

/**

*<b>function:</b>添加Account对象信息

*@authorhoojo

*@createDate2011-4-13上午11:50:05

*@paramentityAccount

*@returnboolean是否成功

*@throwsDataAccessException

*/

publicbooleanaddAccount(Tentity)throwsDataAccessException;

/**

*<b>function:</b>根据id对到Account信息

*@authorhoojo

*@createDate2011-4-13上午11:50:45

*@paramid编号id

*@returnAccount

*@throwsDataAccessException

*/

publicTgetAccount(Integerid)throwsDataAccessException;

/**

*<b>function:</b>查询所有Account信息

*@authorhoojo

*@createDate2011-4-13上午11:51:45

*@paramid编号id

*@returnAccount

*@throwsDataAccessException

*/

publicList<T>getList()throwsDataAccessException;

}

14、AccountDao实现类

packagecom.hoo.dao.impl;

importjava.util.List;

importjavax.inject.Inject;

importorg.springframework.dao.DataAccessException;

importorg.springframework.stereotype.Repository;

importcom.hoo.dao.AccountDao;

importcom.hoo.dao.BaseMapperDao;

importcom.hoo.entity.Account;

importcom.hoo.mapper.AccountMapper;

/**

*<b>function:</b>Account数据库操作dao

*@authorhoojo

*@createDate2011-4-13上午10:25:02

*@fileAccountDaoImpl.java

*@packagecom.hoo.dao.impl

*@projectMyBatisForSpring

*@bloghttp://blog.csdn.net/IBM_hoojo

*@emailhoojo_@126.com

*@version1.0

*/

@SuppressWarnings("unchecked")

@Repository

publicclassAccountDaoImpl<TextendsAccount>implementsAccountDao<T>{

@Inject

privateBaseMapperDao<Account>dao;

publicbooleanaddAccount(Tentity)throwsDataAccessException{

dao.setMapperClass(AccountMapper.class);

booleanflag=false;

try{

dao.add(entity);

flag=true;

}catch(DataAccessExceptione){

flag=false;

throwe;

}catch(Exceptione){

thrownewRuntimeException(e);

}

returnflag;

}

publicTgetAccount(Integerid)throwsDataAccessException{

dao.setMapperClass(AccountMapper.class);

Accountacc=newAccount();

Tentity=null;

try{

acc.setAccountId(id);

entity=(T)dao.get(acc);

}catch(DataAccessExceptione){

throwe;

}catch(Exceptione){

thrownewRuntimeException(e);

}

returnentity;

}

publicList<T>getList()throwsDataAccessException{

dao.setMapperClass(AccountMapper.class);

List<T>list=null;

try{

list=(List<T>)((AccountMapper)dao.getMapper()).getAllAcount();

}catch(DataAccessExceptione){

throwe;

}catch(Exceptione){

thrownewRuntimeException(e);

}

returnlist;

}

}

注意,上面的方法都设置了MapperClass,表示当前dao的Mapper是AccountMapper对象。所有的mapper方法都是调用AccountMapper这个对象中的方法。

15、下面定义服务器层接口

packagecom.hoo.biz;

importjava.util.List;

importorg.springframework.dao.DataAccessException;

/**

*<b>function:</b>biz层Account接口

*@authorhoojo

*@createDate2011-4-13上午11:33:04

*@fileAccountBiz.java

*@packagecom.hoo.biz

*@projectMyBatisForSpring

*@bloghttp://blog.csdn.net/IBM_hoojo

*@emailhoojo_@126.com

*@version1.0

*/

publicinterfaceAccountBiz<T>{

/**

*<b>function:</b>添加Account对象信息

*@authorhoojo

*@createDate2011-4-13上午11:50:05

*@paramentityAccount

*@returnboolean是否成功

*@throwsDataAccessException

*/

publicbooleanaddAccount(Tentity)throwsDataAccessException;

publicbooleanexecute(Tentity)throwsDataAccessException;

/**

*<b>function:</b>根据id对到Account信息

*@authorhoojo

*@createDate2011-4-13上午11:50:45

*@paramid编号id

*@returnAccount

*@throwsDataAccessException

*/

publicTgetAccount(Integerid)throwsDataAccessException;

/**

*<b>function:</b>查询所有Account信息

*@authorhoojo

*@createDate2011-4-13上午11:51:45

*@paramid编号id

*@returnAccount

*@throwsDataAccessException

*/

publicList<T>getList()throwsDataAccessException;

}

16、AccountBiz的实现代码

packagecom.hoo.biz.impl;

importjava.util.List;

importjavax.inject.Inject;

importorg.springframework.dao.DataAccessException;

importorg.springframework.stereotype.Component;

importcom.hoo.biz.AccountBiz;

importcom.hoo.dao.AccountDao;

importcom.hoo.entity.Account;

importcom.hoo.exception.BizException;

/**

*<b>function:</b>AccountBiz接口实现

*@authorhoojo

*@createDate2011-4-13上午11:34:39

*@fileAccountBizImpl.java

*@packagecom.hoo.biz.impl

*@projectMyBatisForSpring

*@bloghttp://blog.csdn.net/IBM_hoojo

*@emailhoojo_@126.com

*@version1.0

*/

//@Component

@Service

publicclassAccountBizImpl<TextendsAccount>implementsAccountBiz<T>{

@Inject

privateAccountDao<T>dao;

publicbooleanaddAccount(Tentity)throwsDataAccessException{

if(entity==null){

thrownewBizException(Account.class.getName()+"对象参数信息为Empty!");

}

returndao.addAccount(entity);

}

publicTgetAccount(Integerid)throwsDataAccessException{

returndao.getAccount(id);

}

publicList<T>getList()throwsDataAccessException{

returndao.getList();

}

publicbooleanexecute(Tentity)throwsDataAccessException{

if(entity==null){

thrownewBizException(Account.class.getName()+"对象参数信息为Empty!");

}

returndao.addAccount(entity);

}

}

直接注入AccountDao完成相关操作即可

17、如果你需要在业务层设置事务传播特性,需要在applicationContext-bean.xml中加入配置如下:

<!--为AccountBiz接口配置事务拦截器,baseTransactionProxy是事务拦截器,在Action中获取这个对象-->

<beanid="accountBiz"parent="baseTransactionProxy">

<!--设置target,也就是AccountBiz的实现类-->

<propertyname="target"ref="accountBizImpl"/>

</bean>

这样在Action中注入accountBiz这个对象后,那么当这个对象出现DataAccessException异常的时候,就会自动回滚事务。

至此,Spring和MyBatis的整合就完成了。

作者:hoojo

出处:/article/4791876.html

blog:http://blog.csdn.net/IBM_hoojo
==========================================================================================================

三、加入Struts2框架

1、准备工作

添加jar文件如下:





org.springframework.web-3.0.5.RELEASE.jar

org.springframework.aop-3.0.5.RELEASE.jar

这2个jar包是spring的context所依赖的jar包

struts2-spring-plugin-2.2.3.jar是struts整合spring的jar包

2、在web.xml加入struts2的控制器

<filter>

<filter-name>struts2</filter-name>

<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>

</filter>

<filter-mapping>

<filter-name>struts2</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>


3、在src目录添加struts.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEstrutsPUBLIC

"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<constantname="struts.i18n.encoding"value="UTF-8"/>


<packagename="ssMyBatis"extends="struts-default">

</package>

</struts>


启动后,可以看到首页index的页面就基本整合完成。

4、首先看看Action代码,代码如下:

packagecom.hoo.action;


importjava.util.ArrayList;

importjava.util.List;

importjavax.inject.Inject;

importjavax.inject.Named;

importorg.springframework.stereotype.Component;

importcom.hoo.biz.AccountBiz;

importcom.hoo.entity.Account;

importcom.opensymphony.xwork2.ActionSupport;


/**

*<b>function:</b>AccountAction

*@authorhoojo

*@createDate2011-5-11下午12:03:05

*@fileAccountAction.java

*@packagecom.hoo.action

*@projectS2SMyBatis

*@blog'target='_blank'>http://blog.csdn.net/IBM_hoojo[/code]
*@emailhoojo_@126.com

*@version1.0

*/

@Component

publicclassAccountActionextendsActionSupport{

/**

*@authorHoojo

*/

privatestaticfinallongserialVersionUID=-973535478139284399L;


@Inject

@Named("accountBiz")

privateAccountBiz<Account>biz;


privateAccountacc;

privateList<Account>results=newArrayList<Account>();


publicList<Account>getResults(){

returnresults;

}


publicAccountgetAcc(){

returnacc;

}


publicvoidsetAcc(Accountacc){

this.acc=acc;

}


publicStringadd()throwsException{

if(!biz.addAccount(acc)){

this.addActionMessage("添加数据失败");

returnERROR;

}

returnSUCCESS;

}


publicStringshow()throwsException{

results=biz.getList();

return"show";

}


publicStringremove()throwsException{

returnSUCCESS;

}


publicStringedit()throwsException{

returnSUCCESS;

}


publicStringtreeData()throwsException{

results=biz.getList();

return"tree";

}

}


这个Action被注解成Component,那么在spring的applicationContext配置文件中就不需要进行<bean/>标签的配置了。上面注入了AccountDao,完成相关操作。

5、由于Struts2要和Spring进行整合,所以struts的配置会有点不同

<actionname="account"class="accountAction">

<resulttype="redirect">account!show.action</result>

<resultname="show">/show.jsp</result>

</action>


上面的class不再是AccountAction的classpath,而是spring容器中配置的bean。就是通过@Component注解过的AccountAction,被注解注释过后它的id默认是类名称首字母小写。所以上面的action的配置是accountAction。

6、由于要整合ExtJS,所以这里用到struts2-json-plugin-2.2.3.jar这个插件,将其加入到lib库中,struts.xml更改成:

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEstrutsPUBLIC

"-//ApacheSoftwareFoundation//DTDStrutsConfiguration2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<constantname="struts.i18n.encoding"value="UTF-8"/>


<packagename="ssMyBatis"extends="json-default">

<global-results>

<resultname="error">/error.jsp</result>

</global-results>


<actionname="account"class="accountAction">

<resulttype="redirect">account!show.action</result>

<resultname="show">/show.jsp</result>

<resultname="tree"type="json">

<paramname="excludeProperties">acc</param>

</result>

</action>

</package>

</struts>


AccountAction中的treeData方法返回的tree,在account这个action配置中找到tree的result,将result的type配置成json。表示该result的数据以json的方式展示。tree这个result还配置了一个param,名称为excludeProperties表示排除的属性。这个参数将排除当前Action中的acc属性。也就是说这个属性将不会得到json的转换。其他属性将会被转换成json。

7、前台页面

index.jsp

<body>

<ahref="account!show.action">显示所有</a><br>

<ahref="add.jsp">添加数据</a><br/>

<ahref="account!treeData.action">JSON</a><br/>

</body>


show.jsp

<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%>

<%@taglibprefix="s"uri="/struts-tags"%>

<%

Stringpath=request.getContextPath();

StringbasePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>


<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">

<html>

<head>

<basehref="<%=basePath%>">


<title>showalldata</title>


<metahttp-equiv="pragma"content="no-cache">

<metahttp-equiv="cache-control"content="no-cache">

<metahttp-equiv="expires"content="0">

</head>


<body>

<s:iteratorvalue="results"status="s"var="data">

${data}<===>

<s:propertyvalue="#data.accountId"/>#

<s:propertyvalue="#data.username"/>#

<s:propertyvalue="#data.password"/>#

<s:propertyvalue="#data.createTime"/>#

<s:datename="#data.createTime"format="yyyy-MM-dd"/>#

<ahref="account!remove.action">删除</a>|<ahref="account!edit.action">修改</a>

<br/>

</s:iterator>

</body>

</html>


Struts标签和OGNL表达式显示数据

add.jsp

<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%>

<%@taglibprefix="s"uri="/struts-tags"%>

<%

Stringpath=request.getContextPath();

StringbasePath=request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

%>


<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">

<html>

<head>

<basehref="<%=basePath%>">


<title>add</title>

<metahttp-equiv="pragma"content="no-cache">

<metahttp-equiv="cache-control"content="no-cache">

<metahttp-equiv="expires"content="0">

</head>


<body>

<s:formaction="account!add.action"method="post">

<s:textfieldname="acc.username"/>

<s:passwordname="acc.password"/>

<s:submitvalue="提交"></s:submit>

</s:form>

</body>

</html>


四、整合ExtJS

1、添加ext的库,版本是2.2.2

需要添加column-tree.css

/*

*ExtJSLibrary2.2.1

*Copyright(c)2006-2009,ExtJS,LLC.

*licensing@extjs.com

*

*'target='_blank'>http://extjs.com/license[/code]
*/


.x-column-tree.x-tree-node{

zoom:1;

}

.x-column-tree.x-tree-node-el{

/*border-bottom:1pxsolid#eee;borders?*/

zoom:1;

}

.x-column-tree.x-tree-selected{

background:#d9e8fb;

}

.x-column-tree.x-tree-nodea{

line-height:18px;

vertical-align:middle;

}

.x-column-tree.x-tree-nodeaspan{


}

.x-column-tree.x-tree-node.x-tree-selectedaspan{

background:transparent;

color:#000;

}

.x-tree-col{

float:left;

overflow:hidden;

padding:01px;

zoom:1;

}


.x-tree-col-text,.x-tree-hd-text{

overflow:hidden;

-o-text-overflow:ellipsis;

text-overflow:ellipsis;

padding:3px3px3px5px;

white-space:nowrap;

font:normal11pxarial,tahoma,helvetica,sans-serif;

}


.x-tree-headers{

background:#f9f9f9url(../ext2/resources/images/default/grid/grid3-hrow.gif)repeat-x0bottom;

cursor:default;

zoom:1;

}


.x-tree-hd{

float:left;

overflow:hidden;

border-left:1pxsolid#eee;

border-right:1pxsolid#d0d0d0;

}


.task{

background-image:url(../shared/icons/fam/cog.png)!important;

}

.task-folder{

background-image:url(../shared/icons/fam/folder_go.png)!important;

}


Ext.tree.ColumnTree.js

/*

*ExtJSLibrary2.2.1

*Copyright(c)2006-2009,ExtJS,LLC.

*licensing@extjs.com

*

*'target='_blank'>http://extjs.com/license[/code]
*/


Ext.tree.ColumnTree=Ext.extend(Ext.tree.TreePanel,{

lines:false,

borderWidth:Ext.isBorderBox?0:2,//thecombinedleft/rightborderforeachcell

cls:'x-column-tree',


onRender:function(){

Ext.tree.ColumnTree.superclass.onRender.apply(this,arguments);

this.headers=this.body.createChild(

{cls:'x-tree-headers'},this.innerCt.dom);


varcols=this.columns,c;

vartotalWidth=0;


for(vari=0,len=cols.length;i<len;i++){

c=cols[i];

totalWidth+=c.width;

this.headers.createChild({

cls:'x-tree-hd'+(c.cls?c.cls+'-hd':''),

cn:{

cls:'x-tree-hd-text',

html:c.header

},

style:'width:'+(c.width-this.borderWidth)+'px;'

});

}

this.headers.createChild({cls:'x-clear'});

//preventfloatsfromwrappingwhenclipped

this.headers.setWidth(totalWidth);

this.innerCt.setWidth(totalWidth);

}

});


Ext.tree.ColumnNodeUI=Ext.extend(Ext.tree.TreeNodeUI,{

focus:Ext.emptyFn,//preventoddscrollingbehavior


renderElements:function(n,a,targetNode,bulkRender){

this.indentMarkup=n.parentNode?n.parentNode.ui.getChildIndent():'';


vart=n.getOwnerTree();

varcols=t.columns;

varbw=t.borderWidth;

varc=cols[0];


varbuf=[

'<liclass="x-tree-node"><divext:tree-node-id="',n.id,'"class="x-tree-node-elx-tree-node-leaf',a.cls,'">',

'<divclass="x-tree-col"style="width:',c.width-bw,'px;">',

'<spanclass="x-tree-node-indent">',this.indentMarkup,"</span>",

'<imgsrc="',this.emptyIcon,'"class="x-tree-ec-iconx-tree-elbow">',

'<imgsrc="',a.icon||this.emptyIcon,'"class="x-tree-node-icon',(a.icon?"x-tree-node-inline-icon":""),(a.iconCls?""+a.iconCls:""),'"unselectable="on">',

'<ahidefocus="on"class="x-tree-node-anchor"href="',a.href?a.href:"#",'"tabIndex="1"',

a.hrefTarget?'target="'+a.hrefTarget+'"':"",'>',

'<spanunselectable="on">',n.text||(c.renderer?c.renderer(a[c.dataIndex],n,a):a[c.dataIndex]),"</span></a>",

"</div>"];

for(vari=1,len=cols.length;i<len;i++){

c=cols[i];


buf.push('<divclass="x-tree-col',(c.cls?c.cls:''),'"style="width:',c.width-bw,'px;">',

'<divclass="x-tree-col-text">',(c.renderer?c.renderer(a[c.dataIndex],n,a):a[c.dataIndex]),"</div>",

"</div>");

}

buf.push(

'<divclass="x-clear"></div></div>',

'<ulclass="x-tree-node-ct"style="display:none;"></ul>',

"</li>");


if(bulkRender!==true&&n.nextSibling&&n.nextSibling.ui.getEl()){

this.wrap=Ext.DomHelper.insertHtml("beforeBegin",

n.nextSibling.ui.getEl(),buf.join(""));

}else{

this.wrap=Ext.DomHelper.insertHtml("beforeEnd",targetNode,buf.join(""));

}


this.elNode=this.wrap.childNodes[0];

this.ctNode=this.wrap.childNodes[1];

varcs=this.elNode.firstChild.childNodes;

this.indentNode=cs[0];

this.ecNode=cs[1];

this.iconNode=cs[2];

this.anchor=cs[3];

this.textNode=cs[3].firstChild;

}

});


2、编写静态ColumnTree

/**

*@functioncolumntreecolumntree多列信息的tree

*@auhor:hoojo

*@createDate:Aug29,201010:39:02PM

*@blog:blog.csdn.net/IBM_hoojo

*@email:hoojo_@126.com

*/

Ext.ns("Ext.hoo.tree");

Ext.hoo.tree.UserColumnTree=Ext.extend(Ext.tree.ColumnTree,{

constructor:function(){

Ext.hoo.tree.UserColumnTree.superclass.constructor.call(this,{

renderTo:"show",

title:"用户信息columntree",

width:450,

hieght:400,

autoScroll:true,

rootVisible:true,

columns:[{

header:"名称",

width:100,

dataIndex:"name"

},{

header:"性别",

width:100,

dataIndex:"sex"

},{

header:"年龄",

width:100,

dataIndex:"age"

},{

header:"班级",

width:100,

dataIndex:"classes"

}],

loader:newExt.tree.TreeLoader({

baseAttrs:{

uiProvider:Ext.tree.ColumnNodeUI

}

}),

root:newExt.tree.AsyncTreeNode({

text:"用户基本信息",

children:[{

name:"大二一班",

classes:"二(1)班",

children:[{

name:"微微",

sex:"女",

age:20,

classes:"二(1)班",

leaf:true

},{

name:"筱筱",

sex:"女",

age:22,

classes:"二(1)班",

leaf:true

},{

name:"珠珠",

sex:"女",

age:19,

classes:"二(1)班",

leaf:true

},{

name:"拉拉",

sex:"女",

age:19,

classes:"二(1)班",

leaf:true

}]

},{

name:"二二班",

classes:"二(2)班",

children:[{

name:"放放",

sex:"男",

age:22,

classes:"二(2)班",

leaf:true

},{

name:"枫枫",

sex:"男",

age:22,

classes:"二(2)班",

leaf:true

}]

},{

name:"未成立",

sex:"",

age:0,

classes:"二(3)班",

leaf:true

}]

})

});

this.on("click",this.onNodeClick,this);

},

onNodeClick:function(node,e){

alert(Ext.encode(node.attributes)+"###"+node.leaf+"###"+Ext.encode(e.getPoint())+"##"+e.getXY());

}

});


Ext.onReady(function(){

Ext.BLANK_IMAGE_URL="ext2/resources/images/default/s.gif";

newExt.hoo.tree.UserColumnTree();

});


上面的就是一个静态的ColumnTree,在Ext的onReady函数中运行它。

3、、需要在页面中导入ext库、css、即我们编写的js

<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html>

<head>

<title>TreePanel示例</title>

<metahttp-equiv="Content-Type"content="text/html;charset=UTF-8"/>

<metahttp-equiv="author"content="hoojo"/>

<metahttp-equiv="email"content="hoojo_@126.com"/>

<metahttp-equiv="ext-lib"content="version2.2"/>

<metahttp-equiv="blog"content="http://blog.csdn.net/IBM_hoojo"/>

<metahttp-equiv="blog"content="http://hoojo.cnblogs.com"/>

<linkrel="stylesheet"type="text/css"href="ext2/resources/css/ext-all.css"/>

<linkrel="stylesheet"type="text/css"href="jslib/column-tree.css"/>

<scripttype="text/javascript"src="ext2/adapter/ext/ext-base.js"></script>

<scripttype="text/javascript"src="ext2/ext-all.js"></script>

<scripttype="text/javascript"src="ext2/build/locale/ext-lang-zh_CN-min.js"></script>

<scripttype="text/javascript"src="jslib/Ext.tree.ColumnTree.js"></script>

<scripttype="text/javascript"src="jslib/Ext.hoo.tree.UserColumnTree.js"></script>

</head>


<body>

<divid="show"style="margin-left:200px;"></div>

<divid="showBasic"style="margin-left:200px;margin-top:50px;"></div>

</body>

</html>


在浏览器中请求http://localhost:8080/S2SMyBatis/columnTree.htm

结果如下





4、下面编写远程数据的ColumnTree,代码如下:

Ext.ns("Ext.hoo.tree");

Ext.hoo.tree.UserBasicColumnTree=Ext.extend(Ext.tree.ColumnTree,{

constructor:function(){

Ext.hoo.tree.UserBasicColumnTree.superclass.constructor.call(this,{

renderTo:"showBasic",

title:"远程数据",

width:550,

hieght:400,

autoScroll:true,

rootVisible:true,

columns:[{

header:"编号",

width:100,

dataIndex:"accountId"

},{

header:"用户名称",

width:100,

dataIndex:"username"

},{

header:"密码",

width:100,

dataIndex:"password"

},{

header:"创建时间",

width:150,

dataIndex:"createTime"

}],

loader:newExt.tree.TreeLoader({

baseAttrs:{

uiProvider:Ext.tree.ColumnNodeUI

}

}),

root:newExt.tree.AsyncTreeNode({

text:"用户基本信息",

children:[]

}),

listeners:{

expandnode:{

fn:this.onExpandNode,

scope:this

}

}

});

},

onExpandNode:function(node){

//只对未加载过的添加子结点,加载后不在重复加载;避免增加请求,浪费资源

if(!node.attributes.isLoad){

Ext.Ajax.request({

url:Ext.hoo.tree.UserBasicColumnTree.TREE_DATA_URL,

success:function(response,options){

node.attributes.isLoad=true;//设置加载标识

varnodes=Ext.decode(response.responseText);//将json的text转换成js对象

node.appendChild(nodes.results);

},

failure:function(response){

Ext.Msg.alert("程序异常",response.responseText);

}

});

}

}

});


Ext.hoo.tree.UserBasicColumnTree.TREE_DATA_URL="account!treeData.action";


由于服务器端返回来的数据是一个对象,而不是一个Array。所以客户端要将数据稍作处理,然后再添加到columnTree的children中。

5、在上面的onReady中创建这个对象就可以了运行

Ext.onReady(function(){

Ext.BLANK_IMAGE_URL="ext2/resources/images/default/s.gif";

newExt.hoo.tree.UserColumnTree();

newExt.hoo.tree.UserBasicColumnTree();

});


同样在浏览器中请求http://localhost:8080/S2SMyBatis/columnTree.htm

可以看到





由于Account对象的数据形式不是一个完整的tree形态。所以展示效果就是上面的样子。正确的数据的格式的话,Account中至少包含以下属性:

Booleanleaf;Listchildren;这样就知道当前节点是否是叶子节点,并且知道其子元素。

作者:hoojo

出处:http://www.cnblogs.com/hoojo/archive/2011/05/11/2043453.html
blog:http://blog.csdn.net/IBM_hoojo

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: