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

分享

.Net Petshop詳解[續(xù)] - torome - 博客園

 orion360doc 2011-05-19

.Net Petshop詳解[續(xù)]

在這里,我將陸續(xù)的系列中逐步與大家一起探討詳解.Net Petshop的方方面面。

 petshop概覽和準備工作

 

前言  

Microsoft公司為了配合推出.NET戰(zhàn)略,不僅發(fā)布了一系列的開發(fā)工具和開發(fā)平臺,同時還推出了.NET平臺上的示范應(yīng)用.其中的.Net Petshop就是極好的一例.這個電子商務(wù)的開發(fā)應(yīng)用是為了應(yīng)對J2EE平臺而出爐的,在J2EE平臺上Sun公司也有一個完整的實例----J2EE Petstore,它體現(xiàn)J2EE的BluePrint。二者解決的問題是一樣的,功能也大同小異,界面也是如出一轍。自然是公說公有禮,婆說婆有禮了,我們姑且不管雙方怎么聲稱自己的東西好,但是從中也能足見.NET和J2EE平臺上的完美杰作是怎么樣的一個實現(xiàn)。在這里,本人無意去爭辯問題的勝負,也不打算去探討J2EE是怎么樣的解決方案和實現(xiàn),只是作為純粹的技術(shù)角度來管窺.NET平臺上的.Net Petshop是如何一套的解決方案和實現(xiàn)的。我想,最好的學習,莫過于鉆研這樣的一套大的經(jīng)典的系統(tǒng),從設(shè)計的思想到最好的編碼,毫無疑問對于我們將是大有裨益的。在這里,我將陸續(xù)的系列中逐步與大家一起探討詳解.Net Petshop的方方面面。希望大家多多指正! 

.NET Pet Shop解決問題的描述  

.NET Pet Shop是一個電子商務(wù)的實例,是在Microsoft的.NET平臺上的一個具體實現(xiàn)。這個系統(tǒng)包含了B2C和B2B的實現(xiàn)。在這里我主要將的是B2C實現(xiàn)的部分,B2B在.NET Pet Shop里面不是重點要解決的問題。

.NET Pet Shop是一個在線的寵物購物系統(tǒng),用戶可以通過各種能夠連接到internet的終端(包括移動終端)進行在線購物(具體界面見圖一)。在這里,我將列出它將要實現(xiàn)的功能,也就是需求了:

(1)  用戶賬號的管理功能:包括賬號創(chuàng)建,賬號登錄,賬號維護;

(2)  產(chǎn)品瀏覽功能:類別瀏覽,具體產(chǎn)品瀏覽,詳細信息,庫存信息等等;

(3)  用戶購物功能:添加購物,計算總價,下訂單等等。

 


圖一   .NET Pet Shop系統(tǒng)的登錄主界面

 

 .NET Pet Shop的邏輯結(jié)構(gòu)  

.NET Pet Shop按照三層的分層模型來部署整個系統(tǒng)。.NET Pet Shop分為數(shù)據(jù)展示層,中間層,數(shù)據(jù)層。這三層被清晰的分割為分布式應(yīng)用的三個方面。其中數(shù)據(jù)展示層主要是完成界面和與最終用戶交互的功能,在應(yīng)用程序里面是一些aspx的頁面和代碼;中間層用于封裝商業(yè)邏輯和規(guī)則,在應(yīng)用程序里面被封裝為.NET組件;數(shù)據(jù)訪問通過中間層中的數(shù)據(jù)訪問組件與SQL Server Provider交互,所有的數(shù)據(jù)獲取依靠存儲過程來進行,而不是通過SQL語句。圖二是參考petshop的白皮書說明.NET Pet Shop的物理部署結(jié)構(gòu)。

 

 

圖二  .NET Pet Shop部署結(jié)構(gòu)

 

.NET Pet Shop的開發(fā)環(huán)境支持   

Microsoft的.NET戰(zhàn)略是如此的宏大,同樣的.NET Pet Shop需要的開發(fā)環(huán)境同樣是很壯觀的。以下是我調(diào)試.NET Pet Shop的環(huán)境,有些東西是可以替換的,有些不是必須的。大家可以根據(jù)自己的情況調(diào)整。

(1) 操作系統(tǒng)win2000 server,web服務(wù)器IIS5.0,數(shù)據(jù)庫服務(wù)器SQL Server 2000;

(2) 開發(fā)工具Visual Studio.NET企業(yè)設(shè)計版。

在這里如果大家想很快的知道.NET Pet Shop 的UML模型,可以利用Visio來進行反向工程,就可以自動生成靜態(tài)的類圖(但是不可能生成用例圖和序列圖等等的)。同時Visio也可以對已經(jīng)有的petshop數(shù)據(jù)庫進行反向工程,生成數(shù)據(jù)庫模型,從而對理解.NET Pet Shop大有幫助,也能夠管窺一點微軟的建模方法和設(shè)計過程。   

 

.NET Pet Shop系統(tǒng)的安裝  

.NET Pet Shop的示例程序代碼和白皮書可以在Microsoft的msdn網(wǎng)站上下載到,也可以到http://www./compare去下載。

在petshop的文件夾下有database、petshopdoc和web以及webservice幾個文件夾。Database是數(shù)據(jù)庫的安裝腳本,將你的數(shù)據(jù)庫的sa密碼設(shè)置為空即可直接運行這些腳本安裝。Petshopdoc是英文的白皮書,后面的比較有參考價值了。Web是我們將要討論的大部分程序代碼。Webservice是用于發(fā)布的web服務(wù)。

petshop三層結(jié)構(gòu)之DataTier

交互的三層綜述<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />  

在前面的文章中,我們叢整個系統(tǒng)的角度了解了petshop的三層部署結(jié)構(gòu)物理上的一個概貌,沒有從應(yīng)用程序的角度來說明是如何劃分的,也不清楚數(shù)據(jù)展示層,中間層,數(shù)據(jù)層是如何交互的。為了更好的說明這個三層的結(jié)構(gòu)以及每一層的具體細節(jié)問題,也讓大家對整個應(yīng)用有一個walkthrough,在這里我將說明從系統(tǒng)的角度來看(見參考圖1),顧客在購物的過程中,系統(tǒng)的三層是如何的工作以及如何的交互。這個東西有點象UML里面的實例情景故事,對需求和分析的進一步是大有幫助的?!?/p>

 

 

圖1 .NET Petshop 架構(gòu)

 

從這個情景中,我們可以很清晰的了解到Internet Customer在購物時系統(tǒng)的運作情形。首先通過數(shù)據(jù)展示層的用戶交互界面Cart.aspx頁面輸入顧客購買的商品以及數(shù)量,然后這些購物清單由后臺的應(yīng)用程序(cart.aspx.cs)做相應(yīng)的預(yù)處理(如安全驗證,校驗,數(shù)據(jù)的格式化等等),接著調(diào)用中間件(在程序結(jié)構(gòu)里面就是一些.NET Assembly,封裝了購物的商業(yè)邏輯),最后通過數(shù)據(jù)訪問接口來更新數(shù)據(jù)庫里面的數(shù)據(jù)(數(shù)據(jù)層)。   

數(shù)據(jù)層(Database)   

.NET Petshop的數(shù)據(jù)庫并不是十分的龐大,總共有12個用戶表和23個存儲過程。Petshop數(shù)據(jù)庫里面存儲的是用戶數(shù)據(jù),賬號數(shù)據(jù),產(chǎn)品數(shù)據(jù),用戶配置數(shù)據(jù),訂單數(shù)據(jù),庫存數(shù)據(jù)以及供應(yīng)商的數(shù)據(jù)。應(yīng)用程序訪問數(shù)據(jù)庫的數(shù)據(jù)并不是直接的與數(shù)據(jù)庫表打交道,而是通過存儲過程的運行來獲取所需要的數(shù)據(jù)。這樣的設(shè)計有一個好處就是,避免了頻繁的表操作,而通過運行在服務(wù)器端的存儲過程可以極大的提高運作效率和提升訪問數(shù)據(jù)的速度,同時也很好的屏蔽了數(shù)據(jù)庫表的邏輯,使得數(shù)據(jù)庫訪問變成了數(shù)據(jù)庫提供的服務(wù)訪問。當然,也有人指責說這些存儲過程遷移性是值得懷疑的。 

下面我將通過表格把這些數(shù)據(jù)庫的基本表列出來(見表1),并一一做說明,希望對大家深入的理解有幫助。 

 

表名稱

備注信息

Account

基本用戶信息。

BannerData

存儲的是系統(tǒng)界面的banner圖片的設(shè)置信息。

Category

寵物的類別目錄表(比如魚類,狗類等等)。

Inventory

寵物產(chǎn)品的存貨信息。

Item

單個產(chǎn)品的詳細信息。

LineItem

訂單的每一項的詳細信息,包括產(chǎn)品名稱和數(shù)量,價格等。

Orders

用戶購物的訂單,一個訂單可以包括多項LineItem

OrderStatus

訂單的狀態(tài)

Product

寵物的產(chǎn)品列表,一條Product可能包括多個Item

Profile

用戶配置表,用于記錄他們的favorites。

Signon

用戶賬號登陸表,因為常用,故從Account獨立出來。

Supplier

供應(yīng)商信息。

 

通過上表我們知道了petshop數(shù)據(jù)庫的數(shù)據(jù)庫表的一些信息,但是這些表之間到底是一種什么樣的關(guān)系呢?關(guān)心數(shù)據(jù)庫建模和設(shè)計的人可能對這個問題比較感興趣。在這里,我將給出圖表(圖2)說明這些數(shù)據(jù)庫表之間的關(guān)系。圖2中列出了這些表之間的關(guān)系和主鍵信息。

 

圖2:petshop數(shù)據(jù)庫物理設(shè)計模式

 

技巧:其實對于從事過數(shù)據(jù)庫建模和設(shè)計的人都知道,得到上面的數(shù)據(jù)庫模型圖形并不是一件很困難的事情。正如我們前面提到的一樣,我們可以用Visio做工程反轉(zhuǎn)就可以得到上面這么美觀的設(shè)計模型圖了。同時,我們也可以在模型圖中做修改設(shè)計,可以馬上應(yīng)用到你的物理數(shù)據(jù)庫,使其保持同步。

 

說完了基本的數(shù)據(jù)庫表,接下來我們看看存儲過程。用微軟的話說,只有設(shè)計稱存儲過程,才算是”cleaner separation of code from the middle-tier”,我個人覺得這樣做是很好的。同樣的,我把它列在一個表格里(表2)。

 

 

存儲過程名稱

備注信息

upAccountAdd

增加一個賬號。

upAccountGetAddress

獲取用戶的地址,主要用于下訂單時注冊地址與送貨地址不一。

upAccountGetDetails

獲取賬號的詳細信息。

upAccountLogin

用戶登陸驗證。

upAccountUpdate

更新用戶賬號。

upCategoryGetList

獲取某個類別的產(chǎn)品列表。

upInventoryAdd

增加指定的項到存活信息。

upInventoryGetList

獲取存貨列表。

upItemAdd

增加一項產(chǎn)品。

upItemGetDetails

獲取指定產(chǎn)品項的詳細信息。

upItemGetList

獲取某一特定類別的產(chǎn)品的具體項目列表。

upItemGetList_ListByPage

功能與上同,但是分頁獲取數(shù)據(jù)。

upOrdersAdd

增加一項訂單。

upOrdersGet

獲取某一訂單的信息。

upOrdersGetDetails

獲取某一訂單的詳細信息。

upOrderStatusGet

獲取訂單的狀態(tài)。

upProductAdd

增加一類別產(chǎn)品。

upProductGetList

返回某類產(chǎn)品的列表。

upProductGetList_ListByPage

與上同,但是分頁獲取結(jié)果數(shù)據(jù)。。

upProductSearch

產(chǎn)品搜索。

upProductSearch_ListByPage

與上同,但是翻頁獲取結(jié)果數(shù)據(jù)。

upProfileGetBannerOption

Banner的配置信息。

upProfileGetListOption

獲取用戶配置信息。

 

2petshop存儲過程列表

 

在這些存儲過程里面使用了SQL Server2000OpenXML的特性來代替?zhèn)鹘y(tǒng)的行集結(jié)果,使用在非常頻繁的數(shù)據(jù)訪問操作,可以減輕系統(tǒng)的負擔。

好了,petshopDatatier就說到這里了,在后面的文章我會就一個數(shù)據(jù)訪問的實例再次解說存儲過程的執(zhí)行。接下來我將就中間層做介紹了。

petshop三層結(jié)構(gòu)之MiddleTire

 

通過前面的文章,我們對.NET Petshop的整個結(jié)構(gòu)有了一個大致的了解,也清楚的知道了數(shù)據(jù)庫的設(shè)計模式和實現(xiàn)的細節(jié),尤其值得一提的是通過存儲過程訪問數(shù)據(jù)庫。在接下來的這篇文章里,我將和大家一起來探究一下.NET Petshop的中間層。

根據(jù)三層結(jié)構(gòu)的設(shè)計原則,中間層封裝的是業(yè)務(wù)邏輯和規(guī)則,在這個網(wǎng)絡(luò)寵物商店的例子中,購物處理,訂單處理,賬號管理,產(chǎn)品查詢等等都是具體的業(yè)務(wù)邏輯,至于與用戶交互并不是中間層要處理的問題。它處理是與具體的用戶界面和交互無關(guān),而僅僅是核心的商業(yè)規(guī)則和邏輯。.NET Petshop的中間層業(yè)務(wù)邏輯被封裝為一個.NET 組件,它的命名空間為Pet Shop.Components(編譯后在bin的文件夾里面有一個petshop.dll的文件)。圖1.NET Petshop解決方案中間層的類視圖和文件視圖。

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /> <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

 

1.NET Petshop解決方案中間層的類視圖和文件視圖

 

接下來,我們模擬顧客到百貨超市采購日常用品的過程來說明運作的流程以及抽象出重要的概念(實際上User case,我們在領(lǐng)域分析的時候會這么做,并且是很重要的一步,從這里可以初步的發(fā)現(xiàn)在我們實施的系統(tǒng)中將要涉及到的邏輯實體,進而可以為數(shù)據(jù)庫建模設(shè)計以及類設(shè)計提供參考)。

購物用例的業(yè)務(wù)分析:

1 客戶有購買商品的意愿;

2 客戶到登陸管理員處登記,且成功登記;

3 在登記處推一個購物車;

4 在超市內(nèi)查找所購商品類別存放的貨架;

5 在具體的貨架上查找某一具體品牌的商品;

6 將符合意愿的商品放入自己的購物車;

7 重復(fù)4-6;

8 購物完畢;

9 到付款處計算總價格并付款;

10 打印購物清單;

11 退還購物車;

12 取走購物,購物完畢;

 

備注:在這個用例中,我們做了一些前提和假設(shè),為的是方便.NET Petshop的分析,比如說在實際生活中根本就不需要第二步。

 

通過這個用例的分析,我們至少可以抽象出一下幾個重要概念,并且能在應(yīng)用程序里面找到對應(yīng)的類:客戶對應(yīng)Customer、商品對應(yīng)Product、購物車對應(yīng)ShoppingCart、商品類別對應(yīng)Category、具體商品對應(yīng)Item、清單對應(yīng)Order。

正如我前面說過的,這幾個概念對于我們的業(yè)務(wù)建模和系統(tǒng)建模是非常有用的。正是通過這樣的分析,在.NET Petshop的業(yè)務(wù)邏輯里面共有9個核心類和5個輕量級的數(shù)據(jù)結(jié)構(gòu)類。同樣的方式,我在這里列出這些類,并加以說明(見表1)。

 

 

類名稱

說明

BasketItem

代表購物車ShoppingCart里的一項購物商品。

Customer

用于賬號管理和登陸驗證。

CustomerDetails

用戶賬號的詳細信息。

CustomerAddress

用戶賬號的地址信息。

Error

用于登陸出錯的幫助功能。

Item

代表某類產(chǎn)品中的具體一項商品。

ItemResults

搜索Item的結(jié)果集。

Order

購物完畢后的購物清單和訂單。

Product

大類別里面的某類產(chǎn)品。

ProductResults

搜索產(chǎn)品的結(jié)果集。

Profile

用戶的配置。

ShoppingCart

購物車,用于購物的整個過程,直到下訂單。

Database

通過ADO.NET訪問數(shù)據(jù)庫,封裝了具體的訪問方法。

SearchResults

模糊搜索的結(jié)果集。

 

1.NET Petshop中間層的類

 

CustomerAddress, CustomerDetails, ItemResults, ProductResults, and SearchResults這幾個輕量級的數(shù)據(jù)結(jié)構(gòu)類為在數(shù)據(jù)層和展示層之間提供了一種松散的數(shù)據(jù)綁定調(diào)用。這些類都被設(shè)計為有公開的屬性,ASP.NET web頁面可以通過這些屬性訪問數(shù)據(jù)。下面這段類的代碼說明了這5個類是如何暴露自己的公開屬性供展示層使用的。

 

public class ProductResults

       {

              private string m_productid;

              private string m_name;

 

              public string productid {

                     get { return m_productid; }

                     set { m_productid = value; } 

              }

              public string name {

                     get { return m_name; }

                     set { m_name = value; } 

              }

       }

 

.NET Petshop詳解(二)中我們就說過數(shù)據(jù)庫的訪問是通過存儲來進行的,我們看看下面這部分代碼就知道了:

 

       public string Login(string userName, string password) {

                     string customerID;

 

                     // params to stored proc

                     Database data = new Database();

                     SqlParameter[] prams = {

                            data.MakeInParam("@username",    SqlDbType.VarChar, 25, password),

                            data.MakeInParam("@password",    SqlDbType.VarChar, 25, userName),

                            data.MakeOutParam("@CustomerID", SqlDbType.VarChar, 25)

                     };

 

                     // create data object and params

                     data.RunProc("upAccountLogin", prams);    // run the stored procedure

                     customerID = (string) prams[2].Value;     // get the output param value

 

                     // if the customer id is an empty string, then the login failed

                     if (customerID == string.Empty)

                            return null;

                     else

                            return customerID;

              }

 

這段代碼是Customer類的Login方法,它是通過將用戶輸入的用戶名userName和密碼password做為輸入?yún)?shù)傳遞給存儲過程upAccountLogin的,這個存儲過程完成在Sigon用戶賬號表里面查找該用戶是否合法,最后返回一個字符串的用戶ID值。在這里沒有使用SQL查詢語句,很好的分離了邏輯。具體的數(shù)據(jù)庫訪問是通過Database來完成的,我們將在后面的文章中繼續(xù)探討它的運作。

ShoppingCart是比較有意思的一個類,也是很重要的一個類。它是與狀態(tài)有關(guān)的一個類,在.NET Petshop里面,它的狀態(tài)是通過ASP.NET Session state來管理的,關(guān)于其進一步的細節(jié)留待后面討論。

.NET Petshop的中間層的探討先到此,我在這里只是拋磚引玉,很多的東西要深入代碼才可以搞的更加清楚。歡迎大家繼續(xù)與我一起關(guān)注下一篇.NET Petshop的數(shù)據(jù)展示層。

petshop三層結(jié)構(gòu)之PresentationTier

在前面的文章中,我們已經(jīng)就.NET Petshop的數(shù)據(jù)層和中間的業(yè)務(wù)邏輯層作了說明,接下來的文章中,我們將就數(shù)據(jù)展示層作探究。與前面的兩層有著很大的差別的是,.NET Petshop的展示層用了很多Microsoft最新的web Forms技術(shù)即Asp.NET。因此,在解說展示層之前,我想就Asp.NET.NET Petshop的開發(fā)中使用到的非常重要的特性做一些說明,以示區(qū)別:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

(1)       Asp.NET代碼不再是解釋型代碼,可以經(jīng)由JIT編譯器編譯后運行,并且引入了很好的頁面緩沖機制。

(2)       ASP.Net的配置模型引入了基于XML文件的零安裝配置模型。零安裝的含義是只需將配置文件Web.config,應(yīng)用程序拷貝到系統(tǒng)指定的目錄下即可,需要更改時直接在文件里更改并保存。

(3)       安全管理 ASP.Net提供了比傳統(tǒng)ASP更強大可靠的安全管理。Asp.NET提供了三種驗證方式以及兩種類型的授權(quán)服務(wù)。

(4)       支持代碼和頁面內(nèi)容的分離。回想以前編寫Asp程序的時候的問題:代碼邏輯混亂,難于管理。

(5)       提供了更好的狀態(tài)管理,包括會話狀態(tài)的管理和視圖狀態(tài)的管理。

(6)       大量的ASP.NET服務(wù)器端控件和對用戶控件的開發(fā)的支持。

.NET Petshop充分的使用了服務(wù)器控件技術(shù)和會話狀態(tài)管理。展示層的交互界面均采用aspx頁面,后端有分離的邏輯代碼。.NET Petshop共有19aspx頁面和代碼邏輯。在這里一一里列出,并說明設(shè)置參數(shù)和其作用。

 

 

ASP.NET Web頁面

EnableSessionState

EnableViewState

備注說明

Cart.aspx

true

true

購物清單

Category.aspx

True

false

產(chǎn)品分類的列表

CheckOut.aspx

Readonly

false

訂單確認

CreateNewAccount.aspx

False

true

創(chuàng)建新賬號

Default.aspx

False

false

系統(tǒng)首頁面

EditAccount.aspx

False

true

賬號編輯

Error.aspx

False

false

錯誤處理

Help.aspx

False

false

幫助

OrderAddressConfirm.aspx

readonly

false

訂單地址確認

OrderBilling.aspx

True

true

訂單信息

OrderProcess.aspx

readonly

false

下訂單

OrderShipping.aspx

True

true

訂單地址和姓名

Product.aspx

False

false

產(chǎn)品列表

ProductDetails.aspx

false

false

產(chǎn)品詳細信息

Search.aspx

false

false

搜索

SignIn.aspx

false

false

賬號登陸

SignOut.aspx

true

false

賬號退出

ValidateAccount.aspx

false

false

賬號創(chuàng)建確認

VerifySignIn.aspx

false

false

賬號登陸確認

 

.NET Petshop使用了很多用戶控件,這些控件位于web/Inc目錄下面。表格2對用戶控件作出說明:

 

 

User Controls

EnableViewState

備注說明

ControlAddress

true

詳細地址列表

ControlBanner

false

頁面底部的banner

ControlCart

true

購物清單

ControlFavList

false

個人Favorites列表

ControlHeader

false

頁面頂部的菜單和鏈接

ControlStaticAddress

false

不能編輯的地址信息

下面列出一段代碼,說明這些參數(shù)的設(shè)置和用戶控件的引用:

/*  摘自Cart.aspx   */

<%@ Register TagPrefix="PetShop" TagName="Cart" Src="Inc/ControlCart.ascx" %>

<%@ Register TagPrefix="PetShop" TagName="Header" Src="Inc/ControlHeader.ascx" %>

<%@ Page language="c#" Codebehind="CheckOut.aspx.cs" AutoEventWireup="false" Inherits="PetShop.Web.CheckOut" EnableSessionState="readonly" enableViewState="False"%>

 

開始的兩個Registe指令用于引用ControlCartControlHeader的用戶控件,Page指令定義 ASP.NET 頁分析器和編譯器使用的頁特定的屬性。

在控件的排放位置使用下面的代碼既可以顯示該控件了:

<PetShop:Cart id="ctlCart" runat="server" allowedit="false" />

在上面的代碼中allowedit一項是向?qū)嵗?/span>ctlCart傳遞參數(shù)。我個人認為用戶控件是一個很好的東西,可以簡化web頁面的開發(fā)模型又可以達到代碼復(fù)用的目的,而且其開發(fā)非常簡單,與aspx的開發(fā)基本是一樣的。圖1說明了設(shè)計模式下和運行時的用戶控件。

 

<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />  

 

 

接下來的文章我們將就系統(tǒng)配置和安全管理作進一步的說明。

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

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多