在SpringMVC中使用WebSocket

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实例就讲完了,本实例是书生参考网络整理的,希望对你有所帮助
Java SpringMVC WebSocket 是一种在 web 应用实现实时通信的技术。WebSocket协议是一种基于TCP协议的全双工通信协议,通过 WebSocket 可以在浏览器和服务器之间建立持久连接,实现服务器向客户端实时推送数据的功能。 SpringMVC 是一个基于 Java 的开源框架,用于构建 JavaEE 应用程序的 Web 层。它提供了一种轻量级的、快捷的开发方式,可以同时支持传统的请求-响应模式和 WebSocket 实时通信模式。 为了在 SpringMVC 使用 WebSocket,我们需要使用到 Spring 的一个模块——Spring Websocket。它提供了一组类和接口,用于定义 WebSocket 的端点(Endpoint),配置 WebSocket 的拦截器(Interceptor),处理客户端发送的消息和向客户端发送消息等操作。通过这些类和接口,我们可以非常方便地实现 WebSocket 的功能。 首先,我们需要定义一个继承自`AbstractWebSocketMessageBrokerConfigurer`的配置类,通过它可以配置 WebSocket 的相关参数,比如设置允许的来源(allowed origins)、配置拦截器等等。 然后,我们需要定义一个继承自`AbstractWebSocketMessageBrokerConfigurer`的类,通过它可以配置消息代理(Message Broker)。消息代理负责接收客户端发送的消息并转发到目标客户端,同时也负责接收服务器推送的消息并发送给目标客户端。 最后,我们可以通过在控制器添加`@MessageMapping`注解来处理客户端发送的消息,并通过`@SendTo`注解将处理结果发送给客户端。 总之,使用 Java SpringMVC WebSocket 可以很方便地实现实时通信功能,在需要实现实时推送数据的场景下,非常适用。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值