Spring WebSocket使用

第一步: 添加Spring WebSocket的依赖jar包

(注:这里使用maven方式添加 手动添加的同学请自行下载相应jar包放到lib目录)

        <!-- 使用spring 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>            

第二步:建立一个类实现WebSocketConfigurer接口

package com.quicksand.push;

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.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.handler.TextWebSocketHandler;

@Configuration
@EnableWebMvc
@EnableWebSocket
public class SpringWebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        registry.addHandler(webSocketHandler(),"/websocket/socketServer.do").addInterceptors(new SpringWebSocketHandlerInterceptor());
        registry.addHandler(webSocketHandler(), "/sockjs/socketServer.do").addInterceptors(new SpringWebSocketHandlerInterceptor()).withSockJS();
    }

    @Bean
    public TextWebSocketHandler webSocketHandler(){
        return new SpringWebSocketHandler();
    }

}

第三步:继承WebSocketHandler对象。该对象提供了客户端连接,关闭,错误,发送等方法,重写这几个方法即可实现自定义业务逻辑

package com.quicksand.push;

import java.io.IOException;
import java.util.ArrayList;
import org.apache.log4j.Logger;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

public class SpringWebSocketHandler extends TextWebSocketHandler {
    private static final ArrayList<WebSocketSession> users;//这个会出现性能问题,最好用Map来存储,key用userid
    private static Logger logger = Logger.getLogger(SpringWebSocketHandler.class);
    static {
        users = new ArrayList<WebSocketSession>();
    }

    public SpringWebSocketHandler() {
        // TODO Auto-generated constructor stub
    }

    /**
     * 连接成功时候,会触发页面上onopen方法
     */
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        // TODO Auto-generated method stub
        System.out.println("connect to the websocket success......当前数量:"+users.size());
        users.add(session);
        //这块会实现自己业务,比如,当用户登录后,会把离线消息推送给用户
        //TextMessage returnMessage = new TextMessage("你将收到的离线");
        //session.sendMessage(returnMessage);
    }

    /**
     * 关闭连接时触发
     */
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        logger.debug("websocket connection closed......");
        String username= (String) session.getAttributes().get("WEBSOCKET_USERNAME");
        System.out.println("用户"+username+"已退出!");
        users.remove(session);
        System.out.println("剩余在线用户"+users.size());
    }

    /**
     * js调用websocket.send时候,会调用该方法
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        super.handleTextMessage(session, message);
    }

    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        if(session.isOpen()){session.close();}
        logger.debug("websocket connection closed......");
        users.remove(session);
    }

    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 给某个用户发送消息
     *
     * @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;
            }
        }
    }

    /**
     * 给所有在线用户发送消息
     *
     * @param message
     */
    public void sendMessageToUsers(TextMessage message) {
        for (WebSocketSession user : users) {
            try {
                if (user.isOpen()) {
                    user.sendMessage(message);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

第四步:继承HttpSessionHandshakeInterceptor对象。该对象作为页面连接websocket服务的拦截器,代码如下:

package com.quicksand.push;
import java.util.Map;

import javax.servlet.http.HttpSession;

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.support.HttpSessionHandshakeInterceptor;

/**
 * WebSocket拦截器
 * @author WANG
 *
 */
public class SpringWebSocketHandlerInterceptor extends HttpSessionHandshakeInterceptor {
    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
            Map<String, Object> attributes) throws Exception {
        // TODO Auto-generated method stub
        System.out.println("Before Handshake");
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
            HttpSession session = servletRequest.getServletRequest().getSession(false);
            if (session != null) {
                //使用userName区分WebSocketHandler,以便定向发送消息
                String userName = (String) session.getAttribute("SESSION_USERNAME");
                if (userName==null) {
                    userName="default-system";
                }
                attributes.put("WEBSOCKET_USERNAME",userName);
            }
        }
        return super.beforeHandshake(request, response, wsHandler, attributes);

    }

    @Override
    public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
            Exception ex) {
        // TODO Auto-generated method stub
        super.afterHandshake(request, response, wsHandler, ex);
    }
}

第5步 让SpringWebSocketConfig配置类随spring容器启动 spring文件中加入如下代码:

<!-- websocket相关扫描,主要扫描:WebSocketConfig  如果前面配置能扫描到此类则可以不加 -->
<context:component-scan base-package="com.quicksand.push"/>

-------------------------------------------------------------------------到这里就算完成啦 下面准备测试-------------------------------------------------------------

1.定义一个控制器用来做连接标识和发送消息

package com.quicksand.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.socket.TextMessage;

import com.quicksand.push.SpringWebSocketHandler;

@Controller
public class WebsocketController {
    @Bean//这个注解会从Spring容器拿出Bean
    public SpringWebSocketHandler infoHandler() {
        return new SpringWebSocketHandler();
    }

    @RequestMapping("/websocket/login")
    public ModelAndView login(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String username = request.getParameter("username");
        System.out.println(username+"登录");
        HttpSession session = request.getSession(false);
        session.setAttribute("SESSION_USERNAME", username);
        //response.sendRedirect("/quicksand/jsp/websocket.jsp");
        return new ModelAndView("websocket");
    }

    @RequestMapping("/websocket/send")
    @ResponseBody
    public String send(HttpServletRequest request) {
        String username = request.getParameter("username");
        infoHandler().sendMessageToUser(username, new TextMessage("你好,测试!!!!"));
        return null;
    }
}

2.建立登录页面

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<h2>Hello World!</h2>
<body>
    <!-- ship是我的项目名-->
    <form action="websocket/login.do">
        登录名:<input type="text" name="username"/>
        <input type="submit" value="登录"/>
    </form>
</body>
</body>
</html>

3.建立发消息页面

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<body>
<script type="text/javascript" src="http://cdn.bootcss.com/jquery/3.1.0/jquery.min.js"></script>
<script type="text/javascript" src="http://cdn.bootcss.com/sockjs-client/1.1.1/sockjs.js"></script>
<script type="text/javascript">
    var websocket = null;
    if (‘WebSocket‘ in window) {
        websocket = new WebSocket("ws://localhost:8080/quicksand/websocket/socketServer.do");
    }
    else if (‘MozWebSocket‘ in window) {
        websocket = new MozWebSocket("ws://localhost:8080/quicksand/websocket/socketServer.do");
    }
    else {
        websocket = new SockJS("http://localhost:8080/quicksand/sockjs/socketServer.do");
    }
    websocket.onopen = onOpen;
    websocket.onmessage = onMessage;
    websocket.onerror = onError;
    websocket.onclose = onClose;

    function onOpen(openEvt) {
        //alert(openEvt.Data);
    }

    function onMessage(evt) {
        alert(evt.data);
    }
    function onError() {}
    function onClose() {}

    function doSend() {
        if (websocket.readyState == websocket.OPEN) {
            var msg = document.getElementById("inputMsg").value;
            websocket.send(msg);//调用后台handleTextMessage方法
            alert("发送成功!");
        } else {
            alert("连接失败!");
        }
    }

   window.close=function()
   {
     websocket.onclose();
   }

</script>
请输入:<textarea rows="5" cols="10" id="inputMsg" name="inputMsg"></textarea>
<button onclick="doSend();">发送</button>
</body>
</html>

测试结果如下图:

文章参考:http://www.myexception.cn/web/1775480.html

时间: 2024-10-10 05:26:07

Spring WebSocket使用的相关文章

Spring Websocket配置

实现的版本jdk1.7.0_25, tomcat7.0.47.0, Tengine/2.1.1 (nginx/1.6.2), servlet3.0, spring4.2.2 使用maven导入版本3.0+的servlet包: <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>3.0-alpha-1<

【spring+websocket的使用】

一.spring配置文件Java代码 <?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:tx="http://www.springfra

Spring WebSocket初探1 (Spring WebSocket入门教程)&lt;转&gt;

See more: Spring WebSocket reference整个例子属于WiseMenuFrameWork的一部分,可以将整个项目Clone下来,如果朋友们有需求,我可以整理一个独立的demo出来. WebSocket是html5带来的一项重大的特性,使得浏览器与服务端之间真正长连接交互成为了可能,这篇文章会带领大家窥探一下Spring 对WebSocket的支持及使用. 1. 基础环境 快速搭建Spring框架,我们使用Spring boot,这里先不讨论SpringBoot,只知

【转】Spring websocket 使用

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html https://spring.io/guides/gs/messaging-stomp-websocket/ https://github.com/rstoyanchev/spring-websocket-portfolio 项目中用到了消息的实时推送,查资料后用到了Spring websocket,找了很多资料,还是感

Spring WebSocket初探2 (Spring WebSocket入门教程)&lt;转&gt;

See more: Spring WebSocket reference整个例子属于WiseMenuFrameWork的一部分,可以将整个项目Clone下来,如果朋友们有需求,我可以整理一个独立的demo出来. 接上一篇:Spring WebSocket初探1 (Spring WebSocket入门教程) WebSocket前端准备 前端我们需要用到两个js文件:sockjs.js和stomp.js SockJS:SockJS 是一个浏览器上运行的 JavaScript 库,如果浏览器不支持 W

spring+websocket整合(springMVC+spring+MyBatis即SSM框架)

spring4.0以后加入了对websocket技术的支持,撸主目前的项目用的是SSM(springMVC+spring+MyBatis)框 架,所以肯定要首选spring自带的websocket了,好,现在问题来了,撸主在网上各种狂搜猛找,拼凑了几个自称是 spring websocket的东东,下来一看,废物,其中包括从github上down下来的.举个例子,在搭建过程中有个问题, 撸主上谷歌搜索,总共搜出来三页结果共30条左右,前15条是纯英文的  后15条是韩语和日语,而这30条结果都不

Spring WebSocket教程(二)

实现目标 这一篇文章,就要直接实现聊天的功能,并且,在聊天功能的基础上,再实现缓存一定聊天记录的功能. 第一步:聊天实现原理 首先,需要明确我们的需求.通常,网页上的聊天,都是聊天室的形式,所以,这个例子也就有了一个聊天的空间的概念,只要在这个空间内,就能够一起聊天.其次,每个人都能够发言,并且被其他的人看到,所以,每个人都会将自己所要说的内容发送到后台,后台转发给每一个人. 在客户端,可以用Socket很容易的实现:而在web端,以前都是通过轮询来实现的,但是WebSocket出现之后,就可以

spring+websocket整合(springMVC+spring+MyBatis即SSM框架和websocket技术的整合)

java-websocket的搭建非常之容易,没用框架的童鞋可以在这里下载撸主亲自调教好的java-websocket程序: Apach Tomcat 8.0.3+MyEclipse+maven+JDK1.7 spring4.0以后加入了对websocket技术的支持,撸主目前的项目用的是SSM(springMVC+spring+MyBatis)框架,所 以肯定要首选spring自带的websocket了,好,现在问题来了,撸主在网上各种狂搜猛找,拼凑了几个自称是spring websocket

Spring WebSocket详解

Spring WebSocket详解 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs Spring框架从4.0版开始支持WebSocket,下面我将详述Spring WebSocket库的相关内容.内容包括Spring框架是如何在Web应用中支持WebSocket方式的消息通信,以及如何利用STOMP协议作为应用层的协议--WebSocket的子协议. 1.WebSocket协议介绍 WebSocket协议是RFC-6455规范定义的一个Web领域的