2008年10月8日
#
服务类中有个一判断条件propertys.get(WIN_INDEXMONTH).toString() != "",在tomcat上能正常处理。
但是到weblogic上就出现问题了。
而后改成
if(!"".equals(propertys.get(WIN_INDEXMONTH).toString())){
。。
}
就都正确了。
equals 是用于比较两个对象的内容是否相等。
== 用于比较基本数据类型 和 引用类型时的区别为
比较两个基本数据类型,若两个值相同则返回true
比较引用时,如果引用指向内存中的同一个对象,则返回true
String str = new String("aaa");
str.equals("aaa");---true
str == "aaa";---false
Struts、Webwork比较
比较内容 Struts WebWork2
Action 类 在Struts里面,每一个
Action
Class都需要扩展org.apache.struts.action.Action;这个在Java编程中会引来一些问题,就是关于多种继承的问题
Webwork仅仅需要implement com.opensymphony.xwork.Action
Interface,您也可以implement其它的interface来实现更多的功能,譬如:validate(验证),localware(国际化)等,当然
webwork2也提供了一个类ActionSupport 集成了以上功能。Developer可以根据需要实现不同的功能。
线程模型 Struts
Actions必须是thread-safe方式,它仅仅允许一个实例去处理所有的请求。所以action用到的所有的资源都必须统一同步,这个就引起了线程安全的问题。
Webwork 2 actions每一个请求对应一个action,因此没有线程的安全问题。实际上Servlet
容器对应每一个请求会产生许多Object,这种一个请求产生许多object的例子没有证明对性能产生太多的影响。现在Web容器都是这么处理Servlet的。
Servlet的依赖 Struts处理一个Action时候必须要依赖ServletRequest and
ServletResponse。所以这一层摆脱不了Server容器。而serveltRequest可能会被web层的Context使用。 Webwork2
每一个action不依赖任何层和任何容器。他们使用Request和response是通过ActionContext,所以这个对于逻辑层的分离是很重要的。
测试
因为Struts的每一个action都必须用到request和response所以都必须通过web层来进行测试。这就导致了许多测试struts都要通过web容器(尽管现在有许多测试方法cactus
mock 等)。
Webwork的action能够通过赋予一定的属性。就可以执行。同时您可以使用一个mock的实例去测试,而不是通过启动web容器来进行测试。
FormBean Struts
需要一个FormBeans针对每一个Form。而使用DynaBeans实际上没有太大的意义。不能够很好的处理现有的模型。 Webwork
能够动态的收集web的数据然后在赋值给bean。同时它还能够使用FormBean模式。Webwork2还允许现有的ModelDrvien进行导入处理。能够处理它就像处理action自己的属性一样。
前端表达语言 Struts大部分使用的是JSTL EL(JSP2。0)去获得数据的。在Collection上面处理显得很弱。
Webwork前端可以使用JSTL同时也可以使用多种表现形式。譬如:velocity freemaker jspparer
xml等等。Webwork2 利用ongl建立一个valuestack来搜集数据
类型的转换 Struts
FormBeans把所有的数据都作为string类型。得到一个自己需要的类型然后展示给用户是很困难的。 Webwork2
数据都是转换成Java中的类型。这个根据Form的类型自动转换。然后操作这些bean十分方便。
对Action 执行前和后的处理
Struts处理action的时候是基于class的hierarchies,很难在action处理前和后进行操作。 Webwork2
允许您处理action可以通过interceptor,就是在每一个action处理前或者后进行其它操作。
验证处理
因为struts的FormBean的属性都被认为是string类型。许多类型的验证都要进行类型转换的处理。FormBean对一个验证链的处理显然不行。
而webwork2的验证采用的是interceptor设计模式。它的这种验证方式决定了它十分灵活。而且一个验证可以重复不断的使用仅仅需要一个XML文件的定义。实际上webwork2的验证是采用了xwork的验证框架。
Action的链的控制 Struts里面每一个action对应一个处理,如果一个action转向另外一个action就很困难了。
Webwork使用一个强大的DispatcherChain去处理这个action链。很方便的从一个处理到另外一个处理。
在spring基础文件中配置数据源,事务管理和事务管理代理bean的。
<!-- ======================== Properties ======================== -->
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath*:conf/configure.properties</value>
</list>
</property>
</bean>
<!-- ======================== data configure ========================== -->
<!-- Apache Database Connection Pool -->
<bean id="dataSource"<!--BasicDataSource类的别名-->
class="org.apache.commons.dbcp.BasicDataSource""<!--BasicDataSource类的别名所指向的真正类-->
destroy-method="close">
<property name="driverClassName">"<!--对应到BasicDataSource类中的属性-->
<value>${db.driver}</value>"<!--该属性值绑定到BasicDataSource类中的属性此处为property中name多对应的属性-->
</property>
<property name="url">
<value>${db.url}</value>
</property>
<property name="username">
<value>${db.user}</value>
</property>
<property name="password">
<value>${db.password}</value>
</property>
<property name="initialSize">
<value>15</value>
</property>
<property name="maxActive">
<value>30</value>
</property>
<property name="maxIdle">
<value>30</value>
</property>
<property name="minIdle">
<value>5</value>
</property>
</bean>
<!-- Transaction manager for a single JDBC DataSource DAO IoC -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref local="dataSource" />
</property>
<!--
- A parent bean definition which is a base definition for transaction proxies.
- It's marked as abstract, since it's not supposed to be instantiated itself.
- We set shared transaction attributes here, following our naming patterns.
- The attributes can still be overridden in child bean definitions.
-
-->
<bean id="baseTransactionProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true"><!-- 为了避免ApplicationContext对它预先的初始化 -->
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
</bean>
如果有很多的bean的某些定义都是类似的(比如对于transaction的定义),那么可以给他们的定义作一个模板。
使用parent可以实现这一点。(注意parent并非意味着两个bean之间存在着java的继承关系,只是表示他们的定义之间存在着共同的部分)。
child bean使用parent来继承模板的定义,同样还可以覆盖模板的定义。
很多时候模板并不需要被实例化,为了避免ApplicationContext对它预先的初始化,一般设置abstract="true"
为了提高事务代理的复用程度,没有在baseTransactionProxy设置target属性。此时设置abstract="true"
下面以一个用户管理UserInfo 用户管理模块为例,设置模块中各个bean的依赖注入和事务的管理
首先定义service实现类
<!-- user target bean -->
<bean id="userTarget"
class="com.zhjy.gmp.service.impl.UserInfoServiceImpl">
<property name="userDAO">
<ref local="userDAO" />
</property>
<!-- 部门DAO -->
<property name="orgDAO">
<ref local="orgInfoDAO" />
</property>
<!-- 角色DAO -->
<property name="roleDAO">
<ref local="roleDAO" />
</property>
</bean>
这里注入了UserInfoServiceImpl所需要的三个dao实例。
接下来对该service进行事务管理的配置
<!-- user service bean -->
<bean id="userService" parent="baseTransactionProxy">
<property name="target">
<ref bean="userTarget" />
</property>
</bean>
此处通过target属性将userTarget实例注入到事务代理中。
最后定义dao实例
<!-- user dao bean -->
<bean id="userDAO" class="com.zhjy.gmp.dao.impl.UserInfoDAOImpl">
<property name="dataSource">
<ref bean="dataSource" /><!-- ref bean 与 ref local 的区别,后者表示从本地的(同一个)xml文件中来寻找bean,前者是全局范围内寻找bean。 -->
</property>
</bean>
spring提供声明式事务管理,这是通过aop实现的,这是最少影响应用代码的选择。
通常通过
TransactionProxyFactoryBean实现事务代理。需要一个目标对象包装在事务代理中。当我们定义
TransactionProxyFactoryBean是,我们需要一个关于PlatformTransactionManager的实现引用和事务属性,是无属性含有事务定义。
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref local="dataSource" />
</property>
</bean>
以上代码是关于PlatformTransactionManager的实现类的定义。在事务代理定义中将引用这个javabean。
<bean id="baseTransactionProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true">
<property name="transactionManager">
<ref bean="transactionManager" />
</property>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="delete*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
此处是定义事务代理,其中应用了关于PlatformTransactionManager的实现和事务属性。
spring中的事务策略
spring事务抽象的关键是事务策略的概念。这个概念由 org.springframework.transaction.PlatformTransactionManager 接口体现。
public interface PlatformTransactionManager
{
public abstract TransactionStatus getTransaction(TransactionDefinition transactiondefinition)
throws TransactionException;
public abstract void commit(TransactionStatus transactionstatus)
throws TransactionException;
public abstract void rollback(TransactionStatus transactionstatus)
throws TransactionException;
}
getTransaction根据一个类型为TransactionDefinition 参数返回一个TransactionStatus 类型的对象,返回的 TransactionStatus对象可能代表一个新的或已经存在的事 务(如果在当前调用堆栈有一个符合条件的事务)。
TransactionDefinition接口指定:
-
事务隔离:当前事务和其它事务的隔离的程度。 例如,这个事务能否看到其他事务未提交的写数据?
-
事务传播:通常在一个事务中执行的 所有代码都会在这个事务中运行。但是,如果一个事务上下文已经存在, 有几个选项可以指定一个事务性方法的执行行为:例如,简单地在现有的 事务中运行(大多数情况);或者挂起现有事务,创建一个新的事务。 Spring提供EJB CMT中熟悉的事务传播选项。
-
事务超时: 事务在超时前能运行多 久(自动被底层的事务基础设施回滚)。
-
只读状态: 只读事务不修改任何数 据。只读事务在某些情况下(例如当使用Hibernate时)可可是一种非常有用的优化
PlatformTransactionManager实现是如何定义的,它将和JDBC一起工作
首先需要定义jdbc数据源。然后使用DataSourceTransactionManager,为它提供一个数据源引用。
<bean id="dataSource" <!-- BasicDataSource的别名 -->
class="org.apache.commons.dbcp.BasicDataSource" <!-- BasicDataSource类的别名所对应的类 -->
destroy-method="close">
<property name="driverClassName"><!-- 对应BasicDataSource类中的属性 -->
<value>${jdbc.driverClassName}</value><!-- 该属性值将绑定到BasicDataSource上所对应的属性上(driverClassName) -->
</property>
<property name="url"><value>${jdbc.url}</value></property>
<property name="username"><value>${jdbc.username}</value></property>
<property name="password"><value>${jdbc.password}</value></property>
</bean>
PlatformTransactionManager的定义如下.
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource">
<ref local="dataSource" />
</property>
</bean>
如果我们使用JTA, 我们需要使用通过JNDI获得的容器数据源,和一个JtaTransactionManager实 现。JtaTransactionManager不需要知道数据源,或任何其他特定资源,因为它将 使用容器的全局事务管理。
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>jdbc/jpetstore</value></property>
</bean>
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"/>
使用hibernate局部事务的配置
在这种情况下,我们需要定义一个Hibernate的LocalSessionFactory,应用程 序将使用它获得Hibernate的会话。
数据源bean定义和上面例子类似,这里不再罗列(如果这是容器数据源,它应该是非事务的,因为Spring会管理事务, 而不是容器)。
这种情况下,“transactionManager” bean的类型是HibernateTransactionManager。
和DataSourceTransactionManager拥有一个数据源的引用一样, HibernateTransactionManager需要一个SessionFactory的引用。
<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="mappingResources">
<value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory"><ref local="sessionFactory"/></property>
</bean>