PC端WebSocket springboot stompjs 简单的实现即时通讯
websocket介绍:
WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端
websocket使用场景分享
如弹幕,网页聊天系统,实时监控,股票行情推送等
效果图:
一,简单地访问8080端口:
二,点击v1 test.html 和index.html连接:
三、v2连接:、
四、v3连接:
’
五、v4:
六、v5连接:
代码:
pom.xml
4.0.0
<groupId>org.example</groupId>
<artifactId>websocket_shy</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>sockjs-client</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>stomp-websocket</artifactId>
<version>2.3.3</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>3.3.7</version>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
一、model包下:(类似实体类,有两个类)
package cn.shy.model;
import java.util.Date;
/**
-
@program: websocket_shy
-
@description: 类似实体类1
-
@author: hylshyshm
-
@create: 2020-09-03 16:02
**/
public class InMessage {
private String from;
private String to;
private String content;
private Date time;public InMessage(){
}
public InMessage(String content){
this.content=content;
}
public String getFrom() {
return from;
}public void setFrom(String from) {
this.from = from;
}public String getTo() {
return to;
}public void setTo(String to) {
this.to = to;
}public String getContent() {
return content;
}public void setContent(String content) {
this.content = content;
}public Date getTime() {
return time;
}public void setTime(Date time) {
this.time = time;
}
}
package cn.shy.model;
import java.util.Date;
/**
-
@program: websocket_shy
-
@description: 类似实体类2
-
@author: hylshyshm
-
@create: 2020-09-03 16:04
**/
public class OutMessage {
private String from;
private String content;
private Date time = new Date();
public OutMessage(){}
public OutMessage(String content){
this.content=content;
}
public String getFrom() {
return from;
}public void setFrom(String from) {
this.from = from;
}public String getContent() {
return content;
}public void setContent(String content) {
this.content = content;
}public Date getTime() {
return time;
}public void setTime(Date time) {
this.time = time;
}
}
二、配置类:config
package cn.shy.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
/**
-
@program: websocket_shy
-
@description: 配置类
-
@author: hylshyshm
-
@create: 2020-09-03 16:09
**/
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {/**
- 注册端点,发布或者订阅消息的时候需要连接此端点
- setAllowedOrigins 非必须,*表示允许其他域进行连接
- withSockJS 表示开始sockejs支持
- addInterceptors 添加拦截器
/
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/endpoint-websocket").setAllowedOrigins("").withSockJS();
stompEndpointRegistry.addEndpoint("/endpoint-websocket").addInterceptors();
}
/**
-
配置消息代理(中介)
-
enableSimpleBroker 服务端推送给客户端的路径前缀
-
setApplicationDestinationPrefixes 客户端发送数据给服务器端的一个前缀
*/
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {registry.enableSimpleBroker("/topic", “/chat”);
registry.setApplicationDestinationPrefixes("/app");
}
}
三、listener监听器类:2个
package cn.shy.listener;
import org.springframework.context.ApplicationListener;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.messaging.SessionConnectEvent;
/**
- @program: websocket_shy
- @description: 监听事件类型1
- @author: hylshyshm
- @create: 2020-09-03 16:13
**/
@Component
public class ConnetEventListent implements ApplicationListener {
@Override
public void onApplicationEvent(SessionConnectEvent sessionConnectEvent) {
StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(sessionConnectEvent.getMessage());
//System.out.println("【sessionConnectedEvent:监听事件类型:】"+headerAccessor.getCommand().getMessageType());
}
}
package cn.shy.listener;
import org.springframework.context.ApplicationListener;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.messaging.SessionSubscribeEvent;
/**
-
@program: websocket_shy
-
@description: 监听事件类型2
-
@author: hylshyshm
-
@create: 2020-09-03 16:19
**/
@Component
public class SubSribeEventListent implements ApplicationListener {
@Override
public void onApplicationEvent(SessionSubscribeEvent sessionSubscribeEvent) {
StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(sessionSubscribeEvent.getMessage());
//System.out.println(“sessionSubscribeEvent【监听事件类型:】”+headerAccessor.getCommand().getMessageType()+headerAccessor.getMessage());}
}
四、controller控制器:
v1:
package cn.shy.controller.v1;
import cn.shy.model.InMessage;
import cn.shy.model.OutMessage;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
/**
-
@program: websocket_shy
-
@description: v1版本控制器
-
@author: hylshyshm
-
@create: 2020-09-03 16:24
**/
@Controller
public class GameInfoController {
@MessageMapping("/v1/chat")
@SendTo("/topic/game_chat")
public OutMessage gameInfo(InMessage inMessage){return new OutMessage(inMessage.getContent());
}
}
v5:
package cn.shy.controller.v5;
import cn.shy.service.WebSocketService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
/**
-
@program: websocket_shy
-
@description: v5控制器
-
@author: hylshyshm
-
@create: 2020-09-03 17:46
**/
@Controller
public class V5RoomController {
@Autowired
private WebSocketService webSocketService;//@MessageMapping("/v4/schedule/push")
@Scheduled(fixedRate = 3000)
public void fuqInfo(){
webSocketService.sendMessageCPUInfo();
}
}
SampleController:
package cn.shy.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class SampleController {
@RequestMapping("/")
@ResponseBody
String home() {
return "Hello World!";
}
}
五、service:业务层
package cn.shy.service;
import cn.shy.model.InMessage;
import cn.shy.model.OutMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;
/**
-
@program: websocket_shy
-
@description: 业务层
-
@author: hylshyshm
-
@create: 2020-09-03 16:27
**/
@Service
public class WebSocketService {
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;//对应v2的控制器–但v2控制器可以不要–注意在app.js中sendName()方法 是公用一个 …send("/app/v1/chat"…
public void sendTopicMessage(String desc, InMessage inMessage){
simpMessagingTemplate.convertAndSend(desc,new OutMessage(inMessage.getContent()));
}//对应v3的控制器–但v3控制器可以不要
public void sendSingleMessage(InMessage inMessage){
simpMessagingTemplate.convertAndSend("/chat/single/"+inMessage.getTo(),
new OutMessage(inMessage.getFrom()+" 发送:"+ inMessage.getContent()));
}//对应v4的控制器–但v4控制器可以不要
public void sendSingleOneMessage(InMessage inMessage){
simpMessagingTemplate.convertAndSendToUser(inMessage.getTo(),"/chat/single",new OutMessage(inMessage.getFrom()+" 发送:"+ inMessage.getContent()));
}//对应v5的控制器
public void sendMessageCPUInfo(){
int pro = Runtime.getRuntime().availableProcessors();
long freeCpu =Runtime.getRuntime().freeMemory();
long maxCpu = Runtime.getRuntime().maxMemory();String message =String.format("服务器可用处理器:%s,虚拟机可用内存大小:%s,已经内存大小:%s",pro,freeCpu,maxCpu); simpMessagingTemplate.convertAndSend("/topic/cpu_info",new OutMessage(message));
}
}
六、启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
/**
- @program: websocket_shy
- @description: 开始启动类
- @author: hylshyshm
- @create: 2020-09-03 16:06
**/
@ComponentScan(basePackages = “cn.shy”)
@SpringBootApplication
@EnableScheduling
class startAppliction {
public static void main(String args[]){
SpringApplication.run(startAppliction.class,args);
}
}
上面实现了后端代码:
如下属于前端代码:在resource下创建构建多层目录
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200903212200680.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2h5bHNoeXNobQ==,size_16,color_FFFFFF,t_70#pic_center
与v1 v2 v3 v4 v5 处于同一级目录的
app.js:
var stompClient = null;
function setConnected(connected) {
$("#connect").prop(“disabled”, connected);
$("#disconnect").prop(“disabled”, !connected);
if (connected) {
$("#conversation").show();
}
else {
$("#conversation").hide();
}
$("#notice").html("");
}
function connect() {
var socket = new SockJS(’/endpoint-websocket’); //连接上端点(基站)
stompClient = Stomp.over(socket); //用stom进行包装,规范协议
stompClient.connect({}, function (frame) {
setConnected(true);
//console.log('Connected: ' + frame);
stompClient.subscribe('/topic/game_chat', function (result) { //v5/app.js与其他的区别在这里!
//console.info(result)
showContent(JSON.parse(result.body));
});
});
}
function disconnect() {
if (stompClient !== null) {
stompClient.disconnect();
}
setConnected(false);
//console.log(“Disconnected”);
}
function sendName() {
stompClient.send("/app/v1/chat", {}, JSON.stringify({'content': $("#content").val()}));
}
function showContent(body) {
$("#notice").append("" + body.content + " “+new Date(body.time).toLocaleString()+”");
}
$(function () {
$(“form”).on(‘submit’, function (e) {
e.preventDefault();
});
$( “#connect” ).click(function() { connect(); });
$( “#disconnect” ).click(function() { disconnect(); });
$( “#send” ).click(function() { sendName(); });
});
同一级目录的main.css
body {
background-color: #f5f5f5;
}
#main-content {
max-width: 940px;
padding: 2em 3em;
margin: 0 auto 20px;
background-color: #fff;
border: 1px solid #e5e5e5;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
v1:
index.html:
Seems your browser doesn't support Javascript! Websocket relies on Javascript being enabled. Please enable Javascript and reload this page!
游戏公告内容 |
---|
Seems your browser doesn't support Javascript! Websocket relies on Javascript being enabled. Please enable Javascript and reload this page!
游戏公告内容 |
---|
v2:
index.html:
Seems your browser doesn't support Javascript! Websocket relies on Javascript being enabled. Please enable Javascript and reload this page!
王者游戏排行榜 |
---|
v3:
index.html:
Seems your browser doesn't support Javascript! Websocket relies on Javascript being enabled. Please enable Javascript and reload this page!
<input type="text" id="content" class="form-control" placeholder="请输入...">
</div>
<button id="send" class="btn btn-default" type="submit">发送</button>
</form>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table id="conversation" class="table table-striped">
<thead>
<tr>
<th>记录</th>
</tr>
</thead>
<tbody id="notice">
</tbody>
</table>
</div>
</div>
v4:
index.html:
Seems your browser doesn't support Javascript! Websocket relies on Javascript being enabled. Please enable Javascript and reload this page!
<input type="text" id="content" class="form-control" placeholder="请输入...">
</div>
<button id="send" class="btn btn-default" type="submit">发送</button>
</form>
</div>
</div>
<div class="row">
<div class="col-md-12">
<table id="conversation" class="table table-striped">
<thead>
<tr>
<th>记录</th>
</tr>
</thead>
<tbody id="notice">
</tbody>
</table>
</div>
</div>
v5:
app.js:
var stompClient = null;
function setConnected(connected) {
$("#connect").prop(“disabled”, connected);
$("#disconnect").prop(“disabled”, !connected);
if (connected) {
$("#conversation").show();
}
else {
$("#conversation").hide();
}
$("#notice").html("");
}
function connect() {
var socket = new SockJS(’/endpoint-websocket’);
stompClient = Stomp.over(socket);
stompClient.connect({}, function (frame) {
setConnected(true);
console.log(‘Connected: ’ + frame);
stompClient.subscribe(’/topic/cpu_info’, function (result) {
showContent(JSON.parse(result.body));
});
});
}
function disconnect() {
if (stompClient !== null) {
stompClient.disconnect();
}
setConnected(false);
console.log(“Disconnected”);
}
function sendName() {
stompClient.send("/app/v4/schedule/push", {}, JSON.stringify({‘content’: KaTeX parse error: Expected 'EOF', got '#' at position 3: ("#̲content").val()…("#to").val(), ‘from’????("#from").val()}));
}
function showContent(body) {
$("#notice").prepend("" + body.content + " “+new Date(body.time).toLocaleString()+”");
}
$(function () {
$(“form”).on(‘submit’, function (e) {
e.preventDefault();
});
$( “#connect” ).click(function() { connect(); });
$( “#disconnect” ).click(function() { disconnect(); });
$( “#send” ).click(function() { sendName(); });
});
index.html:
Seems your browser doesn't support Javascript! Websocket relies on Javascript being enabled. Please enable Javascript and reload this page!
记录 |
---|
上一篇: Unity: 简单血条
下一篇: Unity 角色血条