spring整合websocket通信

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 project's 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));
    });
});

 

posted @ 2018-09-09 16:28  天~宇~翱~翔  阅读(3815)  评论(0编辑  收藏  举报