1、创建Web Project9 D: M$ V6 i+ q/ |' n4 q/ k+ Z1 q
2、web工程与struts2整合$ t. X0 B+ D9 N$ u
(1)添加struts2类库! j0 T+ J! \, K$ N8 Y
struts2-core-2.1.8.1.jar # W( e% r3 u7 `/ V, o- M9 n xwork-core-2.1.6.jar3 K4 C' _* r: m' d6 R( Q2 C
commons-fileupload-1.2.1.jar - T% C( \: }9 M# { commons-io-1.3.2.jar; f6 \! }) v _5 g; @
ognl-2.7.3.jar , a3 m0 @7 G: p- w' O: V freemarker-2.3.15.jar 1 a, X4 R7 y6 p; P (2) 在web.xml文件中添加struts2集成 5 I" _1 Y9 G8 ~0 W9 h <filter> ) w) Z) ]5 M1 O) [ <filter-name>struts</filter-name> & M ?. C, [! N/ B <filter-class>" @ ~- i e0 O+ ?; I
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter # u+ a8 ?$ V1 l: A$ ` </filter-class>7 C: l1 D d" i4 D
<init-param>/ S# i( I( Y' H
<param-name>config</param-name> , I7 ` B8 [# W0 E- H <!-- 9 b" h; E* Z2 t6 V' M5 Y 修改struts2默认配置文件, . Z- j8 N6 q% F( D1 k8 U 必须把struts-default.xml, 8 }6 k! p+ z1 k struts-plugin.xml一起添加3 R: b0 t) a; ~- J1 k" L$ I+ T
必须:按顺序添加 4 g; O, r. L- `" W0 u5 R --> O( T8 ]% d; g6 B2 z# B j. A4 H
<param-value> - e, u7 @* M: s struts-default.xml,struts-plugin.xml,config/struts/struts.xml* F2 a1 z2 y' v3 g; \3 u
</param-value> % L* ?( G. q. L, T </init-param> 8 |" A6 G" o+ D s) Q) q8 o </filter>7 Y, |; ?) E6 B
<filter-mapping>" a$ z6 {+ T; H: }
<filter-name>struts</filter-name>6 W" V2 u p) C' e+ d1 o3 r
<url-pattern>/*</url-pattern> # d6 I' X/ l) v( k+ g </filter-mapping> 0 ?) S9 ]" V: g Q- H% k <!--struts2 *.action struts2 *.do--> Z" Q* _0 u2 A (3)创建struts2配置文件struts.xml配置 ' q0 s# A1 o4 ]' X
(4)完成页面跳转' K5 o8 ]/ z$ t4 ^$ P) Q6 ~
3、测试struts2工程 9 H8 p, t( O3 ]% T# a3 |4、struts2与spring集成 + T. W4 ^4 E& C8 d (1)添加spring类库与struts支持spring插件( f# W; U# m( d: p$ q' z" ?
struts2-spring-plugin-2.1.8.1.jar " u, J/ c7 a7 o& t* a8 D cglib-nodep-2.1_3.jar 1 z6 a6 c5 u+ q9 ^/ J commons-logging.jar # s$ D4 F$ K) K5 D0 t log4j-1.2.15.jar ' K% }7 Z7 E0 y; J% d spring.jar1 H% h# r8 j4 e% n9 _7 x
dom4j-1.6.1.jar0 I- A. _# K: v& P% i1 \2 x
(2)在web.xml中完成spring集成- Z5 Z0 I7 H8 ` X7 O. I
<listener>" {2 H& M( B7 U+ b2 T- q. r6 P
<listener-class>$ j& X# z; E# Y9 W
org.springframework.web.context.ContextLoaderListener& d% n; ^7 Q# i+ e0 s$ o
</listener-class> ' N+ p8 u" m' J </listener> " _: h4 Z7 \5 R9 N <context-param>+ z6 c5 l- D4 y% G4 A E
<param-name>contextConfigLocation</param-name> 3 i% X- V& @* D4 m' A <param-value>& B7 e1 v2 ?% k: O
classpath:config/spring/applicationContext.xml+ z( K% K& d. P+ I3 b! P
<!--classpath:config/spring/applicationContext*.xml-->9 n" B+ F: ?8 ^$ h1 F1 C
</param-value> 8 c( [4 B: k' i: @9 t% K" q </context-param>+ g; i g( y, f5 {1 X
(3)创建spring配置文件applicationContext.xml # P1 C6 O% j. D h9 e (4)在struts2配置文件中添加spring 集成常量* H& D; Z1 ]4 i. g( |
<!-- 设置集成spring框架 --> ) H3 z1 I% a3 `7 {# m <constant name="struts.objectFactory" value="spring"/> 6 W' @+ {. ?8 Q- P0 [ (5)spring管理struts2中Action0 P+ }6 ^6 p, e# t) I
(1)在spring 配置文件中加入bean管理 ; R: L4 T% k5 }) ^ <bean id="userAction" class="com.tarena.web.action.UserAction" > 3 a5 X/ \0 Z0 ]( S# X </bean>$ S3 Z C& J9 m7 ?+ z b( ]
(2)修改struts-user.xml配置$ M' v" A; V0 h* _2 a
<action class="userAction" > 6 p% n" l- Z" C </action>* m+ A% N7 O, I0 s6 p
5 测试struts+spring集成 % S. ^; p N* }! i/ ?! K2 k6 spring+hibernate集成 4 m) [3 t2 F, G! s* | (1)添加hibernate类库! O% S" r1 l, z( _, e
slf4j-nop-1.5.8.jar 6 ^8 O0 I% o$ Y. r& C slf4j-api-1.5.8.jar ' r0 l9 ]- U1 j; G7 k6 M jta-1.1.jar 2 V$ h) n& g' H% e7 h1 C' I s3 j$ j, Bjavassist-3.9.0.GA.jar; O V' g3 J1 Q# W- o# `$ V
hibernate3.jar * C3 t+ M: i2 b: S commons-collections-3.1.jar 2 U5 q7 ?. m# l' N- r; {! P8 g antlr-2.7.6.jar . z3 d q# j" q( C2 s' Q (2)添加MySQL驱动类库 3 W) Z1 Y2 C0 g8 n mysql-connector-java-5.1.16-bin.jar . r- X! H% v, n& v, t8 g (3)创建实体类5 P2 l2 B7 N: R4 m# [( W; ^
(4)编写User.hbm.xml映射文件: D* r* n# p0 h
(5)反向生成表结构 0 G- q M3 c+ { (6)spring管理hibernate " b5 o4 X) G; B- W: X
在spring applicationContext.xml配置文件中添加spring对hibernate管理2 ]2 z5 p6 \! q; V3 v* L
(A) 添加DBCP连接池 : z# ~- a. N6 [6 O' c) W a、添加类库 D! y! ^. |% f! p
commons-dbcp.jar3 r" A7 h( u J0 g( m
commons-pool.jar: Y% [# e% O7 t) [1 D
b、applicationContext.xml在配置连接池0 _+ G3 D5 H. v9 d+ w" [ W
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> : H6 E' S& z% T3 X: u0 k <property name="driverClassName" value="com.mysql.jdbc.Driver"/> + Z8 [/ A6 n) l o6 `" r4 L <property name="url" value="jdbc:mysql://127.0.0.1:3306/mydb"/> 1 K8 L7 ^: M( ]) c* s8 r( x <property name="username" value="root"/>0 Y- ^- i1 L9 p9 u
<property name="password" value="1234"/>+ t/ U3 v; Q: P3 U
<property name="initialSize" value="2"/> / b4 G+ W' O; _6 u; @' `, p0 f <property name="maxActive" value="8"/>% h( c( i- `( x7 u' }; a& T5 H/ Z
<property name="maxIdle" value="5"/> 8 o( u" U d1 r3 q2 ~" z$ E" B <property name="minIdle" value="3"/>, N# B( o; O( i
<property name="maxWait" value="3000"/> 1 ^* f& o% r1 W' K <property name="removeAbandonedTimeout" value="60000"/>$ t9 e$ |- F4 T
<property name="removeAbandoned" value="true"/> 6 x! v" z" j1 ~ </bean> / U, C# y% I" M3 I3 A 连接池参数如下:& G5 W: P8 y1 J8 `0 T* t, @
initialSize , z7 e0 R# O7 ] 连接池启动时创建的初始化连接数量2 K J3 R p5 J0 Q
(默认值initialSize :连接池启动时 * \5 L1 B0 G% Y O1 z 创建的初始化连接数量(默认值为0) - i/ o ~ S) o4 e3 K+ y maxActive 3 a* Q; ^) _7 P9 N5 R. x 连接池中可同时连接的最大的连接数5 ]& _- ] ~- Q' i* V5 k
(默认值为8 ,调整为20,高峰单机器在20并发左右, , W+ p4 P: j- {. S- T 自己根据应用场景定) : O2 V8 P* I! g# l6 ?: _9 b maxIdle 7 f$ A) y9 }4 {* \; h9 X 连接池中最大的空闲的连接数,' ]4 B) J% D! R) U8 u) b2 `
超过的空闲连接将被释放,# n2 l: N& e: @
如果设置为负数表示 不限制(默认为8个) 6 m4 s: y9 ^' ]$ o; o! U) k* K minIdle 2 s2 U4 D N% _1 {! X1 g+ g: `5 P 连接池 中最小的空闲的连接数,低于这个数量会被 ! c/ G4 B# I& T6 T. b 创建新的连接(默认为0,调整为5, 该参数越接近. j* b/ M k/ d- X* T6 u) D
maxIdle,性能越好,因为连接的创建和销毁,6 ]: w! ~1 G$ t
都是需要消耗资源的,但是不能太大, . F: D* Z9 @7 ^6 ~7 ]& C 因为在机器很空闲的时候,也会创建低于 9 m u& _* w4 U; M' M( E3 Q5 _ minidle个数的连接) + Y; R I- M4 v
maxWait , S% _1 v5 g( C) r h9 _ P9 l- o
最大等待时间,当没有可用 连接时, 0 e. F. t# d3 R, s 连接池等待连接释放的最大时间, 8 j) W& Q H/ d9 z+ w( H6 K 超过该时间限制会抛出异常, 1 ]! b3 z7 q9 _& ~* p 如果设 置-1表示无限等待( 5 d9 A# \3 E T! M% d( L/ n, w% A6 S1 N 默认为无限,调整为60000ms, & {# e0 c$ p! {; Z 避免因线程池不够用,而导致 请求被无限制挂起) 9 S# z* |+ V3 R. {, ` removeAbandonedTimeout :$ i/ f0 F9 d, y& ^9 L& F
超过时间限制,回收没有用(废弃)的连接 * G* X% P6 w0 K0 Z- K (默认为 300秒,调整为180) & E7 B1 i, B; g" L. u7 Z' I removeAbandoned :7 i: _/ O. m2 Z8 f* V0 m% k
超过 removeAbandonedTimeout时间后,1 D+ C, j) P3 }" f; P1 ^
是否进行没用连接(废弃)的回收: O5 G Q* q, N7 |. L
(默认为 false,调整为true)4 n: ]5 f* u; N. _7 ~
(B)spring管理hibernate实体映射文件:: q8 P& W' s5 A/ h$ p7 `, T
<bean id="sessionFactory"3 L; [; U/ \& m1 [ ], l" U$ K, c
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 3 \$ C. u5 W& h( d <property name="dataSource" ref="dataSource" />" U1 x8 Y/ K* C7 g4 ~8 m8 X$ Z2 {
<property name="hibernateProperties"> e3 \7 a; r3 ]; K( p' \1 o
<props> ; q+ L7 j, R6 E8 H9 E& L <prop key="hibernate.dialect"> ' v, h+ S& H# m, r( Z$ n org.hibernate.dialect.MySQLDialect6 [ [( W3 i, x0 `
</prop> + J! W8 m) w: Q2 d <prop key="hibernate.show_sql">true</prop> R& Z ]8 ]. N* S9 Z( { <prop key="hibernate.format_sql">true</prop>! x5 S* o* k, W: x
</props> A, m" O+ E- O; [" l2 j8 M" ~6 {' g </property>- K" d" S _/ d y/ L/ F7 F
<property name="mappingLocations">* \7 ~1 q6 d6 {
<list> 2 R+ @; x6 Z. U- U! d2 |& @. J <value> - i1 b* `/ k; u f6 Z! y/ Q classpath:config/hibernate/hbm/User.hbm.xml, g0 ?5 _1 Q# b' Y7 n
</value>8 |% @7 ^* B U; M+ x
</list># ]' f& F8 Y* X2 J j& D: l2 P3 a7 ]" e
</property>/ _1 z# Z" `1 N9 B" m9 q8 U0 k
</bean> & ^ V e+ P9 X6 u, f2 ~ (C)spring读写属性(properties)文件 " e+ H8 c0 D ^. M+ M a、创建属性文件 db.properties! m: g% ]6 O8 i# ]8 a4 M
b、在applicationContext.xml配置 ; W; R7 v! k1 J+ d <bean id="propertyPlaceholderConfigurer" X: c$ I: R4 h& m class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">7 m' C5 R( b6 \, g; p7 v3 f$ y
<property name="locations">* d0 t8 v1 C3 h
<list> ! Y3 R, G. [7 a: Z. U) W <value>classpath:config/props/db.properties</value> ' r7 k2 Z% Q: x6 R* C </list> " {7 i# q5 ?! W9 L$ W" Z </property> ! n. e2 m- A2 q$ R9 X2 \ </bean> 1 i/ O! ]) [; e+ b# z: J c:引用: ${username}/ w6 v( r' H1 u$ L- P _, E C2 c
5 |9 l% Y7 V: l" @* ^1 [7 \
(8)spring分文件管理* v$ P) p$ J# f
<!-- 引入其他spring 配置文件 --> 3 O2 ~8 ^8 a0 ~' Z; A, |. Q applicationContext.xml引入下列文件 4 Q y3 `* Z5 Q& H <import resource="applicationContext-web.xml"/>0 S' |5 Y G) F' A' c/ e+ ^
<import resource="applicationContext-biz.xml"/>' v; K2 }5 i" m0 r: r
<import resource="applicationContext-dao.xml"/> 6 I& d* o: E# M9 l- r7、开发数据访问层4 F7 g/ F# ~3 d! s4 H6 g6 G E0 ^$ ]
使用spring提供hibernate 模板类 HibernateDaoSupport/ G; I. f2 q4 ^+ V
UserDaoImpl extends HibernateDaoSupport 6 s" C U1 K0 l* `, p 在UserDaoImpl注入到spring 配置文件 applicationContext-dao.xml 1 y6 d0 e, R/ r+ q1 X( ?3 r5 K <bean id="userDaoImpl" class="com.tarena.dao.impl.UserDaoImpl"> 1 Y( e- M* H, Y0 ?* I6 C1 \ <!--HibernateDaoSupport中的sessionFactory--> 4 @3 O- C8 @- c4 I: B <property name="sessionFactory" ref="sessionFactory" /> . H6 f! ^/ f- ~) `% s# \ </bean>7 a4 ~/ ^, _! ?) b4 ]
8、添加spring声明事务管理(AOP). Q2 h$ k. e1 x' F' `, j" w
声明式事务管理: * P( J" P D- ? 添加spring 类库$ U9 M, y/ j* i6 F9 P3 ^) q
aspectjrt.jar ! y; z/ `: }/ S/ q. C- q: F+ v aspectjweaver.jar ' P7 g6 M5 j( J& [# X% C. B" R: x* R 了解事务的几种传播特性 - Q7 e2 q5 c* n# K" B5 v- D ( w; h$ b. {5 I9 v( A (1)PROPAGATION_REQUIRED: 0 t3 n; Q/ K5 V& M/ C
如果存在一个事务,则支持当前事务,如果没有事务则开启。9 j; U: v+ A& m& M) q' P8 q
(2)PROPAGATION_SUPPORTS: 6 U( ]2 w/ u. ~2 I# Z
如果存在一个事务,支持当前事务。7 b% g1 a# o2 r* r5 T
如果没有事务,则非事务的执行。; ~8 n: n2 Z( B/ d; v; m. W. l
(3)PROPAGATION_MANDATORY: 4 [* e' w+ k. n3 p/ ^* P& e) Z
如果已经存在一个事务,支持当前事务。9 H# R1 `. R' I2 [
如果没有一个活动的事务,则抛出异常。* f1 ^' H- a, F1 A7 a
(4)PROPAGATION_REQUIRES_NEW: 5 b# ?! y* N, i' s5 c8 w8 s# Z% O 总是开启一个新的事务。如果一个事务已经存在, 1 m! ?, G6 M, T 则将这个存在的事务挂起。 * D% ~: }4 ]) `$ Z( } |5 P (7)PROPAGATION_NESTED:(spring特有) 7 Y$ @3 [( x5 V5 T3 P) ? 如果一个活动的事务存在,则运行在一个嵌套的事务中. ! {6 {# j) l2 [
如果没有活动事务, 则按TransactionDefinition.( o- d% C3 t4 s1 r
PROPAGATION_REQUIRED 属性执行* }+ W4 u: k- x4 {. F
9 v0 l1 s9 U! e% y% c+ z (5)PROPAGATION_NOT_SUPPORTED: 1 d8 B: y) h5 \7 n: k8 ~# K
总是非事务地执行,并挂起任何存在的事务。 / g8 B9 a' E6 f1 D+ V (6)PROPAGATION_NEVER: 8 x7 g5 p6 q) i
总是非事务地执行,如果存在一个活动事务,则抛出异常。3 T: V* Z8 Y, T. u9 R
; u2 P* K y) Y 0 o& i9 e! ^, `# p& Z. g% L
<!-- 配置声明事务管理 spring2.x-->( {: f7 Z$ ?# g0 L; s3 }
<!-- 定义事务管理 -->; Q3 M' ]9 u/ S
<bean id="transactionManager" 1 I$ B( y5 X- l% e& C9 s7 W6 J# C class="org.springframework.orm.hibernate3.HibernateTransactionManager"> # }6 C% I% ?6 ]: V( ? <property name="sessionFactory" ref="sessionFactory" />2 Q' q7 ?: ^ l) t7 ~' E3 T
</bean> ( {) w4 f( c: X8 T& m$ L/ k <!-- 事务规则 --> ! \2 X g" J$ X t <tx:advice id="tmAdvice" transaction-manager="transactionManager">$ Q1 g/ f+ w _: E; K7 b& J# X1 Y
<tx:attributes> 4 t$ t/ t' [9 k0 K N <!--*通配符 save* 方法名必须是以save开始--> $ m, \; K& f% a4 J; { <tx:method name="save*" propagation="REQUIRED" /> / g. C6 f% ]! e <tx:method name="update*" propagation="REQUIRED" />& v8 C# }) F+ o$ _' F. l! c9 A( T
<tx:method name="delete*" propagation="REQUIRED" /> 5 Y' V5 \" [# s* `- G- F1 n <tx:method name="find*" read-only="true" /> : j) n$ J2 n+ C. |" d1 f" _6 P$ @% B <!-- read-only 只读:--> % @8 p/ ]4 y8 ~/ b) b1 a6 l </tx:attributes>! X c. G3 K2 H/ a
</tx:advice>0 i: C8 z; p1 |! S
<aop:config> 3 v3 X* |% s7 T( h7 p% L, p <!-- point cut --> 1 Y8 h/ d2 |+ M- |# J$ l <aop:pointcut id="pointCut" + r# s" k. ` _# o% A expression="execution(* com.tarena.biz.*.*(..))" />7 a$ [0 j( h( _" Y# P0 O; v
<aop:advisor advice-ref="tmAdvice" pointcut-ref="pointCut"/> / F) F" z8 \1 j6 u ~% ~
</aop:config> . ^7 P- v: P6 X6 w7 \ 6 J7 ?1 F6 j8 w: q, I
9、测试 0 V9 {6 z* d' C( D; ~4 W) k: w 添加测试类库 spring2.5.69 a# _6 r& j8 { o2 w
junit-4.4.jar. S( F0 t. A3 s2 r9 a& P3 a
spring-test.jar: a* b+ g7 M9 f ]0 Z* n2 _5 s% [* d
//使用spring测试 + n f+ ` Z. t* l* g/ y @RunWith(SpringJUnit4ClassRunner.class). d' @4 E$ n0 h4 e# P
//加载spring配置文件 8 S0 R( i+ v: M! x! r. \ @ContextConfiguration(locations = { ( |, L* W% s7 A# C! _1 x "classpath:config/spring/applicationContext.xml",4 |. d. G) n1 E$ ~9 g8 @' s; T
"classpath:config/spring/applicationContext-dao.xml",3 j. G: z. l3 V, k! z* u4 y( S5 m
"classpath:config/spring/applicationContext-biz.xml", 3 P: a1 r+ I8 g6 X A L2 i, B7 W1 k "classpath:config/spring/applicationContext-web.xml" })8 j3 [: V) q4 l! E: p; w h
//自动注入5 @' N) k) i1 i$ T
@Autowired - @0 K9 ^2 ~/ Y ^8 m( Q/ p private IUserDao iuserDao; # a o9 `0 G! } ' j' Y) | d9 w; s8 W& _4 I. E @Test1 ~9 ^4 w ?' f' X* U' D
public void saveUserTest(){9 z: o8 a9 L. N: d
//测试方法9 r' ^; [9 |) w* @( H* `+ ]
} 1 _) ~$ l% W3 u, w) f5 I9 _10、完成业务层代码编写; J z3 ~4 F. k/ A5 v3 c# X1 h
11、完成表示层代码编写 / a6 _2 i. J0 N# ]" s12、测试工程 : s* Y( q) N, L3 f% s: f: T7 y( x( {$ X! V5 `$ w% X
13、spring处理hibernate延时加载% _, }& S. p. z0 Z1 C1 h7 q& W! d
1、配置延时过滤器) L9 e) |0 u0 C+ r
OpenSessionInViewFilter.class& b' w+ ^- B/ t3 B) B @
2、在web.xml配置OpenSessionInViewFilter( e3 A1 f! ^. q
6 N# ^. ^# [6 g
<filter>( M2 b8 }2 A t0 q7 g& \
<filter-name>openSessionInViewFilter</filter-name>* i5 l9 Z2 O- b
<filter-class> 6 O& c$ f- G+ a" ]4 i( } org.springframework.orm.hibernate3.support.OpenSessionInViewFilter # [$ d- {0 H: j9 J N" `* l9 q( _ </filter-class> % a1 T* v* q7 V# b' g s <init-param> ) l, Q! c3 g7 e. H/ |5 y <param-name>sessionFactoryBeanName</param-name> . E+ k; g A* _# i2 @+ ?8 N! ^7 N <param-value>sessionFactory</param-value>! u9 g5 {& H& b: W. g* i
</init-param> ) O, ~) t4 s1 `( W7 ] </filter>" O% }1 z2 w! [
<filter-mapping>5 b$ q8 \- T: b) i! n5 H1 j# a
<filter-name>openSessionInViewFilter</filter-name>2 S4 |3 V3 v6 |+ Q3 u7 k( G6 V
<url-pattern>/*</url-pattern> } Q4 R( y1 j" N+ Q6 x; e </filter-mapping> / C" k! S& S8 I7 i1 }: ? J0 L; z# J {) e1 {1 M+ X( e