spring 7大組成模塊:
1:spring core:提供了spring 的核心功能,BeanFactory是spring核心容器的主要組件, 它通過(guò)Ioc把程序的配置和依賴性與實(shí)際的代碼分開,是整個(gè)spring的基礎(chǔ)
2:spring context:通過(guò)配置文件向spring提供上下文信息, 它構(gòu)建在BeanFactory之上,另外增加了國(guó)際化和資源訪問(wèn)等功能
3:spring dao:提供了一個(gè)簡(jiǎn)單有效的JDBC應(yīng)用
4:spring aop:提供了面向方面編程的功能 5:spring orm:spring除了有自己的JDBC以外還提供了對(duì)其他ORM框架的支持,如Hibernate,都可以和spring進(jìn)行良好的結(jié)合 6:spring web:提供了簡(jiǎn)化的處理多部分請(qǐng)求以及把請(qǐng)求參數(shù)綁定到域的任務(wù)。 7:spring MVC:提供了MVC2模式的實(shí)現(xiàn),也可以和struts良好的集成在一起。
這七大模塊可以單獨(dú)使用,不需要其他模塊的支持 -------------------------------------------------------- spring的特點(diǎn): 1:設(shè)計(jì)良好的分層結(jié)構(gòu)。 2:以IOC為核心,提倡面向接口編程。 3:良好的架構(gòu)設(shè)計(jì)。 4:可以代替EJB 5:實(shí)現(xiàn)了MVC2 6:可以和其他框架良好的結(jié)合如:Hibernate ,struts等 編寫第一個(gè)HelloWorld程序: 1:interface public interface IHelloWorld { public void sayHello(); } 2:實(shí)現(xiàn)類: public class HelloWorld implements IHelloWorld{ private String msg; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public void sayHello(){ System.out.println(msg); } } 3:編寫spring配置文件:applicationContext.xml <beans> <bean id="Hello" class="EnHelloWorld"> <property name="msg"> <value>Hello World!</value> </property> </bean> </beans> 4:編寫測(cè)試類: public class TestHelloWorld { public static void main(String[] args) { ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml"); IHelloWorld hw= (IHelloWorld)ac.getBean("Hello"); hw.sayHello(); } }
--------------------------------------------------------------------- 依賴注入的三種方式: 1:接口注入 2:set注入 3:構(gòu)造注入 spring支持set注入和構(gòu)造注入 把上面的HelloWorld改為構(gòu)造注入: 1:實(shí)現(xiàn)類: public class CHelloWorld implements IHelloWorld{ public String msg; public CHelloWorld(String msg){ this.msg = msg; } public void sayHello(){ System.out.print(msg); } } 2:在spring配置文件:applicationContext.xml中: <bean id="CHello" class="CHelloWorld"> <constructor-arg index="0"> <value>C Hello World!</value> </constructor-arg> </bean> constructor-arg 用來(lái)表示用構(gòu)造方式注入?yún)?shù) index="0"表示是構(gòu)造方法中的第一個(gè)參數(shù)
3:編寫測(cè)試類: public class TestHelloWorld { public static void main(String[] args) { ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml"); IHelloWorld hw= (IHelloWorld)ac.getBean("CHello"); hw.sayHello(); } }
--------------------------------------------------------------------------- Spring的核心容器:
spring中兩個(gè)最基本最重要的包: org.springframework.context和org.springframework.beans為spring的IOC提供了基礎(chǔ) 在這兩個(gè)最重要的類是BeanFactory和ApplicationContext。BeanFactory來(lái)管理各種bean。ApplicationContext在BeanFactory之上 增加了其他功能如國(guó)際化,獲取資源事件傳遞等。 1:bean的標(biāo)志(id 和name) 每個(gè)bean都有一個(gè)id在管理bean的BeanFactory和ApplicationContext中必須是唯一標(biāo)志。 id和name都可以用來(lái)指定id這兩者中至少有一個(gè)。區(qū)別是id的命名必須符合xml id中和合法字符。name則沒(méi)有限制,而且可以使用name指定多個(gè)id
2:bean的類
class屬性路徑要完整,包名.類名
3:singleton的使用 在spring 中bean可以定義為兩種部署模式:singleton和non-singleton singleton:只有一個(gè)共享的實(shí)例存在 non-singleton:每次請(qǐng)求都創(chuàng)建新的實(shí)例
4:bean的屬性: 在定義bean的屬性時(shí)除了直接指定bean的屬性外還可以參考配置文件中定義的其他bean 1: <bean id="DateHello" class="DateHelloWorld"> <property name="msg"> <value>Hello World!</value> </property> <property name="date"> <bean id="date" class="java.util.Date"/> </property> </bean> 2: <bean id="DateHello" class="DateHelloWorld"> <property name="msg"> <value>Hello World!</value> </property> <property name="date"> <ref bean="date"/> </property> </bean> <bean id="date" class="java.util.Date"/>
5:null值的處理 把屬性設(shè)為null值有兩種方法: 1: <bean id="DateHello" class="DateHelloWorld"> <property name="msg"> <value>null</value> </property> </bean> 2: <bean id="DateHello" class="DateHelloWorld"> <property name="msg"> <null/> </property> </bean>
6:使用depends-on
bean的depends-on可以用來(lái)在初始化這個(gè)bean前,強(qiáng)制執(zhí)行一個(gè)或多個(gè)bean的初始化。 如: <bean id="DateHello" class="DateHelloWorld" depends-on="date">
---------------------------------------------------------------------------------------
bean的生命周期: 1:bean的定義 //配置bean的開始,beans中包含一個(gè)或多個(gè)bean <beans> //定義一個(gè)bean id是唯一標(biāo)志,class是bean的來(lái)源 <bean id="DateHello" class="DateHelloWorld"> //配置bean的開始 <property name="msg"> <null/> </property> //定義bean的結(jié)束 </bean> //配置bean的結(jié)束 </beans> 2:bean的初始化 初始化有兩種方式: 1在配置文件中指定init-method屬性來(lái)完成 public class HelloWorld { private String msg; public void init(){ msg="Hello World"; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public void sayHello(){ System.out.println(msg); } }
applicationContext.xml文件中 <bean id="DateHello" class="HelloWorld" init-method="init">
2實(shí)現(xiàn)org.springframework.beans.factory.InitialingBean接口 實(shí)現(xiàn)其中的afterPropertiesSet()方法
public class HelloWorld implements InitializingBean{ private String msg; public void afterPropertiesSet(){ msg="Hello World"; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public void sayHello(){ System.out.println(msg); } }
applicationContext.xml文件中 <bean id="DateHello" class="HelloWorld"> </bean> 3:bean的使用 有三種方式: 1:使用BeanWrapper HelloWorld helloWorld = new HelloWorld (); BeanWrapper bw = new BeanWrapperImpl(helloWorld); bw.setPropertyValue("msg","HelloWorld"); System.out.println(bw.getPropertyValue("msg")); 2:使用BeanFactory InputStream is = new FileInputStream("applicationContext.xml"); XmlBeanFactory factory = new XmlBeanFactory (is); HelloWorld helloWorld = (HelloWorld)factory.getBean ("HelloWorld"); helloWorld.sayHello();
3:使用ApplicationContext ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml"); IHelloWorld hw= (IHelloWorld)ac.getBean("CHello"); hw.sayHello();
4:bean的銷毀 銷毀有兩種方式: 1在配置文件中指定destory-method屬性來(lái)完成 public class HelloWorld { private String msg; public void init(){ msg="Hello World"; } public void cleanup(){ msg=""; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public void sayHello(){ System.out.println(msg); } }
applicationContext.xml文件中 <bean id="DateHello" class="HelloWorld" init-method="init" destory-method="cleanup">
2實(shí)現(xiàn)org.springframework.beans.factory.DisposeableBean接口 實(shí)現(xiàn)其中的destory()方法
public class HelloWorld implements InitializingBean,DisposeableBean{ private String msg; public void afterPropertiesSet(){ msg="Hello World"; } public void destory(){ msg=""; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public void sayHello(){ System.out.println(msg); } }
applicationContext.xml文件中 <bean id="DateHello" class="HelloWorld"> </bean> ---------------------------------------------------------- 用ref屬性指定依賴的三種方式 1:用local屬性指定:local屬性的值必須與被參考引用的bean的id一致,如果在同一個(gè)xml文件里沒(méi)有匹配的元素,xml解析將產(chǎn)生一個(gè)錯(cuò)誤 如: <bean id="DateHello" class="DateHelloWorld"> <property name="msg"> <value>Hello World!</value> </property> <property name="date"> <ref local="date"/> </property> </bean> <bean id="date" class="java.util.Date"/> 2:用bean屬性指定 用ref元素中的bean屬性指定被參考引用的bean是spring中最常見的形式,它允許指向的bean可以在同一xml文件中也可以不在同一個(gè)xml文件里 bean屬性的值可以與被引用的bean的id相同也可以與name相同。 <bean id="DateHello" class="DateHelloWorld"> <property name="msg"> <value>Hello World!</value> </property> <property name="date"> <ref bean="date"/> </property> </bean> <bean id="date" class="java.util.Date"/> 3:用parent屬性指定 用ref元素中的parent屬性指定被參考引用的bean時(shí),允許引用當(dāng)前BeanFactory或ApplicationContext的父BeanFactory或ApplicationContext bean屬性的值可以與被引用的bean的id相同也可以與name相同。 <bean id="DateHello" class="DateHelloWorld"> <property name="msg"> <value>Hello World!</value> </property> <property name="date"> <ref parent="date"/> </property> </bean> 用local屬性指定和用bean屬性指定的比較 相同:都可以使用id來(lái)參考引用,可以對(duì)同一xml文件進(jìn)行參考引用 不同:bean屬性的值可以與被引用的bean的id相同也可以與name相同??梢砸貌辉谕粋€(gè)xml文件里的bean ---------------------------------------------------------- bean自動(dòng)裝配的5種模式: 可以使用bean元素的autowire屬性來(lái)指定bean的裝配模式: 1:byName 2: byType 3:constructor 4:autodetect 5:no 顯示的指定依賴如:property 和constructor-arg元素總會(huì)覆蓋自動(dòng)裝配。對(duì)與大型應(yīng)用不鼓勵(lì)使用自動(dòng)裝配 -------------------------------------------------------------- bean 依賴檢查的4種模式: 依賴檢查能夠分別對(duì)每個(gè)bean應(yīng)用或取消應(yīng)用,默認(rèn)的是不檢查依賴關(guān)系, 可以使用bean元素的dependency-check屬性來(lái)指定bean的依賴檢查,共有4種: 1:使用simple模式 是指對(duì)基本類型、字符串和集合進(jìn)行依賴檢查 如: <bean id="DateHello" class="DateHelloWorld" autowire="autodetect" dependency-check="simple"> </bean> <bean id="date" class="java.util.Date"/> 只會(huì)對(duì)msg進(jìn)行檢查 2:使用object模式 是指對(duì)對(duì)象進(jìn)行依賴檢查 如: <bean id="DateHello" class="DateHelloWorld" autowire="autodetect" dependency-check="object"> </bean> <bean id="date" class="java.util.Date"/> 只會(huì)對(duì)date進(jìn)行檢查 3:使用all模式 是指對(duì)所有屬性進(jìn)行依賴檢查 如: <bean id="DateHello" class="DateHelloWorld" autowire="autodetect" dependency-check="all"> </bean> <bean id="date" class="java.util.Date"/> 會(huì)對(duì)msg進(jìn)行檢查和date進(jìn)行檢查 4:使用none模式 是指對(duì)所有屬性不進(jìn)行依賴檢查 如: <bean id="DateHello" class="DateHelloWorld" autowire="autodetect" dependency-check="none"> </bean> <bean id="date" class="java.util.Date"/> 不會(huì)對(duì)msg進(jìn)行檢查和date進(jìn)行檢查 總結(jié):一般情況下依賴檢查和自動(dòng)裝配結(jié)合使用,當(dāng)bean屬性都有默認(rèn)值或不需要對(duì)bean的屬性是否被設(shè)置到bean上檢查時(shí),依賴檢查的作用就不大了 ----------------------------------------------------------------------- 集合的注入方式 對(duì)于集合List Set Map Props元素則有不同的配置方式 1:List public class HelloWorld{ //定義一個(gè)List變量msg List msg=null; public void setMsg(List msg){ this.msg = msg; } } xml文件: <bean id="Hello" class="HelloWorld"> <property name="msg"> <list> <value>Hello World!</value> <value>Hello World2!</value> </list> </property> </bean>
2:set
public class HelloWorld{ //定義一個(gè)Set變量msg Set msg=null; public void setMsg(Set msg){ this.msg = msg; } } xml文件: <bean id="Hello" class="HelloWorld"> <property name="msg"> <set> <value>Hello World!</value> <value>Hello World2!</value> </set> </property> </bean> 3:map public class HelloWorld{ //定義一個(gè)Map變量msg Map msg=null; public void setMsg(Map msg){ this.msg = msg; } } xml文件: <bean id="Hello" class="HelloWorld"> <property name="msg"> <map> <entry key="h1"> <value>Hello World!</value> </entry> <entry key="h2"> <value>Hello World2!</value> </entry> </map> </property> </bean>
4:properties public class HelloWorld{ //定義一個(gè)properties變量msg Properties msg; public void setMsg(Properties msg){ this.msg = msg; } } xml文件: <bean id="Hello" class="HelloWorld"> <property name="msg"> <props> <prop key ="h1">Hello World!</prop> <prop key ="h2">Hello World2!</prop> </props> </property> </bean> --------------------------------------------------------------- Spring AOP(Aspect Oriented Programming) 應(yīng)用程序通常包含兩種代碼:一是核心業(yè)務(wù)代碼,一是和業(yè)務(wù)關(guān)系不大的代碼如日志、事物處理等。 AOP的思想就是使這兩種代碼分離,從而降低了兩種代碼的偶合性,達(dá)到了易于重用和維護(hù)的目的。 AOP和OOP: 在AOP里,每個(gè)關(guān)注點(diǎn)的實(shí)現(xiàn)并不知道是否有其他關(guān)注點(diǎn)關(guān)注它,這是AOP和OOP的主要區(qū)別, 在AOP里組合的流向是從橫切關(guān)注點(diǎn)到主關(guān)注點(diǎn),在OOP中組合流向是從主關(guān)注點(diǎn)到橫切關(guān)注點(diǎn)。 AOP和OOP所關(guān)注的對(duì)象不同,AOP是OOP有益的補(bǔ)充,不是對(duì)立面。 AOP的3個(gè)關(guān)鍵概念: 1:切入點(diǎn):(PiontCut) 連接點(diǎn)(Jion piont):是指程序運(yùn)行中的某個(gè)階段,如方法的調(diào)用、異常的拋出等。 PiontCu就是Jion piont點(diǎn)的集合,它是程序中需要注入的Advice的集合。指明Advice 在什么 條件下才被觸發(fā)。 2:通知(Advice): 某個(gè)連接點(diǎn)采用的處理邏輯,也就是向連接點(diǎn)注入的代碼。 3:Advisor 是PiontCut和Advice的配置器,它包含PiontCut和Advice,是把Advice注入到PiontCut位置的代碼。 Spring 的3種切入點(diǎn)的實(shí)現(xiàn): 1:靜態(tài)切入點(diǎn): 靜態(tài)切入點(diǎn)只限于給定的方法和目標(biāo)類。不考慮方法的參數(shù)。 2:動(dòng)態(tài)切入點(diǎn): 動(dòng)態(tài)切入點(diǎn)不僅限于給定的方法和目標(biāo)類,還可以指定方法的參數(shù)。 動(dòng)態(tài)切入點(diǎn)有很大的性能損耗,一般很少使用。 3:自定義切入點(diǎn): 正在發(fā)展 Spring 的通知: 1:Intercdption Around通知 Intercdption Around在JiontPoint的前后執(zhí)行。實(shí)現(xiàn)Intercdption Around通知要實(shí)現(xiàn) MethodInterceptor接口,示例代碼如下: public class LoginInterceptor implements MethodInterceptor{ public Object invoke(MenthodInvocation invocation) throws Throwable{ System.out.println("開始審核數(shù)據(jù)"); Object result = invocation.proceed(); System.out.println("審核數(shù)據(jù)結(jié)束"); return result; } } 2:Before通知 Before通知在JiontPoint的前執(zhí)行。實(shí)現(xiàn)Befored通知要實(shí)現(xiàn) MethodBeforeAdvice接口,示例代碼如下: public class LoginBeforeAdvice implements MethodBeforeAdvice{ public void Beforee(Menthod m,Object [] atgs,Object target) throws Throwable{ System.out.println("開始審核數(shù)據(jù)"); } } 3:After Return 通知 After Return通知在JiontPoint后執(zhí)行。實(shí)現(xiàn)After Returnd通知要實(shí)現(xiàn) AfterReturningAdvice接口,示例代碼如下: public class LoginAfterAdvice implements AfterReturningAdvice{ public void AfterReturning(Menthod m,Object [] atgs,Object target) throws Throwable{ System.out.println("審核數(shù)據(jù)結(jié)束"); } } 4:Throw通知 Throw通知在JiontPoint拋出異常時(shí)執(zhí)行。實(shí)現(xiàn)Throw通知要實(shí)現(xiàn) ThrowAdvice接口,示例代碼如下: public class LoginThrowAdvice implements ThrowAdvice{ public void AfterThrowing(RemoteException ex) throws Throwable{ System.out.println("審核數(shù)據(jù)異常"); } } 5:Introduction 通知 Introduction通知在JiontPoint 調(diào)用完畢后執(zhí)行。實(shí)現(xiàn)Introduction通知要實(shí)現(xiàn) IntroductionAdvisor接口和IntroductionInterceptor接口。 用ProxyFactoryBean創(chuàng)建AOP代理 使用org.springfamework.aop.framework.ProxyFactoryBean是創(chuàng)建AOP代理的基本方式。 1:使用ProxyFactoryBean代理目標(biāo)類中的所有方法 示例代碼: <beans> <bean id="log" class="logAround"/> <bean id="logBefore" class="logBefore"/> <bean id="logAfter" class="logAfter"/> <bean id="logThrow" class="logThrow"/> <bean id="timebook" class="TimeBook"/> <!-設(shè)定代理類--> <bean id="logProxy" class ="org.springframework.aop.framework.ProxyFactoryBean"> <!--代理的是接口--> <property name="proxyInterface"> <value>TimeBookInterface</value> </property> <!--要代理的目標(biāo)類--> <property name="target"> <ref bean="timebook"/> </property> <!--程序中的Advice--> <property name="interceptorNames"> <list> <value>logBefore</value> <value>logAfter</value> <value>logThrow</value> </list> </property> </bean> </beans> 2:使用ProxyFactoryBean代理目標(biāo)類中的指定方法 示例代碼: <beans> <bean id="log" class="logAround"/> <bean id="logBefore" class="logBefore"/> <bean id="logAfter" class="logAfter"/> <bean id="logThrow" class="logThrow"/> <bean id="timebook" class="TimeBook"/> <!--代理目標(biāo)類的指定方法--> <bean id ="logAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice"> <ref bean="log"/> </property> <!--指定要代理的方法--> <property name="patterns"> <value>doCheck*</value> </property> </bean> <!-設(shè)定代理類--> <bean id="logProxy" class ="org.springframework.aop.framework.ProxyFactoryBean"> <!--代理的是接口--> <property name="proxyInterfaces"> <value>TimeBookInterface</value> </property> <!--要代理的目標(biāo)類--> <property name="target"> <ref bean="timebook"/> </property> <!--程序中的Advice--> <property name="interceptorNames"> <list> <value>logAdvisor</value> </list> </property> </bean> </beans> --------------------------------------------------------- 正則表達(dá)式: 1:.表示可以匹配任何一個(gè)字符 2:[]表示只有[]里指定的字符才能匹配 3:*表示匹配次數(shù) 4:?表示可以匹配1或0次 5:\是正則表達(dá)式的連接符 --------------------------------------------------------------- Spring 中兩種AOP代理方式 1:動(dòng)態(tài)代理 動(dòng)態(tài)代理是指代理的是接口,Spring默認(rèn)的是動(dòng)態(tài)代理 2:CGLIB代理 <beans> <bean id="log" class="logAround"/> <bean id="logBefore" class="logBefore"/> <bean id="logAfter" class="logAfter"/> <bean id="logThrow" class="logThrow"/> <bean id="timebook" class="TimeBook"/> <bean id="logProxy" class ="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyTargetClass"> <value>true</value> </property> <property name="target"> <ref bean="timebook"/> </property> <property name="interceptorNames"> <list> <value>logBefore</value> <value>logAfter</value> <value>logThrow</value> </list> </property> </bean> </beans> ----------------------------------------------------------------------- Spring 中的自動(dòng)代理方式 自動(dòng)代理可以跨越多個(gè)類,不管哪個(gè)類中的方法只要符合要求都可以代理 <beans> <bean id="log" class="logAround"/> <bean id="logBefore" class="logBefore"/> <bean id="logAfter" class="logAfter"/> <bean id="logThrow" class="logThrow"/> <bean id="timebook" class="TimeBook"/> <bean id="timework" class="TimeWork"/> <!--使用自動(dòng)代理--> <bean id="autoProxy" class ="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/> <bean id="logBeforAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="advice"> <ref bean="logBefore"/> </property> <property name="patterns"> <value>.*do.*</value> </property> </bean> </beans> ------------------------------------------------------------ Spring中的事務(wù)處理 事務(wù)處理是由多個(gè)步驟組成,這些步驟之間有一定的邏輯關(guān)系,作為一個(gè)整體的操作過(guò)程,所有的步驟必須同時(shí)成功或失敗。 1:提交 當(dāng)所有的操作步驟都被完整執(zhí)行后,稱為該事物被提交。 2:回滾 由于某個(gè)操作失敗,導(dǎo)致所有的步驟都沒(méi)被提交則事物必須回滾,回到事物執(zhí)行前的狀態(tài)。 事務(wù)的特性: ACID:原子性(Atomicity)一致性(Consistency)隔離性(Isolation)持久性(Durablity) Spring中的事務(wù)處理是基于動(dòng)態(tài)AOP機(jī)制的實(shí)現(xiàn)。 1:編程式事務(wù)處理: spring 提供的TransactionTemplate能夠以編程的方式實(shí)現(xiàn)事務(wù)控制。 HelloADO.java: public int create(String msg){ DefaultTransactionDefinition def = new DefaultTransactionDefinition(); TransactionStatus status = transactionManager.getTransaction(def); try{ JdbcTemplate jt = new JdbcTemplate(dataSource); int i=jt.update("insert into st(name,password) values(‘zz‘,‘zz‘)"); return i; }catch (Exception e){ transactionManager.rollback(status); return 0; } finally { transactionManager.commit(status); } } applicationContext.xml <beans> <bean id ="dataSource" class ="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost:3306/newdb</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value>lxl</value> </property> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean> <bean id="helloDAO" class ="HelloDAO"> <property name="dataSource"> <ref bean="dataSource"/> </property> <property name="transactionManager"> <ref bean="transactionManager"/> </property> </bean> </beans> 2:聲明式事務(wù)處理: HelloADO.java: public class HelloDAO { private DataSource dataSource ; private JdbcTemplate jdbcTemplate; public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; jdbcTemplate = new JdbcTemplate(dataSource); } public void create(String name){ jdbcTemplate.update("insert into st(name,password)values(‘lxl‘,‘lxl‘)"); } } applicationContext.xml <beans> <bean id ="dataSource" class ="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost:3306/newdb</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value>lxl</value> </property> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean> <bean id="helloDAO" class ="HelloDAO"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean> <!-- 聲明式事務(wù)處理--> <bean id="helloDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"> <ref bean="transactionManager"/> </property> <property name="target"> <ref bean="helloDAO"/> </property> <property name="transactionAttributes"> <props> <!-- 對(duì)create方法進(jìn)行事務(wù)管理,PROPAGATION_REQUIRED表示如果沒(méi)有事務(wù)就新建一個(gè)事務(wù)--> <prop key="create*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> </beans> ------------------------------------------------------- Spring持久層的封裝 通過(guò)xml實(shí)現(xiàn)DataSource數(shù)據(jù)源的注入有3種方式: 1:使用spring自帶的DriverManagerDataSource <beans> <bean id ="dataSource" class ="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost:3306/newdb</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value>lxl</value> </property> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean> <bean id="helloDAO" class ="HelloDAO"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean> <!-- 聲明式事務(wù)處理--> <bean id="helloDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"> <ref bean="transactionManager"/> </property> <property name="target"> <ref bean="helloDAO"/> </property> <property name="transactionAttributes"> <props> <!-- 對(duì)create方法進(jìn)行事務(wù)管理,PROPAGATION_REQUIRED表示如果沒(méi)有事務(wù)就新建一個(gè)事務(wù)--> <prop key="create*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> </beans> 2:使用DBCP連接池 <beans> <bean id ="dataSource" class ="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost:3306/newdb</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value>lxl</value> </property> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean> <bean id="helloDAO" class ="HelloDAO"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean> <!-- 聲明式事務(wù)處理--> <bean id="helloDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"> <ref bean="transactionManager"/> </property> <property name="target"> <ref bean="helloDAO"/> </property> <property name="transactionAttributes"> <props> <!-- 對(duì)create方法進(jìn)行事務(wù)管理,PROPAGATION_REQUIRED表示如果沒(méi)有事務(wù)就新建一個(gè)事務(wù)--> <prop key="create*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> </beans> 3:使用Tomcat提供的JNDI <beans> <bean id ="dataSource" class ="org.springframework.jndi.JndiObjectFactoryBean"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost:3306/newdb</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value>lxl</value> </property> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean> <bean id="helloDAO" class ="HelloDAO"> <property name="dataSource"> <ref bean="dataSource"/> </property> </bean> <!-- 聲明式事務(wù)處理--> <bean id="helloDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"> <ref bean="transactionManager"/> </property> <property name="target"> <ref bean="helloDAO"/> </property> <property name="transactionAttributes"> <props> <!-- 對(duì)create方法進(jìn)行事務(wù)管理,PROPAGATION_REQUIRED表示如果沒(méi)有事務(wù)就新建一個(gè)事務(wù)--> <prop key="create*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> </beans> ------------------------------------------------------- Spring 和 Struts的整合使用 Spring 和 Struts的整合有3種方式: 1:通過(guò)Spring的ActionSupport類 2:通過(guò)Spring的DelegatingRequestProcessor類 3:通過(guò)Spring的DelegatingActionProxy類 a: 通過(guò)Spring的ActionSupport類:(對(duì)應(yīng)工程:SpringStruts) 方法是Action類不再繼承Struts的Action而是繼承Spring提供的ActionSupport, 然后在Action中獲得Spring的ApplicationContext. 缺點(diǎn)是Action和Spring耦合在一起,而且Action不在Spring控制之內(nèi)。也不能處理多個(gè)動(dòng)作在一個(gè)Action中的情況。 步驟: 1:加入spring. 2: 加入struts 3:修改struts配置文件struts-config.xml文件注冊(cè)ContextLoaderPlugIn插件。 <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml"/> </plug-in> 4:創(chuàng)建Action時(shí): (1) 處,我通過(guò)從 Spring 的 ActionSupport 類而不是 Struts 的 Action 類進(jìn)行擴(kuò)展,創(chuàng)建了一個(gè)新的 Action。 (2) 處,我使用 getWebApplicationContext() 方法獲得一個(gè) ApplicationContext。為了獲得業(yè)務(wù)服務(wù),我使用在 (3) 處 查找一個(gè) Spring bean。 //(1) public class LoginAction extends ActionSupport { public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { LoginForm loginForm = (LoginForm) form; // TODO Auto-generated method stub //(2) ApplicationContext ac = this.getWebApplicationContext();//獲得ApplicationContext //(3) LoginInterface li = (LoginInterface)ac.getBean("loginInterface");//獲得Bean boolean you = li.checkUser(loginForm.getName(),loginForm.getPassword()); if(you){ request.setAttribute("msg","welcome"); return mapping.findForward("show"); } else{ request.setAttribute("msg","failed"); return mapping.findForward("show"); } } } applicationContext.xml: <beans> <bean id="loginInterface" class="spring.LoginImp"/> </beans> b: 通過(guò)Spring的DelegatingRequestProcessor類:(對(duì)應(yīng)工程:SpringStruts2) 方法是Spring的DelegatingRequestProcessor代替Struts的RequstProcessor, 把Struts的Action置于Spring的的控制之下 缺點(diǎn)是開發(fā)人員可以自己定義RequestProcessor這樣就需要手工整合Struts和Spring。 步驟: 1:加入spring. 2: 加入struts 3:修改struts配置文件struts-config.xml文件注冊(cè)ContextLoaderPlugIn插件。 <struts-config> <form-beans > <form-bean name="loginForm" type="com.yourcompany.struts.form.LoginForm" /> </form-beans> <action-mappings > <action attribute="loginForm" input="/login.jsp" name="loginForm" path="/login" scope="request" type="com.yourcompany.struts.action.LogAction"> <forward name="show" path="/show.jsp" /> </action> </action-mappings> <controller processorClass="org.springframework.web.struts.DelegatingRequestProcessor"></controller> <message-resources parameter="com.yourcompany.struts.ApplicationResources" /> <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml"/> </plug-in> </struts-config> 4:創(chuàng)建Action時(shí): public class LogAction extends Action { private LoginInterface logInterface; public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { LoginForm loginForm = (LoginForm) form; // TODO Auto-generated method stub boolean you = logInterface.checkUser(loginForm.getName(),loginForm.getPassword()); if(you){ request.setAttribute("msg","welcome"); return mapping.findForward("show"); } else{ request.setAttribute("msg","failed"); return mapping.findForward("show"); } } public void setLogInterface(LoginInterface logInterface) { this.logInterface = logInterface; } }
applicationContext.xml: <beans> <bean id="loginInterface" class="spring.LoginImp"/> <!--要和Struts的路徑對(duì)應(yīng)--> <bean name="/login" class="com.yourcompany.struts.action.LogAction"> <property name="logInterface"> <ref bean="loginInterface"/> </property> </bean> </beans> c: 通過(guò)Spring的DelegatingActionProxy類:(對(duì)應(yīng)工程:SpringStruts3) 方法是Spring的DelegatingActionProxy代替Struts的Action, 把Struts的Action置于Spring的的控制之下 這種方式最靈活強(qiáng)大。并且它可以利用 Spring AOP 特性的優(yōu)點(diǎn)。 步驟: 1:加入spring. 2: 加入struts 3:修改struts配置文件struts-config.xml文件注冊(cè)ContextLoaderPlugIn插件。 <struts-config> <data-sources /> <form-beans > <form-bean name="loginForm" type="com.yourcompany.struts.form.LoginForm" /> </form-beans> <action-mappings > <action attribute="loginForm" input="/form/login.jsp" name="loginForm" path="/login" scope="request" type="org.springframework.web.struts.DelegatingActionProxy"> <forward name="show" path="/show.jsp" /> </action> </action-mappings> <message-resources parameter="com.yourcompany.struts.ApplicationResources" /> <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml"/> </plug-in> </struts-config>
4:創(chuàng)建Action時(shí): public class LogAction extends Action { private LoginInterface logInterface; public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { LoginForm loginForm = (LoginForm) form; // TODO Auto-generated method stub boolean you = logInterface.checkUser(loginForm.getName(),loginForm.getPassword()); if(you){ request.setAttribute("msg","welcome"); return mapping.findForward("show"); } else{ request.setAttribute("msg","failed"); return mapping.findForward("show"); } } public void setLogInterface(LoginInterface logInterface) { this.logInterface = logInterface; } }
applicationContext.xml: <beans> <bean id="loginInterface" class="spring.LoginImp"/> <!--要和Struts的路徑對(duì)應(yīng)--> <bean name="/login" class="com.yourcompany.struts.action.LogAction"> <property name="logInterface"> <ref bean="loginInterface"/> </property> </bean> </beans> 攔截 Struts 通過(guò)將 Struts 動(dòng)作委托給 Spring 框架而整合 Struts 和 Spring 的一個(gè)主要的優(yōu)點(diǎn)是:您可以將 Spring 的 AOP 攔截器應(yīng)用于您的 Struts 動(dòng)作。通過(guò)將 Spring 攔截器應(yīng)用于 Struts 動(dòng)作,您可以用最小的代價(jià)處理橫切關(guān)注點(diǎn)。 雖然 Spring 提供很多內(nèi)置攔截器,但是我將向您展示如何創(chuàng)建自己的攔截器并把它應(yīng)用于一個(gè) Struts 動(dòng)作。為了使用攔截器,您需要做三件事: 1: 創(chuàng)建攔截器。
2:注冊(cè)攔截器。
3:聲明在何處攔截代碼。 這看起來(lái)非常簡(jiǎn)單的幾句話卻非常強(qiáng)大。例如,在清單 7 中,我為 Struts 動(dòng)作創(chuàng)建了一個(gè)日志記錄攔截器。 這個(gè)攔截器在每個(gè)方法調(diào)用之前打印一句話: 清單 7. 一個(gè)簡(jiǎn)單的日志記錄攔截器 public class LoggingInterceptor implements MethodBeforeAdvice { public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println("logging before!"); } }
這個(gè)攔截器非常簡(jiǎn)單。before() 方法在攔截點(diǎn)中每個(gè)方法之前運(yùn)行。在本例中,它打印出一句話,其實(shí)它可以做您想做的任何事。下一步就是在 Spring 配置文件中注冊(cè)這個(gè)攔截器,如清單 8 所示: 清單 8. 在 Spring 配置文件中注冊(cè)攔截器 <beans> <bean id="bookService" class="ca.nexcel.books.business.BookServiceImpl"/> <bean name="/searchSubmit" class="ca.nexcel.books.actions.SearchSubmit"> <property name="bookService"> <ref bean="bookService"/> </property> </bean> <!-- Interceptors --> <bean name="logger" class="ca.nexcel.books.interceptors.LoggingInterceptor"/> |(1) <!-- AutoProxies -->
<bean name="loggingAutoProxy"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
|(2) <property name="beanNames"> <value>/searchSubmit</value> |(3) </property> <property name="interceptorNames"> <list> <value>logger</value> |(4) </list> </property> </bean> </beans>
您可能已經(jīng)注意到了,清單 8 擴(kuò)展了 清單 6 中所示的應(yīng)用程序以包含一個(gè)攔截器。具體細(xì)節(jié)如下: 在 (1) 處,我注冊(cè)了這個(gè)攔截器。
在 (2) 處,我創(chuàng)建了一個(gè) bean 名稱自動(dòng)代理,它描述如何應(yīng)用攔截器。還有其他的方法定義攔截點(diǎn),但是這種方法常見而簡(jiǎn)便。
在 (3) 處,我將 Struts 動(dòng)作注冊(cè)為將被攔截的 bean。如果您想要攔截其他的 Struts 動(dòng)作,則只需要在 "beanNames" 下面創(chuàng)建附加的 <value> 標(biāo)記。
在 (4) 處,當(dāng)攔截發(fā)生時(shí),我執(zhí)行了在 (1) 處創(chuàng)建的攔截器 bean 的名稱。這里列出的所有攔截器都應(yīng)用于“beanNames”。 就是這樣。就像這個(gè)例子所展示的,將您的 Struts 動(dòng)作置于 Spring 框架的控制之下,為處理您的 Struts 應(yīng)用程序提供了一系列全新的選擇。在本例中,使用動(dòng)作委托可以輕松地利用 Spring 攔截器提高 Struts 應(yīng)用程序中的日志記錄能力。 ----------------------------------------------------------------------------------------------- Struts + Spring + Hibernate的整合使用 開發(fā)工具:Eclipse3.1,MyEclipse4.0 ,Tomcat5.0.28,mysql-4.0.18 開發(fā)步驟: 1:創(chuàng)建web projectSSHlogin 加入struts1.2
創(chuàng)建loginForm選擇DynaValidatorForm,加入password,username,創(chuàng)建jsp文件打上鉤,將路徑改為
/login.jsp,然后下一步,改LoginAction的Input source改為/login.jsp,加入 <forward
name="ok" path="ok.jsp" />點(diǎn)擊完成 完成后修改struts-config.xml文件加入 <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml" /> </plug-in> 拷貝validator-rules.xml和validation.xml到WEB-INF目錄中 在validation.xml文件中加入 <form-validation> <formset> <form name="loginForm"> <field property="username" depends="required"> <arg0 key="prompt.username" /> </field> <field property="password" depends="required"> <arg0 key="prompt.password" /> </field> </form> </formset> </form-validation> validator-rules.xml文件直接考一個(gè)就行。 編輯資源文件“ApplicationResources.properties” 增加以下內(nèi)容 prompt.username=User Name prompt.password=User Password errors.required={0} is required. 修改LoginAction.java文件的execute方法,內(nèi)容如下 public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { DynaValidatorForm loginForm = (DynaValidatorForm) form; String username=loginForm.getString("username"); String password=loginForm.getString("password"); if(username.equals("test")||password.equals("test")){ return mapping.findForward("indexGo"); }else{ return mapping.getInputForward(); } } 好了,現(xiàn)在可以啟動(dòng)Tomcat進(jìn)行測(cè)試了如果不輸入任何數(shù)據(jù)而直接提交表單的話就可以看到效果了。 好了,如果沒(méi)有什么問(wèn)題的話就繼續(xù)往下看吧,如果有問(wèn)題的話就得往上看了^_^ 2:加入Spring框架 在這里我將Spring所有的包全部加載進(jìn)去,因?yàn)槲疫€不知道具體用到哪些類,全部加進(jìn)去方便點(diǎn) 單選框選第二個(gè),這樣的話所有的類庫(kù)和標(biāo)簽等都將拷貝到項(xiàng)目中去,這樣方便以后的布署 下一步后是創(chuàng)建配置文件,將文件放到“WebRoot/WEB-INF”目錄下,文件名稱為“applicationContext.xml” 配置struts-config.xml文件,添加(spring)的插件 <plug-in className="org.springframework.web.struts.ContextLoaderPlugIn"> <set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml" /> </plug-in> 修改LoginAction配置 原: <action attribute="loginForm" input="/login.jsp" name="loginForm" path="/login" scope="request" validate="true" type="com.test.struts.action.LoginAction" > <forward name="ok" path="ok.jsp" /> </action> </action-mappings> 改為: <action attribute="loginForm" input="/login.jsp" name="loginForm" path="/login" scope="request" validate="true" type="org.springframework.web.struts.DelegatingActionProxy"> <forward name="ok" path="ok.jsp" /> </action> </action-mappings> 這里將使用spring的代理器來(lái)對(duì)Action進(jìn)行控制 當(dāng)提交到/login.do是將控制權(quán)交給了spring,然后由spring來(lái)決定是否轉(zhuǎn)回到struts的Action 現(xiàn)在來(lái)配置spring <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www./dtd/spring-beans.dtd"> <beans> <bean name="/login" class="com.test.struts.action.LoginAction" singleton="false"></bean> </beans> 好了,現(xiàn)在可以啟動(dòng)Tomcat進(jìn)行測(cè)試了如果沒(méi)有什么問(wèn)題的話就繼續(xù)往下看吧,如果有問(wèn)題的話就得往上看了^_^ 3:創(chuàng)建Hibernate框架 建立數(shù)據(jù)庫(kù)在 這里我使用的是mysql4.1.18 CREATE TABLE `user` ( `ID` int(11) NOT NULL auto_increment, `USERNAME` varchar(50) NOT NULL default ‘‘, `PASSWORD` varchar(50) NOT NULL default ‘‘, PRIMARY KEY (`ID`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; 添加記錄 insert into user (USERNAME,PASSWORD) values (‘test‘,‘test‘) 在配置界面中配置數(shù)據(jù)庫(kù)的連接部份,重要的是點(diǎn)擊鏈接將jdbc驅(qū)動(dòng)拷貝到lib目錄中 使用MyEclipse的數(shù)據(jù)Database Explorer工具創(chuàng)建User.hmb.xml、AbstractUser.java、User.java映射文件 創(chuàng)建UserDAO.java、UserDAOImp.java UserDAO.java: public interface UserDAO { public abstract boolean isValidUser(String username, String password); } UserDAOImp.java: import java.util.List; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; public class UserDAOImp extends HibernateDaoSupport implements UserDAO { private static String hql = "from User u where u.username=? and password=?"; public boolean isValidUser(String username, String password) { String[] userlist=new String[2]; userlist[0]=username; userlist[1]=password; List userList = this.getHibernateTemplate().find(hql,userlist); if (userList.size() > 0) { return true; } return false; } }
修改LoginAction.java文件,使用userDao的方法來(lái)進(jìn)行用戶驗(yàn)證 package com.test.struts.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.validator.DynaValidatorForm; import com.test.UserDAO; public class LoginAction extends Action { private UserDAO userDAO; public UserDAO getUserDAO() { return userDAO; } public void setUserDAO(UserDAO userDAO) { this.userDAO = userDAO; } public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { DynaValidatorForm loginForm = (DynaValidatorForm) form; // TODO Auto-generated method stub String username = (String) loginForm.get("username"); String password = (String) loginForm.get("password"); loginForm.set("password", null); if (userDAO.isValidUser(username,password)) { return mapping.findForward("ok"); } else { return mapping.getInputForward(); } } } 現(xiàn)在剩下最后的spring配置了 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www./dtd/spring-beans.dtd"> <beans> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> </property> <property name="url"> <value>jdbc:mysql://localhost/test</value> </property> <property name="username"> <value>root</value> </property> <property name="password"> <value>lxl</value> </property> </bean> <!-- 配置sessionFactory, 注意這里引入的包的不同 --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref local="dataSource" /> </property> <property name="mappingResources"> <list> <value>com/test/Hibernate/User.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">true</prop> </props> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref local="sessionFactory" /> </property> </bean> <bean id="userDAO" class="com.test.UserDAOImp"> <property name="sessionFactory"> <ref local="sessionFactory" /> </property> </bean> <bean id="userDAOProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"> <ref bean="transactionManager" /> </property> <property name="target"> <ref local="userDAO" /> </property> <property name="transactionAttributes"> <props> <prop key="insert*">PROPAGATION_REQUIRED</prop> <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="is*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> <bean name="/login" class="com.test.struts.action.LoginAction" singleton="false"> <property name="userDAO"> <ref bean="userDAOProxy" /> </property> </bean> </beans> 現(xiàn)在可以進(jìn)行測(cè)試了! 在編寫代碼有配置內(nèi)容時(shí)一定要注意 hibernate 和 hibernate3 ,這兩個(gè)包的名字就只差一個(gè)字,千萬(wàn)不要有錯(cuò),否則找錯(cuò)誤可是很難的。 注意要把spring-hibernate.jar或者把spring.jar加到工程lib里 工程原碼見SSHlogin
本文來(lái)源:http://blog.csdn.net/xwchen/archive/2007/04/06/1554245.aspx 本文地址:http://www./info/120271.html
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1562865
|