SSM框架下使用websocket实现后端发送消息至前端
本篇文章本人是根据实际项目需求进行书写的第一版,里面有些内容对大家或许没有用,但是核心代码本人已对其做了红色标注。文章讲解我将从maven坐标、HTML页面、js文件及后端代码一起书写。
一、maven坐标
<!-- WebSocket配置开始-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- WebSocket配置结束-->
二、HTML页面
<!--消息框开始–-->
<!-- 弹窗–>-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="${basePath}/static/css/home/index.css">
<script src="${basePath}/static/js/common/jquery-1.8.3.min.js"></script>
<script src="${basePath}/static/js/home/index.js"></script>
<script src="${basePath}/static/css/layui/layui.js"></script>
<title>后台管理系统</title>
</head>
<body>
<input type="hidden" value="${userId}" id="userId">
<input type="hidden" value="${cnName}" id="cnName">
<div class="tanchuang">
<div class="tanchuangClose"><span class="tanchuangCloseBtn">关闭</span></div>
<h6>消息提示:</h6>
<div id="messages"></div>
</div>
<!--消息框结束–-->
<script src="${basePath}/static/js/home/index.js"></script>
<script src="/static/js/webSocket.js"></script>
</body>
</html>
三、js文件(websocket.js)
var websocket;
// var host = document.location.host;
var userId = $("#userId").val(); // 获得当前登录人员的userName
var cnName=$("#cnName").val();
// alert(username)
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
// alert("浏览器支持Websocket")
if(websocket ==null){
//以下用的是ip路径,那么在本地启动项目时也需要使用ip地址进行访问
websocket = new WebSocket("ws://192.168.200.102:8080/webSocket/"+userId+"/"+cnName);
}
} else {
alert('当前浏览器 Not support websocket')
}
//连接发生错误的回调方法
websocket.onerror = function() {
// setMessageInnerHTML("WebSocket连接发生错误");
};
//连接成功建立的回调方法
websocket.onopen = function() {
// alert("WebSocket连接成功")
// setMessageInnerHTML("WebSocket连接成功");
}
//接收到消息的回调方法
websocket.onmessage = function(event) {
// alert("接收到消息的回调方法")
$('.tanchuang').css('display','block')
// alert("这是后台推送的消息:"+event.data);
$("#messages").append(event.data + '<br/>') ;
// websocket.close();
// alert("webSocket已关闭!")
}
//连接关闭的回调方法
websocket.onclose = function() {
// setMessageInnerHTML("WebSocket连接关闭");
} //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
/*window.onbeforeunload = function() {
closeWebSocket();
}*/
//关闭WebSocket连接
function closeWebSocket() {
websocket.close();
}
//将消息显示在网页上
function setMessageInnerHTML(innerHTML) {
document.getElementById('messages').innerHTML += innerHTML + '<br/>';
}
四、websocket连接控制器
package com.yjlc.platform.utils.webSocket; import com.alibaba.fastjson.JSON;
import com.yjlc.platform.User;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; /**
* --------------------------------------------------------------
* CopyRights(c)2018,YJLC
* All Rights Reserved
* <p>
* FileName: WebSockets.java
* Description:(该处未使用配置类)使用配置类后才可以在该类中进行service的注解注入
* Author: cyb
* CreateDate: 2018-11-28
* --------------------------------------------------------------
*/
@ServerEndpoint("/webSocket/{userId}/{cnName}")
public class WebSockets {
private static int onlineCount = 0;
public static Map<User, WebSockets> clients = new ConcurrentHashMap<User, WebSockets>();
private Session session;
private Long userId;//用户id
private String cnName;//用户真实名称
private User user;//用户实体
public static List<User> list = new ArrayList<>(); //在线列表,记录用户名称 /**
*@description: 连接websocket
*@author:cyb
*@date: 2018-12-03 19:12
*@param: userId 用户id
*@param: cnName 用户真实名称
*@param: session
*@return: void
*/
@OnOpen
public void onOpen(@PathParam("userId") Long userId,@PathParam("cnName") String cnName, Session session) throws IOException {
this.userId = userId;
this.session = session;
this.cnName=cnName;
System.out.println("cnName:"+cnName+"userId"+userId);
user= new User();
user.setUserId(userId);
user.setCnName(cnName);
list.add(user);
addOnlineCount();//添加在线人数
clients.put(user, this);
/* String message = getMessage("["+cnName+"]进入聊天室,当前在线人数为"+getOnlineCount()+"位", "notice", list);
broadcast(message);//调用广播
System.out.println("已连接");*/
}
/**
* 广播消息
* @param message
*/
public void broadcast(String message){
for (WebSockets item : clients.values()) {
String cnName = item.cnName;
//
String msg = message.replace("{userName}",cnName);
item.session.getAsyncRemote().sendText(msg);
}
}
/**
* 组装返回给前台的消息
* @param message 交互信息
* @param type 信息类型
* @param list 在线列表
* @return
*/
public String getMessage(String message, String type, List list){
com.alibaba.fastjson.JSONObject member = new com.alibaba.fastjson.JSONObject();
member.put("message", message);
member.put("type", type);
member.put("list", list);
return member.toString();
}
/**
* 对特定用户发送消息
* @param message
* @param session
*/
public void singleSend(String message, Session session){
try {
session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
*@description: 关闭连接
*@author:cyb
*@date: 2018-12-03 14:33
*@param:
*@return: void
*/
@OnClose
public void onClose() throws IOException {
System.out.println("关闭当前用户连接:"+user.getCnName());
clients.remove(user);
list.remove(user); //从在线列表移除这个用户
subOnlineCount();
}
/**
*@description:前台发送过来的消息
*@author:cyb
*@date: 2018-12-03 14:33
*@param: _message
*@return: void
*/
@OnMessage
public void onMessage(String _message) throws IOException {
com.alibaba.fastjson.JSONObject chat = JSON.parseObject(_message);
com.alibaba.fastjson.JSONObject message = JSON.parseObject(chat.get("message").toString());
if(message.get("to") == null || message.get("to").equals("")){
//如果to为空,则广播;如果不为空,则对指定的用户发送消息
broadcast(_message);
}else{
String [] userlist = message.get("to").toString().split(",");
sendMessageTo(_message,message.get("from").toString());
// singleSend(_message, (Session) routetab.get(message.get("from"))); //发送给自己
}
}
@OnError
public void onError(Session session, Throwable error) {
error.printStackTrace();
}
/**
*@description:消息发送给指定人员
*@author:cyb
*@date: 2018-12-03 14:35
*@param: message
*@param: To
*@return: void
*/
public void sendMessageTo(String message, String To) throws IOException {
for (WebSockets item : clients.values()) {
if (item.userId.equals(To) )
item.session.getAsyncRemote().sendText(message);
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSockets.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSockets.onlineCount--;
}
public static synchronized Map<User, WebSockets> getClients() {
return clients;
}
}
五、websocket辅助类
package com.yjlc.platform.utils.webSocket; import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig; /**
* --------------------------------------------------------------
* CopyRights(c)2018,YJLC
* All Rights Reserved
* <p>
* FileName: HttpSessionConfigurator.java
* Description:配置类 将http中的session传入websocket中
* Author: cyb
* CreateDate: 2018-11-26
* --------------------------------------------------------------
*/
public class HttpSessionConfigurator extends ServerEndpointConfig.Configurator { @Override
public void modifyHandshake(ServerEndpointConfig sec,
HandshakeRequest request, HandshakeResponse response) {
// 获取当前Http连接的session
HttpSession httpSession = (HttpSession) request.getHttpSession();
// 将http session信息注入websocket session
sec.getUserProperties().put(HttpSession.class.getName(), httpSession);
}
}
六、后端代码
/**
*@description:发送信息
*@author:cyb
*@date: 2018-11-19 10:03
*@param: id
*@return: java.util.Map<java.lang.String,java.lang.Object>
*/
@RequestMapping("sndmsg")
@ResponseBody
public Map<String,Object> sndmsg(Long id){
Map<String,Object> map = new HashMap<>();
AdminUser user=(AdminUser) SecurityUtils.getSubject().getSession().getAttribute("users");
try{
// int k=0;
int k= service.sndmsg(id,user);
if(k==200){
map.put("code",200);
return map;
}else {
map.put("code",0);
return map;
}
}catch (Exception e){
e.printStackTrace();
map.put("code",500);
return map;
}
}
七、service层实现类
//该类下标红的未重点,其余的代码大家可以跳过
public int sndmsg(Long id,AdminUser adminUser) {
//获取该条信息模板
SettingTemplateDTO templateDTO = templateDao.getSystemTemplateInfo(id);
List<NotificationSendLog> logList = new ArrayList<>();
String content = templateDTO.getContent();//模板内容
Boolean result = false;
int w=0;//操作结果
int count =0;//发送总条数
int sucNum=0;//发送成功条数
//查询所有用户列表
List<SecurityUser> userList =templateDao.getUserList();
if(templateDTO.getSendMode().equals("1")){//短信发送
}else if(templateDTO.getSendMode().equals("3")){//站内发送(桌面消息提示)
if(templateDTO.getSendPeople().equals("1")){//个人用户
}else if(templateDTO.getSendPeople().equals("2")){//企业用户
WebSockets webSocket = new WebSockets();
List<User> onLineList =WebSockets.list;//获取在线人人员id
List<SecurityUser> userList1 = templateDao.getUserList();
List<NotificationUserLog> userLogList = new ArrayList<>();
for(SecurityUser list:userList1){
NotificationUserLog userLog = new NotificationUserLog();
//调用装配发送日志实体
NotificationSendLog sendLog =setSendLog(templateDTO,adminUser,list);
userLog.setUserId(list.getId());
userLog.setMsgId(templateDTO.getId());
userLog.setMsgStatus(false);
for(int i =0;i<onLineList.size();i++){
Long userId =onLineList.get(i).getUserId();
if(list.getId()==userId){
userLog.setMsgStatus(true);
sendLog.setStatus(true);//发送成功
sucNum+=1;
count+=1;
}
}
userLogList.add(userLog);
count= onLineList.size();
sucNum =onLineList.size();
logList.add(sendLog);
}
//插入发送系统通知与用户的关联关系
int ww = templateDao.insertUserSendLog(userLogList);
webSocket.broadcast(templateDTO.getContent());//调用广播()
//插入系统日志
String category="系统消息";
//调用生成发送日志方法
NotificationLog notificationLog =assembleLog(adminUser,category,count,sucNum,templateDTO);
int h = settingDao.insertLog(notificationLog);
//插入发送日志
w =templateDao.insertSendLog(logList);
}
}
//修改发送状态
templateDTO.setSendStatus(true);
int z = templateDao.updateSystemTemplate(templateDTO);
if(w>0){
return 200;
}
return 0;
注意点:项目在浏览器中访问时,切记路径要和websocket.js中的一致
以上内容仅供参考,如果以上内容有所不当或者不清楚的可以联系本人。技术在于沟通!
SSM框架下使用websocket实现后端发送消息至前端的更多相关文章
- 在Spring Boot框架下使用WebSocket实现聊天功能
上一篇博客我们介绍了在Spring Boot框架下使用WebSocket实现消息推送,消息推送是一对多,服务器发消息发送给所有的浏览器,这次我们来看看如何使用WebSocket实现消息的一对一发送,模 ...
- 在Spring Boot框架下使用WebSocket实现消息推送
Spring Boot的学习持续进行中.前面两篇博客我们介绍了如何使用Spring Boot容器搭建Web项目(使用Spring Boot开发Web项目)以及怎样为我们的Project添加HTTPS的 ...
- 关于在SSM框架下使用PageHelper
首先,如果各位在这块配置和代码有什么问题欢迎说出来,我也会尽自己最大的能力帮大家解答 这些代码我都是写在一个小项目里的,项目的github地址为:https://github.com/Albert-B ...
- ssm框架下怎么批量删除数据?
ssm框架下批量删除怎么删除? 1.单击删除按钮选中选项后,跳转到js函数,由函数处理 2. 主要就是前端的操作 js 操作(如何全选?如何把选中的数据传到Controller中) 3.fun()函数 ...
- Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成)
Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成) 动态表单生成 ElementUI官网引导 Element表单生成 Element动态增减表单,在线代码 关键配置 templa ...
- Jquery DataTable AJAX跨域请求的解决方法及SSM框架下服务器端返回JSON格式数据的解决方法
如题,用HBuilder开发APP,涉及到用AJAX跨域请求后台数据,刚接触,费了不少时间.幸得高手指点,得以解决. APP需要用TABLE来显示数据,因此采用了JQ 的DataTable. 在实现 ...
- SSM框架下分页的实现(封装page.java和List<?>)
之前写过一篇博客 java分页的实现(后台工具类和前台jsp页面),介绍了分页的原理. 今天整合了Spring和SpringMVC和MyBatis,做了增删改查和分页,之前的逻辑都写在了Servle ...
- ssm框架下实现文件上传
1.由于ssm框架是使用Maven进行管理的,文件上传所需要的jar包利用pom.xml进行添加,如下所示: <properties> <commons-fileupload.v ...
- SSM框架下 Failed to load resource: the server responded with a status of 404 (Not Found)错误
这个错误提示的是js的引用路径有错: 1.检查应用路径是否正确(我的问题是路径是正确的但是去到页面就会提示404错误) 引用路径,最好都使用绝对路径 <script type="tex ...
随机推荐
- win10 HTTP 错误 500.21 - Internal Server Error
错误描述: HTTP 错误 500.21 - Internal Server Error 处理程序“ExtensionlessUrlHandler-Integrated-4.0”在其模块列表中有一个错 ...
- Hibernate学习(三)———— 一对多映射关系
序言 前面两节讲了hibernate的两个配置文件和hello world!.还有hibernate的一级缓存和三种状态,基本上hibernate就懂一点了,从这章起开始一个很重要的知识点,hiber ...
- shell的编程结构体(函数、条件结构、循环结构)
bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html 1.1 shell函数 在shell中,函数可以被当作命令一样 ...
- centos7指定yum安装软件路径
网上的命令都是垃圾 yum -c /etc/yum.conf --installroot=/opt/all_venv/ --releasever=/ install nginx 该命令简单解释如下: ...
- ASP.NET Core配置环境变量和启动设置
在这一部分内容中,我们来讨论ASP.NET Core中的一个新功能:环境变量和启动设置,它将开发过程中的调试和测试变的更加简单.我们只需要简单的修改配置文件,就可以实现开发.预演.生产环境的切换. A ...
- CentOS 7 安装 .Net Core 2.0 详细步骤
轰轰烈烈的Core 热潮,从部署环境开始.参照了网上不少前辈的教程,也遇到不少的坑,这边做个完整的笔记. 一.构建.Net core 2的应用程web发布,因为是用来测试centos上的core 环境 ...
- Bell(hdu4767+矩阵+中国剩余定理+bell数+Stirling数+欧几里德)
Bell Time Limit:3000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submit Status ...
- Matlab Euler's method
% matlab script to test efficiency of % Euler's method, classical Runge-Kutta, and ode45 % on Arenst ...
- lnmp首次安装重置mysql密码
第一种方法:一键修改LNMP环境下MYSQL数据库密码脚本 一键脚本肯定是非常方便.具体执行以下命令: wget http://soft.vpser.net/lnmp/ext/reset_mysql_ ...
- JQuery基本知识汇总;JQuery常用方法;浅入了解JQuery
一.jQuery对象与JavaScript对象 ①JavaScript入口函数比jQuery入口函数执行的晚一些: JQuery的入口函数会等页面加载完成才执行,但是不会等待图片的加载: JavaSc ...