Java ee 企業(yè)應(yīng)用開發(fā):第7章 在Spring中管理事務(wù)_第1頁
Java ee 企業(yè)應(yīng)用開發(fā):第7章 在Spring中管理事務(wù)_第2頁
Java ee 企業(yè)應(yīng)用開發(fā):第7章 在Spring中管理事務(wù)_第3頁
Java ee 企業(yè)應(yīng)用開發(fā):第7章 在Spring中管理事務(wù)_第4頁
Java ee 企業(yè)應(yīng)用開發(fā):第7章 在Spring中管理事務(wù)_第5頁
已閱讀5頁,還剩27頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、第7章 在SPRING中管理事務(wù)7.1 知識點(diǎn):AOP簡介7.2 開發(fā)步驟7.1 知識點(diǎn):AOP簡介7.1.1 從代理機(jī)制初探AOP從一個(gè)簡單常見的例子開始。這個(gè)例子當(dāng)中含有日志動(dòng)作,程序中經(jīng)常需要為某些動(dòng)作或事件作下記錄,以便隨時(shí)檢查程序運(yùn)行過程和排除錯(cuò)誤的信息。來看一個(gè)簡單的例子,當(dāng)需要在執(zhí)行某些方法時(shí)留下日志信息,直覺的,可能會這樣寫。import java.util.logging.*;public class HelloSpeakerpirvate Logger logger=Logger.getLogger(this.getClass().getName();public void

2、 hello(String name) logger.log(Level.INFO,”hello method starts”);/方法執(zhí)行開始時(shí)留下日志 Sytem.out.println(”hello, ”+name); /程序的主要功能 Logger.log(Level.INFO, ”hello method ends”);/方法執(zhí)行完畢時(shí)留下日志7.1.1 從代理機(jī)制初探AOP在HelloSpeaker類中,當(dāng)執(zhí)行hello()方法時(shí),程序員希望開始執(zhí)行該方法與執(zhí)行完畢時(shí)都會留下日志,最簡單的做法是用上面的程序設(shè)計(jì),在方法執(zhí)行的前后加上日志動(dòng)作。然而對于HelloSpeaker來說,日

3、志的這種動(dòng)作并不屬于HelloSpeaker邏輯,這使得HelloSpeaker增加了額外的職責(zé)。如果程序中這種日志動(dòng)作到處都有需求,以上的寫法勢必造成程序員必須到處撰寫這些日志動(dòng)作的代碼。這將使得維護(hù)日志代碼的困難加大。如果需要的服務(wù)不只是日志動(dòng)作,有一些非類本身職責(zé)的相關(guān)動(dòng)作也混入到類中,比如權(quán)限檢查,事務(wù)管理等等,會使得類的負(fù)擔(dān)加重,甚至混淆類本身的職責(zé)。另一方面,使用以上的寫法,如果有一天不再需要日志(或權(quán)限檢查,交易管理等)的服務(wù),將需要修改所有留下日志動(dòng)作的程序,無法簡單地就將這些相關(guān)服務(wù)從現(xiàn)有的程序中移除。可以使用代理(Proxy)機(jī)制來解決這個(gè)問題,有兩種代理方式:靜態(tài)代理(s

4、tatic proxy)和動(dòng)態(tài)代理(dynamic proxy)。在靜態(tài)代理的實(shí)現(xiàn)中,代理類與被代理的類必須實(shí)現(xiàn)同一個(gè)接口,在代理類中可以實(shí)現(xiàn)記錄等相關(guān)服務(wù),并在需要的時(shí)候再呼叫被代理類。這樣被代理類中就可以僅僅保留業(yè)務(wù)相關(guān)的職責(zé)了。7.1.1 從代理機(jī)制初探AOP舉個(gè)簡單的例子,首先定義一個(gè)IHello接口:IHello.java代碼如下:public interface Ihello public void hello(String name);然后讓實(shí)現(xiàn)業(yè)務(wù)邏輯的HelloSpeaker類別實(shí)現(xiàn)Ihello接口,HelloSpeaker.java代碼如下:public class Hel

5、loSpeaker implements Ihello public void hello(String name) Sytem.out.println(”hello,”+name); 可以看到,在HelloSpeaker類中沒有任何日志的代碼插入其中,日志服務(wù)的實(shí)現(xiàn)將被放到代理類中,代理類同樣要實(shí)現(xiàn)IHello接口:7.1.1 從代理機(jī)制初探AOPHelloProxy.java代碼如下:public class HelloProxy implements Ihelloprivate Logger logger=Logger.getLogger(this.getClass().getName(

6、);private Ihello helloObject;public HelloProxy(Ihello helloObject) this.helloObject=helloObject;public void hello(String name) log(”hello method starts”);/日志服務(wù) helloObject.hello(name);/執(zhí)行業(yè)務(wù)邏輯 log(”hello method ends”);/日志服務(wù) private void log(String ms) logger.log(Level.INFO,msg);7.1.1 從代理機(jī)制初探AOP在Hello

7、Proxy類的hello()方法中,真正實(shí)現(xiàn)業(yè)務(wù)邏輯前后可以安排記錄服務(wù),可以實(shí)際撰寫一個(gè)測試程序來看看如何使用代理類。public class ProxyDemopublic static void main(String args) IHello proxy=new HelloProxy(new HelloSpeaker(); proxy.hello(”Justin”); 這是靜態(tài)代理的基本示例,但是可以看到,代理類的一個(gè)接口只能服務(wù)于一種類型的類,而且如果要代理的方法很多,勢必要為每個(gè)方法進(jìn)行代理,靜態(tài)代理在程序規(guī)模稍大時(shí)就必定無法勝任。7.1.2 動(dòng)態(tài)代理在JDK1.3之后加入了可協(xié)助

8、開發(fā)動(dòng)態(tài)代理功能的API等相關(guān)類別,不需要為特定類和方法編寫特定的代理類,使用動(dòng)態(tài)代理,可以使得一個(gè)處理者(Handler)為各個(gè)類服務(wù)。要實(shí)現(xiàn)動(dòng)態(tài)代理,同樣需要定義所要代理的接口:IHello.java代碼如下:public interface IHellopublic void hello(String name);然后讓實(shí)現(xiàn)業(yè)務(wù)邏輯的HelloSpeaker類別要實(shí)現(xiàn)IHello接口,如HelloSpeaker.java代碼如下:public class HelloSpeaker implements IHello public void hello(String name) Syste

9、m.out.println(”Hello, ”+name); 7.1.2 動(dòng)態(tài)代理寫一個(gè)測試程序,如果要使用LogHandler的bind()方法來綁定被代理類。ProxyDemo.java代碼如下:public class ProxyDemo public static void main(String args)LogHandler logHandler=new LogHandler();IHello helloProxy=(IHello)logHandler.bind(new HelloSpeaker();helloProxy.hello(”Justin”);HelloSpeaker本身

10、的職責(zé)是顯示文字,卻必須插入日志動(dòng)作,這使得HelloSpeaker的職責(zé)加重。在AOP的是術(shù)語中,日志的程序代碼橫切(cross-cutting)到HelloSpeaker的程序執(zhí)行流程中,日志這樣的動(dòng)作在AOP中被稱為橫切關(guān)注點(diǎn)(cross-cutting concern)。 使用代理類將記錄與業(yè)務(wù)邏輯無關(guān)的動(dòng)作提取出來,設(shè)計(jì)為一個(gè)服務(wù)類,如同前面的范例HelloProxy或者LogHandler,這樣的類稱之為切面(aspect)。AOP中的aspect所指的可以是像日志等這類的動(dòng)作或服務(wù),將這些動(dòng)作(cross-cutting concern)設(shè)計(jì)為通用,不介入特定業(yè)務(wù)類的一個(gè)職責(zé)清楚

11、的Aspect類,這就是所謂的Aspect-oriented programming,AOP。7.1.3 AOP術(shù)語與概念介紹AOP術(shù)語和概念。 Cross-cutting concer在DynamicProxyDemo的例子中,記錄的動(dòng)作原先被橫切(Cross-cutting)到HelloSpeaker本身所負(fù)責(zé)的業(yè)務(wù)流程中。另外類似于日志這類的動(dòng)作,如安全檢查、事務(wù)等服務(wù),在一個(gè)應(yīng)用程序中常被安排到各個(gè)類的處理流程之中。這些動(dòng)作在AOP的術(shù)語中被稱為Cross-cutting conncers。 如圖7-1所示,原來的業(yè)務(wù)流程是很單純的。圖7-1 原來的業(yè)務(wù)流程7.1.3 AOP術(shù)語與概念

12、Cross-cutting concerns如果直接寫在負(fù)責(zé)某業(yè)務(wù)的類的流程中,使得維護(hù)程序的成本增加。如果以后要把類的記錄功能修改或者移除這些服務(wù),則必須修改所有撰寫曾記錄服務(wù)的程序,然后重新編譯。另一方面,Cross-cutting concerns混雜在業(yè)務(wù)邏輯之中,使得業(yè)務(wù)類本身的邏輯或者程序的撰寫更為復(fù)雜。如同7-2所示,為了要加入日志與安全檢查等服務(wù),類的程序代碼中被硬生生地寫如了相關(guān)的Logging、Security程序片段。圖7-2 加入各種服務(wù)的業(yè)務(wù)流程7.1.3 AOP術(shù)語與概念 Aspect將散落在各個(gè)業(yè)務(wù)類中的Cross-cutting concerns收集起來,設(shè)計(jì)各

13、個(gè)獨(dú)立可重用的類,這種類稱之為Aspect。例如在動(dòng)態(tài)代理中將日志的動(dòng)作設(shè)計(jì)為一個(gè)LogHandler類,LogHandler類在AOP術(shù)語中就是Aspect的一個(gè)具體實(shí)例。在需要該服務(wù)的時(shí)候,縫合到應(yīng)用程序中;不需要服務(wù)的時(shí)候,也可以馬上從應(yīng)用程序中脫離。應(yīng)用程序中的可重用組件不用做任何的修改,例如在動(dòng)態(tài)代理中的HelloSpeaker所代表的角色就是應(yīng)用程序中可重用的組件,在它需要日志服務(wù)時(shí)并不用修改本身的程序代碼。另一方面,對于應(yīng)用程序中可重用的組件來說,以AOP的設(shè)計(jì)方式,它不用知道處理提供服務(wù)的類的存在。即與服務(wù)相關(guān)的API不會出現(xiàn)在可重用的應(yīng)用組件中,因而可提高這些組件的重用性,可

14、以將這些組件應(yīng)用到其他的應(yīng)用程序中,而不會因?yàn)槟壳凹尤肓四硞€(gè)服務(wù)或與目前的應(yīng)用框架發(fā)生耦合。 不同的AOP框架對AOP概念有不同的實(shí)現(xiàn)方式,主要的差別在于所提供的Aspects的豐富程度,以及它們?nèi)绾伪豢p合(Weave)到應(yīng)用程序中。7.1.4 通知ADVICESpring提供了5種通知(Advice)類型:Interception Around、Before、After Returning、Throw 和Introduction。它們分別在以下情況被調(diào)用:Interception Around Advice:在目標(biāo)對象的方法執(zhí)行前后被調(diào)用。Before Advice:在目標(biāo)對象的方法執(zhí)行前被

15、調(diào)用。After Returning Advice:在目標(biāo)對象的方法執(zhí)行后被調(diào)用Throw Advice:在目標(biāo)對象的方法拋出異常時(shí)被調(diào)用。Introduction Advice:一種特殊類型的攔截通知,只有在目標(biāo)對象的方法調(diào)用完畢后執(zhí)行。這里,用過前置通知Before Advice來說明。Before Advice會在目標(biāo)對象的方法執(zhí)行之前被呼叫。如同在便利店里,在客戶購買東西之前,老板要給它們一個(gè)熱情的招呼。為了實(shí)現(xiàn)這一點(diǎn),需要擴(kuò)展MethodBeforAdvice接口。這個(gè)接口提供了獲取目標(biāo)方法、參數(shù)以及目標(biāo)對象。public interface MethodBeforeAdvice v

16、oid before(Method method, Object args, Object target) throws Throwable7.1.4 通知ADVICE用實(shí)例來示范如何使用Before Advice。首先要定義目標(biāo)對象必須實(shí)現(xiàn)的接口:IHello.java代碼如下:public inter IHello public void hello(String name);接著定義一個(gè)HelloSpeaker了,讓它實(shí)現(xiàn)IHello接口:HelloSpeaker.java代碼如下:public class HelloSpeaker implements IHellopublic voi

17、d hello(String name) System.out.println(“Hello,”+name);在對HelloSpeader不進(jìn)行任何修改的情況下,想要在hello()方法執(zhí)行之前,可以記錄一些信息,有一個(gè)組件,但是沒有源代碼,但是想對它增加一些日志的服務(wù)。可以先實(shí)現(xiàn)MethodBeoforeAdvice接口,例如:7.1.4 通知ADVICELogBeforeAdvice.java代碼如下:import java.lang.reflect.Method;import java.util.logging.Level;import java.util.logging.Logger;

18、import org.springframework.aop.MethodBeforeAdvice;public class LogBeforeAdvice implements MethodBeforAdviceprivate Logger logger=Logger.getLogger(this.getClass().getName();public void before(Mehod method,Object args,Object target) throws Throwable logger.log(Levl.INFO, ”method starts”+method);7.1.4

19、通知ADVICE在before()方法中,加入了一些記錄信息的程序代碼。LogBeforeAdvice類被設(shè)計(jì)為一個(gè)獨(dú)立的服務(wù),接著只要在定義文檔中如下定義:beans-config.xml代碼如下: IHello logBeforeAdvice 7.1.4 通知ADVICE注意,除了建立Advice和Target實(shí)例之外,還使用了org.springframework.aop.framework.ProxyBean。這個(gè)類會被BeanFactory或者ApplicationContext用來建立代理對象。需要在“proxyInterfaces”屬性中告訴代理可運(yùn)行的界面,在“target”上

20、告訴Target對象,在“interceptorNames”上告訴要應(yīng)用的Advice實(shí)例,在不指定目標(biāo)方法的時(shí)候,Before Advice會被縫合(Weave)到界面上多處有定義的方法之前。寫一個(gè)程序測試一下Before Advice的運(yùn)作:SpringAOPDemo.java代碼如下:import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;public class SpringAOPDem

21、opublic static void main(String args) ApplicationContext context=new FileSystemXmlApplicationContext(“bean-config.xml”); IHello helloProxy=(IHello)context.getBean(“helloProxy”); helloProxy.hello(“Justin”);HelloSpeaker與LogBeforeAdvice是兩個(gè)獨(dú)立的類。對于HelloSpeaker來說,它不用知道LogBeforeAdvice的存在;而LogBeforeAdvice也可

22、以運(yùn)行到其他類之上。HelloSpeaker與LogBefore都可以重復(fù)使用。7.1.5 切入點(diǎn)POINTCUT Pointcut定義了通知Advice應(yīng)用的時(shí)機(jī)。從一個(gè)實(shí)例開始,介紹如何使用Spring提供的org.springframework.aop.support.NameMatchMethodPointcutAdvisor??梢灾付ˋdvice所要應(yīng)用的目標(biāo)上的方法名稱,或者是用*來指定。例如,hello*表示調(diào)用代理對象上以hello作為開頭的方法名稱時(shí),都會應(yīng)用指定的Advices。IHello.java代碼如下:public interface IHello public v

23、oid helloNewbie(String name); public void helloMaster(String name);HelloSpeaker類實(shí)現(xiàn)IHello接口。HelloSpeaker.java代碼如下:public class HelloSpeaker public void helloNewbie(String name) System.out.println(”Hello, ”+name+”newbie! ”); public void helloMaster(String name) System.out.println(”Hello, ”+name+”maste

24、r! ”); 7.1.5 切入點(diǎn)POINTCUT編寫一個(gè)簡單的Advice,這里使用Before Adviece中LogBeforeAdvice。定義Bean文檔,使用NameMatchMethodPointcutAdvisor將Pointcut與Advice結(jié)合在一起:bean-config.xml代碼如下: hello* 7.1.5 切入點(diǎn)POINTCUT IHello helloAdvisor 7.1.5 切入點(diǎn)POINTCUT在NameMatchMethodPointcutAdvosor的“mappedName”屬性上,由于指定了“hello*”,所以當(dāng)調(diào)用helloNewbie()或

25、者h(yuǎn)elloMaster()方法時(shí),由于方法名稱的開頭符合“hello”,就會應(yīng)用logBeforeAdvice的服務(wù)邏輯,可以寫一下程序來測試。SpringAOPDemo.java代碼如下:import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;public class SpringAOPDemo public static void main(String args) Application

26、Context context=new FileSystemXmlApplicationContext(“bean-config.xml”); IHello helloProxy=(IHello)context.getBean(“helloProxy”); helloProxy.helloNewbie(“Justin”); helloProxy.helloMaster(“Tom”); 7.1.5 切入點(diǎn)POINTCUT在Spring中使用PointcutAdvisor把Pointcut與Advice結(jié)合為一個(gè)對象。Spring中大部分內(nèi)建的Pointcut都有對應(yīng)的PointAdvisor。o

27、rg.springframework.aop.support.NameMatchMethodPointcutAdvisor,這是最簡單的PointAdvisor,它是Spring中靜態(tài)的Pointcut實(shí)例。使用org.springframework.aop.support.RegexpMethodPointcut可以實(shí)現(xiàn)靜態(tài)切入點(diǎn),RegexpMethodPointcut是一個(gè)通用的正則表達(dá)式切入點(diǎn),它是通過Jakarta ORO來實(shí)現(xiàn)的。靜態(tài)切入點(diǎn)只限于給定的方法和目標(biāo)類,而不考慮方法的參數(shù)。動(dòng)態(tài)切入點(diǎn)與靜態(tài)切入點(diǎn)的區(qū)別是,它不僅限定于給定的方法和類,動(dòng)態(tài)切入點(diǎn)還可以指定方法的參數(shù)。當(dāng)切入

28、點(diǎn)需要在執(zhí)行時(shí)根據(jù)參數(shù)值來調(diào)用通知時(shí),就需要使用動(dòng)態(tài)切入點(diǎn)。在大多數(shù)的切入點(diǎn)可以使用靜態(tài)切入點(diǎn),很少有機(jī)會創(chuàng)建動(dòng)態(tài)切入點(diǎn)。7.1.6 SPRING對事務(wù)的支持事務(wù)的特性之一是原子(Atomic)性。如對數(shù)據(jù)庫存取,就是一組SQL指令,這一組SQL指令必須全部執(zhí)行成功;如果因?yàn)槟硞€(gè)原因(例如其中一行SQL有錯(cuò)誤),則先前所執(zhí)行過的SQL指令撤銷。在JDBC中,可以用Connection的setAutoCommit()方法,給定它false參數(shù)。在一連串的SQL語句后面,調(diào)用Connection的commit()來送出變更。如果中間發(fā)生錯(cuò)誤,則調(diào)用rollback()來撤銷所有的執(zhí)行,例如:try

29、 connection.setAutoCommit(false); /一連串SQL操作 mit(); /執(zhí)行成功,提交所有變更c(diǎn)atch(SQLException e) connection.rollback(); /發(fā)生錯(cuò)誤,撤銷所有變更7.1.6 SPRING對事務(wù)的支持在Spring中對JDBC的事務(wù)管理加以封裝,Spring事務(wù)管理的抽象關(guān)鍵在于org.springframwork.transaction.PlatformTransactionManager接口的實(shí)現(xiàn)。PlatformTransactionManager接口有許多事務(wù)實(shí)現(xiàn)類別,如DataSourceTransactio

30、nManager、HibernateTransactionManager、JdoTransactionManager、JtaTransactionManager等。借助PlatformTransactionManager接口和各種技術(shù)實(shí)現(xiàn),Spring在事務(wù)管理上可以讓開發(fā)人員使用一致的編程模式。事務(wù)的失敗通常是致命的錯(cuò)誤,Spring不強(qiáng)迫一定要處理,而讓開發(fā)者自行選擇是否要捕捉異常。Spring提供編程式的事務(wù)管理(Programmatic transaction management)與聲明式的事務(wù)管理(Declarative transaction management): 編程式的事

31、務(wù)管理編程式的事務(wù)管理可以清楚的控制事務(wù)的邊界,即自行實(shí)現(xiàn)事務(wù)何時(shí)開始、撤銷、結(jié)束等,可以實(shí)現(xiàn)細(xì)力度的事務(wù)控制。7.1.6 SPRING對事務(wù)的支持 聲明式的事務(wù)管理然而在多數(shù)情況下,事務(wù)并不需要細(xì)粒度的控制,采用聲明式的事務(wù)管理,優(yōu)點(diǎn)是Spring事務(wù)管理的相關(guān)API可以不用介入程序之中,從對象的角度來看,并不知道它正被納入事務(wù)管理之中,不需要事務(wù)管理的時(shí)候,只要在設(shè)定檔案上修改一些設(shè)定,就可以移除事務(wù)管理服務(wù)。這里,主要介紹聲明式事務(wù)管理。Spring的聲明式事務(wù)管理依賴AOP框架來完成。使用聲明式事務(wù)管理的好處是事務(wù)管理不侵入開發(fā)組件。即DAO組件不會意識到正在事務(wù)管理之中。如果想要改變

32、事務(wù)管理策略,只需要在定義文檔中重新組態(tài)即可。 例如,可以在不修改UserDAO類的情況下,為這個(gè)類加入事務(wù)管理的服務(wù)。一個(gè)簡化的方法是使用TransactionProxyFactoryBean,指定要介入的事務(wù)管理對象機(jī)器方法,這里需要修改定義文檔,如下所示:bean-config.xml代碼如下:7.1.6 SPRING對事務(wù)的支持TransactionProxyFactoryBean需要一個(gè)TransactionManager,如果是JDBC,可以使用DataSourceTransactionManagr。由于這里使用的是Hibernate,所以使用org.springframework

33、.orm.hibernate3.HibernateTransactionManag。TransactionProxyFactoryBean是代理類,“target”屬性指定要代理的對象,事務(wù)管理會自動(dòng)介入指定的方法前后。這里是指“transactionAttributes”屬性指定,insert*表示指定方法名稱insert開頭的全部納入事務(wù)管理。也可以指定方法全名,如果在方法執(zhí)行過程中發(fā)生錯(cuò)誤,則所有先前的操作自動(dòng)撤回,否則正常提交。insert*等方法上指定“PROPAGATION_REQUIRED”,表示在目前的事務(wù)執(zhí)行操作中,如果事務(wù)不存在就創(chuàng)建一個(gè)新的,相關(guān)的意義可以在API文件中T

34、ransactionDefinition接口中找到??梢约由隙鄠€(gè)事務(wù)定義,中間使用逗號“,”隔開。例如,可以加上只讀,或者是指定某個(gè)例外發(fā)生時(shí)撤回操作:PROPAGATION_REQUIRED, readOnly,-MyCheckedExceptionMyCheckedException前面加上“”時(shí),表示發(fā)生指定異常撤銷操作,如果加上“”,表示發(fā)生異常時(shí)立即提交。7.1.6 SPRING對事務(wù)的支持由于userDAO被userDAOProxy代理了,所以要做的是取得userDAOProxy,而不是userDAO。例如:SpringAOPDemo.javaimport org.springframework.context.ApplicationContext;import org.springframework.context.s

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論