欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
InfoQ: 實(shí)現Web Service依賴(lài)倒置

實(shí)現Web Service依賴(lài)倒置

作者 譯者 王翔 發(fā)布于 2007年8月1日 下午10時(shí)49分

社區
.NET
主題
設計,
Web服務(wù)

問(wèn)題的提出

作為面向對象設計的一個(gè)基本原則,依賴(lài)倒置原則(DIP)在降低模塊間耦合度方面有很好的指導意義,他的基本要求和示意圖如下:

“高層模塊不應該依賴(lài)于低層模塊,二者都應該依賴(lài)于抽象。抽象不應該依賴(lài)于細節。細節應該依賴(lài)于抽象。”

圖1:直接依賴(lài)(I)和依賴(lài)關(guān)系倒置(II)

這么做有什么優(yōu)勢呢?

  • 降低Client與ConcreteService的耦合度。
  • ConcreteService可以自主的變化,只要符合IService,就可以繼續被Client使用。即這種變化對Client透明。
  • 應用框架可以Client的上下文為他物色一個(gè)合適的ConcreteService,動(dòng)態(tài)構造、動(dòng)態(tài)綁定、運行時(shí)動(dòng)態(tài)調用。

在單應用時(shí)代,基于接口的開(kāi)發(fā)指導了我們養成這種習慣,但是到了SOA環(huán)境下,通常的Web Service開(kāi)發(fā)情況又是怎么樣呢?

  1. 客戶(hù)程序需要調用某個(gè)Web Service,獲得它的WSDL和相關(guān)數據結構的XSD。
  2. 然后客戶(hù)程序調用這個(gè)Web Service,一般情況下如果WSDL不變的話(huà),可以一直使用該Web Service,即便那個(gè)Web Service后面的實(shí)現平臺發(fā)生變化,但因為綁定關(guān)系沒(méi)有變化,所以客戶(hù)程序不需要任何修改(偶爾因為版本問(wèn)題,有可能會(huì )進(jìn)行適應性調整)。
  3. 如果發(fā)現有新的相同服務(wù)接口的Service Provider做的不錯的化或者把原有Web Service做遷移的話(huà),那就需要重新更新WSDL,編譯新的Web Service Client Proxy類(lèi),有可能客戶(hù)程序也要重新編譯。

Web Service很好地隔絕了服務(wù)定義與服務(wù)實(shí)現兩者的關(guān)系,同時(shí)它也把可能的備選功能提供者從內部一下子推到整個(gè)互聯(lián)網(wǎng)環(huán)境下,怎么讓客戶(hù)程序透明的適應眾多可選服務(wù)就成了一個(gè)挑戰。

怎么辦?老辦法——抽象。

實(shí)現Web Service依賴(lài)倒置

分析

相信在實(shí)踐設計模式的過(guò)程中,開(kāi)發(fā)人員已經(jīng)對依賴(lài)倒置的概念有了深刻的體驗,“不依賴(lài)于具體實(shí)現,而是依賴(lài)于抽象”,整理SOA環(huán)境下的Web Service一樣需要借鑒這個(gè)概念,筆者將之稱(chēng)為“Web Service依賴(lài)倒置”。大概邏輯結構變成如下:

圖2:概要Web Service依賴(lài)倒置后的邏輯關(guān)系

但Web Service本身接口是“平的”,沒(méi)有辦法繼承,只有用OO語(yǔ)言把它進(jìn)行包裝之后才可以成為對應的類(lèi),這時(shí)候才能有所謂的“繼承”或“接口實(shí)現”;所謂“抽象”既可能是接口也可能是抽象類(lèi)(當然,也可以考慮用實(shí)體基類(lèi)),所以在處理ConcreteWebService與抽象Web Service的時(shí)候也有兩種方式:

  • 通過(guò)繼承的
  • 通過(guò)單繼承+多接口組合的

筆者更傾向于后者,因為通過(guò)組合可以不斷擴展。同時(shí)考慮到Web Service使用往往在一個(gè)分布式的環(huán)境中,因此參考RPC中常用的叫法,增加了一一個(gè)Stub(用接口IServiceX表示)和Proxy。修改后依賴(lài)倒置的關(guān)系如下:

圖3:分布式環(huán)境下多組合服務(wù)接口實(shí)現的Web Service依賴(lài)倒置

實(shí)現示例

1、對業(yè)務(wù)數據建模(XSD):

假設業(yè)務(wù)對象為報價(jià)信息,報價(jià)分為報價(jià)頭和明細(1:0..n),因此結構如下:

圖4:報價(jià)信息的XSD

XSD
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
  xmlns="http://www.visionlogic.com/trade"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  targetNamespace="http://www.visionlogic.com/trade"
  elementFormDefault="qualified"
  attributeFormDefault="unqualified">
    <xs:element name="Quote">
        <xs:annotation>
            <xs:documentation>Comment describing your root element</xs:documentation>
        </xs:annotation>
        <xs:complexType>
            <xs:sequence>
                <xs:element ref="QuoteItem" minOccurs="0" maxOccurs="unbounded"/>
            </xs:sequence>
            <xs:attribute name="Id" type="xs:string" use="required"/>
            <xs:attribute name="Company" type="xs:string" use="required"/>
        </xs:complexType>
    </xs:element>
    <xs:element name="QuoteItem">
        <xs:complexType>
            <xs:attribute name="ProductId" type="xs:integer" use="required"/>
            <xs:attribute name="Price" type="xs:double" use="required"/>
            <xs:attribute name="QuantitiveInStock" type="xs:double"/>
        </xs:complexType>
    </xs:element>
</xs:schema>

2、完成XSD與對象實(shí)體的映射:(XSD to Object)

Command

通過(guò)Visual Studio.Net自帶的Xsd.exe進(jìn)行如下操作。


xsd Quote.xsd /c /n:DemoService

這樣就生成了結構大概如下的對應的報價(jià)實(shí)體類(lèi):

C#
using System;
using System.Xml.Serialization;
namespace DemoService
{
    [System.SerializableAttribute()]
    [XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.visionlogic.com/trade")]
    [XmlRootAttribute(Namespace = "http://www.visionlogic.com/trade", IsNullable = false)]
    public partial class Quote
    {
        private QuoteItem[] quoteItemField;
        private string idField;
        private string companyField;
        [XmlElementAttribute("QuoteItem")]
        public QuoteItem[] QuoteItem
        {
            get { return this.quoteItemField; }
            set { this.quoteItemField = value; }
        }
        [XmlAttributeAttribute()]
        public string Id
        {
            get { return this.idField; }
            set { this.idField = value; }
        }
        [XmlAttributeAttribute()]
        public string Company
        {
            get { return this.companyField; }
            set { this.companyField = value; }
        }
    }

    [SerializableAttribute()]
    [XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.visionlogic.com/trade")]
    [XmlRootAttribute(Namespace = "http://www.visionlogic.com/trade", IsNullable = false)]
    public partial class QuoteItem
{
… …
    }
}

3、接著(zhù),完成抽象的Web Service定義(optional):

該步驟的目的是獲取wsdl定義。這里筆者為了省事,用Visual Studio.Net自動(dòng)生成,所以寫(xiě)了個(gè)抽象的Web Service類(lèi),實(shí)際開(kāi)發(fā)中完全可以獨立編寫(xiě)wsdl文件。

C#
using System.Web.Services;
using System.Xml.Serialization;
namespace DemoService
{
    [WebService(Name="QuoteService", Namespace="http://www.visionlogic.com/trade")]
    public abstract class QuoteServiceBase : WebService
    {
        [WebMethod()]
        [return:XmlElement("Quote", Namespace="http://www.visoinlogic.com/trade")]
        public abstract Quote GetQuote(string id);
    }
}
WSDL (Quote.wsdl)
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns="http://www.visionlogic.com/trade" xmlns:s1="http://www.visoinlogic.com/trade" xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" targetNamespace="http://www.visionlogic.com/trade" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
  <wsdl:types>
    <s:schema elementFormDefault="qualified" targetNamespace="http://www.visionlogic.com/trade">
      <s:import namespace="http://www.visoinlogic.com/trade" />
      <s:element name="GetQuote">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" name="id" type="s:string" />
          </s:sequence>
        </s:complexType>
      </s:element>
      <s:element name="GetQuoteResponse">
        <s:complexType>
          <s:sequence>
            <s:element minOccurs="0" maxOccurs="1" ref="s1:Quote" />
          </s:sequence>
        </s:complexType>
      </s:element>
… …
  <wsdl:service name="QuoteService">
    <wsdl:port name="QuoteServiceSoap" binding="tns:QuoteServiceSoap">
      <soap:address location="http://localhost:2401/QuoteServiceBase.asmx" />
    </wsdl:port>
    <wsdl:port name="QuoteServiceSoap12" binding="tns:QuoteServiceSoap12">
      <soap12:address location="http://localhost:2401/QuoteServiceBase.asmx" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

4、生成Web Service接口類(lèi)型:

Command

通過(guò)Visual Studio.Net自帶的Wsdl.exe進(jìn)行如下操作。


wsdl /n:DemoService /serverinterface /o:IQuoteStub.cs Quote.wsdl Quote.xsd

這樣就生成了報價(jià)Web Service的抽象接口:

C#
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Services.Description;
using System.Xml.Serialization;
namespace DemoService
{
    [WebServiceBindingAttribute(
        Name = "QuoteServiceSoap", Namespace = "http://www.visionlogic.com/trade")]
    public interface IQuoteServiceSoap
    {
        [WebMethodAttribute()]
        [SoapDocumentMethodAttribute(
            "http://www.visionlogic.com/trade/GetQuote",
            RequestNamespace = "http://www.visionlogic.com/trade",
            ResponseNamespace = "http://www.visionlogic.com/trade",
            Use = SoapBindingUse.Literal,
            ParameterStyle = SoapParameterStyle.Wrapped)]
        [return: XmlElementAttribute("Quote",
            Namespace = "http://www.visoinlogic.com/trade")]
        Quote GetQuote(string id);
    }
}

5、生成具體的報價(jià)Web Service:

為了示例的方便,IntranetQuoteService自己“手捏”了一票測試報價(jià)數據,至此服務(wù)端Web Service工作基本完成,如果需要使用UDDI則還需要把這個(gè)具體服務(wù)publish出來(lái)。

C#
using System;
using System.Web.Services;
using System.Web.Services.Protocols;
namespace DemoService
{
    /// <summary>
    /// 具體的報價(jià)Web Service 功能實(shí)現
    /// </summary>
    [WebService(Namespace = "http://www.visionlogic.com/trade")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class IntranetQuoteService : WebService, IQuoteServiceSoap
    {
        /// <summary>
        /// 實(shí)現抽象的Web Service調用
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [WebMethod]
        public Quote GetQuote(string id)
        {
            #region "手捏"出來(lái)的測試數據
            Quote quote = new Quote();
            quote.Id = id;
            quote.Company = "deluxe";

            QuoteItem[] items = new QuoteItem[2];
            items[0] = new QuoteItem();
            items[0].QuantitiveInStockSpecified = true;
            items[0].ProductId = "Note Bulletin";
            items[0].Price = 220;
            items[0].QuantitiveInStock = 10;
            items[1] = new QuoteItem();
            items[1].QuantitiveInStockSpecified = true;
            items[1].ProductId = "Pen";
            items[1].Price = 3.4;
            items[1].QuantitiveInStock = 3000;
            quote.QuoteItem = items;
            #endregion

            return quote;
        }
    }
}

6、生成客戶(hù)端Proxy:

Command

通過(guò)Visual Studio.Net自帶的Wsdl.exe進(jìn)行如下操作。


wsdl /n:Test.Client /o:QuoteProxy.cs Quote.wsdl Quote.xsd

這樣就生成了報價(jià)Web Service的客戶(hù)端Proxy,他僅通過(guò)最初抽象Web Service的WSDL調用服務(wù)端Web Service。實(shí)際運行過(guò)程中,它并不了解真正使用的時(shí)候是由哪個(gè)服務(wù)提供WSDL中聲明到的“GetQuote”方法。

C#
using System.Web.Services;
using System.Threading;
using System.Web.Services.Protocols;
using System.Web.Services.Description;
using System.Xml.Serialization;
using DemoService;
namespace Test.Client
{
    /// <summary>
    /// Web Service 的客戶(hù)端 Proxy
    /// </summary>
    [WebServiceBindingAttribute(
        Name="QuoteServiceSoap",
        Namespace="http://www.visionlogic.com/trade")]
    public class QuoteService : SoapHttpClientProtocol
    {   
        /// <summary>
        /// 借助 SOAP 消息調用 Web Service 服務(wù)端
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [SoapDocumentMethodAttribute(
            "http://www.visionlogic.com/trade/GetQuote",
            RequestNamespace="http://www.visionlogic.com/trade",
            ResponseNamespace="http://www.visionlogic.com/trade",
            Use=SoapBindingUse.Literal,
            ParameterStyle=SoapParameterStyle.Wrapped)]
        [return: XmlElementAttribute("Quote",
            Namespace="http://www.visoinlogic.com/trade")]
        public Quote GetQuote(string id)
        {
            object[] results = this.Invoke("GetQuote", new object[] {id});
            return ((Quote)(results[0]));
        }
    }
}

7、客戶(hù)程序:

最后,通過(guò)單元測試工具檢查的客戶(hù)程序如下:

C#
using System;
using DemoService;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Test.Client
{
    /// <summary>
    /// 測試用客戶(hù)程序
    /// </summary>
    [TestClass]
    public class Client
    {
        /// <summary>
        /// 為了簡(jiǎn)化,這里在客戶(hù)程序中直接定義了具體報價(jià)Web Service的Uri.
        /// 實(shí)際開(kāi)發(fā)中該信息應該作為服務(wù)端的一個(gè)配置項登記在Directory之中,
        /// 客戶(hù)程序僅僅通過(guò)抽象的服務(wù)邏輯名稱(chēng)從Directory中獲得。)
        /// </summary>
        [TestMethod]
        public void Test()
        {
            QuoteService service = new QuoteService();
            service.Url = "http://localhost:2401/IntranetQuoteService.asmx";
            Quote quote = service.GetQuote("quote:2007-07-15");
            Assert.AreEqual<string>("quote:2007-07-15", quote.Id);
            Assert.AreEqual<string>("deluxe", quote.Company);
            Assert.AreEqual<int>(2, quote.QuoteItem.Length);
            Assert.IsNotNull(quote.QuoteItem[0]);
        }
    }
}

注:為了使用方便,本系列所有示例都沒(méi)有直接采用IIS作為Web Server宿主,而是采用Visual Studio.Net自帶的臨時(shí)服務(wù)進(jìn)程,因此WSDL和Proxy的使用上,相關(guān)端口可能會(huì )變化。

進(jìn)一步改進(jìn)

上面的示例在客戶(hù)端處理上不算成功,因為它需要客戶(hù)程序提供ConcreteService的Uri,怎么改進(jìn)呢?回憶我們通常對連接串的處置辦法:

  • 應用邏輯使用一個(gè)邏輯的數據庫名稱(chēng),通過(guò)一個(gè)數據訪(fǎng)問(wèn)框架調用邏輯的數據庫。
  • 數據訪(fǎng)問(wèn)框架中有一個(gè)類(lèi)似ConnectionManager的機制,負責把邏輯的數據庫連接名翻譯成實(shí)際的連接串。

對上面那個(gè)Web Service示例的也如法炮制,增加一個(gè)邏輯的Directory機制,實(shí)際工程中這個(gè)Directory可能就是個(gè)UDDI服務(wù),不過(guò)這里定義了一個(gè)精簡(jiǎn)對象。

圖5:為客戶(hù)程序增加服務(wù)Uri管理目錄機制

實(shí)現如下

C# IServiceDirectory
using System;
namespace Test.Client
{
    /// <summary>
    /// 抽象的服務(wù)目錄接口
    /// </summary>
    public interface IServiceDirectory
    {
        /// <summary>
        /// 通過(guò)索引器實(shí)現按名稱(chēng)或取實(shí)際服務(wù)Uri 的機制。
        /// 為了約束客戶(hù)程序對服務(wù)目錄的使用,僅提供一個(gè)readonly 的訪(fǎng)問(wèn)機制。
        /// </summary>
        /// <param name="name">邏輯的服務(wù)名稱(chēng)</param>
        /// <returns>實(shí)際服務(wù)實(shí)體的Uri </returns>
        string this[string name] { get;}
    }
}
C# LocalServiceDirectory
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
namespace Test.Client
{
    class LocalServiceDirectory : IServiceDirectory
    {
        /// <summary>
        /// 保存邏輯服務(wù)名稱(chēng)與具體Uri 對應關(guān)系的目錄字典。
        /// </summary>
        private static IDictionary<string, string> dictionary = null;

        /// <summary>
        /// 靜態(tài)構造的過(guò)程中,通過(guò)訪(fǎng)問(wèn)配置,獲取對應關(guān)系。
        /// </summary>
        static LocalServiceDirectory()
        {
            NameValueCollection appSettings = ConfigurationManager.AppSettings;
            if ((appSettings == null) || (appSettings.Count <= 0)) return;
            dictionary = new Dictionary<string, string>();
            foreach (string name in appSettings.Keys)
                dictionary.Add(name, appSettings[name]);
        }

        public string this[string name]
        {
            get
            {
                string uri;
                if (!dictionary.TryGetValue(name, out uri))
                    return string.Empty;
                else
                    return uri;
            }
        }
    }
}
C# DirectoryServiceFactory
using System;
namespace Test.Client
{
    /// <summary>
    /// 為了隔離客戶(hù)程序對實(shí)際DirectoryService 類(lèi)型的以來(lái),引入的服務(wù)目錄工廠(chǎng)。
    /// </summary>
    public static class DirectoryServiceFactory
    {
        /// <summary>
        /// 工廠(chǎng)方法。
        /// 世紀項目中,實(shí)體ServiceDirectory 類(lèi)型可能運行于遠端服務(wù)器上,
        /// 或者就是UDDI服務(wù),獲取IServiceDirectory 過(guò)程可能還需要借助代理程序完成。
        /// </summary>
        /// <returns></returns>
        public static IServiceDirectory Create()
        {
            return new LocalServiceDirectory();
        }
    }
}
C# 修改后的客戶(hù)程序
using System;
using DemoService;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Test.Client
{
    [TestClass]
    public class Client
    {
        [TestMethod]
        public void Test()
        {
            QuoteService service = new QuoteService();
            service.Url = DirectoryServiceFactory.Create()["QuoteService"];
  … …
        }
    }
}

進(jìn)一步討論

在有效的隔離了實(shí)體Web Service與抽象Web Service的關(guān)系后,之前設計模式、架構模式中的那些套路就又有了用武之地,比如Observer、Adapter、Factory、Blackboard、MVC… …,甚至于Visitor這中雙因素以來(lái)的模式也可以套用,只不過(guò)原來(lái)的消息變成了XML SOAP、對象實(shí)體變成了XSD定義下的各種XML,至于UI上能看到的東西還有需要轉換的信息由XSL完成即可。


作者簡(jiǎn)介:王翔,軟件架構師,主要方向為XML技術(shù)、.NET平臺開(kāi)發(fā)與集成、領(lǐng)域設計和公鑰基礎環(huán)境應用。近年主要參與數據交換系統、自訂制業(yè)務(wù)領(lǐng)域語(yǔ)言平臺項目和信息安全類(lèi)項目,工余時(shí)間喜歡旅游、寫(xiě)作、解趣味數學(xué)問(wèn)題和烹飪。
加入書(shū)簽
digg+,
reddit+,
del.icio.us+,
dzone+
標簽
XML

4 條回復

回復

或許應該更進(jìn)一步的抽象 發(fā)表人 Anders Lin 發(fā)表于 2007年8月2日 下午11時(shí)52分
Re: 或許應該更進(jìn)一步的抽象 發(fā)表人 hello hello 發(fā)表于 2007年8月3日 上午5時(shí)36分
Re: 或許應該更進(jìn)一步的抽象 發(fā)表人 hello hello 發(fā)表于 2007年8月3日 上午5時(shí)36分
Re: 或許應該更進(jìn)一步的抽象 發(fā)表人 hello hello 發(fā)表于 2007年8月3日 上午5時(shí)38分
  1. 返回頂部

    或許應該更進(jìn)一步的抽象

    2007年8月2日 下午11時(shí)52分 發(fā)表人 Anders Lin

    目前的抽象僅是隔離Web Service的抽象和實(shí)現,或許可以更進(jìn)一步,隔離接口和實(shí)現。接口的實(shí)現是調用web service還是調用本地,都不是client關(guān)心的。

  2. 返回頂部

    Re: 或許應該更進(jìn)一步的抽象

    2007年8月3日 上午5時(shí)36分 發(fā)表人 hello hello

    確切地說(shuō)現在已經(jīng)是這樣了。
    Client使用的Service其實(shí)不是真正的Service,而是Service的Proxy類(lèi)。
    是否使用Local,:), 其實(shí)也沒(méi)有關(guān)系,確切地說(shuō)把Assembly放到本地的話(huà),加個(gè)Factory就可以區分WS還是本地的某Assembly中的某各類(lèi)。

  3. 返回頂部

    Re: 或許應該更進(jìn)一步的抽象

    2007年8月3日 上午5時(shí)36分 發(fā)表人 hello hello

    確切地說(shuō)現在已經(jīng)是這樣了。
    Client使用的Service其實(shí)不是真正的Service,而是Service的Proxy類(lèi)。
    是否使用Local,:), 其實(shí)也沒(méi)有關(guān)系,確切地說(shuō)把Assembly放到本地的話(huà),加個(gè)Factory就可以區分WS還是本地的某Assembly中的某各類(lèi)。

  4. 返回頂部

    Re: 或許應該更進(jìn)一步的抽象

    2007年8月3日 上午5時(shí)38分 發(fā)表人 hello hello

    確切地說(shuō)現在已經(jīng)是這樣了。
    Client使用的Service其實(shí)不是真正的Service,而是Service的Proxy類(lèi)。
    是否使用Local,:), 其實(shí)也沒(méi)有關(guān)系,確切地說(shuō)把Assembly放到本地的話(huà),加個(gè)Factory就可以區分WS還是本地的某Assembly中的某各類(lèi)。

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
C#客戶(hù)端+PHP服務(wù)端的Web Service通信實(shí)現
用戶(hù)化JAXB綁定生成Java源代碼的簡(jiǎn)單嘗試
Java調用.NET webservice方法的幾種方式
深入研究SOAP消息
使用CXF發(fā)布和調用webservice之HelloWorld入門(mén)
用Axis 1.1 for Java進(jìn)行Web Services開(kāi)發(fā)(1)
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久