websocket是什么不做介绍。开发环境:jdk1.8,win7_64旗舰版,idea
 
1、初始化一个springboot项目
 
2、加入websocket依赖
<!-- springboot的websocket依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

pom.xml如下:

<dependencies>
<!-- 模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- websocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!---->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency> <!-- lombok工具 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 内置tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<!-- 测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> </dependencies>

3、编写websocket的服务端

    3.1、WebSocketEndPoint是websocket服务端的核心
      @PathParam是javax.websocket.server下的注解,是将路径中绑定的占位符的值取出来
  在url中使用key和name,是想通过key和name对websocket的连接进行访问控制,这个key可以是用户登录后服务器给用户的令牌,通过令牌和和name进行权限验证(自己写拦截器或者继承权限框架实现),还可以通过key和name生成唯一值来进行在线websocket
连接的维护<(key+name), websocketSession>, 当然,我在这里没有这样做。
package com.geniuses.sewage_zero_straight.net.websocket;

import com.geniuses.sewage_zero_straight.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map; import static com.geniuses.sewage_zero_straight.net.websocket.WebSocketPool.*;
import static com.geniuses.sewage_zero_straight.net.websocket.WebSocketHandler.createKey; @Slf4j
@Component
@ServerEndpoint("/net/websocket/{key}/{name}")//表明这是一个websocket服务的端点
public class WebSocketEndPoint { private static UserService userService; @Autowired
public void setUserService(UserService userService){
WebSocketEndPoint.userService = userService;
} @OnOpen
public void onOpen(@PathParam("key") String key, @PathParam("name") String name, Session session){
log.info("有新的连接:{}", session);
add(createKey(key, name), session);
WebSocketHandler.sendMessage(session, key + name);
log.info("在线人数:{}",count());
sessionMap().keySet().forEach(item -> log.info("在线用户:", item));
for (Map.Entry<String, Session> item : sessionMap().entrySet()){
log.info("12: {}", item.getKey());
}
} @OnMessage
public void onMessage(String message){
log.info("有新消息: {}", message);
} @OnClose
public void onClose(@PathParam("key") String key, @PathParam("name") String name,Session session){
log.info("连接关闭: {}", session);
remove(createKey(key, name));
log.info("在线人数:{}",count());
sessionMap().keySet().forEach(item -> log.info("在线用户:", (item.split("@"))[1]));
for (Map.Entry<String, Session> item : sessionMap().entrySet()){
log.info("12: {}", item.getKey());
}
} @OnError
public void onError(Session session, Throwable throwable){
try {
session.close();
} catch (IOException e) {
log.error("onError Exception: {}", e);
}
log.info("连接出现异常: {}", throwable);
} }

  3.2、WebSocketPool是websocket的在线连接池

package com.geniuses.sewage_zero_straight.net.websocket;

import lombok.extern.slf4j.Slf4j;

import javax.websocket.Session;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; @Slf4j
public class WebSocketPool { //在线用户websocket连接池
private static final Map<String, Session> ONLINE_USER_SESSIONS = new ConcurrentHashMap<>(); /**
* 新增一则连接
* @param key
* @param session
*/
public static void add(String key, Session session){
if (!key.isEmpty() && session != null){
ONLINE_USER_SESSIONS.put(key, session);
}
} /**
* 根据Key删除连接
* @param key
*/
public static void remove(String key){
if (!key.isEmpty()){
ONLINE_USER_SESSIONS.remove(key);
}
} /**
* 获取在线人数
* @return
*/
public static int count(){
return ONLINE_USER_SESSIONS.size();
} /**
* 获取在线session池
* @return
*/
public static Map<String, Session> sessionMap(){
return ONLINE_USER_SESSIONS;
}
}
 3.3、WebSocketHandler是websocket的动作处理工具
package com.geniuses.sewage_zero_straight.net.websocket;

import lombok.extern.slf4j.Slf4j;

import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;
import java.io.IOException;
import static com.geniuses.sewage_zero_straight.net.websocket.WebSocketPool.sessionMap; @Slf4j
public class WebSocketHandler { /**
* 根据key和用户名生成一个key值,简单实现下
* @param key
* @param name
* @return
*/
public static String createKey(String key, String name){
return key + "@" + name;
} /**
* 给指定用户发送信息
* @param session
* @param msg
*/
public static void sendMessage(Session session, String msg){
if (session == null)
return;
final RemoteEndpoint.Basic basic = session.getBasicRemote();
if (basic == null)
return;
try {
basic.sendText(msg);
} catch (IOException e) {
log.error("sendText Exception: {}", e);
}
} /**
* 给所有的在线用户发送消息
* @param message
*/
public static void sendMessageAll(String message){
log.info("广播:群发消息");
sessionMap().forEach((key, session) -> sendMessage(session, message));
}
}

4、前端访问实现

4.1、index.html,页面引用了jquery和bootstrap样式,请自行应用

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.springframework.org/schema/mvc">
<head>
<meta charset="UTF-8">
<title>chat room websocket</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.min.css}">
<script th:src="@{/js/jquery-3.3.1.min.js}" ></script>
</head>
<body class="container" style="width: 60%">
<div class="form-group" ></br>
<h5>聊天室</h5>
<textarea id="message_content" class="form-control" readonly="readonly" cols="50" rows="10"></textarea>
</div>
<div class="form-group" >
<label for="in_user_name">用户姓名 &nbsp;</label>
<input id="in_user_name" value="" class="form-control" /></br>
<button id="user_join" class="btn btn-success" >加入聊天室</button>
<button id="user_exit" class="btn btn-warning" >离开聊天室</button>
</div>
<div class="form-group" >
<label for="in_room_msg" >群发消息 &nbsp;</label>
<input id="in_room_msg" value="" class="form-control" /></br>
<button id="user_send_all" class="btn btn-info" >发送消息</button>
</div>
</body>
<<script type="text/javascript">
$(document).ready(function(){
var urlPrefix ='ws://192.168.2.156:8080/net/websocket/12/';
var ws = null;
$('#user_join').click(function(){
var username = $('#in_user_name').val();
var url = urlPrefix + username;
ws = new WebSocket(url);
ws.onopen = function () {
console.log("建立 websocket 连接...");
};
ws.onmessage = function(event){
//服务端发送的消息
$('#message_content').append(event.data+'\n');
};
ws.onclose = function(){
$('#message_content').append('用户['+username+'] 已经离开聊天室!' + '\n');
console.log("关闭 websocket 连接...");
}
});
//客户端发送消息到服务器
$('#user_send_all').click(function(){
var msg = $('#in_room_msg').val();
if(ws){
ws.send(msg);
}
});
// 退出聊天室
$('#user_exit').click(function(){
if(ws){
ws.close();
}
});
})
</script>
</html>

  4.2、页面访问控制器,由此来访问index.html

package com.geniuses.sewage_zero_straight.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; @RequestMapping("/view")
@Controller
public class ViewController { /**
* 返回首页
* @return
*/
@GetMapping("/index")
public String index(){
return "index";
}
}

5、websocket配置

package com.geniuses.sewage_zero_straight.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.server.standard.ServerEndpointExporter; @Configuration
@EnableWebSocket
public class WebSocketConfig { @Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
 
6、注意:
    在使用了@ServerEndpoint注解的类是无法直接使用@Autowired的,因为@ServerEndpoint表明当前类是websocket的服务端点,在spring容器启动时会初始化一次该类,当有新的websocket连接的时候,也会进行该类实例的创建(每一次连接时都会创建一个实例),所以在第二次往后创建该类实例的时候,就无法进行有效的@Autowired了,此时发现,即便第一次注入是有效的,但是也没有什么用。这个时候,将需要注入的变量置为类的变量,提供一个set方法(该方法为实例方法),在set方法上面进行依赖注入,这样就可以进行有效的注入了。
 
7、这里只是websocket的简单实现,更多情况...

SpringBoot之集成WebSocket的更多相关文章

  1. 【websocket】spring boot 集成 websocket 的四种方式

    集成 websocket 的四种方案 1. 原生注解 pom.xml <dependency> <groupId>org.springframework.boot</gr ...

  2. springboot集成websocket的两种实现方式

    WebSocket跟常规的http协议的区别和优缺点这里大概描述一下 一.websocket与http http协议是用在应用层的协议,他是基于tcp协议的,http协议建立链接也必须要有三次握手才能 ...

  3. springboot集成websocket实现向前端浏览器发送一个对象,发送消息操作手动触发

    工作中有这样一个需示,我们把项目中用到代码缓存到前端浏览器IndexedDB里面,当系统管理员在后台对代码进行变动操作时我们要更新前端缓存中的代码怎么做开始用想用版本方式来处理,但这样的话每次使用代码 ...

  4. springboot集成websocket实现大文件分块上传

    遇到一个上传文件的问题,老大说使用http太慢了,因为http包含大量的请求头,刚好项目本身又集成了websocket,想着就用websocket来做文件上传. 相关技术 springboot web ...

  5. SpringBoot集成websocket发送后台日志到前台页面

    业务需求 后台为一个采集系统,需要将采集过程中产生的日志实时发送到前台页面展示,以便了解采集过程. 技能点 SpringBoot 2.x websocket logback thymeleaf Rab ...

  6. spring boot 集成 websocket 实现消息主动推送

    spring boot 集成 websocket 实现消息主动 前言 http协议是无状态协议,每次请求都不知道前面发生了什么,而且只可以由浏览器端请求服务器端,而不能由服务器去主动通知浏览器端,是单 ...

  7. tomcat 7下spring 4.x mvc集成websocket以及sockjs完全参考指南

    之所以sockjs会存在,说得不好听点,就是因为微软是个流氓,现在使用windows 7的系统仍然有近半,而windows 7默认自带的是ie 8,有些会自动更新到ie 9,但是大部分非IT用户其实都 ...

  8. springboot elasticsearch 集成注意事项

    文章来源: http://www.cnblogs.com/guozp/p/8686904.html 一 elasticsearch基础 这里假设各位已经简单了解过elasticsearch,并不对es ...

  9. Springboot Application 集成 OSGI 框架开发

    内容来源:https://www.ibm.com/developerworks/cn/java/j-springboot-application-integrated-osgi-framework-d ...

随机推荐

  1. 【微信小程序】---线上环境搭建

    一.前言 通常我们在本地电脑上开发微信小程序,调用和访问小程序会有很多问题.特别是在配有自己后端的情况下,我们通过真机访问我们的小程序会出现不可访问的问题 二.线上环境搭建 在这里我们主要以腾讯云给大 ...

  2. POJ 2987 - Firing - [最大权闭合子图]

    题目链接:http://poj.org/problem?id=2987 Time Limit: 5000MS Memory Limit: 131072K Description You’ve fina ...

  3. 【紫书】Play on Words UVA - 10129 欧拉回路

    题意:给你1e5个字符串,若前一个的末尾字母等于当前的首字母,则可以连在一起(成语接龙一个意思)判断是否可以将他们连在一起 题解:将首位看作点,单词看作边.变成欧拉回路问题. 判断出入度是否相等,再用 ...

  4. POJ - 3026 Borg Maze bfs+最小生成树。

    http://poj.org/problem?id=3026 题意:给你一个迷宫,里面有 ‘S’起点,‘A’标记,‘#’墙壁,‘ ’空地.求从S出发,经过所有A所需要的最短路.你有一个特殊能力,当走到 ...

  5. ionic 下拉选择框中默认显示传入的参数

    开发过程当中遇到一个有趣的问题,如果我在第一个页面需要把 item { "ownerId" : 1 } 传递给第二个页面,并挂在$scope下 $scope.item = $sta ...

  6. Linux 虚拟串口及 Qt 串口通信实例

    Linux 虚拟串口及 Qt 串口通信实例 2011-06-22 17:49 佚名 互联网 字号:T | T Linux 虚拟串口及 Qt 串口通信实例是本文所要介绍的内容,在实现过程中,打开了两个伪 ...

  7. Networking---poj1287最小生成树

    http://poj.org/problem?id=1287 最小生成树模板题类似的还有:poj1258  hdu1233代码几乎一样: 最小生成树详解 #include<stdio.h> ...

  8. 【虫师讲Selenium+Python】第三讲:操作测试对象

    一.首先呢,选择一个编辑器,我们这里选择的是Sublime Text >Ctrl+B为运行当前脚本的快捷方式 二.编写代码 #coding==utf-8 from selenium import ...

  9. SQL实现交,并,差操作

    有的数据库不支持intersect,except,所以交集,和差集使用嵌套查询来做比较靠谱. a表和b表具有完全一样的结构 mysql> desc a; +-------+----------- ...

  10. zabbix 报错汇总

    打开zabbix web界面点击profile出现以下报错信息: scandir() has been disabled for security reasons [profile.php:198 → ...