在SpringMVC中使用WebSocket

2016-06-22|来源:

SpringMvc项目的搭建在这里就不做多解释,要在Spring中实现 WebSocket 必须加上 spring-websocket和 spring-messaging两个包,同样,完整的pom.xml给出如下:
<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/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.656463</groupId>
    <artifactId>demo-websocket</artifactId>
    <packaging>war</packaging>
    <name>demo-websocket Maven Webapp</name>
    <version>0.0.1-SNAPSHOT</version>
    <url>http://maven.apache.org</url>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <spring.version>4.1.6.RELEASE</spring.version>
    </properties>
    <dependencies>
        <!-- spring相关 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <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>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.7.4</version>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.7</version>
        </dependency>
        <dependency>
            <groupId>jstl</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.websocket</groupId>
            <artifactId>javax.websocket-api</artifactId>
            <version>1.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <finalName>demo-websocket</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <port>8080</port>
                    <path>/</path>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>


定义一个简单的WebSocket客户端页面,这里只有一个连接和发送消息的功能,这个示例和上个示例的功能类似
<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <script type="text/javascript" src="/static/js/jquery-1.9.1.js"></script>
    <script type="text/javascript">
        $(function () {
            var websocket;
            var target = "ws://192.168.56.101:8080/hello.htm";
            if ('WebSocket' in window) {
                websocket = new WebSocket(target);
            } else if ('MozWebSocket' in window) {
                websocket = new MozWebSocket(target);
            } else {
                alert('WebSocket is not supported by this browser.');
                return;
            }
            websocket.onopen = function (evnt) {
                $("#tou").html("链接服务器成功!")
            };
            websocket.onmessage = function (evnt) {
                $("#msg").html($("#msg").html() + "<br/>" + evnt.data);
            };
            websocket.onerror = function (evnt) {
            };
            websocket.onclose = function (evnt) {
                $("#tou").html("与服务器断开了链接!")
            }
            $('#send').bind('click', function () {
                send();
            });
            function send() {
                if (websocket != null) {
                    var message = document.getElementById('message').value;
                    websocket.send(message);
                } else {
                    alert('未与服务器链接.');
                }
            }
        });
    </script>
</head>
<body>
<div id="tou"> webSocket及时聊天Demo程序</div>
<div id="msg"></div>
<input type="text" id="message">
<button type="button" id="send"> 发送</button>
</body>
</html>


创建握手拦截器的类 HandInterceptor ,此类实现 HandshakeInterceptor接口。此类的功能有点类似于使用原始J2EE实现的@OnOpen注解
package com._656463.demo.websocket.spring;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.HandshakeInterceptor;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
/**
 * 拦截器(握手)
 */
public class HandInterceptor implements HandshakeInterceptor {
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, 
            ServerHttpResponse response, WebSocketHandler handler,
            Map<String, Object> map) throws Exception {
        if (request instanceof ServletServerHttpRequest) {
            HttpServletRequest req = ((ServletServerHttpRequest) request).getServletRequest();
            String userName = "default-user";
            // 使用userName区分WebSocketHandler,以便定向发送消息
            // String userName = (String)
            // session.getAttribute("WEBSOCKET_USERNAME");
            map.put("WEBSOCKET_USERNAME", userName);
            req.getSession().setAttribute("WEBSOCKET_USERNAME", userName);
        }
        return true;
    }
    @Override
    public void afterHandshake(ServerHttpRequest serverHttpRequest, 
            ServerHttpResponse serverHttpResponse,
            WebSocketHandler webSocketHandler, Exception e) {
    }
}


创建一个类 WebSocketHander,实现 WebSocketHandler接口,此类的主要功能是消息处理中心,相当于使用原始J2EE API实现中的@OnMessage和@OnClose注解功能
package com._656463.demo.websocket.spring;
import org.springframework.web.socket.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
 * 消息处理中心
 */
public class WebSocketHander implements WebSocketHandler {
    private static final List<WebSocketSession> users = new ArrayList<WebSocketSession>();
    /**
     * 初次链接成功执行
     *
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("链接成功......");
        users.add(session);
        String userName = (String) session.getAttributes().get("WEBSOCKET_USERNAME");
        if (userName != null) {
            //查询未读消息
            int count = 5;
            session.sendMessage(new TextMessage(count + ""));
        }
    }
    /**
     * 接受消息处理消息
     *
     * @param session
     * @param message
     * @throws Exception
     */
    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
        sendMessageToUsers(new TextMessage(message.getPayload() + ""));
    }
    @Override
    public void handleTransportError(WebSocketSession session, Throwable throwable) throws Exception {
        if (session.isOpen()) {
            session.close();
        }
        System.out.println("链接出错,关闭链接......");
        users.remove(session);
    }
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("链接关闭......" + status.toString());
        users.remove(session);
    }
    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
    /**
     * 给所有在线用户发送消息
     *
     * @param message
     */
    public void sendMessageToUsers(TextMessage message) {
        for (WebSocketSession user : users) {
            try {
                if (user.isOpen()) {
                    user.sendMessage(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 给某个用户发送消息
     *
     * @param userName
     * @param message
     */
    public void sendMessageToUser(String userName, TextMessage message) {
        for (WebSocketSession user : users) {
            if (user.getAttributes().get("WEBSOCKET_USERNAME").equals(userName)) {
                try {
                    if (user.isOpen()) {
                        user.sendMessage(message);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            }
        }
    }
}


有了握手拦截器和消息处理中心之后,要开启WebSocket,让他工作起来。
开启WebSocket有两种方式,一种是基于注解的方式,二是基本XML配置的方式
1、基于注解的方式
在springmvc的配置文件中,配置扫描包
<!-- websocket相关扫描,主要扫描:WebSocketConfig.java 这个类路径 -->
<context:component-scan base-package="com._656463.demo.websocket.spring"/>
创建WebSocketConfig,开启WebSocket,并注册WebSocket的请求路径
package com._656463.demo.websocket.spring;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
/**
 * EnableWebSocket 开启websocket
 * 
 * @EnableWebMvc //这个标注可以不加,如果有加,要extends WebMvcConfigurerAdapter
 */
@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        // 支持websocket 的访问链接
        registry.addHandler(new WebSocketHander(), "/hello.htm")
                .addInterceptors(new HandInterceptor());
        // 不支持websocket的访问链接
        registry.addHandler(new WebSocketHander(), "/sockjs/hello.htm")
                .addInterceptors(new HandInterceptor())
                .withSockJS();
    }
}


2、基于XML配置的方式
在springmvc的配置文件中,通过websocket标签配置WebSocket
<!-- 可以在这里配置websocket的相关类,也可以用注解,详细可以查看com._656463.demo.websocket.spring.WebSocketConfig -->
<bean id="websocket" class="com._656463.demo.websocket.spring.WebSocketHander"/>
<websocket:handlers>
    <websocket:mapping path="/hello.htm" handler="websocket" />
    <websocket:handshake-interceptors>
        <bean class="com._656463.demo.websocket.spring.HandInterceptor"/>
    </websocket:handshake-interceptors>
</websocket:handlers>


本次基于Springmvc的WebSocket实例就讲完了,本实例是书生参考网络整理的,希望对你有所帮助


相关问答

更多

Spring Boot中使用Test单元测试报错javax.websocket.server.ServerContainer not available。

那说明单元测试里面没有包含servercontainer吧,单元测试加载的东西没有项目正规启动以后那么多,需要仔细检查如何在单元测试中加载servercontainer。

java中使用websocket推送消息服务器端怎么才能主动推送

目前要实现消息实时推送,有两种方法,一种是ajax轮询,由客户端不停地请求服务器端,查询有没有新消息,然后再由服务器返回结果;另外一种就是long poll,通过一次请求,询问服务器有没有新消息更新,如果没有新消息时,会保持长连接,就一直不返回Response给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始。这两种都是单向链接,需要被动的请求服务器,而不是由服务器自动发给客户端。 从上面可以看出其实这两种方式,都是在不断地建立HTTP连接,然后等待服务端处理,可以体现HTTP协 ...

如何使用WebSocket

先装websocket服务器客户端 【java】kaazing websocket getway 【python】mod_pywebsocket 【javascript】node.js 回答 2. WebSocket JavaScript 接口定义 [Constructor(in DOMString url, in optional DOMString protocol)] interface WebSocket { readonly attribute DOMString URL; // rea ...

怎么使用redis和websocket服务器

WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。在WebSocket api中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。 Cocos2d-x引擎集成libwebsockets,并在libwebsockets的客户端api基础上封装了一层易用的接口,使得引擎在C++, js, Lua层都能方便的使用WebSocket来进行游戏网络通讯。 引擎支持最新的WebSocket Version ...

springmvc3中使用hibernate的二级缓存失效

首先要说的是,spring中,需要手动配置缓存信息。不知道你配置了没有 例如如下配置: hibernate.cache.use_query_cache=true hibernate.cache.use_second_level_cache=true hibernate.cache.region.factory_class=org.hibernate.cache.EhCacheRegionFactory 最好贴出你的缓存配置信息才能判断。

专题教程

JAVA概述
第一部分:java入门基础
第二部分:java常用类
第三部分:jdbc系列教程
第四部分:java高级特征
快速入门
Gson教程
快速了解 jdk8 新特征

相关文章

更多

最近更新

更多