Spring实践--Websocket集成和XML配置

WebSocket 简介

WebSocket 是 HTML5 一种新的协议。它实现了浏览器与服务器全双工通信,能更好的节省服务器资源和带宽并达到实时通讯,它建立在 TCP 之上,同 HTTP 一样通过 TCP 来传输数据,但是它和 HTTP 最大不同是:

  • WebSocket 是一种双向通信协议,在建立连接后,WebSocket 服务器和 Browser/Client Agent 都能主动的向对方发送或接收数据,就像 Socket 一样;
  • WebSocket 需要类似 TCP 的客户端和服务器端通过握手连接,连接成功后才能相互通信。

整合示例

本示例为演示WebSocket的广播式模式,即服务端有消息时,会将消息发送给所有连接了当前endpoint的 Browser/Client Agent

 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服务端,在其中一个浏览器窗口中点击获取服务器时间,其他两个也将接收到消息

猜你喜欢

转载自my.oschina.net/spinachgit/blog/1806493
今日推荐