目录
- 整体项目
- 具体代码
- 运行结果
整体项目
具体代码
1、pom.xml配置
主要是添加下面这个依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.moreday</groupId>
<artifactId>messaging-stomp-websocket</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>messaging-stomp-websocket Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId>
</dependency> -->
<!-- https://mvnrepository.com/artifact/org.yeauty/netty-websocket-spring-boot-starter -->
<!-- <dependency> <groupId>org.yeauty</groupId> <artifactId>netty-websocket-spring-boot-starter</artifactId>
<version>0.9.5</version> </dependency> -->
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.68</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>webjars-locator-core</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.1-1</version>
</dependency>
<!-- 热部署,不用重启 ,这个在这里不需要 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<finalName>messaging-stomp-websocket</finalName>
</build>
</project>
server.port=8080
#spring.datasource.jdbc-url=jdbc:mysql://localhost:3306/babaytun?useUnicode=true&characterEncoding=utf-8&useSSL=false
#spring.datasource.username=root
#spring.datasource.password=root
#spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#first.datasource.type=com.alibaba.druid.pool.DruidDataSource
############################################################
# thymeleaf
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.check-template-location=true
spring.thymeleaf.suffix=.html
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.content-type=text/html
spring.thymeleaf.mode=HTML5
spring.thymeleaf.cache=false
app.java
package com.moreday;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
/**
* @ClassName WebSocketApp
* @Description TODO(这里用一句话描述这个类的作用)
* @author 寻找手艺人
* @Date 2020年4月25日 上午10:59:10
* @version 1.0.0
*/
@SpringBootApplication
public class WebSocketApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(WebSocketApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(WebSocketApplication.class, args);
}
}
config.java
package com.moreday.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* @ClassName WebSocketStompConfig
* @Description TODO(实例化一个ServerEndpointExporter对象,交给Spring IOC容器,表示要开启WebSocket功能)
* @author 寻找手艺人
* @Date 2020年4月21日 下午6:58:39
* @version 1.0.0
*/
@Configuration
public class WebSocketStompConfig{
@Bean
public ServerEndpointExporter serverEndpointExporter()
{
return new ServerEndpointExporter();
}
}
websocketserver.java
package com.moreday.service;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
/**
* @ClassName WebSocket
* @Description TODO(这里用一句话描述这个类的作用)
* @author 寻找手艺人
* @Date 2020年4月21日 下午7:00:33
* @version 1.0.0
*/
@ServerEndpoint("/websocket/{username}")
@Component
public class WebSocketServer {
private Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 在线人数
*/
public static int onlineNumber = 0;
/**
* 以用户的姓名为key,WebSocket为对象保存起来
*/
private static Map<String, WebSocketServer> clients = new ConcurrentHashMap<String, WebSocketServer>();
/**
* 会话
*/
private Session session;
/**
* 用户名称
*/
private String username;
/**
* 建立连接
*
* @param session
*/
@OnOpen
public void onOpen(@PathParam("username") String username, Session session)
{
onlineNumber++;
logger.info("现在来连接的客户id:"+session.getId()+"用户名:"+username);
this.username = username;
this.session = session;
logger.info("有新连接加入! 当前在线人数" + onlineNumber);
try {
//messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
//先给所有人发送通知,说我上线了
Map<String,Object> map1 = new HashMap<>();
map1.put("messageType",1);
map1.put("username",username);
sendMessageAll(JSON.toJSONString(map1),username);
//把自己的信息加入到map当中去
clients.put(username, this);
//给自己发一条消息:告诉自己现在都有谁在线
Map<String,Object> map2 = new HashMap<>();
map2.put("messageType",3);
//移除掉自己
Set<String> set = clients.keySet();
map2.put("onlineUsers",set);
sendMessageTo(JSON.toJSONString(map2),username);
}
catch (IOException e){
logger.info(username+"上线的时候通知所有人发生了错误");
}
}
@OnError
public void onError(Session session, Throwable error) {
logger.info("服务端发生了错误"+error.getMessage());
error.printStackTrace();
}
/**
* 连接关闭
*/
@OnClose
public void onClose()
{
onlineNumber--;
//webSockets.remove(this);
clients.remove(username);
try {
//messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
Map<String,Object> map1 = new HashMap<>();
map1.put("messageType",2);
map1.put("onlineUsers",clients.keySet());
map1.put("username",username);
sendMessageAll(JSON.toJSONString(map1),username);
}
catch (IOException e){
logger.info(username+"下线的时候通知所有人发生了错误");
}
logger.info("有连接关闭! 当前在线人数" + onlineNumber);
}
/**
* 收到客户端的消息
*
* @param message 消息
* @param session 会话
*/
@OnMessage
public void onMessage(String message, Session session)
{
try {
logger.info("来自客户端消息:" + message+"客户端的id是:"+session.getId());
JSONObject jsonObject = JSON.parseObject(message);
String textMessage = jsonObject.getString("contentText");
String fromusername = jsonObject.getString("fromUserId");
String tousername = jsonObject.getString("toUserId");
//如果不是发给所有,那么就发给某一个人
//messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
Map<String,Object> map1 = Maps.newHashMap();
map1.put("messageType",4);
map1.put("textMessage",textMessage);
map1.put("fromusername",fromusername);
if("All".equals(tousername)){
map1.put("tousername","所有人");
sendMessageAll(JSON.toJSONString(map1),fromusername);
}else{
map1.put("tousername",tousername);
sendMessageTo(JSON.toJSONString(map1),tousername);
}
}
catch (Exception e){
e.printStackTrace();
logger.info("发生了错误了");
}
}
public void sendMessageTo(String message, String ToUserName) throws IOException {
for (WebSocketServer item : clients.values()) {
if (item.username.equals(ToUserName) ) {
item.session.getAsyncRemote().sendText(message);
break;
}
}
}
public void sendMessageAll(String message,String FromUserName) throws IOException {
for (WebSocketServer item : clients.values()) {
item.session.getAsyncRemote().sendText(message);
}
}
public static synchronized int getOnlineCount() {
return onlineNumber;
}
}
html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebSocket</title>
<link href="/webjars/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/main.css" rel="stylesheet">
<script src="/webjars/jquery/jquery.min.js"></script>
</head>
<body>
<h3>IM聊天</h3>
<p>【发送者】:<div><input id="fromUserId" name="fromUserId" type="text" value="王百万"></div>
<p>【接收者】:<div><input id="toUserId" name="toUserId" type="text" value="刘首付"></div>
<p>【发送内容】:<div><input id="contentText" name="contentText" type="text" value="在家不,我找到一个好楼盘!"></div>
<p>操作:<div><button onclick="openSocket()">开启socket</button> </div>
<p>【操作】:<div><button onclick="sendMessage()">发送消息</button></div>
<div id="main-content" class="container">
<div class="row">
<div class="col-md-12">
<table id="conversation" class="table table-striped">
<thead>
<tr>
<th>消息记录</th>
</tr>
</thead>
<tbody id="greetings">
</tbody>
</table>
</div>
</div>
</div>
</body>
<script>
var socket;
function openSocket() {
if(typeof(WebSocket) == "undefined") {
console.log("您的浏览器不支持WebSocket");
}else{
console.log("您的浏览器支持WebSocket");
//实现化WebSocket对象,指定要连接的服务器地址与端口 建立连接
var userId = document.getElementById('fromUserId').value;
var socketUrl="ws://127.0.0.1:8080/websocket/"+userId;
console.log(socketUrl);
if(socket!=null){
socket.close();
socket=null;
}
socket = new WebSocket(socketUrl);
//打开事件
socket.onopen = function() {
console.log("websocket已打开");
//socket.send("这是来自客户端的消息" + location.href + new Date());
};6
//获得消息事件
socket.onmessage = function(msg) {
var serverMsg = "收到服务端信息:" + msg.data;
$("#greetings").append("<tr><td>" + serverMsg + "</td></tr>");
//发现消息进入 开始处理前端触发逻辑
console.log(msg);
};
//关闭事件
socket.onclose = function() {
console.log("websocket已关闭");
};
//发生了错误事件
socket.onerror = function() {
console.log("websocket发生了错误");
}
}
}
function sendMessage() {
if(typeof(WebSocket) == "undefined") {
console.log("您的浏览器不支持WebSocket");
}else {
// console.log("您的浏览器支持WebSocket");
var fromUserId = document.getElementById('fromUserId').value;
var toUserId = document.getElementById('toUserId').value;
var contentText = document.getElementById('contentText').value;
var msg = '{"fromUserId":"'+fromUserId+'","toUserId":"'+toUserId+'","contentText":"'+contentText+'"}';
console.log(msg);
socket.send(msg);
}
}
</script>
</html>
运行结果
开启两个客户端连接:
王百万->发消息给->刘首付
王百万:在家不,一块吃个饭?
刘首付:必须在,我请客!
#王百万#与#刘首付#约饭的事让#张大嘴#知道了,心里很是不爽,
就把这件吃饭不叫他的事,给群发了~。