小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

InfoQ: 解答有關(guān)REST的十點(diǎn)疑惑

 chanvy 2008-11-23
解答有關(guān)REST的十點(diǎn)疑惑
source: http://www./cn/articles/tilkov-rest-doubts
 
在了解過(guò)REST之后,你肯定很想知道這個(gè)概念在你的實(shí)際應(yīng)用當(dāng)中究竟能派上多大用場(chǎng)。而且,假如你已經(jīng)熟悉另一套完全不同的架構(gòu)手法的話,那么你擔(dān)心“REST或REST式HTTP(RESTful HTTP),是否真的能在實(shí)踐中派上用場(chǎng),還是在介紹性的、‘Hello, World’級(jí)場(chǎng)景以外就不靈光了”是很正常的。我將在本文解答人們——尤其是那些深諳基于SOAP/WSDL的Web服務(wù)架構(gòu)手法的人——開(kāi)始研究REST時(shí)容易產(chǎn)生的關(guān)于REST的十點(diǎn)疑惑。

1. REST也許適用于CRUD,但并不適用于“真實(shí)的”業(yè)務(wù)邏輯

這是那些對(duì)REST的好處持懷疑態(tài)度的人最常見(jiàn)的反應(yīng)。畢竟,要是你只能create/read/update/delete,那你如何表達(dá)更復(fù)雜的應(yīng)用語(yǔ)義呢?我已經(jīng)在本系列介紹性的文章中探討過(guò)這些被大家所關(guān)心的問(wèn)題了,不過(guò)這方面絕對(duì)值得進(jìn)一步討論。

首先,HTTP動(dòng)詞(verbs)——GET、PUT、POST和DELETE——跟數(shù)據(jù)庫(kù)的CRUD操作并不是一一對(duì)應(yīng)的。例如,POST和PUT都可用于創(chuàng)建新資源,它們的區(qū)別在于:PUT請(qǐng)求是由客戶端決定(被創(chuàng)建或更新的)資源的URI;而POST請(qǐng)求是向一個(gè)“集合(collection)”或 “工廠(factory)”資源發(fā)出的,是由服務(wù)器來(lái)指派URI的。不過(guò)無(wú)論怎樣,我們回到那個(gè)問(wèn)題:如何應(yīng)付更復(fù)雜的業(yè)務(wù)邏輯呢?

任何返回一個(gè)結(jié)果 c 的計(jì)算 calc(a, b),都可被轉(zhuǎn)換為一個(gè)標(biāo)識(shí)其結(jié)果的URI——例如 x = calc(2,3) 可被轉(zhuǎn)換為http:///calculation?a=2&b=3。初看,這仿佛是完全錯(cuò)誤的REST式HTTP的用法——我們應(yīng)當(dāng)用URIs來(lái)標(biāo)識(shí)資源(resources)而不是操作(operations),不是嗎?沒(méi)錯(cuò),其實(shí)你就是這么做的:http:///sum?augend=2&addend=3 標(biāo)識(shí)的是一個(gè)資源,即2加3的結(jié)果。在這一特定的(顯然是精心設(shè)計(jì)的)示例中,用GET來(lái)獲取計(jì)算結(jié)果可能是個(gè)好主意——畢竟它是可緩存的(cacheable),你可以引用它,而且該計(jì)算多半是安全的(safe)且代價(jià)很小的。

當(dāng)然,在許多(即便稱不上大多數(shù))情況下,用GET來(lái)執(zhí)行計(jì)算也許是會(huì)犯錯(cuò)的。別忘了,GET應(yīng)當(dāng)是一個(gè)“安全的(safe)”操作,也就是說(shuō),假如客戶端只是通過(guò)發(fā)出GET請(qǐng)求來(lái)跟隨一個(gè)鏈接,那么它不承擔(dān)任何義務(wù)(比如因使用你的服務(wù)而向你付費(fèi))或責(zé)任。所以,在許多其他情況下,“通過(guò)POST請(qǐng)求向服務(wù)器提供輸入數(shù)據(jù)、以便服務(wù)器新建一個(gè)資源”是更合適的做法。服務(wù)器在響應(yīng)該P(yáng)OST請(qǐng)求時(shí),可以給出結(jié)果的URI (而且有可能發(fā)起一個(gè)重定向把你轉(zhuǎn)向過(guò)去)。這個(gè)結(jié)果接下來(lái)便可被重用、被加入書簽、在獲取時(shí)被緩存等等。你基本上可以將這一模型推廣應(yīng)用到任何產(chǎn)生結(jié)果的操作——這涵蓋幾乎你所能想到的所有操作。

2. 沒(méi)有正式的契約與描述語(yǔ)言

從RPC到CORBA,從DCOM到Web服務(wù),我們已習(xí)慣于擁有一個(gè)“列出操作、名稱及輸入輸出參數(shù)類型”的接口描述(interface description)了。沒(méi)有接口描述語(yǔ)言的話,REST怎么用呢?

就這一被十分頻繁問(wèn)到的問(wèn)題,有三點(diǎn)答復(fù)。

首先,假如你決定用XML(這是很普遍的做法)來(lái)配合REST式HTTP的話,那么各種現(xiàn)有的XML模式語(yǔ)言(schema languages)(如DTD、XML Schema、RELAX NGSchematron等) 仍舊可供你使用。可以說(shuō),一個(gè)用WSDL描述的東西,常常有95%的內(nèi)容并不是跟WSDL相關(guān)、而是跟你定義的XML Schema復(fù)雜類型(complex types)相關(guān)的。WSDL所增加的,大部分是有關(guān)操作(operations)及其名稱的——對(duì)于REST的統(tǒng)一接口(uniform interface)來(lái)說(shuō),描述這些是頗為無(wú)趣的,因?yàn)镚ET、PUT、POST和DELETE就是你所能使用的全部操作了。關(guān)于XML Schema的使用,這意味著,即便你依賴于一個(gè)REST式接口,你仍舊可使用你所偏愛(ài)的數(shù)據(jù)綁定工具(假如剛好你有的話)來(lái)為你偏愛(ài)的語(yǔ)言生成數(shù)據(jù)綁定代碼。(回答還沒(méi)結(jié)束,見(jiàn)下。)

第二,問(wèn)問(wèn)你自己需要描述做什么。最常見(jiàn)(盡管并非唯一)的用例(use case)是:描述被用來(lái)給接口生成樁(stubs)和骨架(skeletons)代碼。它通常不是文檔(documentation),因?yàn)閃SDL格式的描述并不是告訴你操作的語(yǔ)義——它只是告訴你操作的名稱。你得通過(guò)一些人類可讀的文檔來(lái)了解如何調(diào)用它。典型的REST做法是,你應(yīng)提供HTML格式的文檔,其中可能包含指向你的資源的直接鏈接(direct links)。如果你采取提供多個(gè)表示(multiple representations)的做法的話,那么你可以真正擁有自文檔化的(self-documenting)資源——你只要在瀏覽器中對(duì)一個(gè)資源做 HTTP GET請(qǐng)求,就可以得到一個(gè)HTML文檔,其中不但包含數(shù)據(jù),還包含你可以對(duì)它執(zhí)行的操作(HTTP動(dòng)詞)的列表以及它接受和返回的內(nèi)容類型(content types)。

最后,假如你堅(jiān)持為你的REST式服務(wù)(RESTful service)使用描述語(yǔ)言,那么你可以使用WADL(Web Application Description Language,Web應(yīng)用描述語(yǔ)言),或適當(dāng)?shù)厥褂?a title="Web Services Description Language (WSDL) Version 2.0 Part 0:Primer" href="http://www./TR/2007/REC-wsdl20-primer-20070626/">WSDL 2.0(其制定者聲稱它也可以描述REST式服務(wù))。不過(guò),WADL和WSDL 2在描述超媒體(hypermedia)方面均無(wú)幫助——而且考慮到這是REST的核心方面之一,我不太確信它們是否充分有用。

3. 誰(shuí)真會(huì)把他們應(yīng)用中如此多的實(shí)現(xiàn)細(xì)節(jié)暴露出來(lái)?

另一個(gè)普遍關(guān)心的問(wèn)題是,資源太低層(low-level),暴露了那些不應(yīng)暴露出來(lái)的實(shí)現(xiàn)細(xì)節(jié)。說(shuō)到底,這不就把“按有意義的方式來(lái)運(yùn)用資源”的擔(dān)子加到客戶端(消費(fèi)者)的身上了嗎?

簡(jiǎn)單的回答是:不。一個(gè)資源的GET、PUT或其他方法的實(shí)現(xiàn),可以跟一個(gè)“服務(wù)”或RPC操作的實(shí)現(xiàn)復(fù)雜程度相當(dāng)。應(yīng)用REST設(shè)計(jì)原則,并不是說(shuō)你必須把下層數(shù)據(jù)模型(underlying data model)中的各項(xiàng)暴露出來(lái)——它只意味著,你采用以數(shù)據(jù)為中心的(data-centric)方式、而不是以操作為中心的(operation-centric)方式把業(yè)務(wù)邏輯暴露出來(lái)。

一個(gè)相關(guān)的關(guān)切是,不支持對(duì)資源的直接訪問(wèn)將增加安全性。這是由“通過(guò)隱匿得到安全(security by obscurity)”這條陳舊的謬論得出的結(jié)論。人們可以這樣反駁:其實(shí)恰恰相反,如果你隱瞞你通過(guò)特定于應(yīng)用的協(xié)議訪問(wèn)哪些資源,你將無(wú)法利用基礎(chǔ)設(shè)施(infrastructure)來(lái)保護(hù)它們。通過(guò)為有意義的資源指派單獨(dú)的URI,你可以利用Apache的安全規(guī)則(以及重寫邏輯、日志和統(tǒng)計(jì)等)對(duì)不同資源采取不同處理。把這些明確化了,你的安全性將得到提升,而不是降低。

4. REST只能配合HTTP使用,它不是傳輸協(xié)議無(wú)關(guān)的

首先,毫無(wú)疑問(wèn),HTTP不是一種傳輸協(xié)議(transport protocol),而是一種應(yīng)用協(xié)議(application protocol)。它采用TCP作為下層傳輸(underlying transport),但它擁有自己的語(yǔ)義(否則它就沒(méi)什么用處了)。僅將HTTP作為傳輸,是不恰當(dāng)?shù)摹?

第二,抽象未必總是好事。Web服務(wù)的做法,是試圖把許多大不相同的技術(shù)隱藏在單個(gè)抽象層背后——但這容易引發(fā)抽象泄露(leak)。例如,通過(guò)JMS和通過(guò)HTTP請(qǐng)求發(fā)送消息存在著巨大的不同,試圖把各種存在極大差異的技術(shù)弱化為它們的最基本共通特性是毫無(wú)益處的。 打個(gè)比方,如果要?jiǎng)?chuàng)建一個(gè)通用抽象(common abstraction),把一個(gè)關(guān)系數(shù)據(jù)庫(kù)和一個(gè)文件系統(tǒng)隱藏在一個(gè)通用API之后,當(dāng)然這可以去做,但一旦你涉及到解決像查詢這樣的問(wèn)題時(shí),該抽象的問(wèn)題就顯露出來(lái)了。

最后,正如Mark Baker曾說(shuō)過(guò)的:“協(xié)議無(wú)關(guān)性是一個(gè)缺陷,而不是一個(gè)特性”。雖然這給人的最初感覺(jué)是比較奇怪,但你要知道,真正的協(xié)議無(wú)關(guān)性(protocol independence)是不可能實(shí)現(xiàn)的——你所能做的只是決定依賴于哪一種協(xié)議。依賴于一種得到了廣泛采納和官方標(biāo)準(zhǔn)化的協(xié)議(如 HTTP)根本不是問(wèn)題,而且它還得到了比試圖取代它的抽象更廣泛的普及與支持。

5. 沒(méi)有實(shí)際的、明確且一致的指南教你如何設(shè)計(jì)REST式應(yīng)用

REST式設(shè)計(jì)在許多方面均沒(méi)有“官方”最佳實(shí)踐和“如何按符合REST原則的方式、用HTTP解決一個(gè)特定問(wèn)題”的標(biāo)準(zhǔn)方式。毋庸置疑,這是會(huì)逐漸得到改善的。盡管如此,REST具體表達(dá)了比基于WSDL/SOAP的Web服務(wù)更多的應(yīng)用概念。換言之,雖然該批評(píng)對(duì)REST有很大價(jià)值,但這一批評(píng)更適用于其替換技術(shù)(它們基本上沒(méi)有向你提供任何建議)。

有時(shí),這種疑慮以“連REST專家們都無(wú)法就具體怎么做達(dá)成一致”的形式出現(xiàn)。但一般說(shuō)來(lái),情況并不是這樣——舉個(gè)例子,我比較相信我數(shù)周前在這里講述的核心概念尚未(而且也不會(huì))遭到REST圈內(nèi)人士(假定存在這個(gè)圈子的話)的質(zhì)疑,這并不是因?yàn)槟鞘且黄貏e好的文章,而是因?yàn)槿藗冊(cè)谧鲞^(guò)更深入的了解以后便能達(dá)成許多共識(shí)。假如你有機(jī)會(huì)做個(gè)實(shí)驗(yàn)的話,可以試試看,是讓五位SOA支持者在某方面達(dá)成一致更容易,還是讓五位REST支持者在某方面達(dá)成一致更容易。根據(jù)我個(gè)人的過(guò)往經(jīng)驗(yàn)和長(zhǎng)期參與數(shù)個(gè)SOA與REST討論組的經(jīng)歷來(lái)看,我傾向于相信后者更加容易。

6. REST不支持事務(wù)

“事務(wù)(transaction)”一詞存在著多種不同解釋,不過(guò)人們一般所說(shuō)的事務(wù),指的是數(shù)據(jù)庫(kù)里的ACID這種。在一個(gè)SOA環(huán)境中——無(wú)論是否基于Web服務(wù)或HTTP——各個(gè)服務(wù)(或系統(tǒng)、或Web應(yīng)用)的實(shí)現(xiàn)仍然有可能與一個(gè)支持事務(wù)的數(shù)據(jù)庫(kù)進(jìn)行交互:這無(wú)需很大改變,假如你不用顯式創(chuàng)建事務(wù)的話(除非你的服務(wù)運(yùn)行在一個(gè)EJB容器或其他可以為你處理事務(wù)創(chuàng)建的環(huán)境中)。如果你與多個(gè)資源交互,情況也一樣。

如果你打算把事務(wù)組合(或者創(chuàng)建)為一個(gè)更大的單元,情況將有所不同。在Web服務(wù)環(huán)境中,至少有一種辦法可以做到跟人們所熟知的(比如Java EE環(huán)境所支持的)兩階段提交(2PC)相似:即采用WS-Atomic Transaction(WS-AT),它是WS-Coordination標(biāo)準(zhǔn)族中的成員。本質(zhì)上,WS-AT所實(shí)現(xiàn)的是跟XA規(guī)定的兩階段提交協(xié)議非常相似或相同的。這意味著,你的事務(wù)上下文(transaction context)將用SOAP報(bào)頭來(lái)傳播,而你的實(shí)現(xiàn)(implementation)將負(fù)責(zé)確保資源管理器進(jìn)入現(xiàn)有事務(wù)。本質(zhì)上,跟EJB開(kāi)發(fā)者所熟悉的模型一樣——你的分布式事務(wù)跟本地事務(wù)一樣是原子性的。

關(guān)于SOA環(huán)境中的原子事務(wù)(atomic transactions),有很多看法或反對(duì)意見(jiàn):

  • 松耦合與事務(wù)(尤其是ACID那樣的)根本格格不入。比如“跨越多個(gè)獨(dú)立系統(tǒng)來(lái)協(xié)調(diào)提交,會(huì)在它們之間造成緊耦合”就充分說(shuō)明了這一點(diǎn)。
  • 為了進(jìn)行這種協(xié)調(diào),需要對(duì)所有服務(wù)進(jìn)行中央控制——而跨越企業(yè)邊界進(jìn)行兩階段提交事務(wù)是不可能或基本無(wú)法做到的。
  • 支持這種事務(wù)所需的基礎(chǔ)設(shè)施(infrastructure)通常極為昂貴和復(fù)雜。

很大程度上,在SOA或REST環(huán)境中需要ACID事務(wù),其實(shí)是一種設(shè)計(jì)異味(design smell)——你很可能已經(jīng)為你的服務(wù)或資源采用了錯(cuò)誤的模型。當(dāng)然,原子事務(wù)只是一種類型的事務(wù)——除此以外還有擴(kuò)展的事務(wù)模型,也許它更適合松耦合系統(tǒng)。不過(guò),即便在Web服務(wù)陣營(yíng)里,它們也沒(méi)得到較多采納。

7. REST是不可靠的

常有人指出,REST式HTTP里沒(méi)有與WS-ReliableMessaging對(duì)等的特性,于是許多人便斷定,REST不能應(yīng)用于講究可靠性(reliability)的場(chǎng)合(那就是說(shuō)差不多所有跟業(yè)務(wù)場(chǎng)景相關(guān)的系統(tǒng))。但很多時(shí)候,你不一定需要一個(gè)處理消息遞送(message delivery)的基礎(chǔ)設(shè)施組件(infrastructure component),相反,你需要知道一個(gè)消息是否已被遞送。

通常,收到一個(gè)響應(yīng)消息——比方說(shuō)HTTP里的200 OK——表明你知道你的通信伙伴已經(jīng)收到請(qǐng)求。但如果你沒(méi)有收到響應(yīng)消息,那問(wèn)題就來(lái)了:你不知道是你的請(qǐng)求沒(méi)有到達(dá)另一端,還是已經(jīng)收到了(觸發(fā)了某些處理)、但響應(yīng)消息丟失了。

確保請(qǐng)求消息抵達(dá)另一端的最簡(jiǎn)單的做法,就是把消息重發(fā)一遍——當(dāng)然,僅當(dāng)接受方有能力處理重復(fù)消息(比如通過(guò)忽略它們)時(shí)才可以這么做。這種能力被稱作冪等性(idempotency)。HTTP確保GET、PUT和DELETE是冪等的(idempotent )——如果你的應(yīng)用實(shí)現(xiàn)得當(dāng)?shù)脑?,那么客戶端在沒(méi)有收到響應(yīng)時(shí)只需把請(qǐng)求重發(fā)一遍即可。但POST消息不是冪等的——至少在HTTP規(guī)范里沒(méi)有保證。對(duì)此你有多種選擇:要么改用PUT(如果你的語(yǔ)義可以映射上去的話),采用Joe Gregorio描述的一種常見(jiàn)的最佳實(shí)踐;要么采納一種致力于統(tǒng)一有關(guān)做法的提案(例如Mark Nottingham的POE(POST Once Exactly)、Yaron Goland的SOA-RityBill de hóra的HTTPLR)。

就我個(gè)人而言,我傾向于上述第一種做法——即把可靠性問(wèn)題轉(zhuǎn)嫁到應(yīng)用設(shè)計(jì)方面,不過(guò)對(duì)此存在多種不同看法。

盡管這些方案均解決了相當(dāng)一部分可靠性問(wèn)題,但沒(méi)有(或至少就我所知沒(méi)有)一個(gè)能支持消息遞送承諾,比如按序遞送一系列HTTP請(qǐng)求和響應(yīng)。不過(guò)值得一提的是,許多現(xiàn)有的SOAP/WSDL方案沒(méi)有依靠WS-ReliableMessaging(或其前身)也勉強(qiáng)應(yīng)付了。

8. 不支持發(fā)布/訂閱

本質(zhì)上,REST基于的是一種客戶端-服務(wù)器模型(client-server model),HTTP總把客戶端和服務(wù)器稱為通信端點(diǎn)(endpoints of communication)??蛻舳送ㄟ^(guò)發(fā)送請(qǐng)求和接受響應(yīng)的方式與服務(wù)器進(jìn)行交互。在發(fā)布/訂閱模型(publish/subscribe model)中,客戶訂閱特定種類的信息,然后每當(dāng)有新信息出現(xiàn)時(shí)它就會(huì)得到通知。REST式HTTP環(huán)境怎么可能支持發(fā)布/訂閱呢?

尋找理想的例子并不難,聚合(syndication)就是一個(gè)。RSSAtom Syndication都是聚合的例子??蛻舳送ㄟ^(guò)“向一個(gè)代表變更集合(collection of changes)的資源發(fā)出HTTP請(qǐng)求”來(lái)查詢新信息,如獲取特殊分類或定時(shí)輪詢。這搞不好會(huì)相當(dāng)?shù)托?,但?shí)際上并沒(méi)有,因?yàn)镚ET是Web上最優(yōu)化的操作。其實(shí),你可以很容易想象,要是一個(gè)受歡迎的博客服務(wù)器主動(dòng)把各個(gè)變更通知各訂閱者的話,那么它應(yīng)該可以在可伸縮性方面得到很大提高。輪流通知(notification by polling)具有極好的可伸縮性。

你可以將這一聚合模型(syndication model)推廣應(yīng)用到你的各個(gè)應(yīng)用資源——例如,為用戶資源或賬目審計(jì)追蹤記錄的變更提供Atom提要(feed)。除了可以滿足任意數(shù)量應(yīng)用的訂閱需求,你還可以用提要閱讀器(feed reader)來(lái)查看這些提要(feeds),就像在瀏覽器里查看一個(gè)資源的HTML表示(representation)一樣。

當(dāng)然,在某些情況下這就不合適了。比如,對(duì)于軟實(shí)時(shí)(soft real-time)需求,采用其他技術(shù)也許更為合適。但在許多情況下,由聚合模型贏得的松耦合(loose coupling)、可伸縮性(scalability)與通知(notification),整體上是相當(dāng)不錯(cuò)的。

9. 無(wú)異步交互

在HTTP的請(qǐng)求/響應(yīng)模型之下,如何實(shí)現(xiàn)異步通信?同樣地,我們應(yīng)注意到人們?cè)谡劶爱惒叫裕╝synchronicity)時(shí)常常指的是不同方面。有人指的是編程模型,它可以是跟線上交互(wire interactions)無(wú)關(guān)的阻塞或非阻塞模型。這不是我們所關(guān)心的。但假如你把一個(gè)請(qǐng)求從客戶端(用戶)遞送到服務(wù)器端(提供者)的過(guò)程需花費(fèi)數(shù)小時(shí),這怎么辦呢?用戶如何知道處理有沒(méi)有結(jié)束?

HTTP有一個(gè)專門的響應(yīng)代碼202 Accepted,它的意思是“請(qǐng)求已被接受處理,但處理還沒(méi)有結(jié)束”。顯然,這正是你所需要的。至于處理結(jié)果,有多種辦法:服務(wù)器可以返回一個(gè)資源的URI,然后客戶端通過(guò)向該URI發(fā)送GET請(qǐng)求來(lái)訪問(wèn)結(jié)果(盡管在專門為一個(gè)請(qǐng)求創(chuàng)建資源時(shí)采用響應(yīng)代碼201 Created更為恰當(dāng))。或者,客戶端可以提供一個(gè)URI,并期待服務(wù)器在處理完成后把結(jié)果POST上去。

10. 缺少工具

最后一點(diǎn),人們常常抱怨缺少用于支持REST式HTTP開(kāi)發(fā)的工具。正如我在第二點(diǎn)里提到的,在數(shù)據(jù)方面其實(shí)不是這樣——你可以使用你熟悉的數(shù)據(jù)綁定與其他數(shù)據(jù)APIs,因?yàn)檫@與方法數(shù)量和調(diào)用它們的方式無(wú)關(guān)。至于普通的HTTP與URI支持,現(xiàn)在所有的編程語(yǔ)言、框架及工具包都能提供立即支持。最后,廠商們正在為“用它們的框架進(jìn)行更便捷的REST式HTTP開(kāi)發(fā)”提供越來(lái)越多的支持,例如Sun的JAX-RS(JSR 311)、微軟的.NET 3.5及ADO.NET數(shù)據(jù)服務(wù)框架里對(duì)REST的支持。

總結(jié)

那么,REST及其最常見(jiàn)的實(shí)現(xiàn)——HTTP——理想嗎?當(dāng)然不。世界上沒(méi)有在所有情況下都理想的東西,而且很多時(shí)候即便在單個(gè)情況下都未必能夠理想。我已經(jīng)避免了許多相當(dāng)合理、但需要更復(fù)雜解答的問(wèn)題領(lǐng)域,比如基于消息的安全、部分更新以及批處理等,我承諾將在后續(xù)文章中討論這些問(wèn)題。希望我已經(jīng)解答了你的一些疑惑——假如我遺漏了你最關(guān)心的問(wèn)題,歡迎在此發(fā)表評(píng)論。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多