??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲日本一线产区和二线产区对比,亚洲成年人在线观看,亚洲国产综合精品中文字幕
http://m.tkk7.com/ashutc/category/42982.html沈阳求职Qjava3q以上经验)Qashutc@126.com zh-cn Fri, 15 Apr 2011 09:12:43 GMT Fri, 15 Apr 2011 09:12:43 GMT 60 spring3.0注解 http://m.tkk7.com/ashutc/archive/2011/04/14/348270.html西瓜 西瓜 Thu, 14 Apr 2011 02:01:00 GMT http://m.tkk7.com/ashutc/archive/2011/04/14/348270.html http://m.tkk7.com/ashutc/comments/348270.html http://m.tkk7.com/ashutc/archive/2011/04/14/348270.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/348270.html http://m.tkk7.com/ashutc/services/trackbacks/348270.html 使用 @Repository、@Service、@Controller ?@Component 类标识?Bean
Spring ?2.0 版本开始,陆箋引入了一些注解用于简?Spring 的开发。@Repository
注解便属于最先引入的一批,它用于将数据讉K?(DAO ?) 的类标识?Spring Bean。具体只需该注解标注?DAO
cM卛_。同ӞZ?Spring 能够扫描c\径中的类q识别出 @Repository 注解Q需要在 XML 配置文g中启?Bean
的自动扫描功能,q可以通过 <context:component-scan/> 实现。如下所C:(x)
// 首先使用 @Repository ?DAO cd明ؓ(f) Bean
package bookstore.dao;
@Repository
public class UserDaoImpl implements UserDao{ …… }
// 其次Q在 XML 配置文g中启?Spring 的自动扫描功?br />
<beans … >
……
<context:component-scan base-package=”bookstore.dao” />
……
</beans>
如此Q我们就不再需要在 XML 中显式?<bean/> q行 Bean 的配|。Spring 在容器初始化时将自动扫描
base-package 指定的包?qing)其子包下的所?class 文gQ所有标注了 @Repository 的类都将被注册ؓ(f) Spring
Bean?/p>
Z?@Repository 只能标注?DAO cM呢?q是因ؓ(f)该注解的作用不只是将c识别ؓ(f)
BeanQ同时它q能所标注的类中抛出的数据讉K异常装?Spring 的数据访问异常类型?Spring
本n提供了一个丰富的q且是与具体的数据访问技术无关的数据讉K异常l构Q用于封装不同的持久层框架抛出的异常Q得异常独立于底层的框架?/p>
Spring 2.5 ?@Repository 的基上增加了功能cM的额外三个注解:(x)@Component、@Service、@ConstrollerQ它们分别用于Y件系l的不同层次Q?/p>
•@Component 是一个泛化的概念Q仅仅表CZ个组?(Bean) Q可以作用在M层次?br />
•@Service 通常作用在业务层Q但是目前该功能?@Component 相同?br />
•@Constroller 通常作用在控制层Q但是目前该功能?@Component 相同?br />
?
q在cM使用 @Repository、@Component、@Service ?@Constroller 注解QSpring ?x)自动创建相应?
BeanDefinition 对象Qƈ注册?ApplicationContext 中。这些类成?Spring
受管lg。这三个注解除了作用于不同Y件层ơ的c,其用方式与 @Repository 是完全相同的?/p>
另外Q除了上面的四个注解外,用户可以创徏自定义的注解Q然后在注解上标?@ComponentQ那么,该自定义注解便具有了与所 @Component 相同的功能。不q这个功能ƈ不常用?/p>
当一?Bean 被自动检到Ӟ?x)根据那个扫描器?BeanNameGenerator {略生成它的 bean
名称。默认情况下Q对于包?name 属性的 @Component、@Repository?@Service ?@ControllerQ会(x)?
name 取g?Bean 的名字。如果这个注解不包含 name 值或是其他被自定义过滤器发现的组Ӟ默认 Bean
名称?x)是写开头的非限定类名。如果你不想使用默认 bean 命名{略Q可以提供一个自定义的命名策略。首先实?BeanNameGenerator
接口Q确认包含了一个默认的无参数构造方法。然后在配置扫描器时提供一个全限定cdQ如下所C:(x)
<beans ...>
<context:component-scan
base-package="a.b" name-generator="a.SimpleNameGenerator"/>
</beans>
与通过 XML 配置?Spring Bean 一P通过上述注解标识?
BeanQ其默认作用域是"singleton"Qؓ(f)了配合这四个注解Q在标注 Bean 的同时能够指?Bean 的作用域QSpring 2.5
引入?@Scope 注解。用该注解时只需提供作用域的名称p了,如下所C:(x)
@Scope("prototype")
@Repository
public class Demo { … }
如果你想提供一个自定义的作用域解析{略而不使用Z注解的方法,只需实现 ScopeMetadataResolver 接口Q确认包含一个默认的没有参数的构造方法。然后在配置扫描器时提供全限定类名:(x)
<context:component-scan base-package="a.b"
scope-resolver="footmark.SimpleScopeResolver" />
--------------------------------------------------------------------------------
回页?/p>
使用 @PostConstruct ?@PreDestroy 指定生命周期回调Ҏ(gu)
Spring Bean 是受 Spring IoC 容器理Q由容器q行初始化和销毁的Qprototype
cd由容器初始化之后便不受容器管理)Q通常我们不需要关注容器对 Bean 的初始化和销毁操作,?Spring l过构造函数或者工厂方法创建的
Bean
是已经初始化完成ƈ立即可用的。然而在某些情况下,可能需要我们手工做一些额外的初始化或者销毁操作,q通常是针对一些资源的获取和释放操作?
Spring 1.x 为此提供了两U方式供用户指定执行生命周期回调的方法?/p>
W一U方式是实现 Spring 提供的两个接口:(x)InitializingBean ?DisposableBean。如果希望在 Bean
初始化完成之后执行一些自定义操作Q则可以?Bean 实现 InitializingBean 接口Q该接口包含一?
afterPropertiesSet() Ҏ(gu)Q容器在 Bean 讄了属性之后,自动调用该Ҏ(gu)Q如?Bean 实现?
DisposableBean 接口Q则容器在销毁该 Bean 之前Q将调用该接口的 destroy() Ҏ(gu)。这U方式的~点是,?Bean
cd?Spring 提供的接口,增加了代码与 Spring 框架的耦合度,因此不推荐用?/p>
W二U方式是?XML 文g中?<bean> ?init-method ?destroy-method
属性指定初始化之后和销毁之前的回调Ҏ(gu)Q代码无需实现M接口。这两个属性的取值是相应 Bean
cM的初始化和销毁方法,Ҏ(gu)名Q意,但是Ҏ(gu)不能有参数。示例如下:(x)
<bean id=”userService”
class=”bookstore.service.UserService”
init-method=”init” destroy-method=”destroy”>
…
</bean>
Spring 2.5 在保留以上两U方式的基础上,提供了对 JSR-250 的支持。JSR-250
规范定义了两个用于指定声明周期方法的注解Q@PostConstruct ?
@PreDestroy。这两个注解使用非常单,只需分别他们标注于初始化之后执行的回调Ҏ(gu)或者销毁之前执行的回调Ҏ(gu)上。由于用了注解Q因此需
要配|相应的 Bean 后处理器Q亦卛_ XML 中增加如下一行:(x)
<context:annotation-config />
比较上述三种指定生命周期回调Ҏ(gu)的方式,W一U是不徏议用的Q不但其用法不如后两U方式灵z,而且无Ş中增加了代码与框架的耦合度。后面两U方式开发者可以根据用习(fn)惯选择其中一U,但是最好不要合用,以免增加l护的难度?/p>
--------------------------------------------------------------------------------
回页?/p>
使用 @Required q行 Bean 的依赖检?/p>
依赖(g)查的作用是,判断l定 Bean 的相?Setter Ҏ(gu)是否都在实例化的时候被调用了。而不是判断字D|否已l存在g。Spring
q行依赖(g)查时Q只?x)判断属性是否用了 Setter 注入。如果某个属性没有?Setter
注入Q即使是通过构造函数已lؓ(f)该属性注入了|Spring 仍然认ؓ(f)它没有执行注入,从而抛出异常。另外,Spring 只管是否通过 Setter
执行了注入,而对注入的值却没有M要求Q即使注入的 <null/>QSpring 也认为是执行了依赖注入?/p>
<bean> 标签提供?dependency-check 属性用于进行依赖检查。该属性的取值包括以下几U:(x)
•none -- 默认不执行依赖检查。可以在 <beans> 标签上?default-dependency-check 属性改变默认倹{?br />
•simple -- 对原始基本类型和集合cdq行(g)查?br />
•objects -- 对复杂类型进行检查(除了 simple 所(g)查类型之外的其他cdQ?br />
•all -- Ҏ(gu)有类型进行检查?br />
?
版本使用 dependency-check 在配|文件中讄Q缺Ҏ(gu)_度较粗。?Spring2.0 提供?@Required
注解Q提供了更细_度的控制。@Required 注解只能标注?Setter Ҏ(gu)之上。因Z赖注入的本质是检?Setter
Ҏ(gu)是否被调用了Q而不是真的去(g)查属性是否赋g以及(qing)赋了什么样的倹{如果将该注解标注在?setXxxx() cd的方法则被忽略?/p>
Z?Spring 能够处理该注解,需要激zȝ应的 Bean 后处理器。要Ȁz该后处理器Q只需?XML 中增加如下一行即可?/p>
<context:annotation-config/>
当某个被标注?@Required ?Setter Ҏ(gu)没有被调用,?Spring 在解析的时候会(x)抛出异常Q以提醒开发者对相应属性进行设|?/p>
--------------------------------------------------------------------------------
回页?/p>
使用 @Resource、@Autowired ?@Qualifier 指定 Bean 的自动装配策?/p>
自动装配是指QSpring 在装?Bean 的时候,Ҏ(gu)指定的自动装配规则,某?Bean 所需要引用类型的 Bean 注入q来?lt;bean> 元素提供了一个指定自动装配类型的 autowire 属性,该属性有如下选项Q?/p>
•no -- 昑ּ指定不用自动装配?br />
•byName -- 如果存在一个和当前属性名字一致的 BeanQ则使用?Bean q行注入。如果名U匹配但是类型不匚wQ则抛出异常。如果没有匹配的cdQ则什么也不做?br />
•byType
-- 如果存在一个和当前属性类型一致的 Bean ( 相同cd或者子cd )Q则使用?Bean q行注入。byType
能够识别工厂Ҏ(gu)Q即能够识别 factory-method 的返回类型。如果存在多个类型一致的
BeanQ则抛出异常。如果没有匹配的cdQ则什么也不做?br />
•constructor -- ?byType cMQ只不过它是针对构造函数注入而言的。如果当前没有与构造函数的参数cd匚w?BeanQ则抛出异常。用该U装配模式时Q优先匹配参数最多的构造函数?br />
•autodetect -- Ҏ(gu) Bean 的自省机制决定采?byType q是 constructor q行自动装配。如?Bean 提供了默认的构造函敎ͼ则采?byTypeQ否则采?constructor q行自动装配?br />
?
使用 byType 或?constructor cd的自动装配的时候,自动装配也支持引用类型的数组或者用了泛型的集合,q样QSpring
׃(x)(g)查容器中所有类型匹配的 BeanQ组成集合或者数l后执行注入。对于用了泛型?Map cdQ如果键?String cdQ则
Spring 也会(x)自动执行装配Q将所有类型匹配的 Bean 作ؓ(f)|Bean 的名字作为键?/p>
我们可以l?<beans> 增加 default-autowire
属性,讄默认的自动封装策略。默认gؓ(f)"no"。如果用自动装配的同时Q也指定?property 或?constructor-arg
标签Q则昑ּ指定的值将覆盖自动装配的倹{目前的自动装不支持简单类型,比如基本cd、String、ClassQ以?qing)它们的数组cd?/p>
在按cd匚w的时?( 可能?byType、constructor、autodetect)Q同一个类型可能存在多?BeanQ如果被注入的属性是数组、集合或?MapQ这可能没有问题Q但是如果只是简单的引用cdQ则?x)抛出异常。解x法有如下几种Q?/p>
•取消?Bean 的自动装配特性,使用昑ּ的注入。我们可能不希望某个 Bean 被当作其?Bean
执行自动装时的候选对象,我们可以l该 <bean> 增加
autowire-candidate="false"?autowire-candidate 属性和 autowire
属性相互独立,互不相干。某?Bean 可以?autowire-candidate 讄?falseQ同时?autowire Ҏ(gu)?
另外Q我们可以设|?<beans> ?default-autowire-candidates
属性,可以在该属性中指定可以用于自动装配候?Bean 的匹配模式,比如
default-autowire-candidates="*serv,*dao"Q这表示所有名字以 serv 或?dao l尾?Bean
被列为候选,其他则忽略,相当于其?Bean 都指定ؓ(f) autowire-candidate="false"Q此时可以显式ؓ(f)
<bean> 指定 autowire-candidate="true"。在 <bean> 上指定的讄要覆?
<beans> 上指定的讄?br />
•如果在多个类型相同的 Bean 中有首选的 BeanQ那么可以将?<bean>
?primary 属性设|ؓ(f) "true" Q这栯动装配时便优先用该 Bean q行装配。此时不能将
autowire-candidate 设ؓ(f) false?br />
•如果使用的是 Java 5 以上版本Q可以用注解进行更l粒度的控制?br />
使用 @Autowired ?@Qualifier 注解执行自动装配
使用 @Autowired 注解q行装配Q只能是Ҏ(gu)cdq行匚w。@Autowired 注解可以用于 Setter
Ҏ(gu)、构造函数、字D,甚至普通方法,前提是方法必L臛_一个参数。@Autowired 可以用于数组和用泛型的集合cd。然?Spring
?x)将容器中所有类型符合的 Bean 注入q来。@Autowired 标注作用?Map cdӞ如果 Map ?key ?String
cdQ则 Spring ?x)将容器中所有类型符?Map ?value 对应的类型的 Bean 增加q来Q用 Bean ?id ?name
作ؓ(f) Map ?key?/p>
@Autowired 标注作用于普通方法时Q会(x)产生一个副作用Q就是在容器初始化该 Bean 实例的时候就?x)调用该?gu)。当Ӟ前提是执行了自动装配Q对于不满装配条g的情况,该方法也不会(x)被执行?/p>
当标注了 @Autowired 后,自动注入不能满Q则?x)抛出异常。我们可以给 @Autowired 标注增加一?
required=false 属性,以改变这个行为。另外,每一个类中只能有一个构造函数的 @Autowired.required() 属性ؓ(f)
true。否则就出问题了。如果用 @Autowired 同时标注了多个构造函敎ͼ那么QSpring 采用贪心算法匹配构造函?( 构造函数最?
)?/p>
@Autowired q有一个作用就是,如果其标注?BeanFactory cd、ApplicationContext
cd、ResourceLoader cd、ApplicationEventPublisher cd、MessageSource cd上,那么
Spring ?x)自动注入这些实现类的实例,不需要额外的操作?/p>
当容器中存在多个 Bean 的类型与需要注入的相同Ӟ注入不能执行,我们可以l?@Autowired 增加一个候选|做法是在
@Autowired 后面增加一?@Qualifier 标注Q提供一?String cd的g为候选的 Bean 的名字。D例如下:(x)
@Autowired(required=false)
@Qualifier("ppp")
public void setPerson(person p){}
@Qualifier 甚至可以作用于方法的参数 ( 对于Ҏ(gu)只有一个参数的情况Q我们可以将 @Qualifer 标注攄在方法声明上面,但是推荐攄在参数前?)QD例如下:(x)
@Autowired(required=false)
public void sayHello(@Qualifier("ppp")Person p,String name){}
我们可以在配|文件中指定某个 Bean ?qualifier 名字Q方法如下:(x)
<bean id="person" class="footmark.spring.Person">
<qualifier value="ppp"/>
</bean>
如果没有明确指定 Bean ?qualifier 名字Q那么默认名字就?Bean 的名字。通常Qqualifier 应该是有业务含义的,例如 "domain"Q?persistent" {,而不应该是类?"person" 方式?/p>
我们q可以将 @Qualifier 标注在集合类型上Q那么所?qualifier 名字与指定值相同的 Bean 都将被注入进来?/p>
最后,配置文g中需要指定每一个自定义注解的属性倹{我们可以?<meta> 标签来代?<qualifier/>
标签Q如?<meta> 标签?<qualifier/> 标签同时出现Q那么优先?
<qualifier> 标签。如果没?<qualifier> 标签Q那么会(x)?<meta>
提供的键值对来封?<qualifier> 标签。示例如下:(x)
<bean class="footmark.HelloWorld">
<qualifier type="MovieQualifier">
<attribute key="format" value="VHS"/>
<attribute key="genre" value="Comedy"/>
</qualifier>
</bean>
<bean class="footmark.HelloWorld">
<meta key="format" value="DVD"/>
<meta key="genre" value="Action"/>
</bean>
@Autowired 注解对应的后处理注册与前面相|只需在配|文件中增加如下一行即可:(x)
<context:annotation-config/>
如果 @Autowired 注入的是 BeanFactory、ApplicationContext、ResourceLoader
{系l类型,那么则不需?@QualifierQ此时即使提供了 @Qualifier 注解Q也会(x)被忽略;而对于自定义cd的自动装配,如果使用?
@Qualifier 注解q且没有名字与之匚w?BeanQ则自动装配匚wp|?/p>
使用 JSR-250 中的 @Resource ?@Qualifier 注解
如果希望Ҏ(gu) name 执行自动装配Q那么应该?JSR-250 提供?@Resource 注解Q而不应该使用 @Autowired ?@Qualifier 的组合?/p>
@Resource 使用 byName 的方式执行自动封装。@Resource 标注可以作用于带一个参数的 Setter
Ҏ(gu)、字D,以及(qing)带一个参数的普通方法上。@Resource 注解有一?name 属性,用于指定 Bean 在配|文件中对应的名字。如果没有指?
name 属性,那么默认值就是字D|者属性的名字。@Resource ?@Qualifier 的配合虽然仍然成立,但是 @Qualifier
对于 @Resource 而言Q几乎与 name 属性等效?/p>
如果 @Resource 没有指定 name 属性,那么使用 byName 匚wp|后,?x)退而?byType
l箋匚wQ如果再p|Q则抛出异常。在没有?@Resource 注解昑ּ指定 name 属性的前提下,如果其标注?BeanFactory
cd、ApplicationContext cd、ResourceLoader cd、ApplicationEventPublisher
cd、MessageSource cd上,那么 Spring ?x)自动注入这些实现类的实例,不需要额外的操作。此?name 属性不需要指?(
或者指定ؓ(f)"")Q否则注入失败;如果使用?@QualifierQ则该注解将被忽略。而对于用戯定义cd的注入,@Qualifier ?
name {h(hun)Qƈ且不被忽略?/p>
<bean> ?primary ?autowire-candidate 属性对 @Resource、@Autowired 仍然有效?/p>
--------------------------------------------------------------------------------
回页?/p>
使用 @Configuration ?@Bean q行 Bean 的声?/p>
虽然 2.0 版本发布以来QSpring 陆箋提供了十多个注解Q但是提供的q些注解只是Z在某些情况下?XML 的配|,q要取?
XML 配置方式。这一点可以从 Spring IoC 容器的初始化cd以看出:(x)ApplicationContext 接口的最常用的实现类?
ClassPathXmlApplicationContext ?FileSystemXmlApplicationContextQ以?qing)面?
Portlet ?XmlPortletApplicationContext 和面?web ?
XmlWebApplicationContextQ它们都是面?XML 的。Spring 3.0
新增了另外两个实现类QAnnotationConfigApplicationContext ?
AnnotationConfigWebApplicationContext。从名字便可以看出,它们是ؓ(f)注解而生Q直接依赖于注解作ؓ(f)容器配置信息?
源的 IoC 容器初始化类。由?AnnotationConfigWebApplicationContext ?
AnnotationConfigApplicationContext ?web 版本Q其用法与后者相比几乎没有什么差别,因此本文以
AnnotationConfigApplicationContext Zq行讲解?/p>
AnnotationConfigApplicationContext 搭配?@Configuration ?@Bean
注解Q自此,XML 配置方式不再?Spring IoC
容器的唯一配置方式。两者在一定范围内存在着竞争的关p,但是它们在大多数情况下还是相互协作的关系Q两者的l合使得 Spring IoC
容器的配|更单,更强大?/p>
之前Q我们将配置信息集中写在 XML 中,如今使用注解Q配|信息的载体?XML 文g转移C Java
cM。我们通常用于存N|信息的cȝcd?“Config” l尾Q比?
AppDaoConfig.java、AppServiceConfig.java {等。我们需要在用于指定配置信息的类上加?
@Configuration 注解Q以明确指出该类?Bean 配置的信息源。ƈ?Spring Ҏ(gu)?Configuration
的类有如下要求:(x)
•配置cM能是 final 的;
•配置cM能是本地化的Q亦即不能将配置cd义在其他cȝҎ(gu)内部Q?br />
•配置cdL一个无参构造函数?br />
AnnotationConfigApplicationContext
配|类中标注了 @Bean 的方法的q回D别ؓ(f) Spring BeanQƈ注册到容器中Q受 IoC 容器理。@Bean 的作用等价于
XML 配置中的 <bean/> 标签。示例如下:(x)
@Configuration
public class BookStoreDaoConfig{
@Bean
public UserDao userDao(){ return new UserDaoImpl();}
@Bean
public BookDao bookDao(){return new BookDaoImpl();}
}
Spring 在解析到以上文gӞ识别出标注 @Bean 的所有方法,执行之,q将Ҏ(gu)的返回?( q里?UserDaoImpl ?
BookDaoImpl 对象 ) 注册?IoC 容器中。默认情况下QBean 的名字即为方法名。因此,与以上配|等L(fng) XML 配置如下Q?/p>
<bean id=”userDao” class=”bookstore.dao.UserDaoImpl”/>
<bean id=”bookDao” class=”bookstore.dao.BookDaoImpl”/>
@Bean h以下四个属性:(x)
•name -- 指定一个或者多?Bean 的名字。这{h(hun)?XML 配置?<bean> ?name 属性?br />
•initMethod -- 容器在初始化?Bean 之后Q会(x)调用该属性指定的Ҏ(gu)。这{h(hun)?XML 配置?<bean> ?init-method 属性?br />
•destroyMethod -- 该属性与 initMethod 功能怼Q在容器销?Bean 之前Q会(x)调用该属性指定的Ҏ(gu)。这{h(hun)?XML 配置?<bean> ?destroy-method 属性?br />
•autowire
-- 指定 Bean 属性的自动装配{略Q取值是 Autowire
cd的三个静态属性。Autowire.BY_NAMEQAutowire.BY_TYPEQAutowire.NO。与 XML 配置中的
autowire 属性的取值相比,q里了 constructorQ这是因?constructor 在这里已l没有意义了?br />
@Bean 没有直接提供指定作用域的属性,可以通过 @Scope 来实现该功能Q关?@Scope 的用法已在上文列举?/p>
下面讲解Z注解的容器初始化。AnnotationConfigApplicationContext 提供了三个构造函数用于初始化容器?/p>
•AnnotationConfigApplicationContext()Q该构造函数初始化一个空容器Q容器不包含M Bean 信息Q需要在E后通过调用?register() Ҏ(gu)注册配置c,q调?refresh() Ҏ(gu)h容器?br />
•AnnotationConfigApplicationContext(Class<?>... annotatedClasses)Q这是最常用的构造函敎ͼ通过涉?qing)到的配|类传递给该构造函敎ͼ以实现将相应配置cM?Bean 自动注册到容器中?br />
•AnnotationConfigApplicationContext(String...
basePackages)Q该构造函C(x)自动扫描以给定的包及(qing)其子包下的所有类Qƈ自动识别所有的 Spring
BeanQ将其注册到容器中。它不但识别标注 @Configuration 的配|类q正解析,而且同样能识别?
@Repository、@Service、@Controller、@Component 标注的类?br />
除了使用上面W三U类型的构造函数让容器
自动扫描 Bean 的配|信息以外,AnnotationConfigApplicationContext q提供了 scan()
Ҏ(gu)Q其功能与上面也cMQ该Ҏ(gu)主要用在容器初始化之后动态增?Bean 臛_器中。调用了该方法以后,通常需要立x动调?refresh()
h容器Q以让变更立即生效?/p>
需要注意的是,AnnotationConfigApplicationContext 在解析配|类Ӟ?x)将配置c自w注册ؓ(f)一?
BeanQ因?@Configuration 注解本n定义时被 @Component 标注了。因此可以说Q一?@Configuration
同时也是一?@Component。大多数情况下,开发者用不到?BeanQƈ且在理想情况下,?Bean
应该是对开发者透明的。@Configuration 的定义如下所C:(x)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
String value() default "";
}
在一般的目中,Zl构清晰Q通常?x)根据Y件的模块或者结构定义多?XML 配置文gQ然后再定义一个入口的配置文gQ该文g使用
<import/> 其他的配置文gl织h。最后只需该文g传给 ClassPathXmlApplicationContext
的构造函数即可。针对基于注解的配置QSpring 也提供了cM的功能,只需定义一个入口配|类Qƈ在该cM使用 @Import
注解引入其他的配|类卛_Q最后只需要将该入口类传递给 AnnotationConfigApplicationContext。具体示例如下:(x)
@Configuration
@Import({BookStoreServiceConfig.class,BookStoreDaoConfig.class})
public class BookStoreConfig{ … }
--------------------------------------------------------------------------------
回页?/p>
混合使用 XML 与注解进?Bean 的配|?/p>
设计 @Configuration ?@Bean 的初Pq不是ؓ(f)了完全取?XMLQ而是Z?XML 之外多一U可行的选择。由?
Spring 自发布以来,Spring 开发小l便不断?XML 配置Q?XML 配置方式已经非常成熟Q加?Spring 2.0
以后出现了一pd命名I间的支持,使得 XML 配置方式成ؓ(f)了用简单、功能强大的 Bean 定义方式。而且QXML
配置的一些高U功能目前还没有相关注解能够直接支持。因此,在目前的多数目中,要么使用Ua(b)?XML 配置方式q行 Bean
的配|,要么使用以注解ؓ(f)主,XML 的配|方式进?Bean 的配|?/p>
之所以会(x)出现两者共存的情况Q主要归lؓ(f)三个原因Q其一Q目前绝大多数采?Spring q行开发的目Q几乎都是基?XML
配置方式的,Spring 在引入注解的同时Q必M证注解能够与 XML 和谐共存Q这是前提;其二Q由于注解引入较晚,因此功能也没有发展多q的
XML 强大Q因此,对于复杂的配|,注解q很隄当一面,在一D|间内仍然需?XML 的配合才能解决问题。除此之外,Spring ?Bean
的配|方式与 Spring 核心模块之间是解耦的Q因此,改变配置方式?Spring 的框架自w是透明的。Spring 可以通过使用 Bean
后处理器 (BeanPostProcessor) 非常方便的增加对于注解的支持。这在技术实C非常Ҏ(gu)的事情?/p>
要用合配|方式,首先需要判断以哪一U配|方式ؓ(f)丅R对q个问题的不同回{将?x)直接?jing)响到实现的方式。然而大可不必ؓ(f)此伤脑筋Q因Z论是?
XML ZQ还是以注解ZQ配|方式都是简单而且Ҏ(gu)理解的。这里不存在错误的决定,因ؓ(f)仅仅是表现方式不一栗我们首先假设以 XML
配置Z的情c(din)?/p>
对于已经存在的大型项目,可能初期是以 XML q行 Bean 配置的,后箋逐渐加入了注解的支持Q这时我们只需?XML 配置文g中将?
@Configuration 标注的类定义为普通的 <bean>Q同时注册处理注解的 Bean 后处理器卛_。示例如下:(x)
// 假设存在如下?@Configuration c:(x)
package bookstore.config;
import bookstore.dao.*;
@Configuration
public class MyConfig{
@Bean
public UserDao userDao(){
return new UserDaoImpl();
}
}
此时Q只需?XML 中作如下声明卛_Q?br />
<beans … >
……
<context:annotation-config />
<bean class=”demo.config.MyConfig”/>
</beans>
׃启用了针Ҏ(gu)解的 Bean 后处理器Q因此在 ApplicationContext 解析?MyConfig cLQ会(x)发现该类标注?
@Configuration 注解Q随后便?x)处理该cM标注 @Bean 的方法,这些方法的q回值注册ؓ(f)容器ȝ Bean?/p>
对于以上的方式,如果存在多个标注?@Configuration 的类Q则需要在 XML 文g中逐一列出。另一U方式是使用前面提到的自动扫描功能,配置如下Q?/p>
<context:component-scan base-package=”bookstore.config” />
如此QSpring 扫描所?demo.config 包及(qing)其子包中的类Q识别所有标C
@Component、@Controller、@Service、@Repository 注解的类Q由?@Configuration
注解本n也用 @Component 标注了,Spring 能够识别出 @Configuration 标注cdƈ正确解析之?/p>
对于以注解ؓ(f)中心的配|方式,只需使用 @ImportResource 注解引入存在?XML 卛_Q如下所C:(x)
@Configuration
@ImportResource(“classpath:/bookstore/config/spring-beans.xml”)
public class MyConfig{
……
}
// 容器的初始化q程和纯_的以配|ؓ(f)中心的方式一_(d)(x)
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(MyConfig.class);
……
]]>3Qaop实现,2.0中pointcut的定?/title> http://m.tkk7.com/ashutc/archive/2010/11/02/336777.html西瓜 西瓜 Tue, 02 Nov 2010 03:50:00 GMT http://m.tkk7.com/ashutc/archive/2010/11/02/336777.html http://m.tkk7.com/ashutc/comments/336777.html http://m.tkk7.com/ashutc/archive/2010/11/02/336777.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/336777.html http://m.tkk7.com/ashutc/services/trackbacks/336777.html 在Spring 2 .0中,Pointcut的定义包括两个部分:(x)Pointcut表示?expression)和Pointcut{(signature)。让我们先看看execution表示式的格式Q?br />
java 代码
1 . execution(modifier - pattern ?
2 . ret - type - pattern
3 . declaring - type - pattern ?
4 . name - pattern(param - pattern)
5 . throws - pattern ? )
括号中各个pattern分别表示修饰W匹配(modifier - pattern ? Q、返回值匹配(ret - type - patternQ、类路径匚wQdeclaring - type - pattern ? Q、方法名匚wQname - patternQ、参数匹配((param - pattern)Q、异常类型匹配( throws - pattern ? Q,其中后面跟着“ ? ”的是可选项?br />
在各个pattern中可以?#8220; * ”来表C匹配所有。在(param - pattern)中,可以指定具体的参数类型,多个参数间用“,”隔开Q各个也可以?#8220; * ”来表C匹配Q意类型的参数Q如(String)表示匚w一个String参数的方法;( * ,String)表示匚w有两个参数的Ҏ(gu)Q第一个参数可以是LcdQ而第二个参数是StringcdQ可以用(..)表示零个或多个Q意参数?br />
现在来看看几个例子:(x)
1 Qexecution( * * (..))
表示匚w所有方?br />
2 Qexecution( public * com. savage.service.UserService. * (..))
表示匚wcom.savage.server.UserService中所有的公有Ҏ(gu)
3 Qexecution( * com.savage.server.. * . * (..))
表示匚wcom.savage.server包及(qing)其子包下的所有方?br />
除了execution表示式外Q还有within?/span>this 、target、args{Pointcut表示式。一个Pointcut定义由Pointcut表示式和Pointcut{l成Q例如:(x)
java 代码
1 . // Pointcut表示?/span>
2 . @Pointcut( " execution(* com.savage.aop.MessageSender.*(..)) " )
3 . // Point{
4 . private void log(){}
然后要用所定义的PointcutӞ可以指定Pointcut{Q如
java 代码
1 . @Before( " og() " )
上面的定义等同与Q?br />
java 代码
1 . @Before( " execution(* com.savage.aop.MessageSender.*(..)) " )
Pointcut定义Ӟq可以?/span>&& ?/span>|| ?/span>! q算Q如Q?br />
java 代码
1 . @Pointcut( " execution(* com.savage.aop.MessageSender.*(..)) " )
2 . private void logSender(){}
3 .
4 . @Pointcut( " execution(* com.savage.aop.MessageReceiver.*(..)) " )
5 . private void logReceiver(){}
6 .
7 . @Pointcut( " logSender() || logReceiver() " )
8 . private void logMessage(){}
q个例子中,logMessage()匹配Q何MessageSender和MessageReceiver中的MҎ(gu)?br />
q可以将一些公用的Pointcut攑ֈ一个类中,以供整个应用E序使用Q如Q?br />
java 代码
1 . package com.savage.aop;
2 .
3 . import org.aspectj.lang.annotation. * ;
4 .
5 . public class Pointcuts {
6 . @Pointcut( " execution(* *Message(..)) " )
7 . public void logMessage(){}
8 .
9 . @Pointcut( " execution(* *Attachment(..)) " )
10 . public void logAttachment(){}
11 .
12 . @Pointcut( " execution(* *Service.*(..)) " )
13 . public void auth(){}
14 . }
在用这些PointcutӞ指定完整的类名加上Pointcut{可以了Q如Q?br />
java 代码
1 . package com.savage.aop;
2 .
3 . import org.aspectj.lang.JoinPoint;
4 . import org.aspectj.lang.annotation. * ;
5 .
6 . @Aspect
7 . public class LogBeforeAdvice {
8 . @Before( " com.sagage.aop.Pointcuts.logMessage() " )
9 . public void before(JoinPoint joinPoint) {
10 . System.out.println( " Logging before " + joinPoint.getSignature().getName());
11 . }
12 . }
当基于XML Sechma实现AdviceӞ如果Pointcut需要被重用Q可以?/span>< aop:pointcut ></ aop:pointcut > 来声明PointcutQ然后在需要用这个Pointcut的地方,用pointcut - ref引用p了,如:(x)
xml 代码
1 . < aop:config >
2 . < aop:pointcut id = " log "
3 . expression = " execution(* com.savage.simplespring.bean.MessageSender.*(..)) " />
4 . < aop:aspect id = " logging " ref = " logBeforeAdvice " >
5 . < aop:before pointcut - ref = " log " method = " before " />
6 . < aop:after - returning pointcut - ref = " log " method = " afterReturning " />
7 . </ aop:aspect >
8 . </ aop:config >
]]> 2:aop实现-spring2.0中的aop实现 http://m.tkk7.com/ashutc/archive/2010/11/02/336776.html西瓜 西瓜 Tue, 02 Nov 2010 03:49:00 GMT http://m.tkk7.com/ashutc/archive/2010/11/02/336776.html http://m.tkk7.com/ashutc/comments/336776.html http://m.tkk7.com/ashutc/archive/2010/11/02/336776.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/336776.html http://m.tkk7.com/ashutc/services/trackbacks/336776.html 在Spring 2.0中,除了传统的通过实现AOP AIP的方式来实现Advice之外Q还提供了两U更加简便的方式来实现AdviceQ?Q基于XML Schema... 阅读全文 ]]> 1:aop实现-advice http://m.tkk7.com/ashutc/archive/2010/11/02/336775.html西瓜 西瓜 Tue, 02 Nov 2010 03:47:00 GMT http://m.tkk7.com/ashutc/archive/2010/11/02/336775.html http://m.tkk7.com/ashutc/comments/336775.html http://m.tkk7.com/ashutc/archive/2010/11/02/336775.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/336775.html http://m.tkk7.com/ashutc/services/trackbacks/336775.html 在Spring1.2或之前的版本中,实现AOP的传l方式就是通过实现Spring的AOP API来定义AdviceQƈ讄代理对象。SpringҎ(gu)Adivce加入C务流E的时机?.. 阅读全文 ]]> spring 3.0 mvc http://m.tkk7.com/ashutc/archive/2010/10/27/336249.html西瓜 西瓜 Wed, 27 Oct 2010 01:43:00 GMT http://m.tkk7.com/ashutc/archive/2010/10/27/336249.html http://m.tkk7.com/ashutc/comments/336249.html http://m.tkk7.com/ashutc/archive/2010/10/27/336249.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/336249.html http://m.tkk7.com/ashutc/services/trackbacks/336249.html
RestController.java
package cn.yu.test;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class RestController {
public RestController() {
}
@RequestMapping(value = " /login/{user} " , method = RequestMethod.GET)
public ModelAndView myMethod(HttpServletRequest request, HttpServletResponse response, @PathVariable( " user " ) String user, ModelMap modelMap) throws Exception {
modelMap.put( " loginUser " , user);
return new ModelAndView( " /hello " , modelMap);
}
@RequestMapping(value = " /welcome " , method = RequestMethod.GET)
public String registjsp() {
return " /welcome " ;
}
@RequestMapping(value = " /welcomehtml " , method = RequestMethod.GET)
public String registPost() {
return " redirect:/jsp/welcomehtml.html " ;
}
}
spring-servlet.xml
< beans xmlns = " http://www.springframework.org/schema/beans " xmlns:xsi = " http://www.w3.org/2001/XMLSchema-instance " xmlns:p = " http://www.springframework.org/schema/p " xmlns:context = " http://www.springframework.org/schema/context " xsi:schemaLocation = " http://www.springframework.org/schema/beans
http: // www.springframework.org/schema/beans/spring-beans-3.0.xsd
http: // www.springframework.org/schema/context
http: // www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 自动扫描beanQ把作了注解的类转换为bean -->
< context:component - scan base - package = " cn.yu.test " />
<!-- 启动Spring MVC的注解功能,完成h和注解POJO的映?nbsp; -->
< bean class = " org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter " />
<!-- Ҏ(gu)型视囑U的解析Q在h时模型视囑U添加前后缀 -->
< bean class = " org.springframework.web.servlet.view.InternalResourceViewResolver " p:prefix = " /jsp " p:suffix = " .jsp " />
< bean id = " multipartResolver " class = " org.springframework.web.multipart.commons.CommonsMultipartResolver " p:defaultEncoding = " utf-8 " />
</ beans >
web.xml
<? xml version = " 1.0 " encoding = " UTF-8 " ?>
< web - app version = " 2.5 " xmlns = " http://java.sun.com/xml/ns/javaee " xmlns:xsi = " http://www.w3.org/2001/XMLSchema-instance " xsi:schemaLocation = " http://java.sun.com/xml/ns/javaee
http: // java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
< servlet - mapping >
< servlet - name > default </ servlet - name >
< url - pattern >* .js </ url - pattern >
</ servlet - mapping >
< servlet - mapping >
< servlet - name > default </ servlet - name >
< url - pattern >* .css </ url - pattern >
</ servlet - mapping >
< servlet - mapping >
< servlet - name > default </ servlet - name >
< url - pattern >* .gif </ url - pattern >
</ servlet - mapping >
< servlet - mapping >
< servlet - name > default </ servlet - name >
< url - pattern >* .jpg </ url - pattern >
</ servlet - mapping >
< servlet - mapping >
< servlet - name > default </ servlet - name >
< url - pattern >* .html </ url - pattern >
</ servlet - mapping >
< servlet >
< servlet - name > spring </ servlet - name >
< servlet - class > org.springframework.web.servlet.DispatcherServlet </ servlet - class >
< load - on - startup > 1 </ load - on - startup >
</ servlet >
< servlet - mapping >
< servlet - name > spring </ servlet - name >
< url - pattern >/</ url - pattern >
<!-- url配置?/span>/ Q不带文件后~Q会(x)造成其它静态文?jsQcss{?不能讉K。如配ؓ(f) * . do Q则不媄(jing)响静态文件的
讉K -->
</ servlet - mapping >
</ web - app >
jsp文g?个网c(din)hello.jsp,welcome.jsp,welcomehtml.html
]]> no matching editors or conversion strategyQ配|事物时出现的错误) http://m.tkk7.com/ashutc/archive/2010/09/27/333020.html西瓜 西瓜 Mon, 27 Sep 2010 01:35:00 GMT http://m.tkk7.com/ashutc/archive/2010/09/27/333020.html http://m.tkk7.com/ashutc/comments/333020.html http://m.tkk7.com/ashutc/archive/2010/09/27/333020.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/333020.html http://m.tkk7.com/ashutc/services/trackbacks/333020.html
Caused by: java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy5 implementing java.lang.Runnable,org.springframework.aop.SpringProxy,org.springframework.aop.framework.Advised] to required type [java.util.TimerTask] for property ' timerTask ' : no matching editors or conversion strategy found
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java: 231 )
at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java: 138 )
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java: 386 )
42 more
< tx:annotation - driven transaction - manager = " txManager " />
更改?br />
< tx:annotation - driven transaction - manager = " txManager " proxy - target - class = " true " />
表示proxy代理的是c而不是接口?br />
<!-- Tranceaction -->
< bean id = " txManager "
class = " org.springframework.jdbc.datasource.DataSourceTransactionManager " >
< property name = " dataSource " >
< ref local = " dataSource " />
</ property >
</ bean >
错误?
Caused by: org.springframework.aop.framework.AopConfigException: Cannot proxy target class because CGLIB2 is not available. Add CGLIB to the class path or specify proxy interfaces.
原因?
~少包:(x)cglib-2.1.3.jar
]]> 用Spring提供的JUnit框架扩展对DAO或Service层进行单元测?/title> http://m.tkk7.com/ashutc/archive/2010/09/06/331175.html西瓜 西瓜 Mon, 06 Sep 2010 03:02:00 GMT http://m.tkk7.com/ashutc/archive/2010/09/06/331175.html http://m.tkk7.com/ashutc/comments/331175.html http://m.tkk7.com/ashutc/archive/2010/09/06/331175.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/331175.html http://m.tkk7.com/ashutc/services/trackbacks/331175.html 一、Spring提供的JUnit框架扩展Q?br />
1 . AbstractSpringContextTestsQspring中用spring上下文测试的Junit扩展c,我们一般不?x)用这个类来进行单元测试,它是spring内部设计使用到的c?br />
2 . AbstractDependencyInjectionSpringContextTestsQ这是AbstractSpringContextTests的直接子c,支持依赖spring上下文的试c,q个cM支持事务?br />
3 . AbstractTransactionalSpringContextTestsQ这?nbsp;AbstractDependencyInjectionSpringContextTests的直接子c,q个cM般应用在事务相关的测试中Q一旦完成每个测试它?yu)׃?x)正常地回滚事务,不会(x)真正更新数据库,若要手动讄事务相关操作Q你可以重蝲onSetUpInTransaction?nbsp;onTearDownInTransactionҎ(gu)Q以便手工开始ƈ提交事务Q或者调用setComplete()Ҏ(gu)。这个类也可以在没有事务的情况下Q用这个类?br />
4 . AbstractTransactionalDataSourceSpringContextTestsQ这?nbsp;AbstractTransactionalSpringContextTests的直接子c,它用了Spring的基于JDBC?nbsp;jdbcTemplate工具c,支持数据库别的事务?br />
二、如何在你的TestCase Class里取得spring context
你的TestCase Class必须l承的是上述四个AbstractXXXSpringContextTests中的其中一个,那么必dC面这个方法来取得spring contextQ?br />
protected abstract String[] getConfigLocations();
例如Q?br />
public String[] getConfigLocations() {
String[] configLocations = { " applicationContext.xml " , " hibernate-context.xml " };
return configLocations;
}
?nbsp;注意要加载的context xml file的\径问题:(x)上述的代码是ZclasspathQ因此applicationContext.xml和hibernate - context.xml必须攑֜classpath里(Ҏ(gu)一是把xml files攑ֈWEB - INF / classes目录下,另一U方法就是在project properties里把xml files的\径加到classpath里)
那么如果你一定要把context xml files攑ֈWEB - INF目录下,也是可以的,那么应该Zfile(Zfile的相对\径是相对于project root folder)Q代码如下:(x)
public String[] getConfigLocations() {
String[] configLocations = { " file:WebContent/WEB-INF/applicationContext.xml " };
return configLocations;
}
AbstractXXXSpringContextTests׃(x)Ҏ(gu)Ҏ(gu)getConfigLocationsҎ(gu)q回的context xml位置的数l来加蝲q且对加载的Context提供~存。这是非帔R要的Q因为如果你在从事一个大目Ӟ启动旉可能成ؓ(f)一个问题-Q这不是 Spring自n的开销Q而是被Spring容器实例化的对象在实?nbsp;化自w时所需要的旉。例如,一个包?0 - 100个Hibernate映射文g的项目可能需?0 - 20U的旉来加载上q的映射文gQ如果在q行每个试fixture里的每个试案例前都有这L(fng)开销Q将D整个试工作的gӞ最l有可能Q实际上很可能)降低效率?br />
在某U极偶然的情况下Q某个测试可?#8220;弄脏”了配|场所Qƈ要求重新加蝲Q-例如改变一个bean的定义或者一个应用对象的状态-Q你可以调用 AbstractDependencyInjectionSpringContextTests 上的 setDirty() Ҏ(gu)来重新加载配|ƈ在执行下一个测试案例前重徏application context
当类 AbstractDependencyInjectionSpringContextTestsQ及(qing)其子c)装蝲你的Application ContextӞ你可以通过SetterҎ(gu)来注入你惌的来自context的bean,而不需要显式的调用 applicationContext.getBean(XXX)。因?nbsp;AbstractDependencyInjectionSpringContextTests?x)从getConfigLocations()Ҏ(gu)指定的配|文件中帮你自动注入
下面的例子就是通过setterҎ(gu)来获得context里的ProductManager beanQ?br />
public class MyTest extends AbstractDependencyInjectionSpringContextTests {
ProductManager productManager;
public String[] getConfigLocations() {
String[] configLocations = { " file:WebContent/WEB-INF/applicationContext.xml " };
return configLocations;
}
public void testGetProduct() {
assertEquals( " tomson " ,productManager.getProductByName( " tomson " ).getName());
}
// 通过setterҎ(gu)自动从context里注入productManager beanQ而不用显C用applicationContext.getBean(XXX)
public void setProductManager(ProductManager productManager) {
this .productManager = productManager;
}
}
但是?nbsp;果context里有多个bean都定义ؓ(f)一个类型(例如有多个bean都是ProductManager classcd的)Q那么对q些bean无法通过setterҎ(gu)来自动依赖注入(因ؓ(f)有多个bean同一个类型,不知要自动注入哪个)。在q种情况?nbsp;你需要显C的调用applicationContext.getBean(XXX)来注入。如Q?br />
public class MyTest extends AbstractDependencyInjectionSpringContextTests {
ProductManager productManager;
public String[] getConfigLocations() {
String[] configLocations = { " file:WebContent/WEB-INF/applicationContext.xml " };
return configLocations;
}
public void onSetUp() {
productManager = (ProductManager) applicationContext.getBean( " productManager " );
}
public void testGetProduct() {
assertEquals( " tomson " ,productManager.getProductByName( " tomson " ).getName());
}
}
如果你的TestCase不用依赖注入,只要不定义Q何settersҎ(gu)卛_。或者你可以l承 AbstractSpringContextTests Q-q个 org.springframework.test 包中的根c,而不是承AbstractDependencyInjectionSpringContextTestsQ及(qing)其子c)。这是因?nbsp;AbstractSpringContextTests 只包括用来加载Spring Context的便利方法但没有自动依赖注入的功能?br />
]]> Unable to load configuration. - bean - jar:file:/D:/Tomcat-6.0.18/webapps/teabank/WEB-INF/lib/struts2-core-2.1.6.jar!/struts-default.xml http://m.tkk7.com/ashutc/archive/2010/07/09/325671.html西瓜 西瓜 Fri, 09 Jul 2010 08:45:00 GMT http://m.tkk7.com/ashutc/archive/2010/07/09/325671.html http://m.tkk7.com/ashutc/comments/325671.html http://m.tkk7.com/ashutc/archive/2010/07/09/325671.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/325671.html http://m.tkk7.com/ashutc/services/trackbacks/325671.html Struts2所需的jar包导入不全,D该错误?/span>
主要需要以下几个jar包:(x)
struts2-core-2.1.6.jar
xwork-2.1.2.jar
ognl-2.6.11.jar
freemarker-2.3.13.jar
commons-logging.jar
commons-fileupload.jar
commons-io.jar
]]> struts2 文g上传?qing)羃?/title> http://m.tkk7.com/ashutc/archive/2010/06/03/322682.html西瓜 西瓜 Thu, 03 Jun 2010 14:54:00 GMT http://m.tkk7.com/ashutc/archive/2010/06/03/322682.html http://m.tkk7.com/ashutc/comments/322682.html http://m.tkk7.com/ashutc/archive/2010/06/03/322682.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/322682.html http://m.tkk7.com/ashutc/services/trackbacks/322682.html package upload;
import java.io.*;
import java.util.*;
import com.sun.im... 阅读全文 ]]> userlogin http://m.tkk7.com/ashutc/archive/2010/04/06/317590.html西瓜 西瓜 Tue, 06 Apr 2010 13:42:00 GMT http://m.tkk7.com/ashutc/archive/2010/04/06/317590.html http://m.tkk7.com/ashutc/comments/317590.html http://m.tkk7.com/ashutc/archive/2010/04/06/317590.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/317590.html http://m.tkk7.com/ashutc/services/trackbacks/317590.html 阅读全文 ]]> Hibernateq发控制乐观锁实现——Version http://m.tkk7.com/ashutc/archive/2010/01/22/310557.html西瓜 西瓜 Fri, 22 Jan 2010 12:09:00 GMT http://m.tkk7.com/ashutc/archive/2010/01/22/310557.html http://m.tkk7.com/ashutc/comments/310557.html http://m.tkk7.com/ashutc/archive/2010/01/22/310557.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/310557.html http://m.tkk7.com/ashutc/services/trackbacks/310557.html 乐观q发控制Q可以有三种方式?/p>
1QVersion版本?/p>
2Q时间戳
3Q自动版本控制?/p>
q里不徏议在新的应用E序中定义没有版本或者时间戳列的版本控制Q它更慢Q更复杂Q如果你正在使用q对象Q它则不?x)生效?/p>
以下信息来自 : http://esffor.javaeye.com/blog/168243
通过在表中及(qing)POJO中增加一个version字段来表C录的版本Q来辑ֈ多用户同时更改一条数据的冲突
数据库脚本:(x)
create table studentVersion (id varchar ( 32 ),name varchar ( 32 ),ver int );
POJO
package Version;
public class Student {
private String id;
private String name;
private int version;
public String getId() {
return id;
}
public void setId(String id) {
this .id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this .name = name;
}
public int getVersion() {
return version;
}
public void setVersion( int version) {
this .version = version;
}
}
Student.hbm.xml
<? xml version="1.0" encoding="utf-8" ?>
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<!--
Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
< hibernate-mapping >
< class name ="Version.Student" table ="studentVersion" >
< id name ="id" unsaved-value ="null" >
< generator class ="uuid.hex" ></ generator >
</ id >
<!-- version标签必须跟在id标签后面 -->
< version name ="version" column ="ver" type ="int" ></ version >
< property name ="name" type ="string" column ="name" ></ property >
</ class >
</ hibernate-mapping >
Hibernate.cfg.xml
<? xml version='1.0' encoding='UTF-8' ?>
<! DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd" >
<!-- Generated by MyEclipse Hibernate Tools. -->
< hibernate-configuration >
< session-factory >
< property name ="connection.username" > root </ property >
< property name ="connection.url" >
jdbc:mysql://localhost:3306/schoolproject?characterEncoding=gb2312& useUnicode=true
</ property >
< property name ="dialect" >
org.hibernate.dialect.MySQLDialect
</ property >
< property name ="myeclipse.connection.profile" > mysql </ property >
< property name ="connection.password" > 1234 </ property >
< property name ="connection.driver_class" >
com.mysql.jdbc.Driver
</ property >
< property name ="hibernate.dialect" >
org.hibernate.dialect.MySQLDialect
</ property >
< property name ="hibernate.show_sql" > true </ property >
< property name ="current_session_context_class" > thread </ property >
< property name ="jdbc.batch_size" > 15 </ property >
< mapping resource ="Version/Student.hbm.xml" />
</ session-factory >
</ hibernate-configuration >
试代码Q?/p>
package Version;
import java.io.File;
import java.util.Iterator;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class Test {
public static void main(String[] args) {
String filePath = System.getProperty( " user.dir " ) + File.separator + " src/Version " + File.separator + " hibernate.cfg.xml " ;
File file = new File(filePath);
System.out.println(filePath);
SessionFactory sessionFactory = new Configuration().configure(file).buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction t = session.beginTransaction();
Student stu = new Student();
stu.setName( " tom11 " );
session.save(stu);
t.commit();
/*
* 模拟多个session操作student数据?br />
*/
Session session1= sessionFactory.openSession();
Session session2 = sessionFactory.openSession();
Student stu1 = (Student)session1.createQuery( " from Student s where s.name='tom11' " ).uniqueResult();
Student stu2 = (Student)session2.createQuery( " from Student s where s.name='tom11' " ).uniqueResult();
// q时候,两个版本h相同?/span>
System.out.println( " v1= " + stu1.getVersion() + " --v2= " + stu2.getVersion());
Transaction tx1 = session1.beginTransaction();
stu1.setName( " session1 " );
tx1.commit();
// q时候,两个版本h不同的,其中一个的版本号递增?/span>
System.out.println( " v1= " + stu1.getVersion() + " --v2= " + stu2.getVersion());
Transaction tx2 = session2.beginTransaction();
stu2.setName( " session2 " );
tx2.commit();
}
}
q行l果Q?/p>
Hibernate: insert into studentVersion (ver, name, id) values (?, ?, ?)
Hibernate:
select student0_.id as id0_, student0_.ver as ver0_, student0_.name as
name0_ from studentVersion student0_ where student0_.name='tom11'
Hibernate:
select student0_.id as id0_, student0_.ver as ver0_, student0_.name as
name0_ from studentVersion student0_ where student0_.name='tom11'
v1=0--v2=0
Hibernate: update studentVersion set ver=?, name=? where id=? and ver=?
v1=1--v2=0
Hibernate: update studentVersion set ver=?, name=? where id=? and ver=?
Exception in thread "main" org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [Version.Student#4028818316cd6b460116cd6b50830001]
可以看到Q第二个“用户”session2修改数据时候,记录的版本号已经被session1更新q了Q所以抛ZU色的异常,我们可以在实际应?
中处理这个异常,例如在处理中重新d数据库中的数据,同时目前的数据与数据库中的数据展示出来Q让使用者有Z(x)比较一下,或者设计程序自动读取新的数
?/p>
注意Q?/strong>
要注意的是,׃乐观锁定是用系l中的程式来控制Q而不是用资料库中的锁定机制Q因而如果有人特意自行更新版本讯息来过(g)查,则锁定机制就?x)无效,例如在上例中自行更?span style="color: #ff0000;">stu 的version属性,使之与资料库中的版本L(fng)同的话就不会(x)有错误,像这L(fng)本号被更改,或是׃资料是由外部pȝ而来Q因而版本资讯不受控制时Q锁定机制将?x)有问题Q设计时必须注意?/span>
如果手工讄stu.setVersion()自行更新版本以蟩q检?则这U乐观锁׃(x)失效Q应Ҏ(gu)法可以将Student.java的setVersion讄成private
]]> struts2验证框架 http://m.tkk7.com/ashutc/archive/2009/11/11/302023.html西瓜 西瓜 Wed, 11 Nov 2009 14:35:00 GMT http://m.tkk7.com/ashutc/archive/2009/11/11/302023.html http://m.tkk7.com/ashutc/comments/302023.html http://m.tkk7.com/ashutc/archive/2009/11/11/302023.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/302023.html http://m.tkk7.com/ashutc/services/trackbacks/302023.html
<action name="saveUser" class="saveUserAction" method="save">
<result name="success" type="redirect">listUser!list.action</result>
<result name="input">/save.jsp</result>
</action>
saveUserAction 里面有方?br />
public String save() throws Exception {
this.service.saveUser(user);
return SUCCESS;
}
然后我们验证文g配置成UserAction-save-validation.xml。这样struts验证是不?x)成功的?br />
因ؓ(f)验证跟本pmethod指定的方法和action里面的方法名无关Q而是和struts.xml里面的name指定的名字有养I
如果我们的配|文件这样命名:(x)UserAction-aveUser-validation.xml 那么才能验证成功
UserAction-aveUser-validation.xml Q?br />
<validators>
<field name="user.age">
<field-validator type="required">
<message>required age</message>
</field-validator>
<field-validator type="int">
<param name="min">1</param>
<param name="max">150</param>
<message>age should be between ${min} and ${max}</message>
</field-validator>
</field>
</validators>
防止验证出现多行重复性提C?scope定义为prototype使struts2的action不用单例模?br />
<bean id="saveUserAction" class="com.yu.useraction.saveUserAction" scope="prototype">
<property name="service" ref="userService"></property>
</bean>
所有在spring里面的action都需要配|scope="prototype"不能使用默认
如果oracle数据?把age的Longcd都改成IntergercdQuser.java和user.hbm.xmlQ,否者验证时?x)不能通过
]]> Caught exception while loading file struts-default.xml 错误 http://m.tkk7.com/ashutc/archive/2009/11/11/302011.html西瓜 西瓜 Wed, 11 Nov 2009 12:56:00 GMT http://m.tkk7.com/ashutc/archive/2009/11/11/302011.html http://m.tkk7.com/ashutc/comments/302011.html http://m.tkk7.com/ashutc/archive/2009/11/11/302011.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/302011.html http://m.tkk7.com/ashutc/services/trackbacks/302011.html 严重: Exception starting filter struts2
Caught exception while loading file struts-default.xml - [unknown location]
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadConfigurationFiles(XmlConfigurationProvider.java:839)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadDocuments(XmlConfigurationProvider.java:131)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.init(XmlConfigurationProvider.java:100)
……………………………………
现象: W一ơ能q行, reload׃?
试了Struts2自带的blank? 没问?
那基本可断定是其他jar包有冲突, 应该是XML解析包有冲突.
(g)查发布后的WEB-INF/lib有两个XML解析? xml-apis.jar和xerces-2.6.2.jar
q种错误真正原因不是JDK 6和Struts 2冲突, 而是 MyEclipse Hibernate cd中多了两个包: xml-apis.jar和xerces-2.6.2.jar, q两个包的功能和JDK的冲H了. 解决办法: 1. 删除发布后目录的 WEB-INF/lib/ 下的q两个文? 2. 或者用JDK 1.5来启动Tomcat 6.
]]> Hibernate二~存ehcache配置 http://m.tkk7.com/ashutc/archive/2009/10/31/300486.html西瓜 西瓜 Sat, 31 Oct 2009 07:45:00 GMT http://m.tkk7.com/ashutc/archive/2009/10/31/300486.html http://m.tkk7.com/ashutc/comments/300486.html http://m.tkk7.com/ashutc/archive/2009/10/31/300486.html#Feedback 2 http://m.tkk7.com/ashutc/comments/commentRss/300486.html http://m.tkk7.com/ashutc/services/trackbacks/300486.html 需要两个包:
commons-logging-1.0.4.jar
ehcache-1.2.3.jar
在src根目录下新徏 ehcache.xml
<? xml version = " 1.0 " encoding = " UTF-8 " ?>
< ehcache >
< diskStore path = " java.io.tmpdir " />
< defaultCache maxElementsInMemory = " 10000 " eternal = " false "
timeToIdleSeconds= " 120 " timeToLiveSeconds = " 120 " overflowToDisk = " true "
diskExpiryThreadIntervalSeconds= " 120 " memoryStoreEvictionPolicy = " LRU " />
< cache name = " cn.yu.vo.Guestbook " maxElementsInMemory = " 1000 " eternal = " false "
timeToIdleSeconds= " 3000 " timeToLiveSeconds = " 600 " overflowToDisk = " true " />
</ ehcache >
<!--
diskStore:保存在硬盘上的(f)时目?br />
nameQCache的唯一标识
maxElementsInMemoryQ内存中最大缓存对象数?br />
maxElementsOnDiskQ磁盘中最大缓存对象数Q若?表示无穷大?br />
eternalQElement是否怹有效Q一但设|了Qtimeout不起作用?br />
overflowToDiskQ配|此属性,当内存中Element数量辑ֈmaxElementsInMemoryӞEhcache会(x)Element写到盘中?br />
timeToIdleSecondsQ设|Element在失效前的允?dng)R|时间。仅当element不是怹有效时用,可选属性,默认值是0Q?nbsp;
也就是可闲置旉无穷大?br />
timeToLiveSecondsQ设|Element在失效前允许存活旉。最大时间介于创建时间和失效旉之间。仅当element不是怹
有效时用,默认?.Q?nbsp; 也就是element存活旉无穷大?br />
diskPersistentQ是否缓存虚拟机重启期数据。(q个虚拟机是指什么虚拟机一直没看明白是什?有高希望能指?br />
一二)?br />
diskExpiryThreadIntervalSecondsQ磁盘失效线E运行时间间隔,默认?20U?br />
diskSpoolBufferSizeMBQ这个参数设|DiskStoreQ磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一
个缓冲区?br />
memoryStoreEvictionPolicyQ当辑ֈmaxElementsInMemory限制ӞEhcache会(x)Ҏ(gu)指定的策略去清理内存。默认策略是
LRUQ最q最用)。你可以讄为FIFOQ先q先出)或是LFUQ较?yu)用)。这里比?br />
遗憾QEhcacheq没有提供一个用户定制策略的接口Q仅仅支持三U指定策略,感觉做的不够
理想?br />
-->
在hibernate.cfg.xml里面新增属?br />
< property name = " cache.provider_class " >
org.hibernate.cache.EhCacheProvider
</ property >
在guestbook.hbm.xml里面新增属?br />
< class name = " cn.yu.vo.Guestbook " table = " GUESTBOOK " schema = " OLIVER " >
< cache usage="read-write" />
< id name = " id " type = " java.lang.Long " >
< column name = " ID " precision = " 22 " scale = " 0 " />
< generator class = " sequence " >
< param name = " sequence " > gb_seq </ param >
</ generator >
</ id >
]]> Hibernate3.0 HQL条g子语句like 中文q http://m.tkk7.com/ashutc/archive/2009/10/31/300439.html西瓜 西瓜 Fri, 30 Oct 2009 20:09:00 GMT http://m.tkk7.com/ashutc/archive/2009/10/31/300439.html http://m.tkk7.com/ashutc/comments/300439.html http://m.tkk7.com/ashutc/archive/2009/10/31/300439.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/300439.html http://m.tkk7.com/ashutc/services/trackbacks/300439.html
String hql = "FROM Table AS t WHERE t.field like '%" + str + "%'";
Query query = getSession().createQuery(hql);
query.list();
使用q种形式传入参数str, ?x)导致控制台输?
FROM Table AS t WHERE t.field like '% ????%'
之类的ؕ? 从而在数据库找不到匚w记录.
据说q是hibernate3.0 like子句处理中文的一个问? 3.1已得C正?.0版可以通过讄参数解决。改正如下:(x)
String str = "中文字符?;
String hql = "FROM Table AS t WHERE t.field LIKE :param";
Query query = getSession().createQuery(hql);
query.setString("param", "%" + str + "%");
query.list();
]]> getCurrentSession ?openSession() 的区? http://m.tkk7.com/ashutc/archive/2009/09/27/296632.html西瓜 西瓜 Sun, 27 Sep 2009 05:50:00 GMT http://m.tkk7.com/ashutc/archive/2009/09/27/296632.html http://m.tkk7.com/ashutc/comments/296632.html http://m.tkk7.com/ashutc/archive/2009/09/27/296632.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/296632.html http://m.tkk7.com/ashutc/services/trackbacks/296632.html getCurrentSession创徏的session?x)和l定到当前线E?而openSession不会(x)?/font>
getCurrentSession创徏的线E会(x)在事务回滚或事物提交后自动关?而openSession必须手动关闭
q里getCurrentSession本地事务(本地事务:jdbc)?要在配置文g里进行如下设|?/font>
如果使用的是本地事务Qjdbc事务Q?br />
<property name="hibernate.current_session_context_class">thread</property>
如果使用的是全局事务Qjta事务Q?br />
<property name="hibernate.current_session_context_class">jta</property>
getCurrentSession ()使用当前的sessionQopenSession()重新建立一个新的session
在一个应用程序中Q如果DAO 层用Spring 的hibernate 模板Q通过Spring 来控制session 的生命周期,则首选getCurrentSession ()?/font>
使用Hibernate的大多数应用E序需要某UŞ式的“上下文相关的” sessionQ特定的session在整个特定的上下文范围内始终有效。然而,对不同类型的应用E序而言Q要Z么是l成q种“上下?#8221;下一个定义通常 是困隄Q不同的上下文对“当前”q个概念定义了不同的范围。在3.0版本之前Q用Hibernate的程序要么采用自行编写的Z ThreadLocal的上下文sessionQ要么采用HibernateUtilq样的辅助类Q要么采用第三方框架Q比如Spring或Pico)Q?它们提供了基于代?proxy)或者基于拦截器(interception)的上下文相关session?
?.0.1版本开 始,Hibernate增加了SessionFactory.getCurrentSession()Ҏ(gu)。一开始,它假定了采用JTA事务QJTA事务 定义了当前session的范围和上下?scope and context)。Hibernate开发团队坚信,因ؓ(f)有好几个独立的JTA TransactionManager实现E_可用Q不论是否被部vC个J2EE容器中,大多?假若不是所有的Q应用程序都应该采用JTA事务理?Zq一点,采用JTA的上下文相关session可以满你一切需要?
更好的是Q从3.1开 始,SessionFactory.getCurrentSession()的后台实现是可拔插的。因此,我们引入了新的扩展接?(org.hibernate.context.CurrentSessionContext)和新的配|参?(hibernate.current_session_context_class)Q以便对什么是“当前session”的范围和上下?scope and context)的定义进行拔插?
请参?org.hibernate.context.CurrentSessionContext接口的Javadoc,那里有关于它的契U的详细讨论。它定义 了单一的方法,currentSession()Q特定的实现用它来负责跟t当前的上下文session。Hibernate内置了此接口的两U实现?
org.hibernate.context.JTASessionContext - 当前sessionҎ(gu)JTA来跟t和界定。这和以前的仅支持JTA的方法是完全一L(fng)。详情请参阅Javadoc?
org.hibernate.context.ThreadLocalSessionContext - 当前session通过当前执行的线E来跟踪和界定。详情也请参阅Javadoc?
q两U实现都提供?#8220;每数据库事务对应一个session”的编E模型,也称作每ơ请求一个session。Hibernate session的v始和l结由数据库事务的生存来控制。假若你采用自行~写代码来管理事务(比如Q在Ua(b)的J2SE,或?JTA/UserTransaction/BMTQ,你用Hibernate Transaction API来把底层事务实现从你的代码中隐藏掉。如果你在支持CMT的EJB容器中执行,事务边界是声明式定义的,你不需要在代码中进行Q何事务或 session理操作。请参阅W?11 ?事务和ƈ发一节来阅读更多的内容和CZ代码?
hibernate.current_session_context_class 配置参数定义了应该采用哪?nbsp;
org.hibernate.context.CurrentSessionContext实现。注意,Z向下兼容Q如果未 配置此参敎ͼ但是存在
org.hibernate.transaction.TransactionManagerLookup的配 |,Hibernate?x)采?nbsp;
org.hibernate.context.JTASessionContext。一般而言Q此参数的值指明了要用的?现类的全名,但那两个内置的实现可以用简写,?jta"?thread"?/font>
利于ThreadLocal模式理Session
早在Java1.2推出之时QJavaq_中就引入了一个新的支持:(x)java.lang.ThreadLocalQ给我们在编写多U程E序
时提供了一U新的选择。ThreadLocal是什么呢Q其实ThreadLocalq是一个线E的本地实现版本Q它q不是一个ThreadQ?br />
而是thread local variable(U程局部变?。也许把它命名ؓ(f)ThreadLocalVar更加合适。线E局部变?ThreadLocal)
其实的功用非常简单,是为每一个用某变量的线E都提供一个该变量值的副本Q是每一个线E都可以独立地改变自q副本Q?br />
而不?x)和其它U程的副本冲H。从U程的角度看Q就好像每一个线E都完全拥有一个该变量?
ThreadLocal是如何做Cؓ(f)每一个线E维护变量的副本的呢Q其实实现的思\很简单,在ThreadLocalcM有一个MapQ?br />
用于存储每一个线E的变量的副本。比如下面的CZ实现(Z单,没有考虑集合的泛?Q?
public class HibernateUtil {
public static final ThreadLocal session =new ThreadLocal();
public static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new Configuration().configure().buildSessionFactory();
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
public static Session currentSession() throws HibernateException {
Session s = session.get();
if(s == null) {
s = sessionFactory.openSession();
session.set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = session.get();
if(s != null) {
s.close();
}
session.set(null);
}
}
openSession() ?getCurrentSession() 有何不同和关联呢Q?
?SessionFactory 启动的时候, Hibernate ?x)根据配|创建相应的 CurrentSessionContext Q在 getCurrentSession() 被调用的时候,实际被执行的Ҏ(gu)?CurrentSessionContext.currentSession() 。在 currentSession() 执行Ӟ如果当前 Session 为空Q?currentSession ?x)调?SessionFactory ?openSession 。所?getCurrentSession() 对于 Java EE 来说是更好的获取 Session 的方法?/font>
本文来自CSDN博客Q{载请标明出处Qhttp://blog.csdn.net/LoveYouT/archive/2009/05/17/4193894.aspx
]]> Struts1和Struts2的区别和Ҏ(gu) http://m.tkk7.com/ashutc/archive/2009/06/19/283206.html西瓜 西瓜 Fri, 19 Jun 2009 04:32:00 GMT http://m.tkk7.com/ashutc/archive/2009/06/19/283206.html http://m.tkk7.com/ashutc/comments/283206.html http://m.tkk7.com/ashutc/archive/2009/06/19/283206.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/283206.html http://m.tkk7.com/ashutc/services/trackbacks/283206.html
• Struts1要求Actioncȝ承一个抽象基cRStruts1的一个普遍问题是使用抽象cȝE而不是接口?
• Struts 2 Actioncd以实C个Action接口Q也可实现其他接口,使可选和定制的服务成为可能。Struts2提供一个ActionSupport基类?实现 常用的接口。Action接口不是必须的,M有execute标识的POJO对象都可以用作Struts2的Action对象?
U程模式:
• Struts1 Action是单例模式ƈ且必LU程安全的,因ؓ(f)仅有Action的一个实例来处理所有的h。单例策略限制了Struts1 Action能作的事Qƈ且要在开发时特别心。Action资源必须是线E安全的或同步的?
• Struts2 Action对象为每一个请求生一个实例,因此没有U程安全问题。(实际上,servlet容器l每个请求生许多可丢弃的对象,q且不会(x)D性能和垃圑֛攉题)
Servlet 依赖:
• Struts1 Action 依赖于Servlet API ,因ؓ(f)当一个Action被调用时HttpServletRequest ?HttpServletResponse 被传递给executeҎ(gu)?
• Struts 2 Action不依赖于容器Q允许Actionq容器单独被测试。如果需要,Struts2 Action仍然可以讉K初始的request和response。但是,其他的元素减或者消除了直接讉KHttpServetRequest ?HttpServletResponse的必要性?
可测?
• 试Struts1 Action的一个主要问题是executeҎ(gu)暴露了servlet APIQ这使得试要依赖于容器Q。一个第三方扩展Q-Struts TestCaseQ-提供了一套Struts1的模拟对象(来进行测试)?
• Struts 2 Action可以通过初始化、设|属性、调用方法来试Q?#8220;依赖注入”支持也ɋ试更容易?
捕获输入:
• Struts1 使用ActionForm对象捕获输入。所有的ActionForm必须l承一个基cR因为其他JavaBean不能用作ActionFormQ开发者经 常创建多余的cL莯入。动态BeanQDynaBeansQ可以作为创ZlActionForm的选择Q但是,开发者可能是在重新描q?创徏)已经?在的JavaBeanQ仍然会(x)D有冗余的javabeanQ?
• Struts 2直接使用Action属性作入属性,消除了对W二个输入对象的需求。输入属性可能是有自??属性的rich对象cd。Action属性能够通过 web面上的taglibs讉K。Struts2也支持ActionForm模式。rich对象cdQ包括业务对象,能够用作输入/输出对象。这U?ModelDriven Ҏ(gu)简化了taglib对POJO输入对象的引用?
表达式语aQ?
• Struts1 整合了JSTLQ因此用JSTL EL。这UEL有基本对象图遍历Q但是对集合和烦引属性的支持很弱?
• Struts2可以使用JSTLQ但是也支持一个更强大和灵zȝ表达式语aQ-"Object Graph Notation Language" (OGNL).
l定值到面QviewQ?
• Struts 1使用标准JSP机制把对象绑定到面中来讉K?
• Struts 2 使用 "ValueStack"技术,使taglib能够讉KD不需要把你的面QviewQ和对象l定h。ValueStack{略允许通过一pd名称相同但类型不同的属性重用页面(viewQ?
cd转换Q?
• Struts 1 ActionForm 属性通常都是Stringcd。Struts1使用Commons-Beanutilsq行cd转换。每个类一个{换器Q对每一个实例来说是不可配置的?
• Struts2 使用OGNLq行cd转换。提供基本和常用对象的{换器?
校验Q?
• Struts 1支持在ActionForm的validateҎ(gu)中手动校验,或者通过Commons Validator的扩展来校验。同一个类可以有不同的校验内容Q但不能校验子对象?
• Struts2支持通过validateҎ(gu)和XWork校验框架来进行校验。XWork校验框架使用为属性类cd定义的校验和内容校验Q来支持chain校验子属?
Action执行的控Ӟ(x)
• Struts1支持每一个模块有单独的Request ProcessorsQ生命周期)Q但是模块中的所有Action必须׃n相同的生命周期?
• Struts2支持通过拦截器堆栈(Interceptor StacksQؓ(f)每一个Action创徏不同的生命周期。堆栈能够根据需要和不同的Action一起用?
]]> struts 四种验证Ҏ(gu) http://m.tkk7.com/ashutc/archive/2009/06/09/280997.html西瓜 西瓜 Tue, 09 Jun 2009 10:51:00 GMT http://m.tkk7.com/ashutc/archive/2009/06/09/280997.html http://m.tkk7.com/ashutc/comments/280997.html http://m.tkk7.com/ashutc/archive/2009/06/09/280997.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/280997.html http://m.tkk7.com/ashutc/services/trackbacks/280997.html
文gstruts-config.xml :
<action-mappings>
<action attribute="userloginForm" input="/login.jsp"
name="userloginForm" parameter="method" path="/userlogin"
scope="request" validate="true"
type="cn.userlogin.struts.action.UserloginAction" />
</action-mappings>
<message-resources
parameter="cn.userlogin.struts.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>
1Q用Javascript在客L(fng)q行验证
配置Q在需要验证的JSP文g中写?/font>
<html:form action="/XXX" onsubmit="return validateXXXX(this);">
q里的XXX 是与要进行验证的 forward name
validateXXXX (this);里面的XXXX是需要进行验证的ActionForm?/font>
<html:javascript formName="mytestForm"/>
在validation.xml文g中写入验证代码就可以q行基本的验证了。具体请参照http://www.chinajavaworld.net/forum/topic.cgi?forum=48&topic=1413&show=50
q种Ҏ(gu)是在客户端进行验证,客户端可以看到JAVASCRIPT部分的全代码。安全性不?/font>
2Q自己的ActionForml承ValidatorFormc,在里面编写自qҎ(gu)Q?br />
public ActionErrors validate (ActionMapping mapping,HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
。。。。。?br />
if ( mytext.equals("aaa") ) { //my example
errors.add("mytext",new ActionError("mytext.error"));
}
。。。。。?br />
return errors;
}
此时Q如果写了这个方法,׃(x)屏蔽掉在Validation.xml中定义的验证部分Q换句话说就是系l运行时QValidation.xml里对应此ActionForm的定义的错误验证部分不实?br />
如果不写q个Ҏ(gu)的话Q系l运行时?x)进行Validation.xml里对应此ActionForm的定义的错误验证部分的操?/font>
此类Ҏ(gu)是在服务器端q行验证Q验证部分代码客L(fng)不可见?/font>
3Q动态验证DynaValidatorForm的?br />
不需要再写对应的ActionFormQ只需在struts-config.xml里把自己的ActionFormq行配置
<form-bean name="testForm"
type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="mytext" type="java.lang.String"/>
<form-property name="mytextarea" type="java.lang.String"/>
<form-property name="mydatetext" type="java.lang.String"/>
</form-bean>
在form-property里设|相应的目Q比如说mytextQmytextarea什么的Q执行的时候会(x)动态生成ActionForm
再在validation.xml里写入所希望的验证代码,可以了
JSP文g里不需要写入Q何东西,验证也是在服务器端进行,验证部分代码在JSP中不可见
4Q组合验?br />
如果使用动态验证DynaValidatorForm的话Q不许编写自q对应的ActionFormQ相应的Ҏ(gu)验证?x)受到相当程度的限制?/font>
q个时候,需要将Ҏ(gu)验证部分写入对应的ActionQ?/font>
if(mytext.equals("aaa")){ //My Example
ActionErrors errors = new ActionErrors();
errors.add("***",new ActionError("***.error"));
saveErrors(request,errors);return (mapping.findForward("false"));
}
]]> struts2 mvc视图实例分析 http://m.tkk7.com/ashutc/archive/2009/05/29/278955.html西瓜 西瓜 Fri, 29 May 2009 14:41:00 GMT http://m.tkk7.com/ashutc/archive/2009/05/29/278955.html http://m.tkk7.com/ashutc/comments/278955.html http://m.tkk7.com/ashutc/archive/2009/05/29/278955.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/278955.html http://m.tkk7.com/ashutc/services/trackbacks/278955.html 从一个高度层ơ来?Strtsu2属性pull-MVC(或是MVC2)框架;q与传统的MVC框架略有不同,因ؓ(f)action的角色采用模?而不是控制器,虽然q样有一些重?"pull"来自于视图从action拉数?而不是持有一个分开的可用模型对?
我们知道在概忉|面意味着什?但在执行层面意味着什?q个模型-视图-控制器模式在Struts2中被实现成了五个核心部分--actions,拦截?值栈/OGNL,l果cd和结?视图技?
?:The MVC / Struts2 Architecture
?描述了从Struts2高度层面上的l构, 包含了模?视图和控制器.控制器是一个实CStruts2里分zServletqo(h)器以?qing)拦截?模型实现的actions,视图则是q果类型和l果的组?值栈和ONGL提供了一个通用的\U,链接和集成其他组?
我们在这章讨Z些通用的部?会(x)有很多信息涉?qing)到配?配置WEB应用,配置a(chn)ctions,拦截?l果{等.C,q些说明只是Z提供如果完成的背?或许不是最有效的配|应用的方式.在后面的章节我们讨论更加容易和更有效的方式以完成同L(fng)目标,使用U定俗成的配|?注释和零配置插g.
在我们进入详l讲解核心构成之前我们先来讨Z下全局的配|?
Configuration
在配|Struts2之前,你需要先下蝲发行版或是在你的Maven2?pom.xml"文g中配|它的依赖关p?
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.0.6</version>
</dependency>
做完之后,Struts2应用的配|就可以分成三个独立的文?如图2中所C?
Figure 2: Configuration file scope for framework elements
需要在你的"web.xml"文g里ؓ(f)WEB应用的配|FilterDispatcher Servletqo(h)?
1 <filter>
2 <filter-name>action2</filter-name>
3 <filter-class>
4 org.apache.struts2.dispatcher.FilterDispatcher
5 </filter-class>
6 </filter>
7 <filter-mapping>
8 <filter-name>action2</filter-name>
9 <url-pattern>/*</url-pattern>
10 </filter-mapping>
11
它配|了基本的WEB应用.剩下来的事就是?struts.properties"配置文g来自定义WEB应用的执行环?通过"struts.xml"配置文g来配|WEB应用的构?我们现在来看看这两个配置文g的详l描q?
The struts.properties File
q个配置文g提供了一个改变框枉认行为的机制.一般情况下,你是不需要修改这个文件的,一个例外是你想配置一个对于开发者友好的调试环境.所有的包含?struts.properties"配置文g中的配置?都可以?init-param"标签配置?web.xml"文g?同样也可以?constant"标签配置?struts.xml"配置文g?
Properties允许修改如改变Freemarker选项,替换action的映类,军_是否重新加蝲XML配置文g,默认使用的用L(fng)面主题等{?更多的关于properties的最C?h阅位?a target="_blank" rel="external">http://struts.apache.org/2.x/docs/strutsproperties.html的Struts2的Wiki.
一个默认的名ؓ(f)"default.properties"配置文g包含在发行版的Struts2-Core JAR文g?惌修改一个配|项,只需在你目的源文g的类路径的根目录里创Z个名?struts.properties"的文?之后,d你想修改的配|项.新的值将覆盖掉默认?
在开发环境中,q有一些配|项你可能需要更?
struts.i18n.reload = true -- 能够重新加蝲国际化文?
struts.devMode = true -- 能够在开发模式下提供更全面的调试
struts.configuration.xml.reload = true 能够重新加蝲XML配置文g(适用于action),修改之后可以在Servlet容器里重新加载整个WEB应用
struts.url.http.prot = 8080 -- 讄服务q行的端?以便生成正确的URL)
The struts.xml File
"struts.xml"文g包含配置信息,你将修改它用于发布action,我们在本章剩余的部分详l的讲解指定的元?现在,让我们看看不?x)改变的l构.
?
Ҏ(gu)你应用的功能,可能?x)从你的应用中移?struts.xml"文g.配置上我们将在本章讨ZU替换的Ҏ(gu),使用注释,"web.xml"启动参数,和交替的URL映射配置.
唯一的配|仍焉?struts.xml"文g,如全局l果,异常处理,和自定义的拦截器?
q是一个XML文g,所以第一个元素是XML的版本和~码信息.下一个则是XML的文档类型定?DTD).DTD提供了一些文仉的元素的l构,q最l用XML来解析和~辑.
1 <?xml version="1.0" encoding="UTF-8" ?>
2 <!DOCTYPE struts PUBLIC
3 "-//Apache Software Foundation//DTD Struts Configuration
4 2.0//EN"
5 "http://struts.apache.org/dtds/struts-2.0.dtd ">
6 <struts>
7 <package
8 name="struts2"
9 extends="struts-default"
10 namespace="/struts2">
11 …
12 </package>
13 </struts>
我们现在到达?lt;struts>标签.q是Struts2具体配置的最外层标签.所有其他的标签都将被包含在q个当中.
The Include Tag:
<include ... />标签用于Struts2应用模块化时引入其他配置文g时用ƈ且它始终?lt;struts>标签的子标签.它仅仅包含一?file"属?用于提供被引入的文g的名U?那个文g必须?struts.xml"配置文g的结构相?例如,如果你想拆分一个计费应用的配置文g,你可以选择按组缴?理和报表配|到单独的文件中:
1 <struts>
2 <include file="billing-config.xml" />
3 <include file="admin-config.xml" />
4 <include file="reports-config.xml" />
5 …
6 </struts>
引入文g?序是重要的.来自引入文g的信息将在文件中引入标签的位|开始有?因此,使用一个配|在另一个文件中的标{?q个引入的配|必d现在被引用之?
有一些文件你是必L的引入,q有一些文件是自动引入?比如?struts-default"?struts-plugin.xml".两者都包含了默认的l果cd,拦截?拦截器栈,?以及(qing)WEB应用执行环境的配|信?也可以配|在"struts.properties"文g?的配|?区别在于"struts-default.xml"文g提供的是Struts2的核心配|??struts-plugin.xml"提供的是详细插g的配|?每个插gJAR文g中都应包含一?struts-plugin.xml"文g,所有这些都在启动的时候加?
]]> ThreadLocal在spring框架中的作用 http://m.tkk7.com/ashutc/archive/2009/05/29/278954.html西瓜 西瓜 Fri, 29 May 2009 14:36:00 GMT http://m.tkk7.com/ashutc/archive/2009/05/29/278954.html http://m.tkk7.com/ashutc/comments/278954.html http://m.tkk7.com/ashutc/archive/2009/05/29/278954.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/278954.html http://m.tkk7.com/ashutc/services/trackbacks/278954.html
我们知道Spring通过各种DAO模板c降低了研发者用各U数据持久技术的隑ֺ。这些模板类都是U程安全的,也就是说Q多个DAO能够复用同一个模板实例而不?x)发生冲H?
我们使用模板c访问底层数据,Ҏ(gu)持久化技术的不同Q模板类需要绑定数据连接或?x)话的资源。但q些资源本n是非U程安全的,也就是说他们不能在同一时刻被多个线E共享?
虽然模板c通过资源池获取数据连接或?x)话Q但资源池本w解决的是数据连接或?x)话的缓存问题,q数据q接或会(x)话的U程安全问题?
按照传统l验Q假如某个对象是非线E安全的Q在多线E环境下Q对对象的访问必采用synchronizedq行U程同步。但Spring的DAO模板cdƈ未采用线E同步机Ӟ因ؓ(f)U程同步限制了ƈ发访问,?x)带来很大的性能损失?
此外Q通过代码同步解决性能安全问题挑战性很大,可能?x)增强好几倍的实现隑ֺ。那模板cȝ竟Ԓ丈何U魔法神功,能够在无需同步的情况下化解线E安全的N呢?{案是ThreadLocalQ?
ThreadLocal在Spring中发挥着重要的作用,在管理request作用域的Bean、事务管理、Q务调度、AOP{模块都出现了他们的w媄(jing)Qv着举轻重的作用。要想了解Spring事务理的底层技术,ThreadLocal是必L克的山头堡垒?
ThreadLocal是什?
早在JDK 1.2的版本中提供java.lang.ThreadLocalQThreadLocal军_U程E式的ƈ发问题提供了一U新的思\。用这个工L(fng)能够很简z地~写Z的多线E程式?
ThreadLocal很容易让人望文生义,惛_然地认ؓ(f)是个“本地U程”。其实,ThreadLocalq不是个ThreadQ而是Thread的局部变量,也许把他命名为ThreadLocalVariable更容易让人理解一些?
当用ThreadLocall护变量ӞThreadLocal为每个用该变量的线E提供单独的变量副本Q所以每一个线E都能够单独地改变自q副本Q而不?x)?jing)响其他线E所对应的副本?
从线E的角度看,目标变量p是线E的本地变量Q这也是cd?#8220;Local”所要表辄意思?
U程局部变量ƈ不是Java的新发明Q很多语aQ如IBM IBM XL FORTRANQ在语法层面提供线E局部变量。在Java中没有提供在语言U支持,而是变相地通过ThreadLocal的类提供支持?
所以,在Java中编写线E局部变量的代码相对来说要笨拙一些,因此造成U程局部变量没有在Java研发者中得到很好的普?qing)?
ThreadLocal的接口方?
ThreadLocalcL口很单,只有4个方法,我们先来了解一下:(x)
* void set(Object value)
配置当前U程的线E局部变量的倹{?
* public Object get()
该方法返回当前线E所对应的线E局部变量?
* public void remove()
当前线E局部变量的值删除,目的是ؓ(f)了减内存的占用Q该Ҏ(gu)是JDK 5.0新增的方法。需要指出的是,当线E结束后Q对应该U程的局部变量将自动被垃圑֛Ӟ所以显式调用该Ҏ(gu)清除U程的局部变量ƈ不是必须的操作,但他能够加快内存回收的速度?
* protected Object initialValue()
q回该线E局部变量的初始|该方法是个protected的方法,昄是ؓ(f)了让子类覆盖而设计的。这个方法是个gq调用方法,在线E第1ơ调用get()或set(Object)时才执行Qƈ且仅执行1ơ。ThreadLocal中的~省实现直接q回一个null?
]]> Spring XML配置实践 http://m.tkk7.com/ashutc/archive/2009/03/09/258594.html西瓜 西瓜 Mon, 09 Mar 2009 06:39:00 GMT http://m.tkk7.com/ashutc/archive/2009/03/09/258594.html http://m.tkk7.com/ashutc/comments/258594.html http://m.tkk7.com/ashutc/archive/2009/03/09/258594.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/258594.html http://m.tkk7.com/ashutc/services/trackbacks/258594.html
Spring是一个强大的Java应用框架Q它q泛地应用于Java应用E序中,为Plain Old Java ObjectsQPOJOQ提供企业服务。Spring利用依赖注入机制来简化工作,同时提高可测试性。其配置文gQ通常是XML格式Q中指定了Spring bean、依赖性以?qing)bean所需的服务。但是,q些XML配置文g既冗长又不实用。对于需要定义大量Spring bean的大型项目来_(d)它们难以阅读和管理?br />
在本文中Q我向(zhn)展C?2U用于Spring XML配置的最?jng)_c(din)其中的一些实践与其说是最?jng)_践,倒不如说是必要实c(din)注意,其他因素Q如域模型的讄Q也可能影响XML的配|,但是本文重点研究XML配置的可L和可管理性?/p>
1。避免用自动绑定(autowiringQ功?/strong>
Spring可以通过beancȝ自省自动l定依赖性,所以不必显式指明bean的属性和构造函数。Bean属性可以通过属性名U或cd匚w来实现自动绑定。构造函数通过cd匚w来实现自动绑定。甚臛_以指定自动检autowiring模式Q它可以引导Spring选择一U适当的运行机制。先来看看下面的一个例子:(x)
<bean id="orderService"
class="com.lizjason.spring.OrderService"
autowire="byName"/>
OrderServicecȝ属性名在容器中用于匚wbean实例。自动绑定可能会(x)节省一些键入工作量q减乱。但是在现实目中不应该使用q种方式Q因为它牺牲了配|的可读性和可维护性。许多指南和介绍中大肆吹捧自动绑定是Spring的一Ҏ(gu)好的Ҏ(gu),而没有提到这一Ҏ(gu)所带来的牺牌Ӏ依我来看,q就像Spring中的对象池(objectQpoolingQ,更大E度上只是宣传的噱头。对于精XML配置文g来说Q它是一个好办法Q但它实际上增加了复杂性,其是在q行包含大量cd明的目时。虽然Spring允许混合使用自动l定和显式绑定,但这?x)XML配置更加晦ӆ难懂?/p>
2.使用命名U定
该原则对于Java~码也一样适用。在目中用清晰的、描q性的、一致的命名U定非常有利于开发h员理解XML配置。例如,对于bean IDQ可以按照JavacdD名U定来命名它。OrderServiceDAO实例的bean ID应该命名为orderServiceDAO。对于大型项目,可以在bean ID前面加上包名作ؓ(f)前缀?/p>
3. 使用zŞ?/strong>
zŞ式避免了冗长Q因为它?yu)属性值和引用从子元素中移入属性中。例如下面的例子Q?br />
<bean id="orderService"
class="com.lizjason.spring.OrderService">
<property name="companyName">
<value>lizjason</value>
</property>
<constructor-arg>
<ref bean="orderDAO">
</constructor-arg>
</bean>
可以使用zŞ式将上述代码重写为:(x)
<bean id="orderService"
class="com.lizjason.spring.OrderService">
<property name="companyName"
value="lizjason"/>
<constructor-arg ref="orderDAO"/>
</bean>
zŞ式自1.2版本起就可以使用。注意,对于<ref local="...">Q没有简zŞ式?br />
zŞ式不但可以节U键入工作量Q而且可以使XML配置文g更清晰。当一个配|文件中定义了大量的cLQ它可以显著提高可读性?/p>
4. 对于构造函数参数匹配,cd比下标好
当构造函数含有一个以上同U类型的参数Q或者属性值的标签已经被占用时QSpring允许使用?开始的下标来避免淆。例如:(x)
<bean id="billingService"
class="com.lizjason.spring.BillingService">
<constructor-arg index="0" value="lizjason"/>
<constructor-arg index="1" value="100"/>
</bean>
利用type属性来~写?x)更好一些,如下Q?br />
<bean id="billingService"
class="com.lizjason.spring.BillingService">
<constructor-arg type="java.lang.String"
value="lizjason"/>
<constructor-arg type="int" value="100"/>
</bean>
使用index可以减少一些代码,但是与type属性相比,它更易于出错且难于阅诅R只有在构造函数参C明确的时候,才应该用index?/p>
5. 可能重用已定义的bean
Spring提供了一U类gl承的机制来减少配置信息的复制ƈ化XML配置。定义一个子c,它就可以从父c那里扉K|信息,而父cd际上成ؓ(f)子类的一个模ѝ这是大型目中所谓的重用。只需在父cbean中设|a(chn)bstract=trueQ然后在子bean中指定parent引用。例如:(x)
<bean id="abstractService" abstract="true"
class="com.lizjason.spring.AbstractService">
<property name="companyName"
value="lizjason"/>
</bean>
<bean id="shippingService"
parent="abstractService"
class="com.lizjason.spring.ShippingService">
<property name="shippedBy" value="lizjason"/>
</bean>
ShippingServicecMabstractServicecȝ承companyName属性的值——lizjason。如果一个bean没有指定cL工厂Ҏ(gu)Q那么这个bean便是抽象的?/p>
6. 在导入时Q首选通过ApplicationContext来汇~bean定义
像Ant脚本中的导入一PSpring的import元素对于汇编模块化的bean定义来说是很有用的。例如:(x)
<beans>
<import resource="billingServices.xml"/>
<import resource="shippingServices.xml"/>
<bean id="orderService"
class="com.lizjason.spring.OrderService"/>
<beans>
然而,相对于用import在XML配置中进行预汇编Q通过ApplicationContext来配|这些bean则显得更加灵zR用ApplicationContext的话QXML配置也更易于理。可以向ApplictionContext构造函C递一lbean定义Q如下:(x)
String[] serviceResources =
{"orderServices.xml",
"billingServices.xml",
"shippingServices.xml"};
ApplicationContext orderServiceContext = new
ClassPathXmlApplicationContext(serviceResources);
7. 使用id作ؓ(f)bean标识W?/strong>
可以指定一个id或名U来作ؓ(f)bean标识W。虽然用id不能提高可读性,但是它可以利用XML分析E序来对bean引用q行验证。如果由于XML IDREF的约束而不能用某个idQ那么可以用名U来作ؓ(f)bean的标识符。XML IDREF的约束是Qid必须以字母(或者XML规范中定义的标点W号Q开_(d)后面是字母、数字、连字符、下划线、冒h句点。实际上Q很会(x)遇到XML IDREFU束问题?/p>
8. 在开发阶D用依赖性检查(dependency-checkQ?/strong>
可以在bean定义中ؓ(f)dependency-check属性设|一个非默认|比如simple、objects或allQ以便容器进行依赖性检查。当需要显式或通过自动l定讄bean的全部属性(或某cd性)Ӟ依赖性检查便昑־很有用?br />
<bean id="orderService"
class="com.lizjason.spring.OrderService"
dependency-check="objects">
<property name="companyName"
value="lizjason"/>
<constructor-arg ref="orderDAO"/>
</bean>
在这个例子中Q容器确保ؓ(f)orderService bean讄的属性不是primitives或collections。也可以为所有的bean讄默认依赖性检查,但是我们很少q样做,因ؓ(f)有些bean属性根本就不必讄?/p>
9. 为每个配|文件添加首部注?/strong>
最好用描q性的id和名U来取代XML配置文g中的内置注释。此外,d一个配|文仉部也很有用,它可以概q文件中所定义的bean。可以选择描q添加到description标签中。例如:(x)
<beans>
<description>
This file defines billing service
related beans and it depends on
baseServices.xml,which provides
service bean templates...
</description>
...
</beans>
使用description标签的一个好处是可以L地利用工具从标签中选获取描q内宏V?/p>
10. 对于更改Q团队成员要U极交流
在重构Java代码Ӟ需要随时更新配|文件ƈ通知团队成员。XML配置文g也是代码Q它们是应用E序的至关重要的部分Q但是它们难于阅dl护。大部分情况下,需要同旉读XML配置文g和运行中的Java代码?/p>
11. Setter注入优于构造函数注?/strong>
Spring提供?U类型的依赖注入Q构造函数注入(constructor injectionQ、setter注入Qsetter injectionQ和Ҏ(gu)注入Qmethod injectionQ。我们一般只用前两种?br />
<bean id="orderService"
class="com.lizjason.spring.OrderService">
<constructor-arg ref="orderDAO"/>
</bean>
<bean id="billingService"
class="com.lizjason.spring.BillingService">
<property name="billingDAO"
ref="billingDAO">
</bean>
在这个例子中QorderServicecM用的是构造函数注入,而BillingServicecM用的是setter注入。构造函数注入可以确保bean不会(x)在一个非法状态下被创建,但是setter注入更加灉|且更易于理Q尤其是在类包含许多属性ƈ且其中一些可选的情况下?/p>
12. 不要滥用依赖注入
最后一点,Spring ApplicationContext可以为?zhn)创徏Java对象Q但q不是所有的Java对象都应通过依赖注入来创建。例如,全局对象不应该通过ApplicationContext来创建。Spring是一个很的框架Q但是,可L和易管理性而言Q如果定义了大量beanQ基于XML的配|就可能成ؓ(f)问题。过度用依赖注入会(x)使XML配置变得复杂且臃ѝ要知道Q借助于功能强大的IDEQ如Eclipse和IntelliJQ,Java代码比XML文g更加易读、易l护、易理?/p>
l束?/strong>
XML是通用的Spring配置方式。但如果定义了大量beanQ基于XML的配|就?x)变得冗长而不实用。Spring提供了丰富的配置选项Q恰当地利用其中的选项可以使XML配置更清晎ͼ但是Q有些选项Q如autowiringQ往往?x)降低配|文件的可读性和可维护性。遵循本文中所描述的最?jng)_践,有助于(zhn)创建出清晰易读的XML配置文g?/p>
]]>
配置WebWork http://m.tkk7.com/ashutc/archive/2009/03/03/257483.html西瓜 西瓜 Tue, 03 Mar 2009 02:27:00 GMT http://m.tkk7.com/ashutc/archive/2009/03/03/257483.html http://m.tkk7.com/ashutc/comments/257483.html http://m.tkk7.com/ashutc/archive/2009/03/03/257483.html#Feedback 0 http://m.tkk7.com/ashutc/comments/commentRss/257483.html http://m.tkk7.com/ashutc/services/trackbacks/257483.html
1. 基本配置
. action?br />
. actionc?br />
. resultcd
<xwork>
<include file="webwork -default.xml">
<package extends="webwork -default" name="default">
<default-action-ref name="home">
<action>
name="helloWorld"
class="ch2.example1.HelloWorld">
<result name="input">login.jsp</result>
<result type="redirect" name="success">/index.jsp</result>
</action>
</default-action-ref>
</package>
以上例子中,如果helloWorld actionq回的result code是SUCCESSQ那么用户将?x)重定向?index.jsp。如果返回的
result code是INPUTQ将?x)显Clogin.jsp面?br />
2. 配置别名重用action
多个名字映到相同的actionc;q个名字UCؓ(f)别名。这时多个请求访问相同的execute()Ҏ(gu)Q?br />
在别名基上,可增加一个可选的method属性,指定webwork 该调用哪个方法。所指定的方法格式与execute()Ҏ(gu)一栗?br />
q时多个h讉K不同的方法;
<action class="ch2.example1.Cal" name="add">
<result name="success">cal.jsp</result>
</action>
<action method="minus" class="ch2.example1.Cal" name="minus">
<result name="success">cal.jsp</result>
</action>
注:(x)WebWork 通过xwork.xml映射x法有两种途径Q?br />
. 通过查找与method属性的g致的Ҏ(gu)Q?br />
. 通过查找doMethod()形式的方法;
WebWork 先找method属性一致方法,如找不到Q再找doMethod()形式Ҏ(gu)Q?br />
3. 不配|别名重用action
通过name!method.action形式h讉Ka(chn)ctionQ其中name为action的映名字。这时不需额外配置?br />
注:(x)优先推荐Q但要预防不怀好意的用户通过该途径使用你不惌用户调用的方法;
4. 通过参数自定义action
可通过在配|文件中讄参数传递给action. 从而达到非常灵z设|的目的?br />
a. 在xwork.xml文g的action配置位置处配|以下信?配置参数名称为url)Q?br />
<action class="ch2.example1.ParamTest" name="paramTest">
<result name="success">paramTest.jsp</result>
</action>
b. action
在action中定义与参数名同名的属性以?qing)对应的setter/getterҎ(gu)Q?span class="hilite1">webwork在action执行时会(x)自动调用
setterҎ(gu)为属性赋在xwork.xml文g中所配置的参数|
c. jsp
通过标记: <ww:property value="属性名"> 获取参数|
? 配置Result
1. 基本配置Q?br />
<result type="redirect" name="success">paramTest.jsp</result>
result׃个部分组?
. result映射Q?通过name属性指定result的逻辑名,name的属性gaction中execute()Ҏ(gu)中的q回值相?
result标记本体内容指定跌{的\径,既可以ؓ(f)l对路径(/代表包含namespace内容在内的web应用根\?Q?br />
也可以ؓ(f)相对路径Q?br />
. resultcdQ?通过type属性指定,默认gؓ(f)dispatcherQ可以指定ؓ(f)redirect。如指定为redirectQ则产生
一个新的请求蟩转至目的地址Q?br />
2. 使用全局result映射减少重复配置
讑֮全局resultQ服务于多个action配置Q减重复配|;
<global-results>
<result type="redirect" name="success">paramTest.jsp</result>
</global-results>
<action class="ch2.example1.ParamTest" name="paramTest">
? 配置interceptor
interceptor(拦截?是一U很Ҏ(gu)的对象,它围l着action?qing)result的执行过E。它可以在action之前或之后及(qing)result
之后工作Q实C某些逻辑的松耦合Q譬如安全、日志和校验?br />
1. 定义interceptor
. 定义
<package name="webwork -default">
<interceptors>
<interceptor class="com.opensymphony.xwork.interceptor.LoggingInterceptor" name="logger">
<interceptor class="com.opensymphony.xwork.interceptor.TimerInterceptor" name="timer">
</interceptor>
</interceptor>
注:(x)一般不需自行定义Q在webwork -default.xml文g中已定义了很多interceptor?span class="hilite1">webwork-default.xml位于
webwork -2.2.4.jar文g根目录中;
. 使用
<package name="webwork -default">
<interceptors>
<interceptor class="com.opensymphony.xwork.interceptor.LoggingInterceptor" name="logger">
<interceptor class="com.opensymphony.xwork.interceptor.TimerInterceptor" name="timer">
</interceptor>
<action class="ch2.example1.ParamTest" name="paramTest">
<interceptor-ref name="timer">
<interceptor-ref name="logger">
</interceptor-ref>
</interceptor-ref>
q样讄后,当paramTest.action被调用的时侯Qtimer和logger两个interceptor也会(x)相应地被调用?br />
2. 多个interceptorl合为栈
多个interceptorl合CP而不需要ؓ(f)每一个action声明数量众多?lt;interceptor-ref>。一个interceptor栈包?br />
一linterceptorQƈ且按照它们本w在栈中定义的顺序来执行?br />
. 定义
<package name="webwork -default">
<interceptors>
<interceptor class="com.opensymphony.xwork.interceptor.LoggingInterceptor" name="logger">
<interceptor class="com.opensymphony.xwork.interceptor.TimerInterceptor" name="timer">
</interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="logger">
<interceptor-ref name="timer">
</interceptor-ref>
</interceptor-ref>
. 使用
<package name="webwork -default">
<interceptors>
<interceptor class="com.opensymphony.xwork.interceptor.LoggingInterceptor" name="logger">
<interceptor class="com.opensymphony.xwork.interceptor.TimerInterceptor" name="timer">
</interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="logger">
<interceptor-ref name="timer">
</interceptor-ref>
<action class="ch2.example1.ParamTest" name="paramTest">
<interceptor-ref name="myStack">
</interceptor-ref>
</action>
3. 使用默认interceptor-ref减少重复配置
通过使用default-interceptor-ref元素Qpackage中每一个action都不再需要定义Q何interceptor?br />
<package name="webwork -default">
<interceptors>
<interceptor class="com.opensymphony.xwork.interceptor.LoggingInterceptor" name="logger">
<interceptor class="com.opensymphony.xwork.interceptor.TimerInterceptor" name="timer">
</interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="logger">
<interceptor-ref name="timer">
</interceptor-ref>
<default-interceptor-ref name="myStack">
<action class="ch2.example1.ParamTest" name="paramTest">
</action>
注:(x)如ؓ(f)一个action定义了interceptorQ那么这个action不再用默认的interceptor?br />
? 高配置
1. package
WebWork 中的package和Java中的package在很多方面非常相|它将多个actionl织成一个模块。简化维护工作,提高
重用性。一个package中包含了所有将用到的action, result, interceptor的定义?br />
2. 扩展package
WebWork 中的package可以扩展另外的packageQؓ(f)其extends属性指定一个用逗号分隔的package列表Q从而扩展该列表?br />
package。当一?span class="hilite1">WebWork package扩展另外一个packageӞ会(x)从被包含的package中复制所有的定义Qƈ在自己本w?br />
已有的定义基上增加这些配|。这让你可以配|的公共部分集中hQ减package中重复定义的内容?br />
<package extends="webwork -default" name="default">
...
</package>
3. 映射namespace
WebWork 通过action名字和所属的namespace标识action。如果package没定义namespace属性,用默认的namespace: "/"?br />
?span class="hilite1">WebWork接收C个请求的时侯Q?span class="hilite1">WebWork?x)将h的URL分ؓ(f)namespace和action名字两个部分Q然后从xwork.xml中查?br />
namespace/action内容Q如果没有找刎ͼ则从默认的namespace中查找action?br />
<package namespace="/enterinfo" extends="webwork -default" name="default">
<action class="ch2.example1.ParamTest" name="paramTest">
<result type="redirect" name="success">paramTest.jsp</result>
</action>
</package>
以上讉KparamTestQ通过URL: http://localhost:8080/enterinfo/paramTest.actionQ其中:(x)
. /enterinfo为namespace的名字;
. paramTest为action的名字;
多个package可以使用相同的namespace?br />
4. 使用include标签实现lg?br />
Z支持应用程序划分ؓ(f)更容易管理的模块Q?span class="hilite1">WebWork提供了一U包含机Ӟ可以xwork.xml划分为多个文Ӟ而每一?br />
子文件又是与一个模块相联系的。可以通过使用<include>标签指定文g名的Ҏ(gu)子文g包含到xwork.xml中,?span class="hilite1">WebWork
׃(x)在应用程序的classpath中查找指定的子文件?br />
<xwork>
<include file="webwork -default.xml">
<package namespace="/enterinfo" extends="webwork -default" name="default">
...
</package>
</include>
? 其它配置
1. web.xml
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" version="2.4">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<servlet>
<servlet-name>webwork </servlet-name>
<servlet-class>
com.opensymphony.webwork .dispatcher.ServletDispatcher
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>webwork </servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<jsp-config>
<taglib>
<taglib-uri>webwork </taglib-uri>
<taglib-location>
/WEB-INF/lib/webwork -2.2.4.jar
</taglib-location>
</taglib>
</jsp-config>
</web-app>
2. webwork .properties
xwork.xml定义了action映射Qƈ且将interceptor和result应用到这些action上。?span class="hilite1">webwork.properties用来定义
application范围的设|,以及(qing)能够改变框架功能的配|参数?br />
WebWork 首先?x)装载位?span class="hilite1">WebWork JAR文g中的default.propertiesQ然后再装蝲webwork .propertiesQƈ且根?br />
webwork .properties内容改写之前装蝲的配|设定?lt;/xwork></include></default-interceptor-ref></interceptor-ref></interceptor-stack></interceptor></interceptors></package> </interceptor-ref></interceptor-stack></interceptor></interceptors></package> </interceptor-stack></interceptor></interceptors></package> </interceptor-ref></action></interceptor></interceptors></package> </interceptors></package> </action></ww:property></include></xwork>
]]>
վ֩ģ壺
þþƷձҰ |
þƷ˳ۺ |
պþ |
һ |
һػɫѴƬƵ |
Ƶ߲ |
պۺ |
Ʒxo߹ۿ |
ľƷ |
18ڵվ |
þþƷۺר |
þþþAV鶹 |
ִӲëƬ |
һŷĻ |
һ |
AV߲ |
һѻɫƬ |
aƬ߹ۿ |
ҹWWWʪˬ |
߹ۿ |
˳˳ۺ |
ŮˬƵ |
ȫ»ɫؼվ
|
ѿڿŮ |
ëƬ߲ |
þþƷƷëƬ |
91Ƶ |
߲ |
ձѹۿ |
Ʒþþ |
һëƬѿ |
99ƷƵ |
97Ƶѹۿ |
Ʒһߵ |
AëƬav |
ձ߿Ƭ |
ƬAVƬѹۿ |
þAV뾫Ʒɫҹ |
ó˾þAvѸ |
պƷһAVۿ |
ֻ߿avƬ |