概述
第一步:
//pom文件添加依赖,thymeleaf是模板,视情况是否添加
<!--websocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>4.3.8.RELEASE</version>
</dependency>
第二步:
//启动类增加bean,和main方法同级
/**springboot 自带tomcat 所以 打成war包之前需要把下面这几行代码注释掉
,注释之后war包放到务器的tomcat下就没问题了
* springboot内置tomcat的话,需要配一下这个。。如果没有这个对象,无法连接到websocket
*/
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
第三步:
//建websocket后台代码
package com.ts.websocket.util;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
/**
*/
@ServerEndpoint("/websocket/{userno}")
@Component
public class WebSocketUtil {
private static final String loggerName = WebSocketUtil.class.getName();
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
private static ConcurrentHashMap<String, WebSocketUtil> webSocketSet = new ConcurrentHashMap<String, WebSocketUtil>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session webSocketSession;
//当前发消息的人员编号
private String userno = "";
/**
* 连接建立成功调用的方法
*
* @param webSocketSession 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
@OnOpen
public void onOpen(@PathParam(value = "userno") String param, Session webSocketSession, EndpointConfig config) {
System.out.println(param);
userno = param;//接收到发送消息的人员编号
this.webSocketSession = webSocketSession;
webSocketSet.put(param, this);//加入map中
addOnlineCount();
//在线数加1
System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
if (!userno.equals("")) {
webSocketSet.remove(userno);
//从set中删除
subOnlineCount();
//在线数减1
System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
}
}
/**
* 收到客户端消息后调用的方法
* 也可以后台调用发送数据
*
message 格式约定为JSON字符串。
*
例:{"to":"All","time":"2020-09-09 16:22:42","message":"自定义消息","type":"text"}
*
to:发送给的用户
*
time:时间
*
type:类型:text时就是字符串
url时就是跳转的地址 (和前端约定)
*
message:消息
*
* @param message 客户端发送过来的消息
*/
@OnMessage
public void onMessage(String message) throws IOException {
//约定message格式为此格式
JSONObject jsonTo = JSONObject.parseObject(message);
//
String mes = (String) jsonTo.get("message");
if (!jsonTo.get("to").equals("All")) {
sendMessageTo(message, jsonTo.get("to").toString());
} else {
sendMessageAll(message);
}
}
public void sendMessageTo(String message, String to) throws IOException {
String now = getNowTime();
if (webSocketSet.get(to) != null) {
//
webSocketSet.get(to).sendMessage("<br/>" + now + "用户" + userno + "发来消息:" + message);
webSocketSet.get(to).sendMessage(message);
} else {
System.out.println("当前用户不在线");
}
}
public void sendMessageAll(String message) throws IOException {
String now = getNowTime();
//遍历HashMap
for (String key : webSocketSet.keySet()) {
try {
//判断接收用户是否是当前发消息的用户
if (!userno.equals(key)) {
webSocketSet.get(key).sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 获取当前时间
*
* @return
*/
private String getNowTime() {
Date date = new Date();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = format.format(date);
return time;
}
/**
* 发生错误时调用
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
System.out.println("发生错误");
error.printStackTrace();
}
/**
* getBasicRemote 同步发送,多条消息的话要等到上一条发完才可以发下一条消息
* getAsyncRemote 异步发送
*
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException {
this.webSocketSession.getAsyncRemote().sendText(message);
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketUtil.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketUtil.onlineCount--;
}
}
//将message改造成自己需要的 MessageVO格式
package com.ts.websocket.vo;
/**
*
*
webSocket 约定的 message值类型
*/
public class MessageVO {
/**
* 时间
*/
private String time;
/**
* 发送人
*/
private String from;
/**
* 接收人
*/
private String to;
/**
* 类型:
* text 是文本
* url 是地址 (前端约定类型是url时候message值是地址,前端跳转指定地址)
*/
private String type;
/**
* 消息
*/
private String message;
/*********************************get/set***********************************************/
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
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 getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
第四步:
//前台页面 下面这个是参考的页面 名称:copy1.html 访问:http://127.0.0.1:8081/项目地址/copy1.html (有shiro拦截的记得关)
发送的数据格式是:{"to":"All","time":"2020-09-09 16:22:42","message":"自定义消息","type":"text"}
JSON数据格式,因为上面后台写了处理,所以格式就定MessageVO 的格式
没打印在页面是应为群发的把自己屏蔽了,把 to 的值改为 1 就可以了
此处的 1 代表的是用户注册的 websocket 的标识,是参数,后面自行替换成自己需要的参数就可以了。
<html>
<head>
<meta charset="UTF-8"></meta>
<title>springboot项目WebSocket测试demo</title>
</head>
<body>
<h3>springboot项目websocket测试demo</h3>
<h4>测试说明</h4>
<h5>文本框中数据数据,点击‘发送测试’,文本框中的数据会发送到后台websocket,后台接受到之后,会再推送数据到前端,展示在下方;点击关闭连接,可以关闭该websocket;可以跟踪代码,了解具体的流程;代码上有详细注解</h5>
<br />
<input id="text" type="text" />
<button onclick="send()">发送测试</button>
<hr />
<button onclick="clos()">关闭连接</button>
<hr />
<div id="message"></div>
<script>
var websocket = null;
if('WebSocket' in window){
websocket = new WebSocket("ws://127.0.0.1:8081/项目标识/websocket/1");
}else{
alert("您的浏览器不支持websocket");
}
websocket.onerror = function(){
setMessageInHtml("send error!");
}
websocket.onopen = function(){
setMessageInHtml("connection success!")
}
websocket.onmessage
= function(event){
setMessageInHtml(event.data);
}
websocket.onclose = function(){
setMessageInHtml("closed websocket!")
}
window.onbeforeunload = function(){
clos();
}
function setMessageInHtml(message){
document.getElementById('message').innerHTML += message;
}
function clos(){
websocket.close(3000,"强制关闭");
}
function send(){
var msg = document.getElementById('text').value;
websocket.send(msg);
}
</script>
</body>
</html>
下面是对js返回数据格式(约定好的)的更改:
websocket.onmessage = function(e) {
var message = e.data;
//约定message格式
var mesMap = JSON.parse(message);
if ("url"===mesMap.type) {
window.open(mesMap.message, '_self');
// window.open(mesMap.message);
// window.location.href=message;
}else{
console.log(message);
}
};
第五步:
//后台方法调用
调用的前提是你的websocket连接已经建立,否则发送不成功。
try {
WebSocketUtil ws = new WebSocketUtil();
MessageVO messageVO = new MessageVO();
messageVO.setTime("2020-09-09 18:00:00");
messageVO.setFrom("系统");
messageVO.setTo("1");//注册的用户是谁就填谁
messageVO.setType("text");//类型url表示跳转页面,text表示打印。(前端约定好)
messageVO.setMessage("测试message");
ws.onMessage(JSON.toJSONString(messageVO));
}catch (IOException e){
System.out.println("webSocket出错:"+e);
}
完毕:初步的就这样了,其他的优化再说吧
参考:
https://blog.csdn.net/qq_39478853/article/details/79413453
https://blog.csdn.net/qq_41700030/article/details/100777937
https://blog.csdn.net/qq_27409289/article/details/81814272
----------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------
简单的优化:
替换第三步中的 WebSocketUtil 类。
onMessage 方法是可以有返回值的,这样就可以在后台调用的时候返回知道发送给指定的用户是成功还是失败了。
package com.ts.websocket.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ts.websocket.vo.WebSocketResult;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
/**
*/
@ServerEndpoint("/websocket/{userno}")
@Component
public class WebSocketUtil {
private static final String loggerName = WebSocketUtil.class.getName();
private static final String sendAll = "All";
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
private static ConcurrentHashMap<String, WebSocketUtil> webSocketSet = new ConcurrentHashMap<String, WebSocketUtil>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session webSocketSession;
//当前发消息的人员编号
private String userno = "";
/**
* 连接建立成功调用的方法
*
* @param webSocketSession 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
@OnOpen
public void onOpen(@PathParam(value = "userno") String param, Session webSocketSession, EndpointConfig config) {
System.out.println(param);
userno = param;//接收到发送消息的人员编号
this.webSocketSession = webSocketSession;
webSocketSet.put(param, this);//加入map中
addOnlineCount();
//在线数加1
System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
if (!userno.equals("")) {
webSocketSet.remove(userno);
//从set中删除
subOnlineCount();
//在线数减1
System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
}
}
/**
* 收到客户端消息后调用的方法
* 也可以后台调用发送数据
* message 格式约定为JSON字符串。
* 例:{"to":"All","time":"2020-09-09 16:22:42","message":"自定义消息","type":"text"}
* to:发送给的用户
* time:时间
* type:类型:text时就是字符串
url时就是跳转的地址 (和前端约定)
* message:消息
*
* @param message 客户端发送过来的消息
* @return JSON格式的String字符串,约定为WebSocketResult格式
*/
@OnMessage
public String onMessage(String message) {
//约定message格式为此格式
JSONObject jsonTo = JSONObject.parseObject(message);
if (!jsonTo.get("to").equals(sendAll)) {
return sendMessageTo(message, jsonTo.get("to").toString());
} else {
return sendMessageAll(message);
}
}
public String sendMessageTo(String message, String to) {
WebSocketResult webSocketResult = new WebSocketResult(WebSocketResult.success, "");
try {
if (webSocketSet.get(to) != null) {
webSocketSet.get(to).sendMessage(message);
} else {
webSocketResult = new WebSocketResult(WebSocketResult.notOnline, "当前用户不在线");
}
} catch (Exception e) {
webSocketResult = new WebSocketResult("error", e.getMessage());
}
return JSON.toJSONString(webSocketResult);
}
public String sendMessageAll(String message) {
WebSocketResult webSocketResult = new WebSocketResult(WebSocketResult.success, "");
String now = getNowTime();
//遍历HashMap
for (String key : webSocketSet.keySet()) {
try {
//判断接收用户是否是当前发消息的用户
if (!userno.equals(key)) {
webSocketSet.get(key).sendMessage(message);
}
} catch (Exception e) {
webSocketResult = new WebSocketResult(WebSocketResult.error, e.getMessage());
}
}
return JSON.toJSONString(webSocketResult);
}
/**
* 获取当前时间
*
* @return
*/
private String getNowTime() {
Date date = new Date();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = format.format(date);
return time;
}
/**
* 发生错误时调用
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
System.out.println("发生错误");
error.printStackTrace();
}
/**
* getBasicRemote 同步发送,多条消息的话要等到上一条发完才可以发下一条消息
* getAsyncRemote 异步发送
*
* @param message
* @throws IOException
*/
public void sendMessage(String message) throws IOException {
this.webSocketSession.getAsyncRemote().sendText(message);
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketUtil.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketUtil.onlineCount--;
}
}
增加一个返回类型类:
package com.ts.websocket.vo;
public class WebSocketResult {
//发送成功
public static final String success = "success";
//发送失败
public static final String error = "error";
//发送的用户不存在
public static final String notOnline = "notOnline";
/**
* 状态:success 成功
* notOnline 不在线(给单个用户发)
* error 失败
*/
private String state;
/**
* 提示信息
*/
private String message;
public WebSocketResult() {
super();
}
public WebSocketResult(String state, String message) {
this.state = state;
this.message = message;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
此时后台调用的方法:
@ResponseBody
@PostMapping(value = "/dw/redirectUrl")
@ApiOperation(value = "测试接口")
public SysResult testDW2(@RequestBody DwParamVO dwParamVO) {
SysResult sysResult = new SysResult();//自己接口返回格式
try {
WebSocketUtil ws = new WebSocketUtil();
MessageVO messageVO = new MessageVO();
messageVO.setFrom("系统");
messageVO.setTo(dwParamVO.getIp());
messageVO.setType("url");
messageVO.setMessage(dwParamVO.getUrl());
//发送消息
String webSocketResult = ws.onMessage(JSON.toJSONString(messageVO));
//对发送消息格式进行处理
JSONObject jsonObject = JSON.parseObject(webSocketResult);
//发送消息的返回,给自己的统一返回中做标识,以便处理
if (WebSocketResult.success.equals(jsonObject.get("state"))) {
sysResult.setObjOther(WebSocketResult.success);
} else if (WebSocketResult.notOnline.equals(jsonObject.get("state"))) {
sysResult.setObjOther(WebSocketResult.notOnline);
} else {
sysResult.setObjOther(WebSocketResult.error);
}
} catch (Exception e) {
sysResult.setObjOther(WebSocketResult.error);
sysResult.onSetErrorMsg(e);
}
return sysResult;
}
最后
以上就是贪玩大船为你收集整理的webSocket 后台发送给前台消息,实现页面跳转消息提示的全部内容,希望文章能够帮你解决webSocket 后台发送给前台消息,实现页面跳转消息提示所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复