<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 使用WebSocket構建交互式Web應用程序 本指南將引導您完成創建“ Hello,world”應用程序的過程,該應用程序在瀏覽器和服務器之間來回發送消息。 WebSocket是TCP之上的薄而輕的層。 這使其適合使用“子協議”來嵌入消息。 在本指南中,我們將 [STOMP](https://en.wikipedia.org/wiki/Streaming_Text_Oriented_Messaging_Protocol) 消息與Spring結合使用來創建一個交互式Web應用程序。 STOMP是在較低級別的WebSocket之上運行的子協議。 ## 你會建立什么 您將構建一個服務器,該服務器接受帶有用戶名的消息。 作為響應,服務器會將問候語推送到客戶端已訂閱的隊列中。 ## 你需要什么 * 約15分鐘 * 最喜歡的文本編輯器或IDE * [JDK 1.8](http://www.oracle.com/technetwork/java/javase/downloads/index.html) 或更高版本 * [Gradle 4+](http://www.gradle.org/downloads) 或 [Maven 3.2+](https://maven.apache.org/download.cgi) * 您還可以將代碼直接導入到IDE中: * [彈簧工具套件(STS)](https://spring.io/guides/gs/sts) * [IntelliJ IDEA](https://spring.io/guides/gs/intellij-idea/) ## 如何完成本指南 像大多數Spring 一樣 [入門指南](https://spring.io/guides) ,您可以從頭開始并完成每個步驟,也可以繞過您已經熟悉的基本設置步驟。 無論哪種方式,您最終都可以使用代碼。 要 **從頭開始** ,請繼續進行“ [從Spring Initializr開始”](https://spring.io/guides/gs/messaging-stomp-websocket/#scratch) 。 要 **跳過基礎知識** ,請執行以下操作: * [下載](https://github.com/spring-guides/gs-messaging-stomp-websocket/archive/master.zip) 并解壓縮本指南的源存儲庫,或使用 對其進行克隆 [Git](https://spring.io/understanding/Git) : `git clone [https://github.com/spring-guides/gs-messaging-stomp-websocket.git](https://github.com/spring-guides/gs-messaging-stomp-websocket.git)` * 光盤進入 `gs-messaging-stomp-websocket/initial` * 繼續 [創建資源表示形式類](https://spring.io/guides/gs/messaging-stomp-websocket/#initial) 。 **完成后** ,您可以根據中的代碼檢查結果 `gs-messaging-stomp-websocket/complete`. ## 從Spring Initializr開始 如果您使用Maven,請訪問 [Spring Initializr](https://start.spring.io/#!type=maven-project&language=java&platformVersion=2.4.3.RELEASE&packaging=jar&jvmVersion=1.8&groupId=com.example&artifactId=messaging-stomp-websocket&name=messaging-stomp-websocket&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.messaging-stomp-websocket&dependencies=websocket) 以生成具有所需依賴項的新項目(Websocket)。 以下清單顯示了 `pom.xml` 選擇Maven時創建的文件: ~~~ <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.3</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>messaging-stomp-websocket</artifactId> <version>0.0.1-SNAPSHOT</version> <name>messaging-stomp-websocket</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> ~~~ 如果您使用Gradle,請訪問 [Spring Initializr](https://start.spring.io/#!type=gradle-project&language=java&platformVersion=2.4.3.RELEASE&packaging=jar&jvmVersion=1.8&groupId=com.example&artifactId=messaging-stomp-websocket&name=messaging-stomp-websocket&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.messaging-stomp-websocket&dependencies=websocket) 以生成具有所需依賴項的新項目(Websocket)。 以下清單顯示了 `build.gradle` 選擇Gradle時創建的文件: ~~~ plugins { id 'org.springframework.boot' version '2.4.3' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-websocket' testImplementation 'org.springframework.boot:spring-boot-starter-test' } test { useJUnitPlatform() } ~~~ ### 手動初始化(可選) 如果要手動初始化項目而不是使用前面顯示的鏈接,請按照以下步驟操作: 1. 導航到 [https://start.spring.io](https://start.spring.io) 。 該服務提取應用程序所需的所有依賴關系,并為您完成大部分設置。 2. 選擇Gradle或Maven以及您要使用的語言。 本指南假定您選擇了Java。 3. 單擊“ **依賴關系”,** 然后選擇“ **Websocket”** 。 4. 點擊 **生成** 。 5. 下載生成的ZIP文件,該文件是使用您的選擇配置的Web應用程序的存檔。 如果您的IDE集成了Spring Initializr,則可以從IDE中完成此過程。 ## 添加依賴項 在這種情況下,Spring Initializr不會提供您所需的一切。 對于Maven,您需要添加以下依賴項: ~~~ <dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator-core</artifactId> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>sockjs-client</artifactId> <version>1.0.2</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>stomp-websocket</artifactId> <version>2.3.3</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.3.7</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.1.1-1</version> </dependency> ~~~ 以下清單顯示了成品 `pom.xml` 文件: ~~~ <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.3</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>messaging-stomp-websocket</artifactId> <version>0.0.1-SNAPSHOT</version> <name>messaging-stomp-websocket</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>webjars-locator-core</artifactId> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>sockjs-client</artifactId> <version>1.0.2</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>stomp-websocket</artifactId> <version>2.3.3</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.3.7</version> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.1.1-1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> ~~~ 如果使用Gradle,則需要添加以下依賴項: ~~~ implementation 'org.webjars:webjars-locator-core' implementation 'org.webjars:sockjs-client:1.0.2' implementation 'org.webjars:stomp-websocket:2.3.3' implementation 'org.webjars:bootstrap:3.3.7' implementation 'org.webjars:jquery:3.1.1-1' ~~~ 以下清單顯示了成品 `build.gradle` 文件: ~~~ plugins { id 'org.springframework.boot' version '2.4.3' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' } group = 'com.example' version = '0.0.1-SNAPSHOT' sourceCompatibility = '1.8' repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-websocket' implementation 'org.webjars:webjars-locator-core' implementation 'org.webjars:sockjs-client:1.0.2' implementation 'org.webjars:stomp-websocket:2.3.3' implementation 'org.webjars:bootstrap:3.3.7' implementation 'org.webjars:jquery:3.1.1-1' testImplementation 'org.springframework.boot:spring-boot-starter-test' } test { useJUnitPlatform() } ~~~ ## 創建資源表示形式類 現在,您已經設置了項目和構建系統,您可以創建STOMP消息服務。 通過考慮服務交互來開始該過程。 該服務將接受正文為JSON對象的STOMP消息中包含名稱的消息。 如果名字是 `Fred`,該消息可能類似于以下內容: ~~~ { "name": "Fred" } ~~~ 要對帶有名稱的消息進行建模,可以創建一個普通的舊Java對象,其中包含一個 `name` 屬性和相應的 `getName()` 方法,如下清單(來自 `src/main/java/com/example/messagingstompwebsocket/HelloMessage.java`)顯示: ~~~ package com.example.messagingstompwebsocket; public class HelloMessage { private String name; public HelloMessage() { } public HelloMessage(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } } ~~~ 收到消息并提取名稱后,服務將通過創建問候語并將該問候語發布到客戶端已訂閱的單獨隊列上來對其進行處理。 問候語也將是一個JSON對象,如以下清單所示: ~~~ { "content": "Hello, Fred!" } ~~~ 要對問候表示進行建模,請添加另一個普通的舊Java對象,其中包含 `content` 屬性和相應的 `getContent()` 方法,如下清單(來自 `src/main/java/com/example/messagingstompwebsocket/Greeting.java`)顯示: ~~~ package com.example.messagingstompwebsocket; public class Greeting { private String content; public Greeting() { } public Greeting(String content) { this.content = content; } public String getContent() { return content; } } ~~~ Spring將使用 [Jackson JSON](https://wiki.fasterxml.com/JacksonHome) 庫自動封送類型的實例 `Greeting` 轉換成JSON。 接下來,您將創建一個控制器來接收問候消息并發送問候消息。 ## 創建一個消息處理控制器 在Spring使用STOMP消息傳遞的方法中,可以將STOMP消息路由到 [`@Controller`](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/stereotype/Controller.html)類。 例如, `GreetingController` (從 `src/main/java/com/example/messagingstompwebsocket/GreetingController.java`)被映射為處理到 `/hello` 目的地,如以下清單所示: ~~~ package com.example.messagingstompwebsocket; import org.springframework.messaging.handler.annotation.MessageMapping; import org.springframework.messaging.handler.annotation.SendTo; import org.springframework.stereotype.Controller; import org.springframework.web.util.HtmlUtils; @Controller public class GreetingController { @MessageMapping("/hello") @SendTo("/topic/greetings") public Greeting greeting(HelloMessage message) throws Exception { Thread.sleep(1000); // simulated delay return new Greeting("Hello, " + HtmlUtils.htmlEscape(message.getName()) + "!"); } } ~~~ 該控制器簡潔明了,但仍在繼續。 我們將其逐步分解。 這 [`@MessageMapping`](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/messaging/handler/annotation/MessageMapping.html) 注釋可確保,如果有消息發送到 `/hello` 目的地, `greeting()` 方法被調用。 消息的有效負載綁定到 `HelloMessage` 對象,該對象被傳遞到 `greeting()`. 在內部,該方法的實現通過使線程休眠一秒鐘來模擬處理延遲。 這表明客戶端發送消息后,服務器可以花費其異步處理消息所需的時間。 客戶可以繼續進行所需的任何工作,而無需等待響應。 一秒鐘的延遲后, `greeting()` 方法創建一個 `Greeting`對象并返回它。 返回值將廣播給 `/topic/greetings`,如 [`@SendTo`](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/messaging/handler/annotation/SendTo.html)注解。 請注意,輸入消息中的名稱已被清除,因為在這種情況下,它將在客戶端的瀏覽器DOM中回顯并重新呈現。 ## 為STOMP消息傳遞配置Spring 現在已經創建了服務的基本組件,您可以配置Spring以啟用WebSocket和STOMP消息傳遞。 創建一個名為的Java類 `WebSocketConfig` 類似于以下清單(來自 `src/main/java/com/example/messagingstompwebsocket/WebSocketConfig.java`): ~~~ package com.example.messagingstompwebsocket; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/gs-guide-websocket").withSockJS(); } } ~~~ `WebSocketConfig` 帶有注釋 `@Configuration`表示它是Spring配置類。 它也帶有注釋 [`@EnableWebSocketMessageBroker`](https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/messaging/simp/config/EnableWebSocketMessageBroker.html)。 顧名思義, `@EnableWebSocketMessageBroker` 啟用由消息代理支持的WebSocket消息處理。 這 `configureMessageBroker()` 方法在中實現默認方法 `WebSocketMessageBrokerConfigurer`配置消息代理。 它首先通過調用 `enableSimpleBroker()` 使基于內存的簡單消息代理能夠將問候消息以前綴為前綴的目的地攜帶回客戶端 `/topic`。 它還指定了 `/app` 消息的前綴,該消息綁定到帶有方法注釋的方法 `@MessageMapping`。 此前綴將用于定義所有消息映射。 例如, `/app/hello` 是端點 `GreetingController.greeting()` 方法被映射為句柄。 這 `registerStompEndpoints()` 方法注冊 `/gs-guide-websocket`端點,啟用SockJS后備選項,以便在WebSocket不可用時可以使用備用傳輸。 SockJS客戶端將嘗試連接到 `/gs-guide-websocket`并使用最佳的傳輸方式(websocket,xhr-streaming,xhr-polling等)。 ## 創建瀏覽器客戶端 在服務器端組件就緒后,您可以將注意力轉移到JavaScript客戶端上,該客戶端將向服務器端發送消息并從服務器端接收消息。 創建一個 `index.html` 類似于以下清單的文件(來自 `src/main/resources/static/index.html`): ~~~ <!DOCTYPE html> <html> <head> <title>Hello WebSocket</title> <link href="/webjars/bootstrap/css/bootstrap.min.css" rel="stylesheet"> <link href="/main.css" rel="stylesheet"> <script src="/webjars/jquery/jquery.min.js"></script> <script src="/webjars/sockjs-client/sockjs.min.js"></script> <script src="/webjars/stomp-websocket/stomp.min.js"></script> <script src="/app.js"></script> </head> <body> <noscript><h2 style="color: #ff0000">Seems your browser doesn't support Javascript! Websocket relies on Javascript being enabled. Please enable Javascript and reload this page!</h2></noscript> <div id="main-content" class="container"> <div class="row"> <div class="col-md-6"> <form class="form-inline"> <div class="form-group"> <label for="connect">WebSocket connection:</label> <button id="connect" class="btn btn-default" type="submit">Connect</button> <button id="disconnect" class="btn btn-default" type="submit" disabled="disabled">Disconnect </button> </div> </form> </div> <div class="col-md-6"> <form class="form-inline"> <div class="form-group"> <label for="name">What is your name?</label> <input type="text" id="name" class="form-control" placeholder="Your name here..."> </div> <button id="send" class="btn btn-default" type="submit">Send</button> </form> </div> </div> <div class="row"> <div class="col-md-12"> <table id="conversation" class="table table-striped"> <thead> <tr> <th>Greetings</th> </tr> </thead> <tbody id="greetings"> </tbody> </table> </div> </div> </div> </body> </html> ~~~ 這個HTML檔案會匯入 `SockJS` 和 `STOMP`javascript庫,這些庫將用于通過websocket通過STOMP與我們的服務器進行通信。 我們也進口 `app.js`,其中包含我們客戶應用程序的邏輯。 以下清單(來自 `src/main/resources/static/app.js`)顯示該文件: ~~~ var stompClient = null; function setConnected(connected) { $("#connect").prop("disabled", connected); $("#disconnect").prop("disabled", !connected); if (connected) { $("#conversation").show(); } else { $("#conversation").hide(); } $("#greetings").html(""); } function connect() { var socket = new SockJS('/gs-guide-websocket'); stompClient = Stomp.over(socket); stompClient.connect({}, function (frame) { setConnected(true); console.log('Connected: ' + frame); stompClient.subscribe('/topic/greetings', function (greeting) { showGreeting(JSON.parse(greeting.body).content); }); }); } function disconnect() { if (stompClient !== null) { stompClient.disconnect(); } setConnected(false); console.log("Disconnected"); } function sendName() { stompClient.send("/app/hello", {}, JSON.stringify({'name': $("#name").val()})); } function showGreeting(message) { $("#greetings").append("<tr><td>" + message + "</td></tr>"); } $(function () { $("form").on('submit', function (e) { e.preventDefault(); }); $( "#connect" ).click(function() { connect(); }); $( "#disconnect" ).click(function() { disconnect(); }); $( "#send" ).click(function() { sendName(); }); }); ~~~ 該JavaScript文件的主要內容是 `connect()` 和 `sendName()` 功能。 這 `connect()`函數使用 [SockJS](https://github.com/sockjs) 和 [stomp.js](http://jmesnil.net/stomp-websocket/doc/) 打開與 `/gs-guide-websocket`,這是我們的SockJS服務器等待連接的地方。 連接成功后,客戶端將訂閱 `/topic/greetings`服務器將在其中發布問候消息的目的地。 在該目的地上收到問候語時,它將在DOM后面添加一個段落元素以顯示問候語消息。 這 `sendName()` 函數檢索用戶輸入的名稱,并使用STOMP客戶端將其發送到 `/app/hello` 目的地(哪里 `GreetingController.greeting()` 將會收到)。 這 `main.css` 可以根據需要將其省略,也可以創建一個空的,這樣 `<link>` 可以解決。 ## 使應用程序可執行 Spring Boot為您創建一個應用程序類。 在這種情況下,無需進一步修改。 您可以使用它來運行該應用程序。 以下清單(來自 `src/main/java/com/example/messagingstompwebsocket/MessagingStompWebsocketApplication.java`)顯示了應用程序類: ~~~ package com.example.messagingstompwebsocket; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MessagingStompWebsocketApplication { public static void main(String[] args) { SpringApplication.run(MessagingStompWebsocketApplication.class, args); } } ~~~ `@SpringBootApplication` 是一個方便注釋,它添加了以下所有內容: * `@Configuration`:將類標記為應用程序上下文的Bean定義的源。 * `@EnableAutoConfiguration`:告訴Spring Boot根據類路徑設置,其他bean和各種屬性設置開始添加bean。 例如,如果 `spring-webmvc` 在類路徑上,此注釋將應用程序標記為Web應用程序并激活關鍵行為,例如設置 `DispatcherServlet`. * `@ComponentScan`:告訴Spring在服務器中尋找其他組件,配置和服務 `com/example` 包,讓它找到控制器。 這 `main()` 方法使用Spring Boot的 `SpringApplication.run()`啟動應用程序的方法。 您是否注意到沒有一行XML? 沒有 `web.xml`文件。 該Web應用程序是100%純Java,因此您無需處理任何管道或基礎結構。 ### 建立可執行的JAR 您可以使用Gradle或Maven從命令行運行該應用程序。 您還可以構建一個包含所有必需的依賴項,類和資源的可執行JAR文件,然后運行該文件。 生成可執行jar使得在整個開發生命周期中,跨不同環境等等的情況下,都可以輕松地將服務作為應用程序進行發布,版本控制和部署。 如果您使用Gradle,則可以通過使用以下命令運行該應用程序 `./gradlew bootRun`。 或者,您可以通過使用以下命令構建JAR文件: `./gradlew build` 然后運行JAR文件,如下所示: ~~~ java -jar build/libs/gs-messaging-stomp-websocket-0.1.0.jar ~~~ 如果您使用Maven,則可以通過使用以下命令運行該應用程序 `./mvnw spring-boot:run`。 或者,您可以使用以下命令構建JAR文件: `./mvnw clean package` 然后運行JAR文件,如下所示: ~~~ java -jar target/gs-messaging-stomp-websocket-0.1.0.jar ~~~ 此處描述的步驟將創建可運行的JAR。 您還可以 構建經典的WAR文件 。 顯示日志記錄輸出。 該服務應在幾秒鐘內啟動并運行。 ## 測試服務 現在該服務正在運行,將瀏覽器指向 [http:// localhost:8080](http://localhost:8080) 并單擊“ **連接”** 按鈕。 打開連接后,系統會要求您輸入名稱。 輸入您的姓名,然后單擊 **發送** 。 您的姓名將通過STOMP作為JSON消息發送到服務器。 經過一秒鐘的模擬延遲后,服務器將向頁面發送回帶有“ Hello”問候的消息,該問候顯示在頁面上。 此時,您可以發送其他名稱,也可以單擊“ **斷開連接”** 按鈕以關閉連接。 ## 概括 恭喜你! 您剛剛使用Spring開發了基于STOMP的消息傳遞服務。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看