1. 程式人生 > >spring整合websocket通信

spring整合websocket通信

row final send 參考 cal utf-8 xtend art 文件

1. 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.dxss.websocket</groupId>
  <artifactId>WebSocketProGram</artifactId>
  <version>1.0
-SNAPSHOT</version> <packaging>war</packaging> <name>WebSocketProGram Maven Webapp</name> <!-- FIXME change it to the projects website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.7
</maven.compiler.source> <maven.compiler.target>1.7</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.3
.0</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!-- 添加Spring支持 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.2.4.RELEASE</version> </dependency> <!-- 添加對websocket的支持 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>4.2.4.RELEASE</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.6.2</version> </dependency> </dependencies> <build> <finalName>WebSocketProGram</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <path>/WebSocketProGram</path> <port>9092</port> </configuration> </plugin> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.0.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.20.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.0</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> </build> </project>

2. servletContext.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:websocket="http://www.springframework.org/schema/websocket"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/websocket
       http://www.springframework.org/schema/websocket/spring-websocket-4.0.xsd">
    <!-- 配置處理器 -->
    <bean id="websocket" class="com.web.common.util.websocket.MyWebSocketHander" />
    <!-- 配置攔截器 -->
    <websocket:handlers>
<!-- 跟前端請求的url相關 --> <websocket:mapping path="/visualizationWebSocket.do" handler="websocket" /> <websocket:handshake-interceptors> <bean class="com.web.common.util.websocket.HandshakeInterceptor" /> </websocket:handshake-interceptors> </websocket:handlers> </beans>

3. servletContext-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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="
       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
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/task
       http://www.springframework.org/schema/task/spring-task.xsd">

    <context:component-scan base-package="com.dxss.java.controller"/>
    <mvc:default-servlet-handler/>
    <mvc:annotation-driven/>

    <bean id="configProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <array>
                <value>classpath:db.properties</value>
            </array>
        </property>
        <property name="fileEncoding" value="UTF-8"></property>
        <property name="ignoreUnresolvablePlaceholders" value="true"></property>
    </bean>

    <!-- 頁面前綴 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

4. webSocket配置

package com.web.common.util.websocket;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

/**
 *  webSocket配置 : 註冊websocket地址和處理類
 */
@Configuration
@EnableWebMvc
@EnableWebSocket
public class MyWebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        // 這裏的url要與頁面的url一致
        // 前臺 可以使用websocket環境
        registry.addHandler(myWebSocketHandler(),"/visualizationWebSocket.do").addInterceptors(new HandshakeInterceptor());
        //至於這裏為什麽要加info,我遇見的情況是,當我使用sockjs來代替websocket時,連接的後面會自動加上info
        //前臺 不可以使用websocket環境,則使用sockjs進行模擬連接
        registry.addHandler(myWebSocketHandler(), "/sockjs/visualizationWebSocket/info").addInterceptors(new HandshakeInterceptor())
                .withSockJS();
    }

    /**
     * websocket 處理類
     *
     * @return
     */
    @Bean
    public WebSocketHandler myWebSocketHandler(){
        return new MyWebSocketHander();
    }



}

5. 會話攔截器

package com.web.common.util.websocket;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import java.util.Map;

/**
 * 創建握手(handshake)接口/攔截器
 * desc : 這個的主要作用是可以在握手前做一些事,把所需要的東西放入到attributes裏面,
 *        然後可以在WebSocketHandler的session中,取到相應的值,具體可參考HttpSessionHandshakeInterceptor,
 *        這兒也可以實現HandshakeInterceptor接口
 *
 * @author lenovo
 */
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {

    @Override
    public boolean beforeHandshake(
            ServerHttpRequest request,
            ServerHttpResponse response,
            WebSocketHandler wsHandler,
            Map<String, Object> attributes
    ) throws Exception {
        /**
         *   獲取請求參數,首先我們要獲取HttpServletRequest對象才能獲取請求參數;
         *   當ServerHttpRequset的層次結構打開後其子類可以獲取到我們想要的http對象,那麽就簡單了。
            我這裏是把獲取的請求數據綁定到session的map對象中(attributes)
         */
        System.out.println( " HandshakeInterceptor: beforeHandshake, attributes is : " + attributes );
        return super.beforeHandshake( request, response, wsHandler, attributes );
    }

    /**
     * 握手後
     */
    @Override
    public void afterHandshake(
            ServerHttpRequest request,
            ServerHttpResponse response, WebSocketHandler wsHandler,
            Exception ex
    ) {
        System.out.println(" HandshakeInterceptor: afterHandshake ");
        super.afterHandshake(request, response, wsHandler, ex);
    }
}

6. websocket處理器

處理器裏面可以註入想要的service

package com.web.common.util.websocket;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.springframework.web.socket.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Map;


/**
 * websocket處理類就是處理:連接開始、關閉、處理信息等方法
 *
 * @author lenovo
 */
public class MyWebSocketHander implements WebSocketHandler {

    /**
     * 保存所有的用戶session
     */
    private static final ArrayList<WebSocketSession> users = new ArrayList<WebSocketSession>();

    /**
     *  連接就緒時
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession webSocketSession) throws Exception {
        System.out.println("connection success ...... ");
        users.add(webSocketSession);
    }

    /**
     * 處理信息
     *
     * @param webSocketSession
     * @param webSocketMessage
     * @throws Exception
     */
    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
        Gson gson = new Gson();
        Map<String, Object> msg = gson.fromJson(webSocketMessage.getPayload().toString(),
                new TypeToken<Map<String, Object>>() {}.getType());
        // 處理消息 msgContent消息內容
        TextMessage textMessage = new TextMessage(msg.get("msgContent").toString(), true);
        System.out.println("頁面傳遞的消息為: "+ msg.get("msgContent").toString());
        // 調用方法(發送消息給所有人)
        sendMsgToAllUsers(textMessage);
    }


    private void sendMsgToAllUsers(TextMessage textMessage) {
        System.out.println("users list is : "+users);
        for (WebSocketSession user : users) {
            try {
                user.sendMessage(textMessage);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 處理傳輸時異常
     *
     * @param webSocketSession
     * @param throwable
     * @throws Exception
     */
    @Override
    public void handleTransportError(WebSocketSession webSocketSession, Throwable throwable) throws Exception {
        System.out.println(" Transport occur error ......");

    }

    /**
     * 關閉連接時
     *
     * @param webSocketSession
     * @param closeStatus
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
        System.out.println("connection close ......");
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}

7. 示例頁面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <title>首頁</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="renderer" content="webkit">
    <!-- 引入 JQuery  -->
    <script type="text/javascript" src="js/jquery/jquery-1.12.4.js"></script>
    <!-- 引入 sockJS  -->
    <script type="text/javascript" src="js/websocket/sockjs.min.js" ></script>
    <!-- 自定義JS文件 -->

</head>

<body>
    <!-- 最外邊框 -->
    <div style="margin: 20px auto; border: 1px solid blue; width: 300px; height: 500px;">
        <!-- 消息展示框 -->
        <div id="msg" style="width: 100%; height: 70%; border: 1px solid yellow;overflow: auto;"></div>
        <!-- 消息編輯框 -->
        <textarea id="tx" style="width: 100%; height: 20%;"></textarea>
        <!-- 消息發送按鈕 -->
        <button id="TXBTN" style="width: 100%; height: 8%;">發送數據</button>
    </div>
</body>
</html>

<script type="text/javascript" src="js/index/index.js"></script>

8. 頁面js

$(function() {
    var websocket;
    // 首先判斷是否 支持 WebSocket
    if(WebSocket in window) {
        websocket = new WebSocket("ws://localhost:9092/WebSocketProGram/visualizationWebSocket.do");
    } else if(MozWebSocket in window) {
        websocket = new MozWebSocket("ws://localhost:9092/WebSocketProGram/visualizationWebSocket.do");
    } else {
        websocket = new SockJS("http://localhost:9092/WebSocketProGram/sockjs/visualizationWebSocket.do");
    }
    // 打開時
    websocket.onopen = function(evnt) {
        console.log("websocket.onopen  ");
    };
    // 處理消息時
    websocket.onmessage = function(evnt) {
        $("#msg").append("<p>(<font color=‘red‘>" + evnt.data + "</font>)</p>");
        console.log("  websocket.onmessage   ");
    };
    websocket.onerror = function(evnt) {
        console.log("  websocket.onerror  ");
    };
    websocket.onclose = function(evnt) {
        console.log("  websocket.onclose  ");
    };
    // 點擊了發送消息按鈕的響應事件
    $("#TXBTN").click(function(){
        // 獲取消息內容
        var text = $("#tx").val();
        // 判斷
        if(text == null || text == ""){
            alert(" content  can not empty!!");
            return false;
        }
        var msg = {
            msgContent: text,
            postsId: 1
        };
        // 發送消息
        websocket.send(JSON.stringify(msg));
    });
});

spring整合websocket通信