Spring實踐--Websocket集成和XML配置

WebSocket 簡介

WebSocket 是 HTML5 一種新的協議。它實現了瀏覽器與服務器全雙工通訊,能更好的節省服務器資源和帶寬並達到實時通信,它創建在 TCP 之上,同 HTTP 同樣經過 TCP 來傳輸數據,可是它和 HTTP 最大不一樣是:javascript

  • WebSocket 是一種雙向通訊協議,在創建鏈接後,WebSocket 服務器和 Browser/Client Agent 都能主動的向對方發送或接收數據,就像 Socket 同樣;
  • WebSocket 須要相似 TCP 的客戶端和服務器端經過握手鍊接,鏈接成功後才能相互通訊。

整合示例

本示例爲演示WebSocket的廣播式模式,即服務端有消息時,會將消息發送給全部鏈接了當前endpoint的 Browser/Client Agenthtml

 1. maven引入依賴包

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>4.3.8.RELEASE</spring.version>
    </properties>
    <dependencies>
        <!-- springmvc jar -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- WEBSOCKET的JAR -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-messaging</artifactId>
            <version>${spring.version}</version>
        </dependency>

    </dependencies>

2. 編寫WebSocket的配置類

Annotation註解配置方式(boot):WebSocketConfig.java

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;


@Configuration
//開啓對WebSocket的支持
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer{

	/**
	 * 註冊一個STOMP協議的節點,並映射到指定的URL
	 * @param registry
	 */
	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		//註冊一個STOMP的endpoint,並指定使用SockJS協議
		registry.addEndpoint("/endpointSocket").withSockJS();
	}

	/**
	 * 配置消息代理
	 * @param registry
	 */
	@Override
	public void configureMessageBroker(MessageBrokerRegistry registry) {
		//配置一個廣播式的消息代理
		registry.enableSimpleBroker("/topic");
	}
}

XML配置方式:spring-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:websocket="http://www.springframework.org/schema/websocket"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/websocket http://www.springframework.org/schema/websocket/spring-websocket.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
    </context:component-scan>
    <mvc:annotation-driven/>

    <mvc:resources mapping="/js/**" location="/js/"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!-- /app:客戶端向服務端 發送的前綴 -->
    <websocket:message-broker application-destination-prefix="/app">
        <websocket:stomp-endpoint path="/ws">
            <websocket:sockjs/>
        </websocket:stomp-endpoint>
        <!-- 服務端向客戶端 發送的前綴 -->
        <websocket:simple-broker prefix="/topic"/>
    </websocket:message-broker>

</beans>

 

3. 請求控制器

import java.util.Map;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
 * 由客戶端觸發,並接受服務器發送信息的例子
 */
@Controller
public class MessageController {

	@RequestMapping(value = "/websocket", method = { RequestMethod.GET })
	public String toHello() {
		System.out.println("messageController ----> tohello()");
		return "websocket";  //定位到頁面
	}

	@MessageMapping("/greeting")
	@SendTo("/topic/greetings")
	public String greeting(Map<String, Object> message) throws Exception {
		System.out.println("MessageController====================================>客戶端鏈接");
		return "服務器返回: Hello,客戶端輸入信息< " + message.get("name") + ">";
	}
}

 

4. 頁面webSocket.jsp

<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page session="false"%>
<%
	String path = request.getContextPath(); //  path = "/travel"
	String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Spring + WebSocket Hello world例子</title>
<script src="<%=basePath%>js/sockjs-1.1.1.min.js"></script>
<script src="<%=basePath%>js/stomp-2.3.4.min.js"></script>
<script src="<%=basePath%>/js/jquery-1.10.2.js"></script>
<script src="<%=basePath%>/js/jquery-ui-1.10.4.custom.js"></script>
<script src="<%=basePath%>/js/jquery.json.js"></script>
<script>
	//建立sockJS協議
	var socket = new SockJS("<c:url value='/ws'/>");
	var stompClient = Stomp.over(socket);
	//鏈接服務器
	//stompClient.connect("guest", "guest", function() {}); 用戶名和密碼
	stompClient.connect({}, function(frame) {
		//setConnected(true);
		$("#recFromServer").append("<br>" + "成功鏈接服務器.!");
		console.log('Connected: ' + frame);
		window.alert('Connected: ' + frame);
		//subscribe:訂閱一個主題,「/topic」前綴是在:
		stompClient.subscribe('/topic/greetings', function(greeting) {
			console.log(greeting.body);
			console.log("本身的操做!");
			var content = JSON.parse(greeting.body).content;
			$("#recFromServer").append("<br>" + content);
		});
	});
	
	function sendMessage() {
		//發送信息給服務器
		stompClient.send("/app/greeting", {}, JSON.stringify({
			'name' : $("#message").val()
		}));
	}
</script>
</head>
<body>
	輸入名稱:${basePath }
	<input id="message" type="text">
	<input type="button" onclick="sendMessage()" value="發送到服務器">
	<div id="recFromServer"></div>
	測試方式: 用兩個瀏覽器打開這個頁面,而後一個頁面提交信息,它能接收到服務器的數據,同時另外一個頁面也能接收到服務器發送的數據。
</body>
</html>

菜鳥代碼示例

<!DOCTYPE HTML>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>My WebSocket</title>
</head>
<body>
    <input id="text" type="text" />
    <button onclick="send()">Send</button>
    <button onclick="closeWebSocket()">Close</button>
    <div id="message">
    </div>
</body>
<script type="text/javascript">
    var websocket = null;

    //判斷當前瀏覽器是否支持WebSocket
    if('WebSocket' in window){
        //若是支持WebSocket,發起WebSocket鏈接
        websocket = new WebSocket("ws://localhost:8088/websocket");
    } else{
        alert('Not support websocket')
    }

    //鏈接發生錯誤的回調方法
    websocket.onerror = function(){
        setMessageInnerHTML("error");
    };

    //鏈接成功創建的回調方法
    websocket.onopen = function(event){
        setMessageInnerHTML("open");
    }

    //接收到消息的回調方法
    websocket.onmessage = function(event){
        setMessageInnerHTML(event.data);
    }

    //鏈接關閉的回調方法
    websocket.onclose = function(){
        setMessageInnerHTML("close");
    }

    //監聽窗口關閉事件,當窗口關閉時,主動去關閉websocket鏈接,防止鏈接還沒斷開就關閉窗口,server端會拋異常。
    window.onbeforeunload = function(){
        //關閉鏈接
        websocket.close();
    }

    //將消息顯示在網頁上
    function setMessageInnerHTML(innerHTML){
        document.getElementById('message').innerHTML += innerHTML + '<br/>';
    }

    //關閉鏈接
    function closeWebSocket(){
        websocket.close();
    }

    //發送消息
    function send(){
        var message = document.getElementById('text').value;
        //發送消息
        websocket.send(message);
    }
</script>
</html>

 

啓動並測試

也可打開多個瀏覽器窗口鏈接到WebSocket服務端,在其中一個瀏覽器窗口中點擊獲取服務器時間,其餘兩個也將接收到消息html5

相關文章
相關標籤/搜索