亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

深入Atlas系列之服務器端支持(下)

2019-11-17 04:51:50
字體:
來源:轉載
供稿:網友

  在上一篇文章里,我們分析了一部分服務器端的代碼。到現在為止,我們已經獲得處理Web Services方法請求的Handler,馬上就要開始PRocess Request了。

  我們知道,處理Web Services方法請求的Handler是RestHandler,所以我們來看一下它的ProcessHandler方法:

  ProcessRequest獲得調用結果代碼分析:

1 public void ProcessRequest(HttpContext context)
2 {
3 // 根據Web Services的Cache設置來配置Cache策略
4 this.InitializeCachePolicy(context);
5
6 try
7 {
8 string contentType;
9
10 // 從body的JSON字符串中得到輸入的參數。
11 IDictionary<string, object> inputParams = this.GetRawParams(context);
12
13 // this._webServiceMethodData.Ower.Type即獲得了即將調用的那個
14 // Web Service類,通過Activator.CreateInstance方法構造實例。
15 object serviceObj = Activator.CreateInstance(this._webServiceMethodData.Owner.Type);
16
17 // 這是一段很有技巧的代碼,我們目前不去分析它。
18 DataService service = serviceObj as DataService;
19 if (service != null)
20 {
21 service.IsCalledRemotely = true;
22 }
23
24 // Call這個Web Service方法來得到結果
25 object resultObj = this._webServiceMethodData.CallMethodFromRawParams(serviceObj, inputParams);
26
27 ……
28 }
29 catch (Exception e)
30 {
31 ……
32 }
33 }
  首先調用InitializeCachePolicy方法來處理緩存策略,代碼很短也很簡單,因此不多解釋了。其次查看serviceObj是否是DataService類型,假如是的話則將IsCalledRemotely設為ture,這是比較有技巧的做法,我們目前不去分析它。接著通過GetRawParams方法方法獲得以Dictionary方式存放的參數,我們需要看一下它的框架,可以了解它獲得參數的方法。

  GetRawParams(HttpContext) :

1 private IDictionary<string, object> GetRawParams(HttpContext context)
2 {
3 // 假如是Cross Domain access,則拋出異常
4 if (!this._webServiceMethodData.SafeForCrossDomain && ChildRequest.IsCrossDomainRequest(context))
5 {
6 throw new InvalidOperationException(
7 string.Format(
8 CultureInfo.CurrentCulture,
9 AtlasWeb.InvalidCrossDomainRequest,
10 new object[] { this._webServiceMethodData.MethodInfo.Name }));
11 }
12
13 // 假如使用HTTP POST方法
14 if (context.Request.HttpMethod == "POST")
15 {
16 // 則通過Body中的JSON代碼獲得參數
17 return this.GetRawParamsFromPostRequest(context);
18 }
19
20 // 由于使用了HTTP GET方法,需要看一下Web Services方法是否答應GET操作
21 if (!this._webServiceMethodData.GetVerbEnabled)
22 {
23 throw new InvalidOperationException(
24 string.Format(
25 CultureInfo.CurrentCulture,
26 AtlasWeb.InvalidGetRequest,
27 new object[] { this._webServiceMethodData.MethodInfo.Name }));
28 }
29
30 // 從Query String中獲得參數
31 return this.GetRawParamsFromGetRequest(context);
32 }
  一個Web Service方法,可以使用Microsoft.Web.Services.WebOperationAttribute來標記是否使用能夠通過GET方法訪問。下面的代碼讓該Web Service方法答應使用GET方法來訪問:

  [WebOperation(true)]

  獲得的Dictionary數據結構以Key - Value的方式對應的參數名和表示參數值的字符串,假如是復雜類型的話會產生許多層的Dictionary或List,大家應該能夠想象出來它是什么樣子,因為這和大名鼎鼎的JSON非常相似!獲得參數之后,會將其傳入WebServiceMethodData的CallMethodFromRawParams方法,以獲得方法執行的結果。

  WebServiceMethodData.CallMethodFromRawParams方法代碼如下:

  CallMethodFromRawParams方法分析


1 internal object CallMethodFromRawParams(object target, IDictionary<string, object> parameters)
2 {
3 // 獲得強類型的參數字典
4 parameters = this.StrongTypeParameters(parameters);
5 return this.CallMethod(target, parameters);
6 }
  首先通過StrongTypeParameters方法來獲得一個強類型的參數字典,它不會有多層的Dictionary或List。此方法非常的復雜,在這里就先不進行分析了,有愛好的朋友可以先看一下相關代碼,我會在今后的文章中分析這些代碼的細節,它們還是寫得非常優秀的。得到強類型的參數后,就會使用CallMethod來調用方法得到結果了。在這里面只是使用了簡單的Reflection,相信大家也能夠想象得到個中實現。

  接下來就要輸出結果了,代碼如下:

  ProcessRequest輸出結果代碼分析 :

1 public void ProcessRequest(HttpContext context)
2 {
3 ……
4
5 try
6 {
7 ……
8
9 // 假如這個Web Service方法被要求使用xml作為Response
10 if (this._webServiceMethodData.UseXmlResponse)
11 {
12 // 假如result是String,那么直接輸出
13 if (resultObj is string)
14 {
15 body = (string) resultObj;
16 }
17 else if (resultObj is XmlNode)
18 {
19 // 假如是一段XML,則輸出它的OuterXml
20 body = ((XmlNode) resultObj).OuterXml;
21 }
22 else // 假如只是一個普通的對象
23 {
24 try
25 {
26 // 使用XmlSerializer來序列化對象
27 body = ServicesUtilities.XmlSerializeObjectToString(resultObj);
28 }
29 catch (Exception e)
30 {
31 throw new InvalidOperationException(
32 string.Format(
33 CultureInfo.CurrentCulture,
34 AtlasWeb.InvalidXmlReturnType,
35 new object[] {
36 this._webServiceMethodData.MethodInfo.Name,
37 resultObj.GetType().FullName,
38 e.Message
39 }
40 )
41 );
42 }
43 }
44
45 // contentType為"text/xml"
46 contentType = "text/xml";
47 }
48 else // 假如不以Xml輸出
49 {
50 // 那么以JSON方式輸出
51 body = javascriptObjectSerializer.Serialize(resultObj, this._webServiceMethodData.Owner);
52 // contentType為"application/json"
53 contentType = "application/json";
54 }
55
56 // 設置ContentType
57 context.Response.ContentType = contentType;
58 // 輸出body
59 if (body != null)
60 {
61 context.Response.Write(body);
62 }
63 }
64 catch (Exception e)
65 {
66 ……
67 }
68 }
  要設置該Web Services方法的輸出方式為XML(UseXmlResponse == true),則也是需要使用Microsoft.Web.Services.WebOperationAttribute來標記方法,如下:

[WebOperation(false, ResponseFormatMode.Xml)]
  后面會有一個例子來演示這一點。假如該方法被標記使用XML方式輸出,則會判定結果類型。假如是字符串則直接輸出;假如是Xml類型的結果,則輸出它的OuterXml;最后則會嘗試使用XmlSerializer來序列化這個對象。

  在默認情況下,該對象會被JSON序列化輸出,這就是我們最常見的做法。

  最后,對于異常情況,也需要進行輸出。代碼如下:

  ProcessRequest輸出異常代碼分析 :

1 public void ProcessRequest(HttpContext context)
2 {
3 ……
4
5 try
6 {
7 ……
8 }
9 catch (Exception e)
10 {
11 // 輸出異常信息
12 context.Response.ClearHeaders();
13 context.Response.Clear();
14 // Status Code設為500
15 context.Response.StatusCode = 500;
16 context.Response.StatusDescription = HttpWorkerRequest.GetStatusDescription(500);
17 using (StreamWriter writer = new StreamWriter(context.Response.OutputStream, new UTF8Encoding(false)))
18 {
19 // 以JSON方式輸出異常信息
20 RestHandler.WriteExceptionJsonString(context, writer, e);
21 return;
22 }
23 }
24 }
  代碼使用RestHandler.WriteExceptionJsonString來分別輸出異常的Message,StackTrace和異常的FullName。在代碼里可以使用這一點。

  到現在為止,可以說Atlas在服務器端對于Web Services的支持代碼已經分析完了。我們通過兩個實例來具體理解這一點。
QQRead.com 推出數據恢復指南教程 數據恢復指南教程 數據恢復故障解析 常用數據恢復方案 硬盤數據恢復教程 數據保護方法 數據恢復軟件 專業數據恢復服務指南
  范例1:在Web Services方法中使用復雜的數據類型。

  首先,我們定義兩個表示數據的類,Employee和Company。代碼如下:

  Employee與Company代碼:

1 [Serializable]
2 public class Employee : IComparable<Employee>
3 {
4 public string Name;
5
6 public int Age;
7
8 #region IComparable<Employee> Members
9
10 public int CompareTo(Employee other)
11 {
12 return this.Name.CompareTo(other.Name);
13 }
14
15 #endregion
16 }
17
18 [Serializable]
19 public class Company
20 {
21 public string Name;
22
23 public Employee[] Employees;
24 }
  接著我們定義一個Web Services方法Sort,該方法的作用是拿到公司姓名和一個Employee數組作為參數,將Employee按照姓名排序之后,再組成一個Company對象輸出。代碼如下:

  Sort方法

1 [WebService(Namespace = "http://tempuri.org/")]
2 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
3 public class ComplexTypeWS : System.Web.Services.WebService {
4
5 [WebMethod]
6 public Company Sort(string companyName, Employee[] employees)
7 {
8 Array.Sort<Employee>(employees);
9
10 Company company = new Company();
11 company.Name = companyName;
12 company.Employees = employees;
13 return company;
14 }
15 }
  然后就是Html了。在頁面最上方(id為employees的div)會顯示內存中目前所有的Employee,之后是向內存中添加Employee的輸入框,接著是填寫公司名的文本框和排序按鈕,最后則是經過了Web Services排序后的結果顯示區域(id為sortedDisplay的div):

  HTML代碼:

1 <body style="font-family:Verdana; font-size: 14px;">
2 <form id="form1" runat="server">
3 <atlas:ScriptManager runat="server" ID="ScriptManager1" />
4
5 <div>Employees:</div>
6 <div id="employees"></div>
7 <hr />
8 <div>Add Employee:</div>
9 <div>Name: <input type="text" id="empName" /></div>
10 <div>Age: <input type="text" id="empAge" /></div>
11 <input type="button" value="Add employee" onclick="addEmployee()" /><br />
12 <hr />
13 <div>Company Name:<input type="text" id="companyName" /></div>
14 <input type="button" value="Sort!" onclick="sort()" /><br />
15 <hr />
16 <div id="sortedDisplay"></div>
17 </form>
18 </body>
  最后我們來看Javascript代碼:

  Javascript代碼:

1 <script language="javascript">
2 // 內存中的Employee數組
3 var empArray = new Array();
4
5 // 添加一個Employee
6 function addEmployee()
7 {
8 // 建立一個對象表示Employee
9 var emp = new Object();
10 emp.Name = $('empName').value;
11 emp.Age = parseInt($("empAge").value, 10);
12
13 // 加入數組
14 empArray.push(emp);
15
16 // 更新最上方的顯示
17 updateSource();
18 }
19
20 // 將內存中的empArray數組顯示在id為employee的div中
21 function updateSource()
22 {
23 var html = "";
24
25 for (var i = 0; i < empArray.length; i++)
26 {
27 var emp = empArray[i];
28 html += ((i + 1) + ". " + emp.Name + ", " + emp.Age + " years old.<br />")
29 }
30
31 $("employees").innerHTML = html;
32 }
33
34 // 訪問Web Service進行排序
35 function sort()
36 {
37 // 構造參數
38 var params = { "companyName" : $("companyName").value, "employees" : empArray };
39 // 構造Web Service方法訪問對象
40 var method = new Sys.Net.ServiceMethod("ComplexTypeWS.asmx", "Sort", null);
41
42 // 調用Web Service方法
43 method.invoke(params, onMethodComplete);
44 }
45
46 // 回調函數
47 function onMethodComplete(company, response, userContext)
48 {
49 // 在id為sortedDisplay的div中顯示所有的Employee,
50 // 可以發現company對象和服務器端對象的結構相同
51 var html = "Company Name: " + company.Name;
52 for (var i = 0; i < company.Employees.length; i++)
53 {
54 var emp = company.Employees[i];
55 html += ("<br />" + (i + 1) + ". " + emp.Name + ", " + emp.Age + " years old.")
56 }
57
58 $("sortedDisplay").innerHTML = html;
59
60 // 清空內存中的Employee
61 empArray.length = 0;
62 // 更新最上方的顯示
63 updateSource();
64 }
65 </script>
  所有的代碼都在這里,我們來看一下使用。首先打開頁面,輸入數個Employee,如圖:


深入Atlas系列之服務器端支持(下)(圖一)

  然后點擊填寫好Company Name并點擊Sort按鈕,則可以看出按照姓名排序后的結果:

深入Atlas系列之服務器端支持(下)(圖二)

  我們使用Fiddler查看一下數據傳輸,可以看到Request Body和Response Body里的JSON代碼:

深入Atlas系列之服務器端支持(下)(圖三)
點擊查看大圖

  可以看出,Atlas使用了JSON方式傳遞數據非常的直觀,對于復雜的類型支持也非常好。在客戶端得到的對象,其結構和服務器端相同,這對于開發人員帶來了不小的便利。 QQRead.com 推出數據恢復指南教程 數據恢復指南教程 數據恢復故障解析 常用數據恢復方案 硬盤數據恢復教程 數據保護方法 數據恢復軟件 專業數據恢復服務指南
  范例2:使用Web Services將對象序列化成XML并使用客戶端XSLTView空間輸出信息

  使用了與上例相同的Employee和Company兩個類,在這里就不重復了,先來看一下Web Service方法GetXmlSerializedCompany的代碼:

  GetXmlSerializedCompany方法代碼:

1 [WebService(Namespace = "http://tempuri.org/")]
2 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
3 public class ComplexTypeWS : System.Web.Services.WebService {
4
5 [WebMethod]
6 [WebOperation(false, ResponseFormatMode.Xml)]
7 public Company GetXmlSerializedCompany(Company company)
8 {
9 return company;
10 }
11 }
  這個方法簡單地令人驚奇,只是直接將參數返回。其精妙之處就是使用了Microsoft.Web.Services.WebOperationAttribute進行標記,表明了該方法將以XML形式輸出。

  接下來是HTML,與上例非常的相似,就不多作解釋了。代碼如下:

  HTML代碼:

1 <atlas:ScriptManager ID="ScriptManager1" runat="server" />
2
3 <form id="form1" runat="server">
4
5 <div>Employees:</div>
6 <div id="employees"></div>
7 <hr />
8 <div>Add Employee:</div>
9 <div>Name: <input type="text" id="empName" /></div>
10 <div>Age: <input type="text" id="empAge" /></div>
11 <input type="button" value="Add employee" onclick="addEmployee()" /><br />
12 <hr />
13 <div>Company Name:<input type="text" id="companyName" /></div>
14 <input type="button" value="Serialize!" onclick="serialize()" /><br />
15 <hr />
16 <div id="xmlDisplay"></div>
17
18 </form>
  然后預備一下Atlas Xml Script,聲明一個XmlDataSource,用來獲得XSLT文件。再添加一個XSLTView,將其transform屬性與XmlDataSource的document屬性綁定起來。代碼如下:

  Atlas Xml Script代碼:

1 <script type="text/xml-script">
2 <page>
3 <components>
4 <xmlDataSource id="xsltSource" autoLoad="true" serviceURL="Company.xsl" />
5 <xsltView id="xmlDisplay">
6 <bindings>
7 <binding property="transform" dataContext="xsltSource" dataPath="document" />
8 </bindings>
9 </xsltView>
10 </components>
11 </page>
12 </script>
  順便給出Company.xsl文件代碼:

  Company.xsl:


1 <?xml version="1.0" encoding="utf-8"?>
2 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
3 <xsl:template match="/Company">
4 <div>
5 Company:
6 <xsl:value-of select="Name" />
7 </div>
8 <xsl:for-each select="Employees/Employee">
9 <div>
10 <xsl:value-of select="Name" />
11 <xsl:text>, </xsl:text>
12 <xsl:value-of select="Age" />
13 <xsl:text> years old.</xsl:text>
14 </div>
15 </xsl:for-each>
16 </xsl:template>
17 </xsl:stylesheet>
  然后是Javascript代碼,大部分與上例相同,只作了少量注釋:

  Javascript代碼:

1 <script language="javascript">
2 var empArray = new Array();
3
4 function addEmployee()
5 {
6 var emp = new Object();
7 emp.Name = $('empName').value;
8 emp.Age = parseInt($("empAge").value, 10);
9
10 empArray.push(emp);
11 updateSource();
12 }
13
14 function updateSource()
15 {
16 var html = "";
17
18 for (var i = 0; i < empArray.length; i++)
19 {
20 var emp = empArray[i];
21 html += ((i + 1) + ". " + emp.Name + ", " + emp.Age + " years old.<br />")
22 }
23
24 $("employees").innerHTML = html;
25 }
26
27 function serialize()
28 {
29 // 構造一個Company對象作為參數,
30 // 結構和服務器端對象相同。
31 var company = new Object();
32 company.Name = $("companyName").value;
33 company.Employees = empArray;
34
35 var params = { "company" : company }
36 var method = new Sys.Net.ServiceMethod("ComplexTypeWS.asmx", "GetXmlSerializedCompany", null);
37
38 method.invoke(params, onMethodComplete);
39 }
40
41 function onMethodComplete(resultXml, response, userContext)
42 {
43 // 這時第一個參數是一個Xml,
44 // 用它來設置XSLTView的document屬性。
45 $("xmlDisplay").control.set_document(resultXml);
46
47 empArray.length = 0;
48 updateSource();
49 }
50 </script>
  代碼就是這些,接下來看一下使用。首先依舊是添加數個Employee:

深入Atlas系列之服務器端支持(下)(圖四)

  填寫Company Name并點擊“Serialize!”按鈕,可以看到下方的XSLT輸出:

深入Atlas系列之服務器端支持(下)(圖五)

  使用Fiddler查看的Request Body和Response Body的信息:

深入Atlas系列之服務器端支持(下)(圖六)
點擊查看大圖

  正如我們所期望的那樣,Response Body里的信息是Company對象被Xml序列化之后的結果,然后使用XSLT轉換后即得到了我們需要的信息!

  通過了上面兩個例子,我們可以看出Atlas對于Web Services的支持是非常靈活的。具體的使用方式讓開發人員有很大的發揮空間,開發人員完全可以選擇合適的方式把Atlas靈活運用在自己的項目中。

  當然,Atlas對于Web Services的支持還遠不止這些,在以后的文章里我會繼續從實現角度對Atlas的Web Services進行分析,并提供更多的范例給大家參考。希望大家支持我的“深入Atlas系列”,謝謝大家。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产精品人人做人人爽| 精品夜色国产国偷在线| 亚洲第一页在线| 日本国产欧美一区二区三区| 日韩美女写真福利在线观看| 岛国av一区二区三区| 久久人人爽人人爽人人片av高请| 国产精品视频久久| 欧美精品亚州精品| 欧美激情视频在线| 日韩欧美在线视频日韩欧美在线视频| 欧美三级免费观看| 欧美一区二区视频97| 久久久免费在线观看| 亚洲第一中文字幕在线观看| 成人午夜一级二级三级| 欧美专区在线视频| 亚洲最新中文字幕| 高清欧美性猛交xxxx| 久久福利视频导航| 亚洲欧美日韩精品久久亚洲区| 亚洲精品欧美日韩专区| 欧美日韩美女在线| 日韩极品精品视频免费观看| 91久久在线观看| 久久免费视频这里只有精品| 日韩av影视在线| 国产一区二区三区丝袜| 精品人伦一区二区三区蜜桃免费| 国产欧美日韩综合精品| 欧美黑人性生活视频| 欧美极品少妇xxxxⅹ裸体艺术| 欧美极品少妇全裸体| 国产一区二区成人| 欧美最顶级丰满的aⅴ艳星| 亚洲人成人99网站| 国语自产精品视频在线看抢先版图片| 国产视频精品自拍| 欧美xxxx18性欧美| 亚洲国产精品热久久| 日韩欧美成人免费视频| 美日韩精品免费观看视频| 在线观看精品自拍私拍| 国产精品国产亚洲伊人久久| 欧美日韩另类在线| 在线观看91久久久久久| 欧美洲成人男女午夜视频| 8090理伦午夜在线电影| 国产精品一区二区三区久久久| 欧美日韩中国免费专区在线看| 国产精品高潮视频| 欧美老女人性视频| 91中文在线视频| 亚洲成人免费网站| 91精品国产综合久久香蕉的用户体验| 国产一区视频在线播放| 欧美性资源免费| 97香蕉超级碰碰久久免费的优势| 一本一道久久a久久精品逆3p| 中文字幕视频在线免费欧美日韩综合在线看| 91久久精品日日躁夜夜躁国产| 国产成人精品视频在线观看| 亚洲成人精品视频在线观看| 日韩欧美主播在线| 色婷婷av一区二区三区久久| 亚洲国产97在线精品一区| 国产亚洲精品美女久久久| 国产精品免费一区豆花| 亚洲国产欧美一区二区三区同亚洲| 最近2019中文字幕第三页视频| 国产精品高清在线| 菠萝蜜影院一区二区免费| 日韩专区在线观看| 国产欧美日韩亚洲精品| 精品日韩视频在线观看| 中文字幕亚洲情99在线| 亚洲欧美日韩天堂| 久久久久久成人精品| 日韩电影在线观看免费| 日韩欧美亚洲国产一区| 国产精品一区二区三区毛片淫片| 最近日韩中文字幕中文| 久久精品国产久精国产思思| 久久久精品一区二区三区| 最近更新的2019中文字幕| 久久亚洲精品成人| 国产精品偷伦免费视频观看的| 国产精品久久久久不卡| 欧美性xxxx极品高清hd直播| 亚洲第一精品久久忘忧草社区| 久久精品国产96久久久香蕉| 美女扒开尿口让男人操亚洲视频网站| 亚洲国产欧美自拍| 色琪琪综合男人的天堂aⅴ视频| 日韩免费在线看| 亚洲国产99精品国自产| 亚洲欧洲午夜一线一品| 国产精品青青在线观看爽香蕉| 日韩欧美在线一区| 欧美区二区三区| 国产精品va在线播放我和闺蜜| 国产精品极品美女在线观看免费| 91亚洲午夜在线| 日韩在线播放一区| 国产在线视频2019最新视频| 日本一区二区在线免费播放| 国产一区二区三区视频免费| 久久久久久网址| 亚洲成av人片在线观看香蕉| 91国在线精品国内播放| 亚洲欧美综合图区| 隔壁老王国产在线精品| 精品亚洲aⅴ在线观看| 国产在线98福利播放视频| 奇门遁甲1982国语版免费观看高清| 在线丨暗呦小u女国产精品| 欧美性少妇18aaaa视频| 亚洲精品欧美日韩| 九九热精品在线| 亚洲色图35p| 国产精品久久久久免费a∨| 亚洲免费福利视频| 欧美猛交ⅹxxx乱大交视频| 欧美精品一区二区三区国产精品| 国产成人+综合亚洲+天堂| 欧美裸体xxxx| 欧美巨大黑人极品精男| 欧美激情伊人电影| 国产精品日本精品| 亚洲欧美日本伦理| 久久久久久12| 一本色道久久综合亚洲精品小说| 黄网动漫久久久| 亚洲国产欧美久久| 国产精品福利久久久| 久久久999成人| 中文字幕亚洲综合| 亚洲免费小视频| 亚洲国产精品一区二区三区| 国产精品久久久久久超碰| 国产成人精品一区二区| 亚洲一区二区福利| 一本色道久久88综合亚洲精品ⅰ| 91精品国产777在线观看| 亚洲综合在线播放| 日韩第一页在线| 国产成人jvid在线播放| 亚洲美女在线视频| 91精品国产色综合久久不卡98口| 午夜精品视频在线| 欧美成人精品在线视频| 一个色综合导航| 国产成人综合av| 久久影视免费观看| 91av在线国产| 欧美成年人网站| 国产精品视频一区二区高潮| 亚洲va国产va天堂va久久| 色综合老司机第九色激情| www.日韩av.com| 日韩人在线观看| 97精品国产97久久久久久| 亚洲免费伊人电影在线观看av| 成人免费淫片视频软件|