在Spring中實(shí)現(xiàn)聲明控制的事務(wù)管理_第1頁
在Spring中實(shí)現(xiàn)聲明控制的事務(wù)管理_第2頁
在Spring中實(shí)現(xiàn)聲明控制的事務(wù)管理_第3頁
在Spring中實(shí)現(xiàn)聲明控制的事務(wù)管理_第4頁
在Spring中實(shí)現(xiàn)聲明控制的事務(wù)管理_第5頁
已閱讀5頁,還剩10頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、在Eclipse中實(shí)現(xiàn)Spring中聲明控制的事務(wù)管理1、實(shí)現(xiàn)Spring的聲明控制的事務(wù)管理(1)聲明控制的事務(wù)管理的實(shí)現(xiàn)借助于Spring IoC和AOPSpring提供聲明控制的事務(wù)管理,這是借助于Spring IoC和AOP所提供的功能,同時提供了Transactioninterceptor攔截器和常用的代理類TransactionProxyFactoryBean,可以直接對組件進(jìn)行事 務(wù)代理。(2)盡量使用聲明控制的事務(wù)管理不過現(xiàn)在我們不必太理會Spring AOP的編程實(shí)現(xiàn),而只需要進(jìn)行基本的配置,我們就可以使用聲明 控制的事務(wù)管理。建議在基于Spring Framework的應(yīng)用

2、開發(fā)中,盡量使用聲明控制的事務(wù)管理,以獲得數(shù)據(jù)邏輯代碼 的最佳可讀性。(3)所需要的*.jar包文件應(yīng)該加入到系統(tǒng)中Spring的事務(wù)管理依賴于aopalliance.jar與cglib-nodep-2.1_3.jar。因此,我們必須在Web應(yīng)用 的 lib 目錄下增加對 aopalliance.jar (在 spring-framework-1.2.6libaopalliance 目錄內(nèi))與對 cglib-nodep-2.1_3.jar 的引用(在 spring-framework-1.2.6libcglib 目錄內(nèi))。將它們加入到我們的lib目錄中(4)優(yōu)點(diǎn)實(shí)現(xiàn)類似EJB CMT的特性使用

3、聲明控制的事務(wù)管理的好處是,事務(wù)管理不侵入我們所開發(fā)的組件(此時,在DAO類中不再需要 對TransactionManager 類的對象的引入),具體來說,我們的DAO類不會意識到正在事務(wù)管理之中,而 且如果我們想要改變事務(wù)管理的策略的話,也只需要在定義配置文件中重新組織即可。2、實(shí)現(xiàn)的基本原理Spring中進(jìn)行事務(wù)管理的通常方式是利用AOP (面向切片編程)的方式,為普通Java類封裝事務(wù)控 制,它是通過動態(tài)代理實(shí)現(xiàn)的,由于接口是延遲實(shí)例化的,Spring在這段時間內(nèi)通過其攔截器來加載事 務(wù)管理器。3、實(shí)現(xiàn)的主要形式(1)面向目標(biāo)接口動態(tài)代理的一個重要特征是,它是針對接口的,所以我們的DAO

4、要通過動態(tài)代理來讓Spring接管事 務(wù),就必須在DAO前面抽象出一個接口并面向該目標(biāo)接口。(2)面向目標(biāo)實(shí)現(xiàn)類當(dāng)然如果沒有這樣的目標(biāo)接口,那么Spring會使用CGLIB來解決問題,但這不是Spring所推薦的方 式(此時應(yīng)該設(shè)置proxyTargetClass屬性為true)。4、TransactionProxyFactoryBean類作為DAO組件的事務(wù)代理組件(1)作用要進(jìn)行聲明控制的事務(wù)管理,一個簡化的方法是使用TransactionProxyFactoryBean組件,通過它可 以指定要介入的事務(wù)管理對象及其方法。(2)定義org.springfraA ercept orClass

5、 Transact!onProxyFactoryBeanjga. lanq Qb jectI MprinEf rajuEwurk. acip. f ramewcirk. PrcixyCcmfI org.springfraievork.transaction, interceptor. TransactionProzyFactoryBeanAll Implemented Interfaces:S-ri-lizabli, B-mF日口 b碗ar巳, Fmc:t lyBian, Ini tializingB己an(3)應(yīng)用的要求TransactionProxyFactoryBean 需要一個 tra

6、nsactionManager 屬性,由于我們直接使用 JDBC,所以 在下面的示例中繼續(xù)使用DataSourceTransactionManager類。同時還需要target屬性,該屬性定義需要進(jìn)行事務(wù)代理的類也就是我們的DAO組件類最后,還需要一個transactionAttributes屬性,定義具體的事務(wù)要求。在Eclipse中實(shí)現(xiàn)本例中的聲明式的事務(wù)管理的過程Spring聲明式事務(wù)處理中由于主要使用了 IoC和AOP思想,同時提供了 Transactioninterceptor攔 截器和常用的代理類TransactionProxyFactoryBean,從而可以允許開發(fā)者直接以配置的

7、方式實(shí)現(xiàn)對組件 進(jìn)行事務(wù)代理。注意:下面的具體實(shí)現(xiàn)過程是在前面的代碼方式的過程的基礎(chǔ)上進(jìn)行的。因此,省略了前面的表示層 和控制層的代碼的實(shí)現(xiàn)過程的說明具體,可以看前面的代碼方式的過程。1、添加*.jar包文件到本項(xiàng)目中最后為下面的狀態(tài)aopalliance .jar cglib-nodep-2 .l_3.jar2、具體的實(shí)現(xiàn)過程在springapp-servlet.xml文件中再增加下面的配置(1)添加 transactionManager 的配置(2)添加一個 TransactionProxyFactoryBean 的對象聲明id=daoImpleProxyproperty name=pro

8、xyInterfaces com.px1987.springwebapp.dao.DAOInterface/property(property name=transactionManagerPROPAGATION_REQUIREDPROPAGATION_REQUIRED, readOnly對上面的各個標(biāo)簽的說明:TransactionProxyFactoryBean 是個代理類,其 target 屬性指定要代理的對象(daoImpleProxy 節(jié)點(diǎn)配置了一個針對daoImpleObject的事務(wù)代理),事務(wù)管理會自動地介入指定的方法前后。由于工程大部分的類都要數(shù)據(jù)庫操作,如果每次都要實(shí)例化這

9、個bean (daoImpleProxy”這個bean) 的話,會非常消耗資源的一一Spring默認(rèn)都是被管理的對象都是單例的。proxyInterfaces:代理類應(yīng)該實(shí)現(xiàn)的接口列表這里,我們通過transactionAttributes屬性指定了事務(wù)的管理策略,updateOneUserInfo*表示 指定方法名稱updateOneUserInfo開頭的都要納入事務(wù)管理,我們也可以指定方法的全名,如果 在方法執(zhí)行過程中發(fā)生了錯誤(拋出異常),則所有操作自動撤回,否則正常提交。updateOneUserInf *等方法上指定了 PROPAGATION_REQUIRED,表示在目前的事務(wù)中執(zhí)行

10、操作,如 果事務(wù)不存在就建立一個新的,相關(guān)的常量的含義都可以在API文件中TransactionDefinition 接口中找到。另一方面,對于其他方法(通過通配符*表示),則進(jìn)行只讀事務(wù)管理,以獲得更好的性能一一不會讀 取未提交的數(shù)據(jù),同時它的數(shù)據(jù)為只讀(可提高執(zhí)行速度)一一如可以避免對臟數(shù)據(jù)的檢查。PROPAGATION_REQUIRED, readOnly 注意:Spring的事務(wù)屬性支持一個稱為“回滾規(guī)則”的概念默認(rèn)情況下,任何RuntimeException或Error的拋出均會導(dǎo)致回滾。當(dāng)然,我們也可以加上多個事務(wù)的定義,中間使用逗號,隔離開,例如我們可以加上只讀,或者 是指定某個

11、異常產(chǎn)生時(并告訴事務(wù)代理,在拋出該異常時執(zhí)行進(jìn)行回滾),執(zhí)行回滾操作。PROPAGATION_REQUIRED,readOnly,-ExamerException上面的這個事務(wù)策略表示某個方法將需要一個事務(wù)支持,同時當(dāng)在事務(wù)過程中,如果產(chǎn)生了 ExamerException異常,事務(wù)將會回滾。在MyCheckedException前面加上“-”畤,表示產(chǎn)生指定的異常時撤消操作,如果前面加上+,表 示產(chǎn)生指定的異常時立即提交。下面列出事務(wù)屬性各個參數(shù)的含義PROPAGATION_REQUIRED-支持當(dāng)前事務(wù),如果當(dāng)前沒有事務(wù),就新建一個事務(wù)。這是最常見的選 擇。PROPAGATION_REQ

12、UIRED 等同于 EJB 中的 TX_REQUIRED其實(shí)現(xiàn)的策略為如果我們希望服務(wù)方法一直在事務(wù)中運(yùn)行,就可以使用PROPAGATION_REQUIRED。我們使用 PROPAGATION_REQUIRED的時候,如果某個TX已經(jīng)在運(yùn)行中,那么bean方法加入那個TX,否則Spring輕 量級TX管理器將為你重新啟動一個。PROPAGATION_SUPPORTS-支持當(dāng)前事務(wù),如果當(dāng)前沒有事務(wù),就以非事務(wù)方式執(zhí)行。PROPAGATION_MANDATORY-支持當(dāng)前事務(wù),如果當(dāng)前沒有事務(wù),就拋出異常。PROPAGATION_REQUIRES_NEW-新建事務(wù),如果當(dāng)前存在事務(wù),把當(dāng)前事務(wù)掛

13、起這可以保證它 將始終運(yùn)行在一個事務(wù)中。PROPAGATION_REQUIRES_NEW 等同于 EJB 中的 TX_REQUIRES_NEW其實(shí)現(xiàn)的策略為如果我們希望在組件服務(wù)被調(diào)用的時候,一般情況下啟動新事務(wù),那么就可以使用 PROPAGATION_REQUIRES_NEW 屬性了。PROPAGATION_NOT_SUPPORTED-以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起。PROPAGATION_NEVER-以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常。PROPAGATION_NESTED-如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行。如果當(dāng)前沒有事務(wù),則進(jìn)行與 PROPAGA

14、TION_REQUIRED 類似的操作。前六個策略類似于EJB CMT中的常量名相同(請見下面的EJB中的事務(wù)的屬性說明),因此,對EJB 開發(fā)人員來說,應(yīng)該立刻就感到熟悉。第七個(PROPAGATION_NESTED)是Spring所提供的一個特殊變量。它要求事務(wù)管理器或者使用JDBC 3.0 Savepoint API 提供嵌套事務(wù)行為(如 Spring 的 DataSourceTransactionManager),或者通過 JTA 支持嵌 套事務(wù)。注意:EJB中的事務(wù)的屬性說明Nerver :不參與事務(wù),如果參與產(chǎn)生RemoteExceptionNotSupported:不能參與Sup

15、ports:如果調(diào)用者正在參與事務(wù),相應(yīng)的EJB調(diào)用也可以參與事務(wù),否則不能Mandatory如果調(diào)用者有一個事務(wù),相應(yīng)的EJB可以參與事務(wù),否 則,TransactionRequiredExceptionRequired如果調(diào)用者有一個事務(wù),相應(yīng)的EJB可以參與事務(wù),否則,容器將在調(diào)用相應(yīng)的EJB之前, 開始一個事務(wù)。當(dāng)方法調(diào)用完成以后,即提交該事務(wù)。RequiresNew在調(diào)用相應(yīng)的EJB之前,開始一個新的事務(wù),當(dāng)方法調(diào)用返回時,即提交這個事務(wù)。注意:嵌套事務(wù)類型(PROPAGATION_NESTED),是相對上面提到的六種情況(上面的六種應(yīng)該稱為平面事務(wù) 類型),打個比方我現(xiàn)在有一個事務(wù)

16、主要有一下幾部分:從A用戶帳戶里面減去100元錢往B用戶帳戶里面添加100元錢這樣看和以前不同的事務(wù)可能沒有什么區(qū)別,那我現(xiàn)在有點(diǎn)特殊的要求就是,A用戶有3個帳戶,B 用戶有2個帳戶,現(xiàn)在我的要求就是只要再A用戶的3個帳戶里面任意一個減去100元,往B用戶的兩個 帳戶中任意一個里面增加100元就可以了!一旦我們有這樣的要求,那嵌套事務(wù)類型就非常適合我們的需要!我們可以這樣理解:將“從A用戶帳戶里面減去100元錢”和“往B用戶帳戶里面增加100元錢”我們暫時認(rèn)為是 一級事務(wù)操作將從A用戶的3個帳戶的任意一個帳戶里面減錢看做是“從A用戶帳戶里面減去100元錢”這個 一級事務(wù)的子事務(wù)(二級事務(wù)),同

17、樣把后面存錢的看成是另一個的二級事務(wù)。(3)完整的配置內(nèi)容為下面的狀態(tài)showResultspringappControlleruserLoginControlleruserLoginControlleruserLoginControllerorg.springframework.web.servlet.view.InternalResourceView/.jspproperty name=defaultErrorViewshowOtherError/propertyproperty name=exceptionMappingsshowDBErrorshowRuntimeErrornet.so

18、urceforge.jtds.jdbc.Driverjdbc:jtds:sqlserver:/localhost:1433/WebStudyDBsa1234com.px1987.springwebapp.dao.DAOInterfacePROPAGATION_REQUIREDPROPAGATION_REQUIRED, readOnly3、在UserManageImple類中獲得daoImpleProxy,并將它轉(zhuǎn)換為DAOInterface類的對象只需要在userManager.xml中做下面的配置修改。 TOC o 1-5 h z 將 daoImpleProxy 對象動態(tài)地、(propert

19、y name=daoImpleObject”、* 注入到業(yè)務(wù)層組件中/ 4、在DAOImple類中不需要做任何附加編程 package com.px1987.springwebapp.dao;import com.px1987.springwebapp.model.UserInfoVO;import org.springframework.jdbc.core.*;import java.util.*;public class DAOImple implements DAOInterfaceJdbcTemplate jdbcTemplate=null;public DAOImple()/ TOD

20、O自動生成構(gòu)造函數(shù)存根public boolean deleteOneUserInfo(int userID)/ TODO自動生成方法存根 return false;public boolean insertOneUserInfo(UserInfoVO oneUserInfoVO)String insertStatement=insert into UserInfo values(?,?,?,?,?,?,?,?)”;java.util.Date now=new java.util.Date();Object userInfoParameter=oneUserInfoVO.getUserName

21、(),oneUserInfoVO.getUserPassWord(),oneUserInfoVO.getUserDepartment(),new Integer(oneUserInfoVO.getUserAdminLevel(),new Integer(oneUserInfoVO.getDepartAdminLevel(),oneUserInfoVO.getUserImage(),oneUserInfoVO.getRegisterTime(),new Integer(int)now.getTime() ;boolean okOrNot=false;int returnCount=jdbcTem

22、plate.update(insertStatement,userInfoParameter); if(returnCount!=0) okOrNot=true;elseokOrNot=false;return okOrNot;public UserInfoVO selectUserInfo(String userName, String userPassWord)UserInfoVO oneUserInfoVO=null;/ String sqlStatement=select * from UserInfo where userName=+userName+ and userPassWor

23、d =+ userPassWord+”;String sqlStatement=select * from UserInfo where userName=? and userPassWord =?;Object userInfoPara= userName,userPassWord;java.util.List resultRows = jdbcTemplate.queryForList(sqlStatement,userInfoPara);if (resultRows!=null)&(resultRows.size() != 0)/現(xiàn)在已經(jīng)對對數(shù)據(jù)庫表的訪問Map oneUserMap =

24、 (Map) resultRows.get(0);String returnUserName=(String)oneUserMap.get(userName);String returnUserPassWord=(String)oneUserMap.get(userPassWord);oneUserInfoVO=new UserInfoVO();oneUserInfoVO.setUserName(returnUserName);oneUserInfoVO.setUserPassWord(returnUserPassWord)elseoneUserInfoVO=null;return oneUs

25、erInfoVO;public boolean updateOneUserInfo(UserInfoVO oneUserInfoVO)/ TODO自動生成方法存根 return false;public boolean updateOneUserInfo(UserInfoVO oneUserInfoVO,String newUserPassWord)String userName=oneUserInfoVO.getUserName();String userPassWord=oneUserInfoVO.getUserPassWord();Object parameter=newUserPass

26、Word,userName,userPassWord;String updateSQL1 = update userInfo set userPassWord = ? where userName =? and userPassWord=?;String updateSQL2 = update abcTable set userPassWord = ? where userName =? and userPassWord=?”;this.jdbcTemplate.update(updateSQL1,parameter);this.jdbcTemplate.update(updateSQL2,p

27、arameter);return true;public void setJdbcTemplate(JdbcTemplate jdbcTemplate) this.jdbcTemplate = jdbcTemplate;可以看到,doUpdateUserInfo方法變得非常簡潔并且在整個代碼中沒有出現(xiàn)與Spring的事務(wù)管理相 關(guān)的API提高了系統(tǒng)的可移植性。同時,數(shù)據(jù)訪問的邏輯清晰可見,對比前面代碼控制的事務(wù)管理,以及傳統(tǒng)的JDBC操作,相信大家 會有一些霍然開朗的感覺。5、具體的實(shí)現(xiàn)過程執(zhí)行該Web應(yīng)用(以updateUserInfo.jsp作為測試啟動頁)(1)將出現(xiàn)下面的狀態(tài)地址m I

28、哆1 httu;憧1口匚司h毗;曰曰日日口inciMT匚ubjlddi門門Ft?,詁口請輸入用戶名稱,枚河 請輸入用,戶密碼.|* 請輸入新刑戶密詞:阿T開始修改| 取消倏改(2)仍然會出現(xiàn)下面的錯誤地址口 |httud/l匚nlhcist:8888/5口rinciMw匚WmbjuucImtEUsmrlnFcLcIci r g s p r 1 ngt r :5Ltue iijn r K i clij c b acih q i ijr jLtniriar E x c e p 11 n:Prepare cih t at erne nt C a 1 iin ac K;in act hijL gris

29、irflrg- _ spr ingrairiEtjqrk . j dkiiz - support . SQLErr rC deSQLEcept i nTrans latcir - trans late ( SQ; ueijt. spr inglriziiri已ixnutK. 1 lUjc cor已 JciHcT已印口1 政匚已已k已cur.已(jruicTernplace . java: 546)rg- spr ingf tiziiri已ixnur/. j lUjc - cor已 JlIIjcT已印口】耳匚已 ujjiAmt已(JlUjcT已印口】日匚已 j ava: 73 6) n r |

30、g-. a p r i ngf r :=urie wo r k . j ell j c . c q r e . J cUii c Tetrip late . up cl at e (J ell j i=? T eirip 1 at e j ava : 7 9 5 )rg- spr ingrtiziiri已ixnur代.1 lUjc - cor已 JlUjct已印口1耳匚已 ujjczhmiz.已tJclDi二丁已印匚口日匚已 1 ava: SD3 ) spr ina- dao . DAOIrnri 1 e . uindat.eUser Inf (DAOIniijle . j ava: 17)s

31、pr i ng . iriQ de 1 - User McLiiCLge Imp 1 e clnUpdeLt eUser I nf o ( User McLncige I trip It . j civ a : 52 )spring - cont.ru Iler . us e r Manage C n t. r 11 e r . do Up clat. e Us e r I nf (us e r Manage C nt. roller - j av: spr i mj - c ont.ru Iler . user Manage C ont.ru Iler . onS uljtri i t. (

32、us 已 r Manage C unt.ru 1 ler . i ava: 3 6)rq-. 3pn i ngf u cune wri p k . titeIzi . servlet . rrr.rc 5 imp leF 口匚 mCizint 匚口 lien nnSutimi t i: 5 imp leF 口匚 mCurit:rg- spr ingf r日印已wrirk. Tijeki. servlet.mvc . SimpleFormCunt.ruIler . onSulzuriit. (SiinpleFurinCont.: o r g . s p r i ngf r :=ine w 口 r

33、 k weki . servlet. . ttivc S inip 1 e F o miCo ntro Iler pr ocessF o rinS ukmi iss ion ( S urg. spr 1 ngrr日in已worK weti. servler.rnvc aidsr.rac匚Furrncurnz.roller nanci 1 eRequeslinr.erna 1rg. spr ingf ram已woi:k web servlet. nivc AJjstractCunt-roller . hand 1 eRequest i: AJjstractCun, o r ig- a p u i

34、 ng r eurie wq r k web . s e rv le t . nivc S inip 1 e C o nt u o 11 e r Hand leu Adap ter hand le (S imp 1 e rg. spr 1 ngrr;5LtrieworK. weti servlet. Dlspatctierervlet ciuDlspatcli (Dlspatclier5ervlet. 1:ra. srir inaf tiziiri已ixnur/. dt已In servl已t Dispatch已已rvl已七匚1口5已tvic已(Disriat.cherServl已t janri

35、g- =ipr ingr curie w口r k TiTtb . 3erv 1 e t . Fr cune w口r kServ 1 et prqce33Requeat ( Frcuriew口rkS已rvle t ueijt. spr ingf tiziiri 已 ixnur/. dt 已 In servl 已 t Frmrn 已可口己代導(dǎo)已 rvl 已七 do Post i:Ft;min 已可t/E:已 rvl 已七 j ava: 3 6i jl- serrlet . http - Hr tpSe虹”let - service ( HttpEJervlet . j elEl : 709 )j

36、以41口天.scnvlc t . http . HttpSc匚vlet . sc匚vice ( Http3c匚v 1 n t . j 以口 : SOS :iroot causejava, aql . SQLEXcepr. Ion : M 寸寥一落 1 US 已!7工11口口, 無效口net. - sourc已f 口?。阂?j t.ds . j dljc . SQLD iaijnost. ic . acldD 14gnus1.1 c (5QLD1 agnos1.1 c - J ava: 3 55 i net. - sourcef urae - j t.ds . j dljc . TdsCore

37、- t.dsErruirTcikcn ( TlIsCoee . j ava: 2 781)但打開數(shù)據(jù)庫表,用戶的密碼沒有被修改!將代碼中的String updateSQL2 = update userInfol set userPassWord = ? where userName =?; 中的數(shù)據(jù)庫表名稱由“userinfol”改變?yōu)檎_的“userinfo”,再執(zhí)行本應(yīng)用,將能夠正確地對用戶的密 碼進(jìn)行修改。分析Spring中的聲明式事務(wù)管理機(jī)制的實(shí)現(xiàn)原理詳細(xì)的內(nèi)容將涉及到Spring中的AOP技術(shù)1、Spring事務(wù)管理實(shí)現(xiàn)的代碼示例public class TxHandler implements InvocationHandlerprivate Object originalObject;public Object bind(Object obj)this.originalObject = obj;return Proxy.newProxyInstance(obj.getClass

溫馨提示

  • 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)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論