??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲在成人网在线看,亚洲福利在线视频,久久精品国产亚洲av麻豆色欲http://www.tkk7.com/zjrstar/archive/2009/01/05/249857.html一叶笑?/dc:creator>一叶笑?/author>Mon, 05 Jan 2009 02:40:00 GMThttp://www.tkk7.com/zjrstar/archive/2009/01/05/249857.htmlhttp://www.tkk7.com/zjrstar/comments/249857.htmlhttp://www.tkk7.com/zjrstar/archive/2009/01/05/249857.html#Feedback0http://www.tkk7.com/zjrstar/comments/commentRss/249857.htmlhttp://www.tkk7.com/zjrstar/services/trackbacks/249857.html
很多人对二~存都不太了解,或者是有错误的认识Q我一直想写一文章介l一下hibernate的二U缓存的Q今天终于忍不住了?
我的l验主要来自hibernate2.1版本Q基本原理和3.0?.1是一LQ请原谅我的固不化?

hibernate的session提供了一U缓存,每个sessionQ对同一个idq行两次loadQ不会发送两条sqll数据库Q但是session关闭的时候,一U缓存就失效了?

二~存是SessionFactoryU别的全局~存Q它底下可以使用不同的缓存类库,比如ehcache、oscache{,需要设|hibernate.cache.provider_classQ我们这里用ehcacheQ在2.1中就?
hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider
如果使用查询~存Q加?
hibernate.cache.use_query_cache=true


~存可以单的看成一个MapQ通过key在缓存里面找value?

Class的缓?/strong>
对于一条记录,也就是一个PO来说Q是ҎID来找的,~存的key是IDQvalue是POJO。无论listQloadq是iterateQ只要读Z个对象,都会填充~存。但是list不会使用~存Q而iterate会先取数据库select id出来Q然后一个id一个id的loadQ如果在~存里面有,׃~存取,没有的话去数据库load。假设是d~存Q需要设|:
<cache usage="read-write"/>
如果你用的二~存实现是ehcache的话Q需要配|ehcache.xml
<cache name="com.xxx.pojo.Foo" maxElementsInMemory="500" eternal="false" timeToLiveSeconds="7200" timeToIdleSeconds="3600" overflowToDisk="true" />
其中eternal表示~存是不是永q不时QtimeToLiveSeconds是缓存中每个元素Q这里也是一个POJOQ的时旉Q如果eternal="false"Q超q指定的旉Q这个元素就被移C。timeToIdleSeconds是发呆时_是可选的。当往~存里面put的元素超q?00个时Q如果overflowToDisk="true"Q就会把~存中的部分数据保存在硬盘上的时文仉面?
每个需要缓存的class都要q样配置。如果你没有配置Qhibernate会在启动的时候警告你Q然后用defaultCache的配|,q样多个class会共享一个配|?
当某个ID通过hibernate修改Ӟhibernate会知道,于是U除~存?
q样大家可能会想Q同L查询条gQ第一ơ先listQ第二次再iterateQ就可以使用到缓存了。实际上q是很难的,因ؓ你无法判断什么时候是W一ơ,而且每次查询的条仉常是不一LQ假如数据库里面?00条记录,id??00Q第一ơlist的时候出了前50个idQ第二次iterate的时候却查询?0?0号idQ那?0-50是从~存里面取的Q?1?0是从数据库取的,共发?+20条sql。所以我一直认为iterate没有什么用QL会有1+N的问题?
Q题外话Q有说法说大型查询用list会把整个l果集装入内存,很慢Q而iterate只select id比较好,但是大型查询L要分|的,谁也不会真的把整个结果集装进来,假如一?0条的话,iterate共需要执?1条语句,list虽然选择若干字段Q比iterateW一条select id语句慢一些,但只有一条语句,不装入整个结果集hibernateq会Ҏ数据库方a做优化,比如使用mysql的limitQ整体看来应该还是list快。)
如果惌对list或者iterate查询的结果缓存,p用到查询~存?

查询~存
首先需要配|hibernate.cache.use_query_cache=true
如果用ehcacheQ配|ehcache.xmlQ注意hibernate3.0以后不是net.sf的包名了
<cache name="net.sf.hibernate.cache.StandardQueryCache"
   maxElementsInMemory="50" eternal="false" timeToIdleSeconds="3600"
   timeToLiveSeconds="7200" overflowToDisk="true"/>
<cache name="net.sf.hibernate.cache.UpdateTimestampsCache"
   maxElementsInMemory="5000" eternal="true" overflowToDisk="true"/>
然后
query.setCacheable(true);//ȀzL询缓?
query.setCacheRegion("myCacheRegion");//指定要用的cacheRegionQ可?
W二行指定要使用的cacheRegion是myCacheRegionQ即你可以给每个查询~存做一个单独的配置Q用setCacheRegion来做q个指定Q需要在ehcache.xml里面配置它:
<cache name="myCacheRegion" maxElementsInMemory="10" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200" overflowToDisk="true" />
如果省略W二行,不设|cacheRegion的话Q那么会使用上面提到的标准查询缓存的配置Q也是net.sf.hibernate.cache.StandardQueryCache

对于查询~存来说Q缓存的key是根据hql生成的sqlQ再加上参数Q分늭信息Q可以通过日志输出看到Q不q它的输Z是很可读Q最好改一下它的代码)?
比如hqlQ?
from Cat c where c.name like ?
生成大致如下的sqlQ?
select * from cat c where c.name like ?
参数?tiger%"Q那么查询缓存的key*大约*是这L字符Ԍ我是凭记忆写的,q不_Q不q看了也该明白了Q:
select * from cat c where c.name like ? , parameter:tiger%
q样Q保证了同样的查询、同L参数{条件下h一Lkey?
现在说说~存的valueQ如果是list方式的话Qvalue在这里ƈ不是整个l果集,而是查询出来的这一串ID。也是_不管是listҎq是iterateҎQ第一ơ查询的时候,它们的查询方式很它们qx的方式是一LQlist执行一条sqlQiterate执行1+N条,多出来的行ؓ是它们填充了~存。但是到同样条gW二ơ查询的时候,都和iterate的行Z样了Q根据缓存的keyȝ存里面查CvalueQvalue是一串idQ然后在到class的缓存里面去一个一个的load出来。这样做是ؓ了节U内存?
可以看出来,查询~存需要打开相关cȝclass~存。list和iterateҎW一ơ执行的时候,都是既填充查询缓存又填充class~存的?
q里q有一个很Ҏ被忽视的重要问题Q即打开查询~存以后Q即使是listҎ也可能遇?+N的问题!相同条gW一ơlist的时候,因ؓ查询~存中找不到Q不class~存是否存在数据QL发送一条sql语句到数据库获取全部数据Q然后填充查询缓存和class~存。但是第二次执行的时候,问题来了,如果你的class~存的超时时间比较短Q现在class~存都超时了Q但是查询缓存还在,那么listҎ在获取id串以后,会一个一个去数据库loadQ因此,class~存的超时时间一定不能短于查询缓存设|的时旉Q如果还讄了发呆时间的话,保证class~存的发呆时间也大于查询的缓存的生存旉。这里还有其他情况,比如class~存被程序强制evict了,q种情况p自己注意了?

另外Q如果hql查询包含select字句Q那么查询缓存里面的value是整个l果集了?

当hibernate更新数据库的时候,它怎么知道更新哪些查询~存呢?
hibernate在一个地方维护每个表的最后更新时_其实也就是放在上面net.sf.hibernate.cache.UpdateTimestampsCache所指定的缓存配|里面?
当通过hibernate更新的时候,hibernate会知道这ơ更新媄响了哪些表。然后它更新q些表的最后更新时间。每个缓存都有一个生成时间和q个~存所查询的表Q当hibernate查询一个缓存是否存在的时候,如果~存存在Q它q要取出~存的生成时间和q个~存所查询的表Q然后去查找q些表的最后更新时_如果有一个表在生成时间后更新q了Q那么这个缓存是无效的?
可以看出Q只要更新过一个表Q那么凡是涉及到q个表的查询~存失效了Q因此查询缓存的命中率可能会比较低?

Collection~存
需要在hbm的collection里面讄
<cache usage="read-write"/>
假如class是CatQcollection叫childrenQ那么ehcache里面配置
<cache name="com.xxx.pojo.Cat.children"
   maxElementsInMemory="20" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200"
   overflowToDisk="true" />
Collection的缓存和前面查询~存的list一P也是只保持一串idQ但它不会因个表更新q就失效Q一个collection~存仅在q个collection里面的元素有增删时才失效?
q样有一个问题,如果你的collection是根据某个字D|序的Q当其中一个元素更C该字D|Q导致顺序改变时Qcollection~存里面的顺序没有做更新?

~存{略
只读~存Qread-onlyQ:没有什么好说的
?写缓存(read-writeQ?E序可能要的更新数据
不严格的?写缓存(nonstrict-read-writeQ:需要更新数据,但是两个事务更新同一条记录的可能性很,性能比读写缓存好
事务~存QtransactionalQ:~存支持事务Q发生异常的时候,~存也能够回滚,只支持jta环境Q这个我没有怎么研究q?

d~存和不严格d~存在实C的区别在于,d~存更新~存的时候会把缓存里面的数据换成一个锁Q其他事务如果去取相应的~存数据Q发现被锁住了,然后q接取数据库查询?
在hibernate2.1的ehcache实现中,如果锁住部分~存的事务发生了异常Q那么缓存会一直被锁住Q直?0U后时?
不严D写缓存不锁定~存中的数据?


使用二~存的前|条?/strong>
你的hibernateE序Ҏ据库有独占的写访问权Q其他的q程更新了数据库Qhibernate是不可能知道的。你操作数据库必需直接通过hibernateQ如果你调用存储q程Q或者自׃用jdbc更新数据库,hibernate也是不知道的。hibernate3.0的大扚w更新和删除是不更CU缓存的Q但是据?.1已经解决了这个问题?
q个限制相当的棘手,有时候hibernate做批量更新、删除很慢,但是你却不能自己写jdbc来优化,很郁闷吧?
SessionFactory也提供了U除~存的方法,你一定要自己写一些JDBC的话Q可以调用这些方法移除缓存,q些Ҏ是:
void evict(Class persistentClass)
          Evict all entries from the second-level cache.
void evict(Class persistentClass, Serializable id)
          Evict an entry from the second-level cache.
void evictCollection(String roleName)
          Evict all entries from the second-level cache.
void evictCollection(String roleName, Serializable id)
          Evict an entry from the second-level cache.
void evictQueries()
          Evict any query result sets cached in the default query cache region.
void evictQueries(String cacheRegion)
          Evict any query result sets cached in the named query cache region.
不过我不q样做,因ؓq样很难l护。比如你现在用JDBC扚w更新了某个表Q有3个查询缓存会用到q个表,用evictQueries(String cacheRegion)U除?个查询缓存,然后用evict(Class persistentClass)U除了class~存Q看上去好像完整了。不q哪天你d了一个相x询缓存,可能会忘记更新这里的U除代码。如果你的jdbc代码到处都是Q在你添加一个查询缓存的时候,q知道其他什么地方也要做相应的改动吗Q?

----------------------------------------------------

ȝQ?/strong>
不要惛_然的以ؓ~存一定能提高性能Q仅仅在你能够驾驭它q且条g合适的情况下才是这L。hibernate的二U缓存限制还是比较多的,不方便用jdbc可能会大大的降低更新性能。在不了解原理的情况下ؕ用,可能会有1+N的问题。不当的使用q可能导致读数据?
如果受不了hibernate的诸多限Ӟ那么q是自己在应用程序的层面上做~存吧?
在越高的层面上做~存Q效果就会越好。就好像管盘有缓存,数据库还是要实现自己的缓存,管数据库有~存Q咱们的应用E序q是要做~存。因为底层的~存它ƈ不知道高层要用这些数据干什么,只能做的比较通用Q而高层可以有针对性的实现~存Q所以在更高的别上做缓存,效果也要好些吧?

]]>
[转脓]SSH2 - Struts2+Hibernate+Spring目结http://www.tkk7.com/zjrstar/archive/2008/12/26/248440.html一叶笑?/dc:creator>一叶笑?/author>Fri, 26 Dec 2008 05:45:00 GMThttp://www.tkk7.com/zjrstar/archive/2008/12/26/248440.htmlhttp://www.tkk7.com/zjrstar/comments/248440.htmlhttp://www.tkk7.com/zjrstar/archive/2008/12/26/248440.html#Feedback0http://www.tkk7.com/zjrstar/comments/commentRss/248440.htmlhttp://www.tkk7.com/zjrstar/services/trackbacks/248440.html
1、在web.xml中加载Spring的配|文?br /> <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/*.xml</param-value>
</context-param>

<!--Spring ApplicationContext 载入 -->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>


2、配|属性文?br /> <!-- 属性文件读?-->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:config/ct-db-c3p0.properties</value>
<value>classpath*:config/mail.properties</value>
</list>
</property>
</bean>

3、配|数据源
<!-- 数据源定?使用Apache c3p0 q接?-->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${....common.dbutils.c3p0.driver}" />
<property name="jdbcUrl" value="${....common.dbutils.c3p0.url}" />
<property name="user" value="${....common.dbutils.c3p0.user}" />
<property name="password" value="${....common.dbutils.c3p0.password}" />
<property name="maxStatementsPerConnection" value="${....common.dbutils.c3p0.maxStatementsPerConnection}"/>
<property name="checkoutTimeout" value="${....common.dbutils.c3p0.checkoutTimeout}"/>
<property name="initialPoolSize" value="${....common.dbutils.c3p0.initialPoolSize}"/>
<property name="minPoolSize" value="${....common.dbutils.c3p0.minPoolSize}"/>
<property name="maxPoolSize" value="${....common.dbutils.c3p0.maxPoolSize}"/>
<property name="maxStatements" value="${....common.dbutils.c3p0.maxStatements}"/>
<property name="acquireIncrement" value="${....common.dbutils.c3p0.acquireIncrement}"/>
<property name="maxIdleTime" value="${....common.dbutils.c3p0.maxIdleTime}"/>
</bean>

<!--Hibernate SessionFatory-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="annotatedClasses">
<list>
<!--dbean -->
<value>....bean.AddressBook</value>
.......
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.generate_statistics">false</prop>
<prop key="hibernate.connection.release_mode">auto</prop>
<prop key="hibernate.autoReconnect">true</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
</props>
</property>
</bean>

<!--Hibernate TransactionManager-->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>


4、依赖注入配|?br /> <bean id="companyAction" class="....action.CompanyAction" scope="request"></bean>
<bean name="companyBaseModel" class="....CompanyBaseModel"></bean>
<bean class="....CompanyService" id="companyService"></bean>
<bean class="....CompanyDAO" id="companyDAO"></bean>
注:对beans的设|?br /> <beans default-autowire="byName" default-lazy-init="true">...</beans>



5、Spring怎样注入Class<T>Q泛型类型对象)Q?br /> 在事务配|时Q将proxy-target-class讄为false卛_。不能ؓtrueQ因针对接口代理?br /> 如:<aop:config proxy-target-class="false">

6、Spring中采用构造方法注入注意要点:
在配|文件中昑ּ书写注入的参数。如Q?br /> <bean class="....impl.JobService"
id="retJobService">
<constructor-arg ref="retJobDao" />
</bean>
多个参数的构造函数示?br /> <bean class="....impl.TypeService"
id="typeService">
<constructor-arg index="0" ref="typeDAO" />
<constructor-arg index="1" type="boolean">
<value>false</value>
</constructor-arg>
</bean>


7、Spring 2.0 l合AspectJ pointcut语法配置AOP详解
Spring参考文?7.3 chema-based AOP support 提供了aspect,advisor,advide三种l装Ҏ的解释,其中aspect是aspectJ原装Q但E复杂,
<aop:config proxy-target-class="true">
<aop:advisor pointcut="execution(* *..BookManager.save(..))||execution(* *..BookManager.remove(..))" advice-ref="lowStockBookFlushingAdvice"/>
<aop:advisor pointcut="execution(* *..BookStockChecker.getLowStockBooks())" advice-ref="lowStockBookCachingAdvice"/>
</aop:config>
以上几句定义使用cglib创徏Proxy, 为BookManager的save()和remove()加上lowStockBookFlushingAdviceQؓ BookStockChecker.getLowStockBooks加上lowStockBookCachingAdvice.

execution(* *..BookManager.save(..))
W一? 代表ret-type-pattern q回值可LQ?br /> *..BookManager 代表LPacakge里的BookManagercR?br /> 如果写成com.xyz.service.* 则代表com.xyz.service下的Lc?br /> com.xyz.service..* com.xyz.service则代表com.xyz.service及其子package下的Lc?br /> save代表saveҎQ也可以写save* 代表saveBook(){方?br /> (..) 匚w0个参数或者多个参数的QQ意类?br /> (x,..) W一个参数的cd必须是X
(x,*,*,s,..) 匚w臛_4个参敎ͼW一个参数必LxcdQ第二个和第三个参数可以LQ第四个必须是scd?br />
8、事务配|的不同形式
事务配置一Q?br /> <!-- 支持 @AspectJ 标记-->
<aop:aspectj-autoproxy />

<!-- 以AspectJ方式 定义 AOP -->
<aop:config proxy-target-class="false">
<aop:advisor
pointcut="execution(* ....recruitment.service.impl..*.*(..)) || execution(* ....employeeinfo.service.impl..*Service.*(..))"
advice-ref="txAdvice" />
</aop:config>

<!-- 基本事务定义,使用transactionManager作事务管?默认get*Ҏ的事务ؓreadonly,其余Ҏ按默认设|?
默认的设|请参考Spring文档事务一? -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" propagation="REQUIRED" />
<tx:method name="load*" read-only="true" propagation="REQUIRED" />
<tx:method name="find*" read-only="true" propagation="REQUIRED" />
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>


事务配置二:
<!-- 支持 @AspectJ 标记-->
<aop:aspectj-autoproxy />

<!-- 以AspectJ方式 定义 AOP -->
<aop:config proxy-target-class="false">
<aop:advisor
pointcut="execution(* ....employeeinfo.service.impl..*Service.*(..))"
advice-ref="txAdvice" />

<aop:advisor
pointcut="execution(* ....recruitment.service.impl..*.*(..)) "
advice-ref="txAdviceRet" />
</aop:config>

<!-- 基本事务定义,使用transactionManager作事务管?默认get*Ҏ的事务ؓreadonly,其余Ҏ按默认设|?
默认的设|请参考Spring文档事务一? -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
......
</tx:attributes>
</tx:advice>
<tx:advice id="txAdviceRet"
transaction-manager="transactionManager">
<tx:attributes>
.........
</tx:attributes>
</tx:advice>

事务配置三:Q在java文g中配|)
需要单独配|事务的cd前配|事务开?br /> @Transactional(propagation = Propagation.SUPPORTS)
需要用事务的Ҏ前配|开启事务的信息
@Transactional(propagation = Propagation.REQUIRED)
如:
@Transactional(propagation = Propagation.SUPPORTS)
public class ApplierService extends BaseService<Applier> implements
IApplierService {
@Transactional(propagation = Propagation.REQUIRED)
public void addOrModify(Applier t) {
applierDao.saveOrUpdate(toDBValue(t));
}
}

9、正配|重写父cL法时事务
参阅Q?a target="_blank">http://aumy2008.javaeye.com/admin/blogs/152928

10、spring中bean的作用域详解
bean属性scope的选取Qprototype、request、session、global sessionQ:
<bean name="companyAction"
class="....CompanyAction" scope="prototype"/>
s:datetimepicker录入框提交正常?br /> prototype作用域部|的beanQ每一ơ请求(其注入到另一个bean中,或者以E序的方式调用容器的getBean()ҎQ?br /> 都会产生一个新的bean实例Q相当一个new的操作,对于prototype作用域的beanQ有一炚w帔R要,
那就是Spring不能对一个prototype bean的整个生命周期负责,
容器在初始化、配|、装饰或者是装配完一个prototype实例后,它交给客户端,
随后对该prototype实例不闻不问了。不何U作用域Q容器都会调用所有对象的初始化生命周期回调方法,
而对prototype而言QQ何配|好的析构生命周期回调方法都不会被调用?br /> 清除prototype作用域的对象q放Q何prototype bean所持有的昂贵资源,都是客户端代码的职责?br /> Q让Spring容器释放被singleton作用域bean占用资源的一U可行方式是Q通过使用bean的后|处理器Q?br /> 该处理器持有要被清除的bean的引用。)

request、session、global session使用的时候首先要在web.xml中做如下配置Q?br /> 如果你用的是Servlet 2.4及以上的web容器Q那么你仅需要在web应用的XML声明文gweb.xml中增加下qContextListener卛_Q?br /> <listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

<bean name="companyAction"
class="....action.CompanyAction" scope="request"/>
s:datetimepicker录入框提交正常?br />
<bean name="companyAction"
class="....action.CompanyAction" scope="session"/>
s:datetimepicker录入框不能正常提交?br />
<bean name="companyAction"
class="....action.CompanyAction" scope="global session"/>
java.lang.IllegalStateException: No Scope registered for scope 'global session'
分析Qglobal session作用域类g标准的HTTP Session作用域,不过它仅仅在Zportlet的web应用中才有意义?br />
Spring中bean的作用域相关|站Q?br /> http://doc.javanb.com/spring-framework-reference-zh-2-0-5/ch03s04.html


]]>
[转脓]Hibernate 的jar?/title><link>http://www.tkk7.com/zjrstar/archive/2008/12/24/248067.html</link><dc:creator>一叶笑?/dc:creator><author>一叶笑?/author><pubDate>Wed, 24 Dec 2008 06:30:00 GMT</pubDate><guid>http://www.tkk7.com/zjrstar/archive/2008/12/24/248067.html</guid><wfw:comment>http://www.tkk7.com/zjrstar/comments/248067.html</wfw:comment><comments>http://www.tkk7.com/zjrstar/archive/2008/12/24/248067.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/zjrstar/comments/commentRss/248067.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/zjrstar/services/trackbacks/248067.html</trackback:ping><description><![CDATA[原文地址Q?a >http://www.ilina.cn/cto/p278/J27834217.shtml</a><br /> <br /> <p class="g_w_100 g_t_wrap g_t_center g_t_bold g_t_24 g_c_pdin c07" id="blogtitle_fks_085066084094083074086082085095085081088071083082083070">Hibernate 的jar包说明(转)<br /> </p> <p style="text-indent: 2em">Hibernate一共包括了23个jar包,令hD~ؕ。下载HibernateQ例?.0.3E_版本Q解压羃Q可以看C个hibernate2.jar和lib目录下有22个jar包: </p> <p style="text-indent: 2em">Q?Qhibernate2.jar: </p> <p style="text-indent: 2em">  Hibernate的库Q没有什么可说的Q必M用的jar?</p> <p style="text-indent: 2em">Q?Qcglib-asm.jar: </p> <p style="text-indent: 2em">  CGLIB库,Hibernate用它来实现PO字节码的动态生成,非常核心的库Q必M用的jar?</p> <p style="text-indent: 2em">Q?Qdom4j.jar: </p> <p style="text-indent: 2em">  dom4j是一个Java的XML APIQ类gjdomQ用来读写XML文g的。dom4j是一个非帔R怼U的Java XML APIQ具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的YӞ可以在SourceForge上找到它。在IBM developerWorks上面可以扑ֈ一文章,对主的Java XML APIq行的性能、功能和易用性的评测Qdom4j无论在那个方面都是非常出色的。我早在近两年之前开始用dom4jQ直到现在。如今你可以看到来多的Java软g都在使用dom4j来读写XMLQ特别值得一提的是连Sun的JAXM也在用dom4j。这是必M用的jar包,Hibernate用它来读写配|文件?</p> <p style="text-indent: 2em">Q?Qodmg.jar: </p> <p style="text-indent: 2em">  ODMG是一个ORM的规范,Hibernate实现了ODMG规范Q这是一个核心的库,必须使用的jar包?</p> <p style="text-indent: 2em">Q?Qcommons-collections.jarQ?</p> <p style="text-indent: 2em">  Apache Commons包中的一个,包含了一些Apache开发的集合c,功能比java.util.*强大。必M用的jar包?</p> <p style="text-indent: 2em">Q?Qcommons-beanutils.jarQ?</p> <p style="text-indent: 2em">  Apache Commons包中的一个,包含了一些Bean工具cȝ。必M用的jar包?</p> <p style="text-indent: 2em">Q?Qcommons-lang.jar: </p> <p style="text-indent: 2em">  Apache Commons包中的一个,包含了一些数据类型工LQ是java.lang.*的扩展。必M用的jar包?</p> <p style="text-indent: 2em">Q?Qcommons-logging.jar: </p> <p style="text-indent: 2em">  Apache Commons包中的一个,包含了日志功能,必须使用的jar包。这个包本n包含了一个Simple LoggerQ但是功能很弱。在q行的时候它会先在CLASSPATH找log4jQ如果有Q就使用log4jQ如果没有,找JDK1.4带的java.util.loggingQ如果也找不到就用Simple Logger。commons-logging.jar的出现是一个历史的的遗留的遗憾Q当初Apache极力游说Sun把log4j加入JDK1.4Q然而JDK1.4目组已经接近发布JDK1.4产品的时间了Q因此拒l了Apache的要求,使用自己的java.util.loggingQ这个包的功能比log4j差的很远Q性能也一般?/p> <p style="text-indent: 2em">  后来Apache开发出来了commons-logging.jar用来兼容两个logger。因此用commons-logging.jar写的logE序Q底层的Logger是可以切换的Q你可以选择log4jQjava.util.logging或者它自带的Simple Logger。不q我仍然强烈使用log4jQ因为log4j性能很高Qlog输出信息旉几乎{于System.outQ而处理一条logq_只需?us。你可以在Hibernate的src目录下找到Hibernate已经Z准备好了的log4j的配|文Ӟ你只需要到Apache |站M载log4j可以了。commons-logging.jar也是必须的jar包?</p> <p style="text-indent: 2em">使用Hibernate必须的jar包就是以上的q几个,剩下的都是可选的?</p> <p style="text-indent: 2em">  ant.jar: </p> <p style="text-indent: 2em">  Ant~译工具的jar包,用来~译Hibernate源代码的。如果你不准备修改和~译Hibernate源代码,那么没有什么用Q可选的jar?</p> <p style="text-indent: 2em">  optional.jarQ?</p> <p style="text-indent: 2em">  Ant的一个辅助包?</p> <p style="text-indent: 2em">  c3p0.jarQ?</p> <p style="text-indent: 2em">  C3PO是一个数据库q接池,Hibernate可以配置Z用C3POq接池。如果你准备用这个连接池Q就需要这个jar包?</p> <p style="text-indent: 2em">  proxool.jarQ?</p> <p style="text-indent: 2em">  也是一个连接池Q同上?</p> <p style="text-indent: 2em">  commons-pool.jar, commons-dbcp.jar: </p> <p style="text-indent: 2em">  DBCP数据库连接池QApache的Jakartal织开发的QTomcat4的连接池也是DBCP?</p> <p style="text-indent: 2em">  实际上Hibernate自己也实C一个非帔R常简单的数据库连接池Q加上上?个,你实际上可以在Hibernate上选择4U不同的数据库连接池Q选择哪一个看个h的偏好,不过DBCP可能更通用一些。另外强调一点,如果在EJB中用HibernateQ一定要用App Server的连接池Q不要用以上4U连接池Q否则容器管理事务不起作用?</p> <p style="text-indent: 2em">  connector.jar: </p> <p style="text-indent: 2em">  JCA 规范Q如果你在App Server上把Hibernate配置为Connector的话Q就需要这个jar。不q实际上一般App Server肯定会带上这个包Q所以实际上是多余的包?</p> <p style="text-indent: 2em">  jaas.jar: </p> <p style="text-indent: 2em">  JAAS是用来进行权限验证的Q已l包含在JDK1.4里面了。所以实际上是多余的包?</p> <p style="text-indent: 2em">  jcs.jarQ?</p> <p style="text-indent: 2em">  如果你准备在Hibernate中用JCS的话Q那么必d括它Q否则就不用?</p> <p style="text-indent: 2em">  jdbc2_0-stdext.jar: </p> <p style="text-indent: 2em">  JDBC2.0的扩展包Q一般来说数据库q接池会用上它。不qApp Server都会带上Q所以也是多余的?</p> <p style="text-indent: 2em">  jta.jarQ?</p> <p style="text-indent: 2em">  JTA规范Q当Hibernate使用JTA的时候需要,不过App Server都会带上Q所以也是多余的?</p> <p style="text-indent: 2em">  junit.jar: </p> <p style="text-indent: 2em">  Junit包,当你q行Hibernate自带的测试代码的时候需要,否则׃用?</p> <p style="text-indent: 2em">  xalan.jar, xerces.jar, xml-apis.jar: </p> <p style="text-indent: 2em">  Xerces是XML解析器,Xalan是格式化器,xml-apis实际上是JAXP。一般App Server都会带上QJDK1.4也包含了解析器,不过不是XercesQ是CrimsonQ效率比较差Q不qHibernate用XML只不q是d配置文gQ性能没什么紧要的Q所以也是多余的?/p> <p style="text-indent: 2em"> <table> <tbody> <tr> <td> <p> </p> <p style="text-indent: 2em"><a >ant-1.63.jar</a></p> <p style="text-indent: 2em">http://ant.apache.org/                                   </p> <p style="text-indent: 2em">Ant 的核心包,在构建Hibernate 时会用到</p> <p style="text-indent: 2em"><a >antlr-2.7.5H3.jar</a></p> <p style="text-indent: 2em">http://www.antlr.org/                                      </p> <p style="text-indent: 2em">语言转换?Hibernate利用它实?HQL ?SQL的{?/p> <p style="text-indent: 2em"><a >asm.jar/asm-attrs.jar </a></p> <p style="text-indent: 2em">http://asm.objectweb.org/                              </p> <p style="text-indent: 2em">ASM 字节转换?/p> <p style="text-indent: 2em"><a >c3p0-0.8.5.2.jar</a></p> <p style="text-indent: 2em">http://sourceforge.net/projects/c3p0            </p> <p style="text-indent: 2em">C3PO JDBC q接池工?/p> <p style="text-indent: 2em"><a >cglib-2.1.jar</a></p> <p style="text-indent: 2em">http://cglib.sourceforge.net/                          </p> <p style="text-indent: 2em">高效的代码生成工? Hibernate用它在运行时扩展 Javacd实现 Java 接口</p> <p style="text-indent: 2em"><a >commons-collections-2.1.1.jar</a></p> <p style="text-indent: 2em">http://jakarta.apache.org/commons/collections</p> <p style="text-indent: 2em">Apache 的工具集,用来增强Java寚w合的处理能力</p> <p style="text-indent: 2em"></p> <p style="text-indent: 2em"><a >commons-logging-1.0.4.jar</a></p> <p style="text-indent: 2em">http://jakarta.apache.org/commons/logging/  </p> <p style="text-indent: 2em">Apache 软g基我l所提供的日志工?/p> <p style="text-indent: 2em"></p> <p style="text-indent: 2em"><a >concurrent-1.3.2.jar</a></p> <p style="text-indent: 2em">http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html              </p> <p style="text-indent: 2em">U程同步工具,在用JBoss 的树状缓存时需要用?/p> <p style="text-indent: 2em"><a >connector.jar</a></p> <p style="text-indent: 2em">http://java.sun.com/j2ee/connector/                 </p> <p style="text-indent: 2em">用连接多个应用服务器的标准连接器</p> <p style="text-indent: 2em"><a >dom4j-1.6.jar</a></p> <p style="text-indent: 2em">http://dom4.j.org/                                             </p> <p style="text-indent: 2em">dom4j XML 解析?/p> <p style="text-indent: 2em"><a >ehcache-1.1.jar</a></p> <p style="text-indent: 2em">http://sourceforge.net/projects/echache  </p> <p style="text-indent: 2em">~存工具.在没有提供其他缓存工h,q个~存工具是必不可的</p> <p style="text-indent: 2em"><a >jaas.jar</a></p> <p style="text-indent: 2em">http://java.sun.com/products/jass/                    </p> <p style="text-indent: 2em">标准?Java 权限和认证服务包</p> <p style="text-indent: 2em"><a >jaxen-1.1-beta-4.jar</a></p> <p style="text-indent: 2em">http:jaxen.org/                                                  </p> <p style="text-indent: 2em">通用?XPath 处理引擎</p> <p style="text-indent: 2em"><a >jboss-cache.jar</a></p> <p style="text-indent: 2em">http://www.jboss.com/products/jbosscache     </p> <p style="text-indent: 2em">JBoss 的一U树状缓存实现工?/p> <p style="text-indent: 2em"><a >jboss-common.jar</a></p> <p style="text-indent: 2em">http://jboss.org/                                                 </p> <p style="text-indent: 2em">Jboss 的基?在?JBoss 的树状缓存时必须有此?/p> <p style="text-indent: 2em"><a >jboss-jmx.jar</a></p> <p style="text-indent: 2em">http://jboss.org/                                                 </p> <p style="text-indent: 2em">JBoss ?JMX 实现?/p> <p style="text-indent: 2em"><a >jboss-system.jar</a></p> <p style="text-indent: 2em">http://jboss.org/                                                 </p> <p style="text-indent: 2em">JBoss 的核?包括服务器和部v引擎</p> <p style="text-indent: 2em"><a >jdbc2_0-stdext.jar</a></p> <p style="text-indent: 2em">http://java.sun.com/products/jdbc/download.html#spec                    </p> <p style="text-indent: 2em">标准?JDBC 2.0 扩展API</p> <p style="text-indent: 2em"><a >jgroups2.2.7.jar</a></p> <p style="text-indent: 2em">http://www.jgroups.org/                                      </p> <p style="text-indent: 2em">|络通信工具?/p> <p style="text-indent: 2em"><a >jta.jar</a></p> <p style="text-indent: 2em">http://java.sun.com/products/jta                        </p> <p style="text-indent: 2em">标准?JAVA 事务处理接口</p> <p style="text-indent: 2em"><a >junit-3.8.1.jar</a></p> <p style="text-indent: 2em">http://www.junit.org/                                         </p> <p style="text-indent: 2em">JUnit 试框架</p> <p style="text-indent: 2em"><a >log4.j-1.2.9.jar</a></p> <p style="text-indent: 2em">http://logging.apache.org/log4j/                         </p> <p style="text-indent: 2em">log4j ?Apache 的日志工?/p> <p style="text-indent: 2em"><a >oscache-2.1.jar</a></p> <p style="text-indent: 2em">http://www.opensymphony.com/oscache/         </p> <p style="text-indent: 2em">Java 对象的缓存工?/p> <p style="text-indent: 2em"><a >proxool-0.8.3.jar</a></p> <p style="text-indent: 2em">http://proxool.sourceforge.net/                          </p> <p style="text-indent: 2em">Proxool JDBC q接池工?/p> <p style="text-indent: 2em"><a >swarmcache-1.0rc2.jar</a></p> <p style="text-indent: 2em">http://swarmcache.sourceforge.net/                  </p> <p style="text-indent: 2em">Hibernate 可以使用的一U缓存工?/p> <p style="text-indent: 2em">versioncheck.jar </p> <p style="text-indent: 2em">版本查工具包,用于在构建Hibernate 的时候检查辅?jar 包文件的版本</p> <p style="text-indent: 2em"><a >xerces-2.6.2.jar</a></p> <p style="text-indent: 2em">http://xml.apache.org/xerces2-j/                        </p> <p style="text-indent: 2em">SAX XML 解析?/p> <p style="text-indent: 2em"><a >xml-apis.jar</a></p> <p style="text-indent: 2em">http://xml.apache.org/xerces2-j/                        </p> <p style="text-indent: 2em">Java语言中标准的XML 解析?/p> </td> </tr> </tbody> </table> </p> <p class="g_w_100 g_t_wrap g_t_center g_t_bold g_t_24 g_c_pdin c07" id="blogtitle_fks_085066084094083074086082085095085081088071083082083070"><br /> <br />  </p> <img src ="http://www.tkk7.com/zjrstar/aggbug/248067.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/zjrstar/" target="_blank">一叶笑?/a> 2008-12-24 14:30 <a href="http://www.tkk7.com/zjrstar/archive/2008/12/24/248067.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转脓]Struts相关jar?/title><link>http://www.tkk7.com/zjrstar/archive/2008/12/24/248065.html</link><dc:creator>一叶笑?/dc:creator><author>一叶笑?/author><pubDate>Wed, 24 Dec 2008 06:27:00 GMT</pubDate><guid>http://www.tkk7.com/zjrstar/archive/2008/12/24/248065.html</guid><wfw:comment>http://www.tkk7.com/zjrstar/comments/248065.html</wfw:comment><comments>http://www.tkk7.com/zjrstar/archive/2008/12/24/248065.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/zjrstar/comments/commentRss/248065.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/zjrstar/services/trackbacks/248065.html</trackback:ping><description><![CDATA[原文地址Qhttp://blog.163.com/panyonglong_917/blog/static/179474552008728112039503/<br /> <br />                                                     Struts相关jar包简?nbsp; <br /> <br /> <strong>commons-beanutils.jar</strong> <div>Commons-Beanutils q个是jakarta commons目中的一个子目。这个项目开发的目的是帮助开发者动态的获取/讑րJava Bean的属性,同时解决每次都要写getXXX和setXXX的麻烦?</div> <div><strong>commons-digester.jar</strong> </div> <div>Digester本来仅仅是Jakarta Struts中的一个工P用于处理struts-config.xml配置文g。显ӞXML文g转换成相应的Java对象是一很通用的功能,q个工具理应h更广泛的用途,所以很快它在Jakarta Commons目(用于提供可重用的Javalg?中有了一席之地?</div> <div>在内部, Struts 使用来自于Jakarta Commons[ASF, Commons] 目的Digester 来解析Struts配置文g。Digester 使用struts-config DTD 来校验文档的格式Qƈ且创建文档所描述的Java对象。如果XML文g包含了非正式文档化的元素Q或者以非正式文档化的方式用了元素QDigester 不会处理这个文件?</div> <div><strong>commons-fileupload.jar</strong> </div> <div>Commons-FileUpload FileUpload 使得在你可以在应用和Servlet中容易的加入强大和高性能的文件上传能力struts中上传文件要用到?/div> <div>struts的验证框架依赖以下的两个包:</div> <div><strong> commons-validator.jar</strong> </div> <div>(校验Ҏ)和校验规则。支持校验规则的和错误消息的国际化?struts使用它对表单q行验证?</div> <div><strong>    jakarta-oro.jar</strong> </div> <div>Commons-EL Commons-Jexl Search Jakarta ORO Jakarta ORO一套文本处理工?能提供perl5.0兼容的正则表辑ּ,AWK-like正则表达? glob表达式。还提供替换,分割,文g名过虑等功能?/div> <div><strong>struts.jar</strong></div> <div>struts核心包?/div> <div>其他的一下jar?/div> <div><strong>commons-collections.jar</strong></div> <div>扩展了标准的Java Collection框架Q提供了额外的Map、List 和Set实现以及多个有用的工L库。功能比java.util.*强大?/div> <div><strong>commons-logging.jar:</strong> </div> <div>Apache Commons包中的一个,包含了日志功能。这个包本n包含了一个Simple LoggerQ但是功能很弱。在q行的时候它会先在CLASSPATH找log4jQ如果有Q就使用log4jQ如果没有,找JDK1.4带的 java.util.loggingQ如果也找不到就用Simple Logger。commons-logging.jar的出现是一个历史的的遗留的遗憾Q当初Apache极力游说Sun把log4j加入JDK1.4Q然而JDK1.4目组已经接近发布JDK1.4产品的时间了Q因此拒l了Apache的要求,使用自己的java.util.loggingQ这个包的功能比log4j差的很远Q性能也一般?/div> <div>后来Apache开发出来了commons-logging.jar用来兼容两个 logger。因此用commons-logging.jar写的logE序Q底层的Logger是可以切换的Q你可以选择 log4jQjava.util.logging或者它自带的Simple Logger。不q我仍然强烈使用log4jQ因为log4j性能很高Qlog输出信息旉几乎{于System.outQ而处理一条logq_只需?us。你可以在Hibernate的src目录下找到Hibernate已经Z准备好了的log4j的配|文Ӟ你只需要到Apache |站M载log4j可以了。commons-logging.jar也是必须的jar包?/div> <img src ="http://www.tkk7.com/zjrstar/aggbug/248065.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/zjrstar/" target="_blank">一叶笑?/a> 2008-12-24 14:27 <a href="http://www.tkk7.com/zjrstar/archive/2008/12/24/248065.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转脓]spring jar 包详?/title><link>http://www.tkk7.com/zjrstar/archive/2008/12/24/248064.html</link><dc:creator>一叶笑?/dc:creator><author>一叶笑?/author><pubDate>Wed, 24 Dec 2008 06:22:00 GMT</pubDate><guid>http://www.tkk7.com/zjrstar/archive/2008/12/24/248064.html</guid><wfw:comment>http://www.tkk7.com/zjrstar/comments/248064.html</wfw:comment><comments>http://www.tkk7.com/zjrstar/archive/2008/12/24/248064.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/zjrstar/comments/commentRss/248064.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/zjrstar/services/trackbacks/248064.html</trackback:ping><description><![CDATA[原文位置Qhttp://blog.163.com/panyonglong_917/blog/static/179474552008728112259392/<br /> <br /> <p class="g_w_100 g_t_wrap g_t_center g_t_bold g_t_24 g_c_pdin c07" id="blogtitle_fks_085066084095084066081087086095085081088071083082083070">                                                                         spring jar 包详?br /> spring.jar是包含有完整发布的单个jar包,spring.jar中包含除?spring-mock.jar里所包含的内容外其它所有jar包的内容Q因为只有在开发环境下才会用到spring-mock.jar来进行辅助测试,正式应用pȝ中是用不得这些类的。  除了spring.jar文gQSpringq包括有其它13个独立的jar包,各自包含着对应的SpringlgQ用户可以根据自q需要来选择l合自己的jar包,而不必引入整个spring.jar的所有类文g?br />  (1) spring-core.jar q个jar文g包含Spring框架基本的核心工LQSpring其它lg要都要用到q个包里的类Q是其它lg的基本核心,当然你也可以在自q应用pȝ中用这些工L?br />  (2) spring-beans.jar q个jar文g是所有应用都要用到的Q它包含讉K配置文g、创建和理bean以及q行Inversion of Control / Dependency InjectionQIoC/DIQ操作相关的所有类。如果应用只需基本的IoC/DI支持Q引入spring-core.jar及spring- beans.jar文g可以了?<br /> (3) spring-aop.jar q个jar文g包含在应用中使用Spring的AOPҎ时所需的类。用基于AOP的SpringҎ,如声明型事务理QDeclarative Transaction ManagementQ,也要在应用里包含q个jar包?br />  (4) spring-context.jar   q个jar文g为Spring核心提供了大量扩展。可以找C用Spring ApplicationContextҎ时所需的全部类QJDNI所需的全部类QUI斚w的用来与模板QTemplatingQ引擎如 Velocity、FreeMarker、JasperReports集成的类Q以及校验Validation斚w的相关类?<br /> (5) spring-dao.jar   q个jar文g包含Spring DAO、Spring Transactionq行数据讉K的所有类。ؓ了用声明型事务支持Q还需在自q应用里包含spring-aop.jar?<br /> (6) spring-hibernate.jar   q个jar文g包含Spring对Hibernate 2及Hibernate 3q行装的所有类?<br /> (7) spring-jdbc.jar   q个jar文g包含对Spring对JDBC数据讉Kq行装的所有类?br />  (8) spring-orm.jar   q个jar文g包含Spring对DAOҎ集q行了扩展,使其支持 iBATIS、JDO、OJB、TopLinkQ因为Hibernate已经独立成包了,现在不包含在q个包里了。这个jar文g里大部分的类都要依赖 spring-dao.jar里的c,用这个包时你需要同时包含spring-dao.jar包?br />  (9) spring-remoting.jar   q个jar文g包含支持EJB、JMS、远E调用RemotingQRMI、Hessian、Burlap、Http Invoker、JAX-RPCQ方面的cR?<br /> (10) spring-support.jar   q个jar文g包含支持~存CacheQehcacheQ、JCA、JMX、邮件服务(Java Mail、COS MailQ、Q务计划SchedulingQTimer、QuartzQ方面的cR?br />  (11) spring-web.jar   q个jar文g包含Web应用开发时Q用到Spring框架时所需的核心类Q包括自动蝲入WebApplicationContextҎ的cR?Struts与JSF集成cR文件上传的支持cRFiltercd大量工具辅助cR?br />  (12) spring-webmvc.jar   q个jar文g包含Spring MVC框架相关的所有类。包含国际化、标{、Theme、视囑ֱ现的FreeMarker、JasperReports、Tiles、Velocity?XSLT相关cR当Ӟ如果你的应用使用了独立的MVC框架Q则无需q个JAR文g里的McR?<br /> (13) spring-mock.jar   q个jar文g包含Spring一整套mockcL辅助应用的测试。Spring试套g使用了其中大量mockc,q样试更加简单。模?HttpServletRequest和HttpServletResponsecdWeb应用单元试是很方便的。  <br /> 如何选择q些发布包,军_选用哪些发布包其实相当简单。如果你正在构徏Web应用q将全程使用SpringQ那么最好就使用单个全部?spring.jar文gQ如果你的应用仅仅用到简单的Inversion of Control / Dependency InjectionQIoC/DIQ容器,那么只需spring-core.jar与spring-beans.jar卛_Q如果你对发布的大小要求很高Q那么就得精挑细选了Q只取包含自己所需Ҏ的jar文g了。采用独立的发布包你可以避免包含自己的应用不需要的全部cR当然你可以采用其它的一些工h设法令整个应用包变小Q节省空间的重点在于准确地找己所需的Spring依赖c,然后合ƈ所需的类与包可以了。Eclispe有个插g?ClassPath Helper可以帮你找找所依赖的类?<br /> <br /> Spring包依赖说? <br /> 1) spring-core.jar需commons-collections.jarQspring-core.jar是以下其它各个的基本?br />  2) spring-beans.jar需spring-core.jarQcglib-nodep-2.1_3.jar <br /> 3) spring-aop.jar需spring-core.jarQspring-beans.jarQcglib-nodep- 2.1_3.jarQaopalliance.jar <br /> 4) spring-context.jar需spring-core.jarQspring-beans.jarQspring- aop.jarQcommons-collections.jarQaopalliance.jar <br /> 5) spring-dao.jar需spring-core.jarQspring-beans.jarQspring-aop.jarQspring- context.jar <br /> 6) spring-jdbc.jar需spring-core.jarQspring-beans.jarQspring-dao.jar <br /> 7) spring-web.jar需spring-core.jarQspring-beans.jarQspring-context.jar <br /> 8) spring-webmvc.jar需spring-core.jar/spring-beans.jar/spring-context.jar /spring-web.jar <br /> 9) spring -hibernate.jar需spring-core.jarQspring-beans.jarQspring-aop.jarQspring- dao.jarQspring-jdbc.jarQspring-orm.jarQspring-web.jarQspring-webmvc.jar <br /> 10) spring-orm.jar需spring-core.jarQspring-beans.jarQspring-aop.jarQspring- dao.jarQspring-jdbc.jarQspring-web.jarQspring-webmvc.jar <br /> 11) spring -remoting.jar需spring-core.jarQspring-beans.jarQspring-aop.jarQspring- dao.jarQspring-context.jarQspring-web.jarQspring-webmvc.jar <br /> 12) spring-support.jar需spring-core.jarQspring-beans.jarQspring- aop.jarQspring-dao.jarQspring-context.jarQspring-jdbc.jar <br /> 13) spring-mock.jar需spring-core.jarQspring-beans.jarQspring-dao.jarQspring- context.jarQspring-jdbc.jar <br /> </p> <img src ="http://www.tkk7.com/zjrstar/aggbug/248064.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/zjrstar/" target="_blank">一叶笑?/a> 2008-12-24 14:22 <a href="http://www.tkk7.com/zjrstar/archive/2008/12/24/248064.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转脓]Spring JTA应用之Atomikos配置 http://www.tkk7.com/zjrstar/archive/2008/12/23/247924.html一叶笑?/dc:creator>一叶笑?/author>Tue, 23 Dec 2008 07:47:00 GMThttp://www.tkk7.com/zjrstar/archive/2008/12/23/247924.htmlhttp://www.tkk7.com/zjrstar/comments/247924.htmlhttp://www.tkk7.com/zjrstar/archive/2008/12/23/247924.html#Feedback0http://www.tkk7.com/zjrstar/comments/commentRss/247924.htmlhttp://www.tkk7.com/zjrstar/services/trackbacks/247924.htmlhttp://tom-duan.javaeye.com/blog/147599

Atomikos,是一个基于Java的开源事务管理器Q提供了事务理和连接池Q不需要应用服务器支持Q支持JDBC和JMS事务Q能提供对SpringQHibernate的集成,有兴多了解的可以直接参考说明文当,有详l的介绍和用说明?

Atomikos可以到http://www.atomikos.com/products.html#ate下蝲,最新版本是3.2.0

首先,仍然是一个相关的配置文gQ用来设|相关的环境,打开解压~后Atomikos根目?拯jta.properties到classpath中,q修改ؓ如下内容
jta.properties
Java代码
  1. com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory   
  2. com.atomikos.icatch.console_file_name = tm.out   
  3. com.atomikos.icatch.log_base_name = tmlog   
  4. com.atomikos.icatch.tm_unique_name = com.atomikos.spring.jdbc.tm   
  5. com.atomikos.icatch.console_log_level = INFO   


随后Q是Spring上下文配|,建立一个名为ApplicationContext-atomikos.xml的Spring上下?

ApplicationContext-atomikos.xml
Java代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">   
  5.     <!-- XA Datasource -->   
  6.     <bean id="datasource1" class="com.atomikos.jdbc.SimpleDataSourceBean" init-method="init" destroy-method="close">      
  7.         <property name="uniqueResourceName">      
  8.             <value>mysql/main</value>      
  9.         </property>      
  10.         <property name="xaDataSourceClassName">      
  11.             <value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value>      
  12.         </property>      
  13.         <property name="xaDataSourceProperties">      
  14.             <value>URL=jdbc:mysql://localhost:3306/test;user=root;password=admin</value>      
  15.         </property>      
  16.         <property name="exclusiveConnectionMode">      
  17.             <value>true</value>      
  18.         </property>      
  19.         <property name="connectionPoolSize">      
  20.             <value>3</value>      
  21.         </property>      
  22.         <property name="validatingQuery">      
  23.             <value>SELECT 1</value>      
  24.         </property>      
  25.     </bean>   
  26.        
  27.     <bean id="datasource2" class="com.atomikos.jdbc.SimpleDataSourceBean" init-method="init" destroy-method="close">      
  28.         <property name="uniqueResourceName">      
  29.             <value>mysql/news</value>   
  30.         </property>      
  31.         <property name="xaDataSourceClassName">      
  32.             <value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value>      
  33.         </property>   
  34.         <property name="xaDataSourceProperties">      
  35.             <value>URL=jdbc:mysql://localhost:3306/test2;user=root;password=admin</value>      
  36.         </property>      
  37.         <property name="exclusiveConnectionMode">      
  38.             <value>true</value>      
  39.         </property>      
  40.         <property name="connectionPoolSize">      
  41.             <value>3</value>      
  42.         </property>      
  43.         <property name="validatingQuery">      
  44.             <value>SELECT 1</value>      
  45.         </property>      
  46.     </bean>   
  47.        
  48.     <bean id="template1" class="org.springframework.jdbc.core.JdbcTemplate">   
  49.         <property name="dataSource" ref="datasource1" />   
  50.     </bean>   
  51.        
  52.     <bean id="template2" class="org.springframework.jdbc.core.JdbcTemplate">   
  53.         <property name="dataSource" ref="datasource2" />   
  54.     </bean>   
  55.            
  56.     <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">   
  57.         <property name="forceShutdown"><value>true</value></property>   
  58.     </bean>   
  59.        
  60.     <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">   
  61.         <property name="transactionTimeout" value="300"/>    
  62.     </bean>   
  63.   
  64.     <bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">   
  65.         <property name="transactionManager"><ref bean="atomikosTransactionManager"  /></property>   
  66.         <property name="userTransaction"><ref bean="atomikosUserTransaction"  /></property>   
  67.     </bean>   
  68.        
  69.     <bean id="dao1" class="com.xa.dao.UserDao1">   
  70.         <property name="jdbcTemplate">   
  71.             <ref bean="template1"></ref>   
  72.         </property>   
  73.     </bean>   
  74.        
  75.     <bean id="dao2" class="com.xa.dao.UserDao2">   
  76.         <property name="jdbcTemplate">   
  77.             <ref bean="template2"></ref>   
  78.         </property>   
  79.     </bean>   
  80.     <!-- -->   
  81.     <bean id="userServiceTarget" class="com.xa.service.UserServiceImpl">   
  82.         <property name="dao1" ref="dao1"/>   
  83.         <property name="dao2" ref="dao2"/>   
  84.     </bean>   
  85.        
  86.     <bean id="userTest" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">       
  87.         <property name="transactionManager">   
  88.             <ref bean="springTransactionManager"/>   
  89.         </property>       
  90.         <property name="target">   
  91.             <ref bean="userServiceTarget"/>   
  92.         </property>   
  93.         <property name="transactionAttributes">           
  94.             <props>   
  95.                 <prop key="insert*">PROPAGATION_REQUIRED,-Exception</prop>               
  96.             </props>   
  97.         </property>   
  98.     </bean>   
  99. </beans>  


看上下文中的代码Q很大部分和JOTM的相|atomikos使用com.atomikos.jdbc.SimpleDataSourceBeancL创徏datasource beanQ这里需要特别注?
Java代码
  1. <property name="uniqueResourceName">      
  2.     <value>mysql/main</value>      
  3. </property>    


Java代码
  1. <property name="uniqueResourceName">      
  2.     <value>mysql/news</value>   
  3. </property>  

上面的代码ؓ每个Datasource配置了一个唯一的名Uͼ名称不允许相同,否则会使用同一个datasourceQ而不会出现异常?

另外在配|文件中定义了Atomikos的事务管理器Qƈ在Spring的JtaTransactionManager中引?
Java代码
  1. <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">   
  2.         <property name="forceShutdown"><value>true</value></property>   
  3.     </bean>   
  4.        
  5.     <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp">   
  6.         <property name="transactionTimeout" value="300"/>    
  7.     </bean>   
  8.   
  9.     <bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">   
  10.         <property name="transactionManager"><ref bean="atomikosTransactionManager"  /></property>   
  11.         <property name="userTransaction"><ref bean="atomikosUserTransaction"  /></property>   
  12.     </bean>  


其它的代码没什么特别,和JOTM配置基本相同QJdbcTemplateQDAOQServiceQ事务代理等{?...

仍然使用TestXa.javaQ修Ҏ引用ApplicationContext-atomikos.xml的上下文配置
Java代码
  1. protected String[] getConfigLocations() {   
  2.     //return new String[] { "classpath:ApplicationContext-jotm.xml" };   
  3.     return new String[] { "classpath:ApplicationContext-atomikos.xml" };   
  4. }  


q行testQ然后查看数据库状态,
然后修改Ҏ参数使其不违反数据库U束Q再q行Test观察数据?Q)?

]]>
[转脓]Spring JTA应用之JOTM配置http://www.tkk7.com/zjrstar/archive/2008/12/23/247922.html一叶笑?/dc:creator>一叶笑?/author>Tue, 23 Dec 2008 07:44:00 GMThttp://www.tkk7.com/zjrstar/archive/2008/12/23/247922.htmlhttp://www.tkk7.com/zjrstar/comments/247922.htmlhttp://www.tkk7.com/zjrstar/archive/2008/12/23/247922.html#Feedback0http://www.tkk7.com/zjrstar/comments/commentRss/247922.htmlhttp://www.tkk7.com/zjrstar/services/trackbacks/247922.html
JOTM(Java Open Transaction Manager)是ObjectWeb的一个开源JTA实现Q本w也是开源应用程序服务器JOnAS(Java Open Application Server)的一部分Qؓ其提供JTA分布式事务的功能。Spring对JOTM提供了较好的支持Q提供了一个org.springframework.transaction.jta.JotmFactoryBean的支持类Q在Spring2.0中也包含了JOTM相关的一些library?

jotm的下载地址为http://jotm.objectweb.org,最新版本ؓ2.0.10.

下蝲完成后解压羃Q然后打开jotm下面conf文g夹,拯carol.properties文g到classpath中,q修改这个文件如?
carol.properties
Java代码
  1. do not use CAROL JNDI wrapper      
  2. carol.start.jndi=false      
  3.       
  4. do not start a name server      
  5. carol.start.ns=false      
  6.       
  7. # Naming Factory   
  8. carol.jndi.java.naming.factory.url.pkgs=org.apache.naming  

上面配置文g的目的是不用JNDI的方式来加蝲JOTM的配|,当然也可以根据需要选择其它的一些配|,例如JTOM所提供的默认配|?

然后开始在Spring上下文中配置JOTMQ在classpath中徏立一个ApplicationContext-jotm.xmlQ配|如?

ApplicationContext-jotm.xml
Java代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">   
  5.   
  6.     <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>   
  7.        
  8.     <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">   
  9.         <property name="userTransaction" ref="jotm" />   
  10.     </bean>   
  11.   
  12.     <bean id="ds1" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">   
  13.         <property name="dataSource">   
  14.             <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">   
  15.                 <property name="transactionManager" ref="jotm" />   
  16.                 <property name="driverName" value="com.mysql.jdbc.Driver" />   
  17.                 <property name="url" value="jdbc:MySQL://localhost:3306/test" />   
  18.             </bean>   
  19.         </property>   
  20.         <property name="user" value="root" />   
  21.         <property name="password" value="admin" />   
  22.     </bean>   
  23.        
  24.     <bean id="ds2" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">   
  25.         <property name="dataSource">   
  26.             <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">   
  27.                 <property name="transactionManager" ref="jotm" />   
  28.                 <property name="driverName" value="com.mysql.jdbc.Driver" />   
  29.                 <property name="url" value="jdbc:MySQL://localhost:3306/test2" />   
  30.             </bean>   
  31.         </property>   
  32.         <property name="user" value="root" />   
  33.         <property name="password" value="admin" />   
  34.     </bean>   
  35.   
  36.     <bean id="template1" class="org.springframework.jdbc.core.JdbcTemplate">   
  37.         <property name="dataSource" ref="ds1" />   
  38.     </bean>   
  39.        
  40.     <bean id="template2" class="org.springframework.jdbc.core.JdbcTemplate">   
  41.         <property name="dataSource" ref="ds2" />   
  42.     </bean>   
  43.        
  44.     <bean id="dao1" class="com.xa.dao.UserDao1">   
  45.         <property name="jdbcTemplate">   
  46.             <ref bean="template1"></ref>   
  47.         </property>   
  48.     </bean>   
  49.        
  50.     <bean id="dao2" class="com.xa.dao.UserDao2">   
  51.         <property name="jdbcTemplate">   
  52.             <ref bean="template2"></ref>   
  53.         </property>   
  54.     </bean>   
  55.        
  56.     <bean id="userServiceTarget" class="com.xa.service.UserServiceImpl">   
  57.         <property name="dao1" ref="dao1"/>   
  58.         <property name="dao2" ref="dao2"/>   
  59.     </bean>   
  60.   
  61.   
  62.     <bean id="userTest" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">       
  63.         <property name="transactionManager">   
  64.             <ref bean="txManager"/>   
  65.         </property>       
  66.         <property name="target">   
  67.             <ref bean="userServiceTarget"/>   
  68.         </property>   
  69.         <property name="transactionAttributes">           
  70.             <props>   
  71.                 <prop key="insert*">PROPAGATION_REQUIRED,-Exception</prop>               
  72.             </props>   
  73.         </property>   
  74.     </bean>   
  75. </beans>  

上面是一个完整的Spring上下文配|,可以看第一个bean “jotm”Q实际上引用了Spring内部所提供的对JOTM支持的工厂类Q参考下面的配置代码D?
Java代码
  1. <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>  


随后Q配|了JTA事务理器,q且在管理器中用上面所配置的jotmQ如下面的代?
Java代码
  1. <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager">   
  2.     <property name="userTransaction" ref="jotm" />   
  3. </bean>  


再接下来是配置多个数据源了Q用jotm提供的org.enhydra.jdbc.pool.StandardXAPoolDataSourcec,Ҏcd可以明确地看出它是用以配|多个数据源的啦,配置的代码如?
Java代码
  1. <bean id="ds1" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">   
  2.         <property name="dataSource">   
  3.             <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">   
  4.                 <property name="transactionManager" ref="jotm" />   
  5.                 <property name="driverName" value="com.mysql.jdbc.Driver" />   
  6.                 <property name="url" value="jdbc:MySQL://localhost:3306/test" />   
  7.             </bean>   
  8.         </property>   
  9.         <property name="user" value="root" />   
  10.         <property name="password" value="admin" />   
  11.     </bean>   
  12.        
  13.     <bean id="ds2" class="org.enhydra.jdbc.pool.StandardXAPoolDataSource" destroy-method="shutdown">   
  14.         <property name="dataSource">   
  15.             <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">   
  16.                 <property name="transactionManager" ref="jotm" />   
  17.                 <property name="driverName" value="com.mysql.jdbc.Driver" />   
  18.                 <property name="url" value="jdbc:MySQL://localhost:3306/test2" />   
  19.             </bean>   
  20.         </property>   
  21.         <property name="user" value="root" />   
  22.         <property name="password" value="admin" />   
  23.     </bean>  

q里配置的两个数据源都连接到本地的mysqlQ实际上可以q接C同的db server和不同类型的数据库,已经l过试Q这里ؓ了方便,在本地徏立了两个不同的数据库(test,test2)做测试?

随后的配|基本上和普通的Spring上下文配|相同了Q根据不同的数据源配|两个jdbcTemplateQ两个dao分别引用不同的jdbcTemplate, 两个dao注入到UserService? 最后将serviceU_事务理,q在事务代理配置中配|回滚规?意思ؓ如遇异常Q则强制回滚内容。配|如下所C?
Java代码
  1. <property name="transactionAttributes">           
  2.     <props>   
  3.         <prop key="insert*">PROPAGATION_REQUIRED,-Exception</prop>               
  4.     </props>   
  5. </property>  


q样Q一个用JOTM JTA事务的简单应用算大致成型了,最后,写一个JUnitQ来试一下结?
TestXa.java
Java代码
  1. package com.xa;   
  2.   
  3. import org.springframework.context.ApplicationContext;   
  4. import org.springframework.test.AbstractDependencyInjectionSpringContextTests;   
  5.   
  6. import com.xa.service.UserService;   
  7.   
  8. public class TestXa extends AbstractDependencyInjectionSpringContextTests   
  9. {   
  10.     protected String[] getConfigLocations() {   
  11.         return new String[] { "classpath:ApplicationContext-jotm.xml" };   
  12.     }   
  13.   
  14.     public void testInsertBothDatabase() {   
  15.         ApplicationContext ctx = this.getApplicationContext();   
  16.         UserService ut = (UserService)ctx.getBean("userTest");   
  17.         try {   
  18.             ut.insertBothDatabase("1"null);   
  19.         }   
  20.         catch (Exception e) {   
  21.             e.printStackTrace();   
  22.         }   
  23.     }   
  24. }  

在test中,调用了UserService的insertBothDatabaseҎQ有两个参数QuserId和UserNameQ另外在Ҏ的实C调用了两个用不同数据源daoQ分别向两个不同的数据库插入输入Q而test2数据库的xa_test表中Qname字段是不允许为空的,因此Q在插入test2数据库时会失?

q行q个testQ然后察看数据库l果Q)Qtest和test2数据库中都没有插入成功,看serviceImpl中的代码可以知道Q逻辑上dao1会先于dao2执行Q但是由于JTA事务Q在dao2插入数据出现异常时整个事务被回滚Q由于事务被配置在service层,dao1和dao2都被U_一个事务进行管理,呵呵。修改一下方法的参数Q修改ؓ
Java代码
  1. ut.insertBothDatabase("1""name1");  


然后再试试test看数据库l果Q如何?


]]>
使用AutowiringRequestProcessor整合struts和Spring2.0http://www.tkk7.com/zjrstar/archive/2008/12/22/247747.html一叶笑?/dc:creator>一叶笑?/author>Mon, 22 Dec 2008 05:55:00 GMThttp://www.tkk7.com/zjrstar/archive/2008/12/22/247747.htmlhttp://www.tkk7.com/zjrstar/comments/247747.htmlhttp://www.tkk7.com/zjrstar/archive/2008/12/22/247747.html#Feedback0http://www.tkk7.com/zjrstar/comments/commentRss/247747.htmlhttp://www.tkk7.com/zjrstar/services/trackbacks/247747.html
论坛中用StrutsQSpring的h不少Q以前的帖子也有问过StrutsQSpring的整合方式。前面的帖子中ReadOnly老大曄提到qSpring2.0新增加的一个整合方式。今天简单把q几U整合方式小l一下?

在这之前Q别忘了用一下Google大法Q一般早有h会对cM的问题做q回{,果然Q在ibm developworks上有一文章,一下子늛了三U整合方式,有兴的xdjm可以参考下面的链接Qhttp://www-128.ibm.com/developerworks/cn/java/j-sr2.html?

下面着重谈一下Spring2.0新增的一个整个方式,我感觉挺不错Q可以完全将Struts的配|和Spring的配|分R具体步骤如下:
1. ~写Spring的配|文件applicationContext.xmlQ简单v见,仅仅定义一个Service对象?
引用

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<bean id="userService" class="com.bearingpoint.gdc.zero.service.impl.UserServiceImpl" />

</beans>

q看上去和普通的Spring配置文g没有M分别?
2. ~写Struts的配|文件struts-config.xmlQ注意其中的controller的配|,用到了Spring2.0的新Ҏ?
引用

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config
PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd"
>

<struts-config>

<action-mappings>

<action path="/addUser"
type="com.bearingpoint.gdc.zero.action.user.AddUser"
scope="request"
>
<forward name="success" path="/index.jsp" />
</action>

</action-mappings>

<controller processorClass="org.springframework.web.struts.AutowiringRequestProcessor" />

</struts-config>


3. 然后Z的Struts的Action注入你需要的Service
引用

private UserService userService;

public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
User user = new User();
userService.addUser(user);
return mapping.findForward("success");
}

/**
* @param userService
*            The userService to set.
*/
public void setUserService(UserService userService) {
this.userService = userService;
}

看上M好像啥都没做Q而事实上Q注入工作已l由AutowiringRequestProcessor自动完成?

4. ~写web.xmlq行试?
引用

?xml version="1.0" ?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/classes/applicationContext.xml</param-value>
    </context-param>

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
<servlet-name>struts</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/classes/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>validate</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>struts</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>


最后,启动Jettyq行试Q顺利运行通过Q?

看上d此简单,配置h也没有什么很特别的地方,只是按照常规来写你的Spring和Struts的配|文件就好了?

不过在这里还是说一下其中的要注意两个问题:
1. q种autowire的注入支持两U不同的方式Q分别是byName和byTypeQ默认是byType。我惌对于l大多数开发者来说是够了?
2. 鉴于在http://www.javaeye.com/topic/15057中所提到的OpenSessionInView模式的失效的问题。我仔细看了一下Spring的源码。对于这Uautowire的整合方式,不推荐在struts-config.xml文g中配|ContextLoaderPlugInQ而是采用web.xml中的ContextLoaderListener来加载Spring的初始化配置。否则,你的OpenSessionInView模式可能会失效?

]]>
转脓:三种整合 Struts 应用E序?Spring 的方?/title><link>http://www.tkk7.com/zjrstar/archive/2008/12/22/247746.html</link><dc:creator>一叶笑?/dc:creator><author>一叶笑?/author><pubDate>Mon, 22 Dec 2008 05:49:00 GMT</pubDate><guid>http://www.tkk7.com/zjrstar/archive/2008/12/22/247746.html</guid><wfw:comment>http://www.tkk7.com/zjrstar/comments/247746.html</wfw:comment><comments>http://www.tkk7.com/zjrstar/archive/2008/12/22/247746.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/zjrstar/comments/commentRss/247746.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/zjrstar/services/trackbacks/247746.html</trackback:ping><description><![CDATA[<table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr valign="top"> <td width="100%"> <h1>原文位置Qhttp://www-128.ibm.com/developerworks/cn/java/j-sr2.html</h1> <h1>使用 Spring 更好地处?Struts 动作</h1> <p id="subtitle"><em>三种整合 Struts 应用E序?Spring 的方?/em></p> <img class="display-img" height="6" alt="" src="http://www.ibm.com/i/c.gif" width="1" /></td> <td class="no-print" width="192"></td> </tr> </tbody> </table> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr valign="top"> <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td> <td width="100%"> <p>U别Q?中</p> <p><a cmimpressionsent="1">George Franciscus</a> (<a href="mailto:george.franciscus@nexcel.ca?subject=使用 Spring 更好地处?Struts 动作" cmimpressionsent="1">george.franciscus@nexcel.ca</a>), 负责? Nexcel<br /> </p> <p>2005 q?10 ?11 ?/p> <blockquote><em>Struts Recipes</em> 的合著?George Franciscus 介l另一个重大的 Struts 整合H门 —?q次是将 Struts 应用E序导入 Spring 框架。请跟随 GeorgeQ他向您展C如何改?Struts 动作Q得管?Struts 动作像理 Spring beans 那样。结果是一个增强的 web 框架Q这个框架可以方便地利用 Spring AOP 的优ѝ?/blockquote><!--start RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--end RESERVED FOR FUTURE USE INCLUDE FILES--> <p>您肯定已l听说过控制反{ (IOC) 设计模式Q因为很长一D|间以来一直在传关于它的信息。如果您在Q何功能中使用q?Spring 框架Q那么您q道其原理的作用。在本文中,我利用这一原理把一?Struts 应用E序注入 Spring 框架Q您亲w体会到 IOC 模式的强大?/p> <p>一?Struts 应用E序整合q?Spring 框架h多方面的优点。首先,Spring 是ؓ解决一些关?JEE 的真实世界问题而设计的Q比如复杂性、低性能和可试性,{等。第二,Spring 框架包含一?AOP 实现Q允许您面向方面技术应用于面向对象的代码。第三,一些h可能会说 Spring 框架只有<em>处理</em> Struts ?Struts 处理自己好。但是这是观炚w题,我演CZU将 Struts 应用E序整合?Spring 框架的方法后Q具体由您自己决定用哪一U?/p> <p>我所演示的方法都是执行v来相对简单的Q但是它们却h明显不同的优炏V我为每一U方法创Z一个独立而可用的例子Q这h可以完全理解每U方法。请参阅 <a cmimpressionsent="1">下蝲</a> 部分获得完整例子源代码。请参阅 <a cmimpressionsent="1">参考资?/a>Q下?Struts MVC ?Spring 框架?/p> <p><a name="N1008C"><span id="f7bbbd3" class="atitle">Z?Spring q么了不P</span></a></p> <p>Spring 的创立?Rod Johnson 以一U批判的眼光看待 Java™ 企业软g开发,q且提议很多企业N都能够通过战略C?IOC 模式Q也UC依赖注入Q来解决。当 Rod 和一个具有奉献精的开放源码开发者团队将q个理论应用于实跉|Q结果就产生?Spring 框架。简a之,Spring 是一个轻型的容器Q利用它可以使用一个外?XML 配置文g方便地将对象q接在一赗每个对象都可以通过昄一?JavaBean 属性收C个到依赖对象的引用,留给您的单Q务就只是在一?XML 配置文g中把它们q接好?/p> <table cellspacing="0" cellpadding="0" width="40%" align="right" border="0"> <tbody> <tr> <td width="10"><img height="1" alt="" src="http://www.ibm.com/i/c.gif" width="10" /></td> <td> <table cellspacing="0" cellpadding="5" width="100%" border="1"> <tbody> <tr> <td bgcolor="#eeeeee"><a name="N10099"><strong>IOC ?Spring</strong></a><br /> <p>IOC 是一U应用E序逻辑外在化的设计模式Q所以它是被注入而不是被写入客户Z码中。将 IOC 与接口编E应用结合,像 Spring 框架那样Q生了一U架构,q种架构能够减少客户机对特定实现逻辑的依赖。请参阅 <a cmimpressionsent="1">参考资?/a> 了解更多关于 IOC ?Spring 的信息?/p> </td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <p>依赖注入是一个强大的Ҏ,但是 Spring 框架能够提供更多Ҏ。Spring 支持可插拔的事务理器,可以l您的事务处理提供更q泛的选择范围。它集成了领先的持久性框Ӟq且提供一个一致的异常层次l构。Spring q提供了一U用面向方面代码代替正常的面向对象代码的简单机制?/p> <p>Spring AOP 允许您?em>拦截?/em> 在一个或多个执行点上拦截应用E序逻辑。加强应用程序在拦截器中的日志记录逻辑会生一个更可读的、实用的代码基础Q所以拦截器q泛用于日志记录。您很快׃看到Qؓ了处理横切关注点QSpring AOP 发布了它自己的拦截器Q您也可以编写您自己的拦截器?/p> <br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /> <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td> </tr> </tbody> </table> <table class="no-print" cellspacing="0" cellpadding="0" align="right"> <tbody> <tr align="right"> <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br /> <table cellspacing="0" cellpadding="0" border="0"> <tbody> <tr> <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /> </td> <td valign="top" align="right"><a class="fbox" cmimpressionsent="1"><strong>回页?/strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br /> <br /> <p><a name="N100B0"><span id="vzjdfvh" class="atitle">整合 Struts ?Spring</span></a></p> <p>?Struts 怼QSpring 可以作ؓ一?MVC 实现。这两种框架都具有自q优点和缺点,管大部分h同意 Struts ?MVC 斚w仍然是最好的。很多开发团队已l学会在旉紧迫的时候利?Struts 作ؓ构造高品质软g的基。Struts h如此大的推动力,以至于开发团队宁愿整?Spring 框架的特性,而不愿意转换?Spring MVC。没必要q行转换Ҏ来说是一个好消息。Spring 架构允许您将 Struts 作ؓ Web 框架q接到基?Spring 的业务和持久层。最后的l果是现在一切条仉具备了?/p> <p>在接下来的小H门中,您将会了解到三种?Struts MVC 整合?Spring 框架的方法。我揭C每U方法的~陷q且Ҏ它们的优炏V?一旦您了解到所有三U方法的作用Q我会向您展示一个o人兴奋的应用E序Q这个程序用的是这三种Ҏ中我最喜欢的一U?/p> <br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /> <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td> </tr> </tbody> </table> <table class="no-print" cellspacing="0" cellpadding="0" align="right"> <tbody> <tr align="right"> <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br /> <table cellspacing="0" cellpadding="0" border="0"> <tbody> <tr> <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /> </td> <td valign="top" align="right"><a class="fbox" cmimpressionsent="1"><strong>回页?/strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br /> <br /> <p><a name="N100BC"><span id="dzjjvdr" class="atitle">三个窍?/span></a></p> <p>接下来的每种整合技术(或者窍门)都有自己的优点和特点。我偏爱其中的一U,但是我知道这三种都能够加深您?Struts ?Spring 的理解。在处理各种不同情况的时候,q将l您提供一个广阔的选择范围。方法如下:</p> <ul> <li>使用 Spring ?<code>ActionSupport</code> cL?Structs <li>使用 Spring ?<code>DelegatingRequestProcessor</code> 覆盖 Struts ?<code>RequestProcessor </code> <li>?Struts <code>Action</code> 理委托l?Spring 框架 </li> </ul> <p><a name="N100E1"><span id="flvvp3f" class="smalltitle">装蝲应用E序环境</span></a></p> <p>无论您用哪U技术,都需要?Spring ?<code>ContextLoaderPlugin</code> ?Struts ?<code>ActionServlet</code> 装蝲 Spring 应用E序环境。就像添加Q何其他插件一P单地向您?struts-config.xml 文gd该插Ӟ如下所C:</p> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode"><plug-in className= "org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property= "contextConfigLocation" value="/WEB-INF/beans.xml"/> </plug-in> </pre> </td> </tr> </tbody> </table> <br /> <p>前面已经提到q,?<a cmimpressionsent="1">下蝲</a> 部分Q您能够扑ֈq三个完全可使用的例子的完整源代码。每个例子都Z个书c搜索应用程序提供一U不同的 Struts ?Spring 的整合方法。您可以在这里看C子的要点Q但是您也可以下载应用程序以查看所有的l节?/p> <br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /> <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td> </tr> </tbody> </table> <table class="no-print" cellspacing="0" cellpadding="0" align="right"> <tbody> <tr align="right"> <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br /> <table cellspacing="0" cellpadding="0" border="0"> <tbody> <tr> <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /> </td> <td valign="top" align="right"><a class="fbox" cmimpressionsent="1"><strong>回页?/strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br /> <br /> <p><a name="N100FE"><span id="vf9lvnx" class="atitle">H门 1. 使用 Spring ?ActionSupport</span></a></p> <p>手动创徏一?Spring 环境是一U整?Struts ?Spring 的最直观的方式。ؓ了它变得更单,Spring 提供了一些帮助。ؓ了方便地获得 Spring 环境Q?code>org.springframework.web.struts.ActionSupport</code> cL供了一?<code>getWebApplicationContext()</code> Ҏ。您所做的只是?Spring ?<code>ActionSupport</code> 而不?Struts <code>Action</code> cL展您的动作,如清?1 所C:</p> <br /> <a name="N1011C"><strong>清单 1. 使用 ActionSupport 整合 Struts</strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">package ca.nexcel.books.actions; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.DynaActionForm; import org.springframework.context.ApplicationContext; import org.springframework.web.struts.ActionSupport; import ca.nexcel.books.beans.Book; import ca.nexcel.books.business.BookService; public class SearchSubmit extends ActionSupport { <span id="rdvfnnv" class="boldcode">|(1)</span> public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { DynaActionForm searchForm = (DynaActionForm) form; String isbn = (String) searchForm.get("isbn"); //the old fashion way //BookService bookService = new BookServiceImpl(); ApplicationContext ctx = getWebApplicationContext(); <span id="j9n91fh" class="boldcode">|(2)</span> BookService bookService = (BookService) ctx.getBean("bookService"); <span id="v7rt9hr" class="boldcode">|(3)</span> Book book = bookService.read(isbn.trim()); if (null == book) { ActionErrors errors = new ActionErrors(); errors.add(ActionErrors.GLOBAL_ERROR,new ActionError ("message.notfound")); saveErrors(request, errors); return mapping.findForward("failure") ; } request.setAttribute("book", book); return mapping.findForward("success"); } } </pre> </td> </tr> </tbody> </table> <br /> <p>让我们快速思考一下这里到底发生了什么。在 (1) 处,我通过?Spring ?<code>ActionSupport</code> c而不?Struts ?<code>Action</code> c进行扩展,创徏了一个新?<code>Action</code>。在 (2) 处,我?<code>getWebApplicationContext()</code> Ҏ获得一?<code>ApplicationContext</code>。ؓ了获得业务服务,我用在 (2) 处获得的环境?(3) 处查找一?Spring bean?/p> <p>q种技术很单ƈ且易于理解。不q的是,它将 Struts 动作?Spring 框架耦合在一赗如果您x换掉 SpringQ那么您必须重写代码。ƈ且,׃ Struts 动作不在 Spring 的控制之下,所以它不能获得 Spring AOP 的优ѝ当使用多重独立?Spring 环境Ӟq种技术可能有用,但是在大多数情况下,q种Ҏ不如另外两种Ҏ合适?/p> <br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /> <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td> </tr> </tbody> </table> <table class="no-print" cellspacing="0" cellpadding="0" align="right"> <tbody> <tr align="right"> <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br /> <table cellspacing="0" cellpadding="0" border="0"> <tbody> <tr> <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /> </td> <td valign="top" align="right"><a class="fbox" cmimpressionsent="1"><strong>回页?/strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br /> <br /> <p><a name="N10146"><span id="7nnhj3p" class="atitle">H门 2. 覆盖 RequestProcessor</span></a></p> <p>?Spring ?Struts 动作中分L一个更巧妙的设计选择。分ȝ一U方法是使用 <code>org.springframework.web.struts.DelegatingRequestProcessor</code> cL覆盖 Struts ?<code>RequestProcessor</code> 处理E序Q如清单 2 所C:</p> <br /> <a name="N1015C"><strong>清单 2. 通过 Spring ?DelegatingRequestProcessor q行整合</strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode"><?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config> <form-beans> <form-bean name="searchForm" type="org.apache.struts.validator.DynaValidatorForm"> <form-property name="isbn" type="java.lang.String"/> </form-bean> </form-beans> <global-forwards type="org.apache.struts.action.ActionForward"> <forward name="welcome" path="/welcome.do"/> <forward name="searchEntry" path="/searchEntry.do"/> <forward name="searchSubmit" path="/searchSubmit.do"/> </global-forwards> <action-mappings> <action path="/welcome" forward="/WEB-INF/pages/welcome.htm"/> <action path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/> <action path="/searchSubmit" type="ca.nexcel.books.actions.SearchSubmit" input="/searchEntry.do" validate="true" name="searchForm"> <forward name="success" path="/WEB-INF/pages/detail.jsp"/> <forward name="failure" path="/WEB-INF/pages/search.jsp"/> </action> </action-mappings> <message-resources parameter="ApplicationResources"/> <controller processorClass="org.springframework.web.struts. DelegatingRequestProcessor"/> <span id="7d1tnbl" class="boldcode">|(1)</span> <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/> </plug-in> <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="csntextConfigLocation" value="/WEB-INF/beans.xml"/> </plug-in> </struts-config> </pre> </td> </tr> </tbody> </table> <br /> <p>我利用了 <code><controller></code> 标记来用 <code>DelegatingRequestProcessor</code> 覆盖默认?Struts <code>RequestProcessor</code>。下一步是在我?Spring 配置文g中注册该动作Q如清单 3 所C:</p> <br /> <a name="N10179"><strong>清单 3. ?Spring 配置文g中注册一个动?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode"><?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/> <bean name="/searchSubmit" class="ca.nexcel.books.actions.SearchSubmit"> <span id="zddvfnz" class="boldcode">|(1)</span> <property name="bookService"> <ref bean="bookService"/> </property> </bean> </beans> </pre> </td> </tr> </tbody> </table> <br /> <p>注意Q在 (1) 处,我用名U属性注册了一?beanQ以匚w struts-config 动作映射名称?code>SearchSubmit</code> 动作揭示了一?JavaBean 属性,允许 Spring 在运行时填充属性,如清?4 所C:</p> <br /> <a name="N1018E"><strong>清单 4. h JavaBean 属性的 Struts 动作</strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">package ca.nexcel.books.actions; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.DynaActionForm; import ca.nexcel.books.beans.Book; import ca.nexcel.books.business.BookService; public class SearchSubmit extends Action { private BookService bookService; public BookService getBookService() { return bookService; } public void setBookService(BookService bookService) { <span id="tnxxr73" class="boldcode">| (1)</span> this.bookService = bookService; } public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { DynaActionForm searchForm = (DynaActionForm) form; String isbn = (String) searchForm.get("isbn"); Book book = getBookService().read(isbn.trim()); <span id="tpjrtd7" class="boldcode">|(2)</span> if (null == book) { ActionErrors errors = new ActionErrors(); errors.add(ActionErrors.GLOBAL_ERROR,new ActionError("message.notfound")); saveErrors(request, errors); return mapping.findForward("failure") ; } request.setAttribute("book", book); return mapping.findForward("success"); } } </pre> </td> </tr> </tbody> </table> <br /> <p>在清?4 中,您可以了解到如何创徏 Struts 动作。在 (1) 处,我创Z一?JavaBean 属性?code>DelegatingRequestProcessor</code>自动地配|这U属性。这U设计 Struts 动作q不知道它正?Spring 理Qƈ且您能够利?Sping 的动作管理框架的所有优炏V由于您?Struts 动作注意不到 Spring 的存在,所以您不需要重写您?Struts 代码可以用其他控制反转容器来替换?Spring?/p> <p><code>DelegatingRequestProcessor</code> Ҏ的确比第一U方法好Q但是仍然存在一些问题。如果您使用一个不同的 <code>RequestProcessor</code>Q则需要手动整?Spring ?<code>DelegatingRequestProcessor</code>。添加的代码会造成l护的麻烦ƈ且将来会降低您的应用E序的灵zL。此外,q有q一些用一pd命o来代?Struts <code>RequestProcessor</code> 的传闅R?q种改变会对这U解x法的使用寿命造成负面的媄响?/p> <br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /> <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td> </tr> </tbody> </table> <table class="no-print" cellspacing="0" cellpadding="0" align="right"> <tbody> <tr align="right"> <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br /> <table cellspacing="0" cellpadding="0" border="0"> <tbody> <tr> <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /> </td> <td valign="top" align="right"><a class="fbox" cmimpressionsent="1"><strong>回页?/strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br /> <br /> <p><a name="N101B4"><span id="zvpx3nn" class="atitle">H门 3. 动作管理委托给 Spring</span></a></p> <p>一个更好的解决Ҏ是将 Strut 动作理委托l?Spring。您可以通过?<code>struts-config</code> 动作映射中注册一个代理来实现。代理负责在 Spring 环境中查?Struts 动作。由于动作在 Spring 的控制之下,所以它可以填充动作?JavaBean 属性,qؓ应用诸如 Spring ?AOP 拦截器之cȝҎ带来了可能?</p> <p>清单 5 中的 <code>Action</code> cM清单 4 中的相同。但?struts-config 有一些不同:</p> <br /> <a name="N101CD"><strong>清单 5. Spring 整合的委托方?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode"><?xml version="1.0" encoding="ISO-8859-1" ?> <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"> <struts-config> <form-beans> <form-bean name="searchForm" type="org.apache.struts.validator.DynaValidatorForm"> <form-property name="isbn" type="java.lang.String"/> </form-bean> </form-beans> <global-forwards type="org.apache.struts.action.ActionForward"> <forward name="welcome" path="/welcome.do"/> <forward name="searchEntry" path="/searchEntry.do"/> <forward name="searchSubmit" path="/searchSubmit.do"/> </global-forwards> <action-mappings> <action path="/welcome" forward="/WEB-INF/pages/welcome.htm"/> <action path="/searchEntry" forward="/WEB-INF/pages/search.jsp"/> <action path="/searchSubmit" type="org.springframework.web.struts.DelegatingActionProxy" <span id="9rldfnh" class="boldcode">|(1)</span> input="/searchEntry.do" validate="true" name="searchForm"> <forward name="success" path="/WEB-INF/pages/detail.jsp"/> <forward name="failure" path="/WEB-INF/pages/search.jsp"/> </action> </action-mappings> <message-resources parameter="ApplicationResources"/> <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/> </plug-in> <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/beans.xml"/> </plug-in> </struts-config> </pre> </td> </tr> </tbody> </table> <br /> <p>清单 5 是一个典型的 struts-config.xml 文gQ只有一个小的差别。它注册 Spring 代理cȝ名称Q而不是声明动作的cdQ如Q?Q处所C。DelegatingActionProxy cM用动作映名U查?Spring 环境中的动作。这是我们使用 <code>ContextLoaderPlugIn</code> 声明的环境?/p> <p>一?Struts 动作注册Z?Spring bean 是非常直观的Q如清单 6 所C。我利用动作映射使用 <code><bean></code> 标记的名U属性(在这个例子中?"<code>/searchSubmit</code>"Q简单地创徏了一?bean。这个动作的 JavaBean 属性像M Spring bean 一栯填充Q?</p> <br /> <a name="N101ED"><strong>清单 6. ?Spring 环境中注册一?Struts 动作</strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode"><?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/> <bean name="/searchSubmit" class="ca.nexcel.books.actions.SearchSubmit"> <property name="bookService"> <ref bean="bookService"/> </property> </bean> </beans> </pre> </td> </tr> </tbody> </table> <br /> <br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /> <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td> </tr> </tbody> </table> <table class="no-print" cellspacing="0" cellpadding="0" align="right"> <tbody> <tr align="right"> <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br /> <table cellspacing="0" cellpadding="0" border="0"> <tbody> <tr> <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /> </td> <td valign="top" align="right"><a class="fbox" cmimpressionsent="1"><strong>回页?/strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br /> <br /> <p><a name="N101F4"><span id="jdbv7tv" class="atitle">动作委托的优?/span></a></p> <p>动作委托解决Ҏ是这三种Ҏ中最好的。Struts 动作不了?SpringQ不对代码作M改变可用于?Spring 应用E序中?code>RequestProcessor</code> 的改变不会媄响它Qƈ且它可以利用 Spring AOP Ҏ的优点?</p> <p>动作委托的优点不止如此。一旦让 Spring 控制您的 Struts 动作Q您可以?Spring l动作补充更强的zd。例如,没有 Spring 的话Q所有的 Struts 动作都必LU程安全的。如果您讄 <code><bean></code> 标记?singleton 属性ؓ“false”Q那么不用何种ҎQ您的应用程序都在每一个请求上有一个新生成的动作对象。您可能不需要这U特性,但是把它攑֜您的工具׃也很好。您也可以利?Spring 的生命周期方法。例如,当实例化 Struts 动作Ӟ<code><bean></code> 标记?init-method 属性被用于q行一个方法。类似地Q在从容器中删除 bean 之前Qdestroy-method 属性执行一个方法。这些方法是理昂贵对象的好办法Q它们以一U与 Servlet 生命周期相同的方式进行管理?/p> <br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /> <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td> </tr> </tbody> </table> <table class="no-print" cellspacing="0" cellpadding="0" align="right"> <tbody> <tr align="right"> <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br /> <table cellspacing="0" cellpadding="0" border="0"> <tbody> <tr> <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /> </td> <td valign="top" align="right"><a class="fbox" cmimpressionsent="1"><strong>回页?/strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br /> <br /> <p><a name="N1020D"><span id="rvx97jr" class="atitle">拦截 Struts</span></a></p> <p>前面提到q,通过?Struts 动作委托l?Spring 框架而整?Struts ?Spring 的一个主要的优点是:您可以将 Spring ?AOP 拦截器应用于您的 Struts 动作。通过?Spring 拦截器应用于 Struts 动作Q您可以用最的代h处理横切x炏V?/p> <p>虽然 Spring 提供很多内置拦截器,但是我将向您展示如何创徏自己的拦截器q把它应用于一?Struts 动作。ؓ了用拦截器Q您需要做三g事:</p> <ol> <li>创徏拦截器? <li>注册拦截器? <li>声明在何处拦截代码?</li> </ol> <p>q看h非常单的几句话却非常强大。例如,在清?7 中,我ؓ Struts 动作创徏了一个日志记录拦截器?q个拦截器在每个Ҏ调用之前打印一句话Q?/p> <br /> <a name="N1022D"><strong>清单 7. 一个简单的日志记录拦截?/strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode">package ca.nexcel.books.interceptors; import org.springframework.aop.MethodBeforeAdvice; import java.lang.reflect.Method; public class LoggingInterceptor implements MethodBeforeAdvice { public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println("logging before!"); } } </pre> </td> </tr> </tbody> </table> <br /> <p>q个拦截器非常简单?code>before()</code> Ҏ在拦截点中每个方法之前运行。在本例中,它打印出一句话Q其实它可以做您惛_的Q何事。下一步就是在 Spring 配置文g中注册这个拦截器Q如清单 8 所C:</p> <br /> <a name="N1023F"><strong>清单 8. ?Spring 配置文g中注册拦截器</strong></a><br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td class="code-outline"> <pre class="displaycode"><?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/> <bean name="/searchSubmit" class="ca.nexcel.books.actions.SearchSubmit"> <property name="bookService"> <ref bean="bookService"/> </property> </bean> <!-- Interceptors --> <bean name="logger" class="ca.nexcel.books.interceptors.LoggingInterceptor"/> <span id="jdxhr7h" class="boldcode">|(1)</span> <!-- AutoProxies --> <bean name="loggingAutoProxy" class="org.springframework.aop.framework.autoproxy. BeanNameAutoProxyCreator"> <span id="n1ph1h9" class="boldcode">|(2)</span> <property name="beanNames"> <value>/searchSubmit</valuesgt; <span id="9p9pr93" class="boldcode">|(3)</span> </property> <property name="interceptorNames"> <list> <value>logger</value> <span id="nrrlxnn" class="boldcode">|(4)</span> </list> </property> </bean> </beans> </pre> </td> </tr> </tbody> </table> <br /> <p>您可能已l注意到了,清单 8 扩展?<a cmimpressionsent="1">清单 6</a> 中所C的应用E序以包含一个拦截器。具体细节如下:</p> <ul> <li>?(1) 处,我注册了q个拦截器? <li>?(2) 处,我创Z一?bean 名称自动代理Q它描述如何应用拦截器。还有其他的Ҏ定义拦截点,但是q种Ҏ常见而简ѝ? <li>?(3) 处,我将 Struts 动作注册为将被拦截的 bean。如果您惌拦截其他?Struts 动作Q则只需要在 "beanNames" 下面创徏附加?<code><value></code> 标记? <li>?(4) 处,当拦截发生时Q我执行了在 (1) 处创建的拦截?bean 的名U。这里列出的所有拦截器都应用于“beanNames”?</li> </ul> <p>是q样。就像这个例子所展示的,您?Struts 动作|于 Spring 框架的控制之下,为处理您?Struts 应用E序提供了一pd全新的选择。在本例中,使用动作委托可以L地利?Spring 拦截器提?Struts 应用E序中的日志记录能力?/p> <br /> <table cellspacing="0" cellpadding="0" width="100%" border="0"> <tbody> <tr> <td><img height="1" alt="" src="http://www.ibm.com/i/v14/rules/blue_rule.gif" width="100%" /><br /> <img height="6" alt="" src="http://www.ibm.com/i/c.gif" width="8" border="0" /></td> </tr> </tbody> </table> <table class="no-print" cellspacing="0" cellpadding="0" align="right"> <tbody> <tr align="right"> <td><img height="4" alt="" src="http://www.ibm.com/i/c.gif" width="100%" /><br /> <table cellspacing="0" cellpadding="0" border="0"> <tbody> <tr> <td valign="middle"><img height="16" alt="" src="http://www.ibm.com/i/v14/icons/u_bold.gif" width="16" border="0" /><br /> </td> <td valign="top" align="right"><a class="fbox" cmimpressionsent="1"><strong>回页?/strong></a></td> </tr> </tbody> </table> </td> </tr> </tbody> </table> <br /> <br /> <p><a name="N1026F"><span id="nz9xzzr" class="atitle">l束?/span></a></p> <p>在本文中Q您已经学习了将 Struts 动作整合?Spring 框架中的三种H门。?Spring ?<code>ActionSupport</code> 来整?StrutsQ第一U窍门中是q样做的Q简单而快P但是会将 Struts 动作?Spring 框架耦合在一赗如果您需要将应用E序ULC个不同的框架Q则需要重写代码。第二种解决Ҏ通过委托 <code>RequestProcessor</code> 巧妙地解开代码的耦合Q但是它的可扩展性不强,q且?Struts ?<code>RequestProcessor</code> 变成一pd命oӞq种Ҏ持l不了很长时间。第三种Ҏ是这三种Ҏ中最好的Q将 Struts 动作委托l?Spring 框架可以使代码解耦,从而您可以在您的 Struts 应用E序中利?Spring 的特性(比如日志记录拦截器)?/p> <p>三种 Struts-Spring 整合H门中的每一U都被实现成一个完整可用的应用E序。请参阅 <a cmimpressionsent="1">下蝲</a> 部分仔细研究它们?/p> </td> </tr> </tbody> </table> <img src ="http://www.tkk7.com/zjrstar/aggbug/247746.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/zjrstar/" target="_blank">一叶笑?/a> 2008-12-22 13:49 <a href="http://www.tkk7.com/zjrstar/archive/2008/12/22/247746.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转脓Q?解惑 spring 嵌套事务http://www.tkk7.com/zjrstar/archive/2008/12/15/246364.html一叶笑?/dc:creator>一叶笑?/author>Mon, 15 Dec 2008 03:15:00 GMThttp://www.tkk7.com/zjrstar/archive/2008/12/15/246364.htmlhttp://www.tkk7.com/zjrstar/comments/246364.htmlhttp://www.tkk7.com/zjrstar/archive/2008/12/15/246364.html#Feedback0http://www.tkk7.com/zjrstar/comments/commentRss/246364.htmlhttp://www.tkk7.com/zjrstar/services/trackbacks/246364.htmlhttp://www.javaeye.com/topic/35907

   在所有?spring 的应用中, 声明式事务管理可能是使用率最高的功能? 但是, 从我观察到的情况?
l大多数人ƈ不能深刻理解事务声明中不同事务传播属性配|的的含? 让我们来看一?TransactionDefinition 接口中的定义

Java代码
  1. /**  
  2.      * Support a current transaction, create a new one if none exists.  
  3.      * Analogous to EJB transaction attribute of the same name.  
  4.      * <p>This is typically the default setting of a transaction definition.  
  5.      */  
  6.     int PROPAGATION_REQUIRED = 0;   
  7.   
  8.     /**  
  9.      * Support a current transaction, execute non-transactionally if none exists.  
  10.      * Analogous to EJB transaction attribute of the same name.  
  11.      * <p>Note: For transaction managers with transaction synchronization,  
  12.      * PROPAGATION_SUPPORTS is slightly different from no transaction at all,  
  13.      * as it defines a transaction scopp that synchronization will apply for.  
  14.      * As a consequence, the same resources (JDBC Connection, Hibernate Session, etc)  
  15.      * will be shared for the entire specified scope. Note that this depends on  
  16.      * the actual synchronization configuration of the transaction manager.  
  17.      * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization  
  18.      */  
  19.     int PROPAGATION_SUPPORTS = 1;   
  20.   
  21.     /**  
  22.      * Support a current transaction, throw an exception if none exists.  
  23.      * Analogous to EJB transaction attribute of the same name.  
  24.      */  
  25.     int PROPAGATION_MANDATORY = 2;   
  26.   
  27.     /**  
  28.      * Create a new transaction, suspend the current transaction if one exists.  
  29.      * Analogous to EJB transaction attribute of the same name.  
  30.      * <p>Note: Actual transaction suspension will not work on out-of-the-box  
  31.      * on all transaction managers. This in particular applies to JtaTransactionManager,  
  32.      * which requires the <code>javax.transaction.TransactionManager</code> to be  
  33.      * made available it to it (which is server-specific in standard J2EE).  
  34.      * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager  
  35.      */  
  36.     int PROPAGATION_REQUIRES_NEW = 3;   
  37.   
  38.     /**  
  39.      * Execute non-transactionally, suspend the current transaction if one exists.  
  40.      * Analogous to EJB transaction attribute of the same name.  
  41.      * <p>Note: Actual transaction suspension will not work on out-of-the-box  
  42.      * on all transaction managers. This in particular applies to JtaTransactionManager,  
  43.      * which requires the <code>javax.transaction.TransactionManager</code> to be  
  44.      * made available it to it (which is server-specific in standard J2EE).  
  45.      * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager  
  46.      */  
  47.     int PROPAGATION_NOT_SUPPORTED = 4;   
  48.   
  49.     /**  
  50.      * Execute non-transactionally, throw an exception if a transaction exists.  
  51.      * Analogous to EJB transaction attribute of the same name.  
  52.      */  
  53.     int PROPAGATION_NEVER = 5;   
  54.   
  55.     /**  
  56.      * Execute within a nested transaction if a current transaction exists,  
  57.      * behave like PROPAGATION_REQUIRED else. There is no analogous feature in EJB.  
  58.      * <p>Note: Actual creation of a nested transaction will only work on specific  
  59.      * transaction managers. Out of the box, this only applies to the JDBC  
  60.      * DataSourceTransactionManager when working on a JDBC 3.0 driver.  
  61.      * Some JTA providers might support nested transactions as well.  
  62.      * @see org.springframework.jdbc.datasource.DataSourceTransactionManager  
  63.      */  
  64.     int PROPAGATION_NESTED = 6;  


我们可以看到, ?spring 中一共定义了六种事务传播属? 如果你觉得看h不够直观, 那么我来转脓一个满大街都有的翻?

引用

PROPAGATION_REQUIRED -- 支持当前事务Q如果当前没有事务,新Z个事务。这是最常见的选择?
PROPAGATION_SUPPORTS -- 支持当前事务Q如果当前没有事务,׃非事务方式执行?
PROPAGATION_MANDATORY -- 支持当前事务Q如果当前没有事务,抛出异常?
PROPAGATION_REQUIRES_NEW -- 新徏事务Q如果当前存在事务,把当前事务挂赗?
PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作Q如果当前存在事务,把当前事务挂v?
PROPAGATION_NEVER -- 以非事务方式执行Q如果当前存在事务,则抛出异常?
PROPAGATION_NESTED -- 如果当前存在事务Q则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIREDcM的操作?
前六个策略类gEJB CMTQ第七个QPROPAGATION_NESTEDQ是Spring所提供的一个特D变量?
它要求事务管理器或者用JDBC 3.0 Savepoint API提供嵌套事务行ؓQ如Spring的DataSourceTransactionManagerQ?


在我所见过的误解中, 最常见的是下面q种:

引用

假如有两个业务接?ServiceA ?ServiceB, 其中 ServiceA 中有一个方法实现如?

/**
* 事务属性配|ؓ PROPAGATION_REQUIRED
*/
void methodA() {
// 调用 ServiceB 的方?
ServiceB.methodB();
}

那么如果 ServiceB ?methodB  如果配置了事? 必配|ؓ PROPAGATION_NESTED


q种x可能害了不少? 认ؓ Service 之间应该避免互相调用, 其实Ҏ不用担心q点QPROPAGATION_REQUIRED 已经说得很明?
如果当前U程中已l存在事? Ҏ调用会加入此事务, 果当前没有事务,新Z个事? 所?ServiceB#methodB() 的事务只要遵循最普通的规则配置?PROPAGATION_REQUIRED 卛_, 如果 ServiceB#methodB (我们UC为内部事? Z文打下基) 抛了异常, 那么 ServiceA#methodA(我们UC为外部事? 如果没有Ҏ配置此异常时事务提交 (?+MyCheckedException的用?, 那么整个事务是一定要 rollback ? 什?Service 只能?Dao 之类的言论纯属无E之? spring 只负责配|了事务属性方法的拦截, 它怎么知道你这个方法是?Service q是 Dao ??

     说了q么半天, 那到底什么是真正的事务嵌套呢, 解释之前我们来看一?nbsp; Juergen Hoeller 的原?

Juergen Hoeller 写道

PROPAGATION_REQUIRES_NEW starts a new, independent "inner" transaction for the given scope. This transaction will be committed or rolled back completely independent from the outer transaction, having its own isolation scope, its own set of locks, etc. The outer transaction will get suspended at the beginning of the inner one, and resumed once the inner one has completed.

Such independent inner transactions are for example used for id generation through manual sequences, where the access to the sequence table should happen in its own transactions, to keep the lock there as short as possible. The goal there is to avoid tying the sequence locks to the (potentially much longer running) outer transaction, with the sequence lock not getting released before completion of the outer transaction.

PROPAGATION_NESTED on the other hand starts a "nested" transaction, which is a true subtransaction of the existing one. What will happen is that a savepoint will be taken at the start of the nested transaction. íf the nested transaction fails, we will roll back to that savepoint. The nested transaction is part of of the outer transaction, so it will only be committed at the end of of the outer transaction.

Nested transactions essentially allow to try some execution subpaths as subtransactions: rolling back to the state at the beginning of the failed subpath, continuing with another subpath or with the main execution path there - all within one isolated transaction, and not losing any previous work done within the outer transaction.

For example, consider parsing a very large input file consisting of account transfer blocks: The entire file should essentially be parsed within one transaction, with one single commit at the end. But if a block fails, its transfers need to be rolled back, writing a failure marker somewhere. You could either start over the entire transaction every time a block fails, remembering which blocks to skip - or you mark each block as a nested transaction, only rolling back that specific set of operations, keeping the previous work of the outer transaction. The latter is of course much more efficient, in particular when a block at the end of the file fails.


Juergen Hoeller 写道

Rolling back the entire transaction is the choice of the demarcation code/config that started the outer transaction.

So if an inner transaction throws an exception and is supposed to be rolled back (according to the rollback rules), the transaction will get rolled back to the savepoint taken at the start of the inner transaction. The immediate calling code can then decide to catch the exception and proceed down some other path within the outer transaction.

If the code that called the inner transaction lets the exception propagate up the call chain, the exception will eventually reach the demarcation code of the outer transaction. At that point, the rollback rules of the outer transaction decide whether to trigger a rollback. That would be a rollback of the entire outer transaction then.

So essentially, it depends on your exception handling. If you catch the exception thrown by the inner transaction, you can proceed down some other path within the outer transaction. If you let the exception propagate up the call chain, it's eventually gonna cause a rollback of the entire outer transaction.


    也就是说, 最Ҏ弄؜淆的其实?PROPAGATION_REQUIRES_NEW ?PROPAGATION_NESTED, 那么q两U方式又有何区别? 我简单的译一?Juergen Hoeller 的话 :
   
    PROPAGATION_REQUIRES_NEW 启动一个新? 不依赖于环境?"内部" 事务. q个事务被完全 commited ?rolled back 而不依赖于外部事? 它拥有自q隔离范围, 自己的锁, {等. 当内部事务开始执行时, 外部事务被挂v, 内务事务l束? 外部事务l执?


    另一斚w, PROPAGATION_NESTED 开始一?"嵌套? 事务,  它是已经存在事务的一个真正的子事? 潜套事务开始执行时,  它将取得一?savepoint. 如果q个嵌套事务p|, 我们回滚到?savepoint. 潜套事务是外部事务的一部分, 只有外部事务l束后它才会被提?

    由此可见, PROPAGATION_REQUIRES_NEW ?PROPAGATION_NESTED 的最大区别在? PROPAGATION_REQUIRES_NEW 完全是一个新的事? ?PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 潜套事务也会?commit, q个规则同样适用?roll back.
   
   
    那么外部事务如何利用嵌套事务?savepoint Ҏ呢, 我们用代码来说话
   
Java代码
  1. ServiceA {   
  2.        
  3.     /**  
  4.      * 事务属性配|ؓ PROPAGATION_REQUIRED  
  5.      */  
  6.     void methodA() {   
  7.         ServiceB.methodB();   
  8.     }   
  9.   
  10. }   
  11.   
  12. ServiceB {   
  13.        
  14.     /**  
  15.      * 事务属性配|ؓ PROPAGATION_REQUIRES_NEW  
  16.      */    
  17.     void methodB() {   
  18.     }   
  19.        
  20. }     
   

q种情况? 因ؓ ServiceB#methodB 的事务属性ؓ PROPAGATION_REQUIRES_NEW, 所以两者不会发生Q何关p? ServiceA#methodA ?ServiceB#methodB 不会因ؓҎ的执行情况而媄响事务的l果, 因ؓ它们Ҏ是两个事务, ?ServiceB#methodB 执行?ServiceA#methodA 的事务已l挂起了 (关于事务挂v的内容已l超Z本文的讨? 有时间我会再写一些挂L文章) .

那么 PROPAGATION_NESTED 又是怎么回事? l箋看代?

Java代码
  1. ServiceA {   
  2.        
  3.     /**  
  4.      * 事务属性配|ؓ PROPAGATION_REQUIRED  
  5.      */  
  6.     void methodA() {   
  7.         ServiceB.methodB();   
  8.     }   
  9.   
  10. }   
  11.   
  12. ServiceB {   
  13.        
  14.     /**  
  15.      * 事务属性配|ؓ PROPAGATION_NESTED  
  16.      */    
  17.     void methodB() {   
  18.     }   
  19.        
  20. }     


现在的情况就变得比较复杂? ServiceB#methodB 的事务属性被配置?PROPAGATION_NESTED, 此时两者之间又如何协作呢? ?Juergen Hoeller 的原话中我们可以扑ֈ{案, ServiceB#methodB 如果 rollback, 那么内部事务(?ServiceB#methodB) 回滚到它执行前?SavePoint(注意, q是本文中第一ơ提到它, 潜套事务中最核心的概?, 而外部事??ServiceA#methodA) 可以有以下两U处理方?

1. 改写 ServiceA 如下
Java代码
  1. ServiceA {   
  2.        
  3.     /**  
  4.      * 事务属性配|ؓ PROPAGATION_REQUIRED  
  5.      */  
  6.     void methodA() {   
  7.         try {   
  8.             ServiceB.methodB();   
  9.         } catch (SomeException) {   
  10.             // 执行其他业务, ?nbsp;ServiceC.methodC();   
  11.         }   
  12.     }   
  13.   
  14. }   


q种方式也是潜套事务最有h值的地方, 它vC分支执行的效? 如果 ServiceB.methodB p|, 那么执行 ServiceC.methodC(), ?ServiceB.methodB 已经回滚到它执行之前?SavePoint, 所以不会生脏数据(相当于此Ҏ从未执行q?, q种Ҏ可以用在某些特D的业务? ?PROPAGATION_REQUIRED ?PROPAGATION_REQUIRES_NEW 都没有办法做到这一? (题外?: 看到q种代码, g似曾相识, 惌v?prototype.js 中的 Try 函数 )

2. 代码不做M修改, 那么如果内部事务(?ServiceB#methodB) rollback, 那么首先 ServiceB.methodB 回滚到它执行之前?SavePoint(在Q何情况下都会如此),
   外部事务(?ServiceA#methodA) 根据具体的配置军_自己?commit q是 rollback (+MyCheckedException).
  
  
上面大致讲述了潜套事务的使用场景, 下面我们来看如何?spring 中?PROPAGATION_NESTED, 首先来看 AbstractPlatformTransactionManager

Java代码
  1. /**  
  2.  * Create a TransactionStatus for an existing transaction.  
  3.  */  
  4. private TransactionStatus handleExistingTransaction(   
  5.         TransactionDefinition definition, Object transaction, boolean debugEnabled)   
  6.         throws TransactionException {   
  7.   
  8.    ... 省略   
  9.   
  10.     if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {   
  11.         if (!isNestedTransactionAllowed()) {   
  12.             throw new NestedTransactionNotSupportedException(   
  13.                     "Transaction manager does not allow nested transactions by default - " +   
  14.                     "specify 'nestedTransactionAllowed' property with value 'true'");   
  15.         }   
  16.         if (debugEnabled) {   
  17.             logger.debug("Creating nested transaction with name [" + definition.getName() + "]");   
  18.         }   
  19.         if (useSavepointForNestedTransaction()) {   
  20.             // Create savepoint within existing Spring-managed transaction,   
  21.             // through the SavepointManager API implemented by TransactionStatus.   
  22.             // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.   
  23.             DefaultTransactionStatus status =   
  24.                     newTransactionStatus(definition, transaction, falsefalse, debugEnabled, null);   
  25.             status.createAndHoldSavepoint();   
  26.             return status;   
  27.         }   
  28.         else {   
  29.             // Nested transaction through nested begin and commit/rollback calls.   
  30.             // Usually only for JTA: Spring synchronization might get activated here   
  31.             // in case of a pre-existing JTA transaction.   
  32.             doBegin(transaction, definition);   
  33.             boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);   
  34.             return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);   
  35.         }   
  36.     }   
  37. }  

  
一目了?

1. 我们要设|?transactionManager ?nestedTransactionAllowed 属性ؓ true, 注意, 此属性默认ؓ false!!!

再看 AbstractTransactionStatus#createAndHoldSavepoint() Ҏ

Java代码
  1. /**  
  2.  * Create a savepoint and hold it for the transaction.  
  3.  * @throws org.springframework.transaction.NestedTransactionNotSupportedException  
  4.  * if the underlying transaction does not support savepoints  
  5.  */  
  6. public void createAndHoldSavepoint() throws TransactionException {   
  7.     setSavepoint(getSavepointManager().createSavepoint());   
  8. }  


  可以看到 Savepoint ?SavepointManager.createSavepoint 实现? 再看 SavepointManager 的层ơ结? 发现
  ?Template 实现?JdbcTransactionObjectSupport, 常用?DatasourceTransactionManager, HibernateTransactionManager
  中的 TransactonObject 都是它的子类 : 

 
   
  JdbcTransactionObjectSupport 告诉我们必须要满两个条件才?createSavepoint :
 
2. java.sql.Savepoint 必须存在, ?jdk 版本?1.4+
3. Connection.getMetaData().supportsSavepoints() 必须?true, ?jdbc drive 必须支持 JDBC 3.0


保以上条g都满_, 你就可以试使用 PROPAGATION_NESTED ? (全文?


]]>
转脓Q【学习笔记】开源缓存包 EHCache 全接?/title><link>http://www.tkk7.com/zjrstar/archive/2008/08/14/222052.html</link><dc:creator>一叶笑?/dc:creator><author>一叶笑?/author><pubDate>Thu, 14 Aug 2008 08:59:00 GMT</pubDate><guid>http://www.tkk7.com/zjrstar/archive/2008/08/14/222052.html</guid><wfw:comment>http://www.tkk7.com/zjrstar/comments/222052.html</wfw:comment><comments>http://www.tkk7.com/zjrstar/archive/2008/08/14/222052.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/zjrstar/comments/commentRss/222052.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/zjrstar/services/trackbacks/222052.html</trackback:ping><description><![CDATA[原文地址Qhttp://www.uusam.com/uu/blog/article.asp?id=60<br /> <br /> EHCache 是一个纯java的,在Hibernate2.1充当可插入的的在q程中的~存Q它h以下~存Q最的依赖性,全面的文Ҏ:快速,单,丰富的文档和试用例?<br /> <br />     官方|站 http://ehcache.sourceforge.net/ <br /> <br /> Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-<br /> Q-Q-Q-Q-Q-使用介-Q-Q-Q-Q-Q-Q?br /> Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-<br />     ehcache-1.2 cacheNames 列表的取得;<br /> <br />     Ҏ一Q?br />         CacheManager.create();<br />         String[] cacheNames = CacheManager.getInstance().getCacheNames();<br /> <br />     Ҏ二:<br />         CacheManager manager = new CacheManager();<br />         String[] cacheNames = manager.getCacheNames();<br /> <br />     Ҏ三:<br />         CacheManager manager1 = new CacheManager("src/config/ehcache1.xml");<br />         CacheManager manager2 = new CacheManager("src/config/ehcache2.xml");<br />         String[] cacheNamesForManager1 = manager1.getCacheNames();<br />         String[] cacheNamesForManager2 = manager2.getCacheNames();<br /> <br /> <br />     ehcache-1.2 理器各U徏立的ҎQ?br /> <br />     Ҏ一Q?br />          CacheManager manager = new CacheManager();<br /> <br />     Ҏ二:<br />         CacheManager manager = new CacheManager("src/config/ehcache.xml");<br /> <br />     Ҏ三:<br />         URL url = getClass().getResource("/anotherconfigurationname.xml");<br />         CacheManager manager = new CacheManager(url);<br /> <br />     Ҏ四:<br />         InputStream fis = new FileInputStream(new File("src/config/ehcache.xml").getAbsolutePath());<br />         try {<br />             CacheManager manager = new CacheManager(fis);<br />         } finally {<br />             fis.close();<br />         }<br /> <br /> <br />     d和删除缓存元?br /> <br />         讄一个名为test 的新cache,test属性ؓ默认<br />         CacheManager singletonManager = CacheManager.create();<br />         singletonManager.addCache("testCache");<br />         Cache test = singletonManager.getCache("testCache");<br /> <br />         讄一个名为test 的新cache,q定义其属?<br />         CacheManager singletonManager = CacheManager.create();<br />         Cache memoryOnlyCache = new Cache("testCache", 5000, false, false, 5, 2);<br />         manager.addCache(memoryOnlyCache);<br />         Cache test = singletonManager.getCache("testCache");<br />         <br />         Cache 属性说明:<br /> <br />             构造函敎ͼ<br />             public Cache(java.lang.String name,<br />                          int maxElementsInMemory,<br />                          boolean overflowToDisk,<br />                          boolean eternal,<br />                          long timeToLiveSeconds,<br />                          long timeToIdleSeconds)<br /> <br />             参数说明Q?br />             name                          - 元素名字?br />                 maxElementsInMemory           - 讑֮内存中创建对象的最大倹{?br />                 overflowToDisk                - 讄当内存中~存辑ֈ maxInMemory 限制时元素是否可写到盘<br />                                                        上?br />                 eternal                       - 讄元素Q译注:内存中对象)是否怹ȝ。如果是Q将忽略?br />                                                       旉制且元素怸消亡?br />                 timeToIdleSeconds             - 讄某个元素消亡前的停顿旉?br />                                                       也就是在一个元素消亡之前,两次讉K旉的最大时间间隔倹{?br />                                                       q只能在元素不是怹ȝ时有效(译注Q如果对象永恒不灭,?br />                                                       讄该属性也无用Q?br />                                                       如果该值是 0 意味着元素可以停顿无穷长的旉?br />                 timeToLiveSeconds             - 为元素设|消亡前的生存时间?br />                                                        也就是一个元素从构徏到消亡的最大时间间隔倹{?br />                                                        q只能在元素不是怹ȝ时有效?br /> <br />         删除~存元素Q?br />         CacheManager singletonManager = CacheManager.create();<br />         singletonManager.removeCache("test");<br /> <br /> <br />     关闭~存理?CacheManager<br />         <br />         CacheManager.getInstance().shutdown();<br /> <br /> <br />     对于~存对象的操作:<br />         攑օ一个简单的对象到缓存元素;<br />         Cache cache = manager.getCache("sampleCache1");<br />         Element element = new Element("key1", "value1");<br />         cache.put(element);<br /> <br />         得到一个序列化后的对象属性|<br />         Cache cache = manager.getCache("sampleCache1");<br />         Element element = cache.get("key1");<br />         Serializable value = element.getValue();<br /> <br />         得到一个没有序列化后的对象属性|<br />         Cache cache = manager.getCache("sampleCache1");<br />         Element element = cache.get("key1");<br />         Object value = element.getObjectValue();<br />         <br />         删除一个对象从元素Q?br />         Cache cache = manager.getCache("sampleCache1");<br />         Element element = new Element("key1", "value1"<br />         cache.remove("key1");<br /> <br />     对于永固性磁盘存储,立即存储到磁盘:<br /> <br />         Cache cache = manager.getCache("sampleCache1");<br />         cache.flush();<br /> <br /> <br />     获得~存大小Q?br />         得到~存的对象数量;<br />         Cache cache = manager.getCache("sampleCache1");<br />         int elementsInMemory = cache.getSize();<br /> <br />         得到~存对象占用内存的数?br />         Cache cache = manager.getCache("sampleCache1");<br />         long elementsInMemory = cache.getMemoryStoreSize();<br /> <br />         得到~存对对象占用磁盘的数量<br />         Cache cache = manager.getCache("sampleCache1");<br />         long elementsInMemory = cache.getDiskStoreSize();<br /> <br />     关于~存的读取和丢失的记?br />         得到~存d的命中次敎ͼ<br />         Cache cache = manager.getCache("sampleCache1");<br />         int hits = cache.getHitCount();<br />         <br />         得到内存中缓存读取的命中ơ数Q?br />         Cache cache = manager.getCache("sampleCache1");<br />         int hits = cache.getMemoryStoreHitCount();<br /> <br />         得到盘中缓存读取的命中ơ数Q?br />         Cache cache = manager.getCache("sampleCache1");<br />         int hits = cache.getDiskStoreCount();<br />         <br />         得到~存d的丢失次敎ͼ<br />         Cache cache = manager.getCache("sampleCache1");<br />         int hits = cache.getMissCountNotFound();<br /> <br />         得到~存d的已l被销毁的对象丢失ơ数Q?br />         Cache cache = manager.getCache("sampleCache1");<br />         int hits = cache.getMissCountExpired();<br /> <br /> Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-<br /> Q-Q-Q-Q-Q-单例子-Q-Q-Q-Q-Q-Q?br /> Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-<br /> <br />     实战Q?br />         XML文g格式:<br /> <br />             <ehcache><br /> <br />                 <diskStore path="java.io.tmpdir"/><br /> <br />                 <defaultCache<br />                         maxElementsInMemory="10000"<br />                         eternal="false"<br />                         timeToIdleSeconds="120"<br />                         timeToLiveSeconds="120"<br />                         overflowToDisk="true"<br />                         diskPersistent="false"<br />                         diskExpiryThreadIntervalSeconds="120"<br />                         memoryStoreEvictionPolicy="LRU"<br />                         /><br /> <br />                 <cache name="cache1"<br />                        maxElementsInMemory="10000"<br />                        eternal="false"<br />                        overflowToDisk="true"<br />                        timeToIdleSeconds="2"<br />                        timeToLiveSeconds="3"<br />                        memoryStoreEvictionPolicy="LFU"<br />                         /><br />                         <br />             </ehcache><br /> <br />     源码Q?br /> <br />         import java.io.Serializable;<br /> <br />         import net.sf.ehcache.Cache;<br />         import net.sf.ehcache.CacheManager;<br />         import net.sf.ehcache.Element;<br /> <br />         /**<br />          #############################################################################<br />          # DESCRIBE ehcache ~存操作DEMO<br />          # AUTHOR   悠~?br />          # DATE     2006-7-10<br />          # COMPANY  FLX<br />          # PORJECT  ehcache-demo<br />          #############################################################################<br />          */<br /> <br />         public class Demo {<br />             <br />             static CacheManager manager= new CacheManager();<br /> <br />             /**<br />              *##############################################################################<br />              * <br />              * @DESCRIBE    <br />              * @param args<br />              * @throws InterruptedException<br />              *                         <br />              *##############################################################################<br />              */<br />             public static void main(String[] args) throws InterruptedException {<br />                 <br />                 String[] cacheNames = manager.getCacheNames();<br />                 System.out.println("d的缓存列表ؓQ?);<br />                 for(int i=0;i<cacheNames.length;i++){ <br />                     System.out.println("-- "+(i+1)+" "+cacheNames[i]);<br />                 }<br />                 <br />                 Cache cache = manager.getCache("cache1");<br />                 Element element = new Element("key1", "value1");<br />                 cache.put(element);<br />                 <br />                 element = cache.get("key1");<br />                 Serializable value = element.getValue();<br />                 System.out.println("序列化后的gؓQ?+value.toString());<br /> <br />                 element = cache.get("key1");<br />                 Object value1 = element.getObjectValue();<br />                 System.out.println("未序列化的gؓQ?+value1.toString());<br />                 <br />                 int elementsInMemory = cache.getSize();<br />                 System.out.println("得到~存的对象数量:"+elementsInMemory);<br />                 <br />                 long elementsInMemory1 = cache.getMemoryStoreSize();<br />                 System.out.println("得到~存对象占用内存的数量:"+elementsInMemory1);<br />                 <br />                 long elementsInMemory2 = cache.getDiskStoreSize();<br />                 System.out.println("得到~存对对象占用磁盘的数量Q?+elementsInMemory2);        <br />                 <br />                 int hits = cache.getHitCount();<br />                 System.out.println("得到~存d的命中次敎ͼ"+hits);        <br />                 <br />                 int hits1 = cache.getMemoryStoreHitCount();<br />                 System.out.println("得到内存中缓存读取的命中ơ数Q?+hits1);        <br />                 <br />                 int hits2 =cache.getDiskStoreHitCount();<br />                 System.out.println("得到盘中缓存读取的命中ơ数Q?+hits2);        <br />                 <br />                 int hits3 = cache.getMissCountNotFound();<br />                 System.out.println("得到~存d的丢失次敎ͼ"+hits3);        <br />                 <br />                 int hits4 = cache.getMissCountExpired();<br />                 System.out.println("得到~存d的已l被销毁的对象丢失ơ数Q?+hits4);    <br />             }<br /> <br />         }<br /> <br /> <img src ="http://www.tkk7.com/zjrstar/aggbug/222052.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/zjrstar/" target="_blank">一叶笑?/a> 2008-08-14 16:59 <a href="http://www.tkk7.com/zjrstar/archive/2008/08/14/222052.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://22youjizz.com" target="_blank">߹ۿվ</a>| <a href="http://jack-fx.com" target="_blank">Ʒѹһ </a>| <a href="http://wangquanai.com" target="_blank">97ѹۿƵ߹ۿ</a>| <a href="http://bbyy7.com" target="_blank">ŷ</a>| <a href="http://67f6.com" target="_blank">Ӱѹۿ</a>| <a href="http://trgod.com" target="_blank">þþƷƷް</a>| <a href="http://yuyang0752.com" target="_blank">˳wwwӰҳ</a>| <a href="http://sdnuoyuan.com" target="_blank">޹Ʒһþ</a>| <a href="http://qzllw.com" target="_blank">h˻ƽ</a>| <a href="http://yuase.com" target="_blank">޾ƷNVþþþþþþþ</a>| <a href="http://www-959kj.com" target="_blank">ŷ뾫ƷVA</a>| <a href="http://zhaosaohuo.com" target="_blank">þþþAVۿ</a>| <a href="http://ahbbht.com" target="_blank">һͼƬ</a>| <a href="http://1314c.com" target="_blank">ۺϹƷ</a>| <a href="http://2828228.com" target="_blank">Ļ߹ۿպ</a>| <a href="http://bjlfggcm.com" target="_blank">ɫַѹۿ</a>| <a href="http://dyj696.com" target="_blank">ŷƵ</a>| <a href="http://xxxxyz.com" target="_blank">һëƬѲ</a>| <a href="http://haiholr.com" target="_blank">Ů18ëƬˮѹۿ</a>| <a href="http://xxxxcccc.com" target="_blank">һAvëƬþþƷ</a>| <a href="http://www-006688.com" target="_blank">޾Ʒ˳߹ۿ</a>| <a href="http://my94ok.com" target="_blank">պƷר</a>| <a href="http://tlyyt.com" target="_blank">AVպAVɫ</a>| <a href="http://xsjxp.com" target="_blank">ĻĻ</a>| <a href="http://whdysdt.com" target="_blank">שש</a>| <a href="http://j3223.com" target="_blank">պ޾Ʒ</a>| <a href="http://langtuojidian.com" target="_blank">߹ۿëƬ</a>| <a href="http://zgj688.com" target="_blank">þ޾Ʒavվ</a>| <a href="http://rdccc.com" target="_blank">AVպAVվ</a>| <a href="http://lzlcp.com" target="_blank">ĻѲ</a>| <a href="http://www-83118.com" target="_blank">ѿŮͰ</a>| <a href="http://wwwseselu.com" target="_blank">Ʒާѡ벥</a>| <a href="http://jcmy5188.com" target="_blank">޹˾þþƷţӰ</a>| <a href="http://tjtangpu.com" target="_blank">޾ƷһۺAV</a>| <a href="http://5shitou.com" target="_blank">ɫƬѿ</a>| <a href="http://323799.com" target="_blank">ѰƵ̫ˬ</a>| <a href="http://cqyouyongpx.com" target="_blank">޵һƵվ</a>| <a href="http://qianmiu.com" target="_blank">Ļ߹ۿ</a>| <a href="http://19b1.com" target="_blank">þ޾Ʒ߳ۺɫaƬ</a>| <a href="http://c7372.com" target="_blank">˳վ߹ۿ </a>| <a href="http://wangquanai.com" target="_blank">ѹ߹ۿ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>