这几天在研究websocket,搭建demo环境时遇到了不少坑,总算搭起来了,记录下,希望也能帮到其他人。

本文参考:

https://blog.csdn.net/manerfan/article/details/48526681

https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#websocket(官网)

首先说明几点注意内容:

1.spring web工程需要3.0及以上

2.一定注意spring-websocket(及其他几个websocket相关jar包)要与spring-core等spring包版本一致(否则会报方法未发现异常)

3.tomcat版本使用7.0.50以上

好了,不多说了,让我们开始搭建吧:

环境:jdk1.8, web3.0,maven,spring包版本5.0.7

第一步:使用maven搭建springMVC web3.0框架,具体流程操作见本人上一篇文章:

https://blog.csdn.net/qq_16860417/article/details/81017579

第二部:引入websocket相关jar包,下面贴出pom文件(包含spring等所有依赖,按需要获取)

<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.cgd</groupId><artifactId>test</artifactId><packaging>war</packaging><version>0.0.1-SNAPSHOT</version><name>test Maven Webapp</name><url>http://maven.apache.org</url><properties><srping.version>5.0.7.RELEASE</srping.version><mybatis.version>3.2.8</mybatis.version><slf4j.version>1.7.12</slf4j.version><log4j.version>1.2.17</log4j.version></properties><!-- 用到的jar包 --><dependencies><!-- 单元测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><!-- 表示开发的时候引入,发布的时候不会加载此包 --><scope>test</scope></dependency><!-- spring框架包 start --><dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${srping.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${srping.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${srping.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-oxm</artifactId><version>${srping.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-tx</artifactId><version>${srping.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${srping.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>${srping.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${srping.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>${srping.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>${srping.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-expression</artifactId><version>${srping.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-orm</artifactId><version>${srping.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>${srping.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${srping.version}</version></dependency><!-- spring框架包 end --><!-- mybatis框架包 start --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>${mybatis.version}</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.2.2</version></dependency><!-- mybatis框架包 end --><!-- 数据库驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.35</version></dependency><!-- 导入dbcp的jar包,用来在applicationContext.xml中配置数据库 --><dependency><groupId>commons-dbcp</groupId><artifactId>commons-dbcp</artifactId><version>1.4</version></dependency><!-- jstl标签类 --><dependency><groupId>jstl</groupId><artifactId>jstl</artifactId><version>1.2</version></dependency><!-- log start --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>${log4j.version}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>${slf4j.version}</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>${slf4j.version}</version></dependency><!-- websocket --><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-websocket</artifactId><version>8.0.23</version><scope>provided</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-websocket</artifactId><version>5.0.7.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-messaging</artifactId><version>5.0.7.RELEASE</version></dependency><dependency><groupId>javax.websocket</groupId><artifactId>javax.websocket-api</artifactId><version>1.0</version><scope>provided</scope></dependency><!-- cors --><dependency><groupId>com.thetransactioncompany</groupId><artifactId>cors-filter</artifactId><version>2.4</version></dependency><!-- commons-io --><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency><dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.3.3</version></dependency><!--Jackson required包 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.9.6</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.6</version></dependency><dependency><groupId>org.codehaus.jackson</groupId><artifactId>jackson-mapper-asl</artifactId><version>1.9.13</version></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-annotations</artifactId><version>2.9.6</version></dependency></dependencies><build><finalName>test</finalName><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins></build></project>

第三步:创建websocket.jsp文件,用于客户端界面(下面贴出简单多客户端聊天面板页面)

<%@ page contentType="text/html;charset=UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>SSIT</title>
</head>
<script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="js/sockjs-0.3.4.min.js"></script><script type="text/javascript">var websocket;$(function() {// 首先判断是否 支持 WebSocketif ('WebSocket' in window) {websocket = new WebSocket("ws://localhost:8080/test/websocket/doubanfm");} else if ('MozWebSocket' in window) {websocket = new MozWebSocket("ws://localhost:8080/test/websocket/doubanfm");} else { websocket = new SockJS("http://localhost:8080/test/sockjs/websocket/doubanfm");}// 打开时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  ");};});// 点击了发送消息按钮的响应事件function sendMsg(){// 获取消息内容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));}
</script>
<body><!-- 最外边框 --><divstyle="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%;" οnclick="sendMsg()">发送数据</button></div>
</body>
</html>

第四步:创建WebSocketConfig配置类、

注意: 这里使用注解方式添加依赖,确保注解可以被扫描到

package com.cgd.websocket.config;import org.springframework.beans.factory.annotation.Autowired;
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;/*** WebSocket初始化配置* * @author ManerFan 2015年9月7日*/@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {@Autowiredprivate DoubanFMWebSocketHandler doubanFmWebSocketHandler;@Autowiredprivate DoubanFMHandshakeInterceptor doubanFMHandshakeInterceptor;@Overridepublic void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {/** Douban FM */System.out.println("========WebSocketConfig registerWebSocketHandlers=============");// 支持websocket 的访问链接registry.addHandler(doubanFmWebSocketHandler, "/websocket/doubanfm").addInterceptors(doubanFMHandshakeInterceptor).setAllowedOrigins("*");/* 不加AllowedOrigins,有可能会全拒绝 */// 不支持websocket的访问链接registry.addHandler(doubanFmWebSocketHandler, "/sockjs/websocket/doubanfm").addInterceptors(doubanFMHandshakeInterceptor).setAllowedOrigins("*").withSockJS();}}

也可以使用xml配置,方式如下:

<!-- 可以在这里配置websocket的相关类,也可以用注解,详细可以查看com._656463.demo.websocket.spring.WebSocketConfig --><!-- <websocket:handlers><websocket:mapping path="/myHandler" handler="myHandler"/><websocket:handshake-interceptors><bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor"/></websocket:handshake-interceptors></websocket:handlers><bean id="myHandler" class="com.cgd.websocket.config.MyHandler"/> -->

第五步:创建拦截器DoubanFMHandshakeInterceptor

package com.cgd.websocket.config;import java.util.Map;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;/*** @author  ManerFan 2015年9月7日*/
@Component
public class DoubanFMHandshakeInterceptor extends HttpSessionHandshakeInterceptor {@Overridepublic boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response,WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {// 握手前的处理逻辑System.out.println("=========握手前的处理逻辑=============");return super.beforeHandshake(request, response, wsHandler, attributes);}@Overridepublic void afterHandshake(ServerHttpRequest request, ServerHttpResponse response,WebSocketHandler wsHandler, Exception ex) {// 握手后的处理逻辑System.out.println("===========握手后的处理逻辑===========");super.afterHandshake(request, response, wsHandler, ex);}}

第六步:创建消息处理类DoubanFMWebSocketHandler

package com.cgd.websocket.config;import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;import org.springframework.stereotype.Component;
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;import com.cgd.tyrz.util.JsonUtil;
/*** @author ManerFan 2015年9月7日*/
@Component
public class DoubanFMWebSocketHandler extends TextWebSocketHandler {/*** 记录连接上的所有session*/private Map<String, WebSocketSession> sessionMap = Collections.synchronizedMap(new HashMap<String, WebSocketSession>());@Overridepublic void afterConnectionEstablished(WebSocketSession session) throws Exception {// 建立连接之后System.out.println("==========建立连接之后============");sessionMap.put(session.getId(), session);}@Overrideprotected void handleTextMessage(WebSocketSession session, TextMessage message)throws Exception {// 收到消息之后System.out.println(session+"==========收到消息之后============"+message);String sessionId = session.getId();String payload = message.getPayload();String txt = (String) JsonUtil.getMapObject(payload).get("msgContent");
//        session.sendMessage(new TextMessage(payload + ""));sendMessageToUsers(new TextMessage(sessionId+"说:"+txt));}@Overridepublic void afterConnectionClosed(WebSocketSession session, CloseStatus status)throws Exception {// 连接断开之后System.out.println("==========连接断开之后============");sessionMap.remove(session.getId());if (sessionMap.isEmpty()) {/* 没有客户端在线了 */System.out.println("==========没有客户端在线了============");}}/*** 给所有在线用户发送消息*/public void sendMessageToUsers(TextMessage message) {for (Entry<String, WebSocketSession> entry : sessionMap.entrySet()) {
//          System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());try {if (entry.getValue().isOpen()) {entry.getValue().sendMessage(message);}} catch (IOException e) {e.printStackTrace();}}}/*** 给某个用户发送消息*/public void sendMessageToUser(String sessionId, TextMessage message) {WebSocketSession us = sessionMap.get(sessionId);if(us!=null) {try {if (us.isOpen()) {us.sendMessage(message);}} catch (IOException e) {e.printStackTrace();}}}}

第七步:根据需要修改websocket.jsp和WebSocketConfig.java的请求拦截路径

第八步:启动项目,打开多个websocket.jsp,这样就可以多客户端通信了

SpringMVC使用websocke相关推荐

  1. 【SpringMVC】概述

    概述: SpringMVC:是基于spring的一个框架, 实际上就是spring的一个模块, 专门是做web开发的.                       理解是servlet的一个升级 Sp ...

  2. 【SpringMVC】基本概念

    SpringMVC的基本概念 三层架构 我们的开发一般都是基于c/s或者b/s架构.在JavaEE开发中,几乎全都是基于B/S架构开发.在B/S架构中,系统标准的三层架构包括:表现层,业务层,持久层. ...

  3. SSM框架整合(Spring+SpringMVC+MyBatis)

    输出结果 1.Maven Web项目创建 之前有写过Eclipse+Maven创建web项目的帖子,如果需要,请参考这里写链接内容 创建好项目之后因为入下图: 2.SSM整合 2.1 引入需要的JAR ...

  4. SpringBoot-web开发(四): SpringMVC的拓展、接管(源码分析)

    [SpringBoot-web系列]前文: SpringBoot-web开发(一): 静态资源的导入(源码分析) SpringBoot-web开发(二): 页面和图标定制(源码分析) SpringBo ...

  5. SpringMVC——通俗易懂讲讲Ajax~

    聊聊Ajax 一.什么是Ajax 二.iframe标签简单伪造Ajax 三.Ajax的实现 1. 基本概念的了解 Ajax的核心是什么? XMLHttpRequest是什么? Ajax数据传输的数据格 ...

  6. Jackson、FastJson快速入门(整合SpringMVC)

    目录 1. 什么是 JSON 2. JSON 语法规则 3. JSON 与 JS 对象的关系 4. JSON 和 JS 对象互转 5. Jackson-数据格式转换 1. 环境搭建 2. 对象转jso ...

  7. RESTful风格及其SpringMVC实现

    目录 1.RESTful概念 2.RESTful功能 3.对比:传统方式操作资源 4.SpringMVC实现传统方式操作资源 5.使用RestFul操作资源 6.SpringMVC实现RESTful操 ...

  8. 使用注解开发SpringMVC详细配置教程

    目录 1.使用注解开发SpringMVC 1.新建一个普通的maven项目,添加web支持 2.在pom.xml中导入相关依赖 3.配置web.xml 4.编写SpringMVC配置文件 1. 自动扫 ...

  9. SpringMVC的form:form表单的使用

    为什么要使用SpringMVC的form:form表单,有两个原因:一是可以更加快捷的完成表单的开发,比如会替你做好数据类型装换等本来需要你自己动手的工作.其次就是能够更加方便的实现表单回显. 首先要 ...

最新文章

  1. python类中方法的执行顺序-Python实例化class的执行顺序实例方法
  2. go语言打印日期_判定是否掌握Go语言的最重要标准:对并发的掌握
  3. Java NIO学习系列七:Path、Files、AsynchronousFileChannel
  4. 【RS】Local Latent Space Models for Top- N Recommendation-利用局部隐含空间模型进行Top-N推荐...
  5. linux 字符串截取_第13篇:Linux防火墙的日志基本审计
  6. JavaScript:单选钮的事件处理
  7. vs2008 jQuery 智能提示失败可能是Jquery版本问题
  8. python 以图搜图1688_python 以图搜图
  9. 后台运行命令nohup、job 等
  10. Xcode调试中如何将指定地址转换为其指向的对象
  11. 2018.7.26 为RapidMiner5进行插件扩展(extension)开发
  12. 媲美celery的分布式调度框架funboost
  13. 东华软件张涵诚:政府大数据应用的案例和数据价值释放的方法
  14. [Unity]腾讯SDK踩坑之路(2)--配置Xcode工程(MSDK和米大师配置代码冲突)
  15. win32gui, win32con, win32api 安装失败
  16. ArcMap 小知识(5):拓扑检查及修改
  17. tp5.1 前台模板使用公共模板网页(header.html、foot.html、base.html)
  18. 小程序之战,泡沫之后鹿死谁手?
  19. 人民币记账中,数字中间的逗号是什么意思?
  20. SCT2280,一款17V 8A输出同步降压DCDC转换器

热门文章

  1. 高数 | 【重积分】线面积分880例题
  2. 如何根据样本估计总体的均值、比例与方差?如何进行参数估计及选择对应公式?
  3. 怎样使用Chrome浏览器截取整个网页?
  4. 计算机名词解释显存,显卡名词解释之显存类型
  5. 某资讯App signature签名分析 (一)
  6. 有没有什么软件可以把视频转文字?看看这些转换软件
  7. Pycharm专业版申请免费学生激活连接远程服务器编译配置图片显示变量观察等
  8. 任务01-信息编码:纯⽩⾊的bmp图⽚ 用Hex Editor Neo画一个“C
  9. PAT 1058 选择题 python
  10. UWP 禁止Pivot swip 手势