栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java中Spring Boot+Socket实现与html页面的长连接实例详解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java中Spring Boot+Socket实现与html页面的长连接实例详解

Spring Boot+Socket实现与html页面的长连接,客户端给服务器端发消息,服务器给客户端轮询发送消息,附案例源码

功能介绍

客户端给所有在线用户发送消息客户端给指定在线用户发送消息服务器给客户端发送消息(轮询方式)

注意:socket只是实现一些简单的功能,具体的还需根据自身情况,代码稍微改造下

项目搭建

项目结构图

pom.xml



 4.0.0
 
  org.springframework.boot
  spring-boot-starter-parent
  2.3.2.RELEASE
   
 
 com.cyb
 socket_test
 0.0.1-SNAPSHOT
 socket_test
 Demo project for Spring Boot

 
  1.8
 

 
  
  
   org.springframework.boot
   spring-boot-starter-websocket
  
  
  
   com.google.guava
   guava
   18.0
  
  
  
   com.alibaba
   fastjson
   1.2.46
  
  
   org.springframework.boot
   spring-boot-starter-web
  

  
   org.springframework.boot
   spring-boot-starter-test
   test
   
    
     org.junit.vintage
     junit-vintage-engine
    
   
  
 

 
  
   
    org.springframework.boot
    spring-boot-maven-plugin
   
  
 

appliccation.properties

SocketTestApplication.java(Spring Boot启动类)

WebSocketStompConfig.java

package com.cyb.socket.websocket;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketStompConfig {
 //这个bean的注册,用于扫描带有@ServerEndpoint的注解成为websocket ,如果你使用外置的tomcat就不需要该配置文件
 @Bean
 public ServerEndpointExporter serverEndpointExporter()
 {
  return new ServerEndpointExporter();
 }
}

WebSocket.java(Socket核心类)

package com.cyb.socket.websocket;

import java.io.IOException;
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 com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;



@Component
@ServerEndpoint(value = "/connectWebSocket/{userId}")
public class WebSocket {

 private Logger logger = LoggerFactory.getLogger(this.getClass());
 
 public static int onlineNumber = 0;
 
 private static Map clients = new ConcurrentHashMap();
 
 private Session session;
 
 private String userId;

 
 @onOpen
 public void onOpen(@PathParam("userId") String userId, Session session) {
  onlineNumber++;
  System.out.println("现在来连接的客户id:" + session.getId() + "用户名:" + userId);
  //logger.info("现在来连接的客户id:"+session.getId()+"用户名:"+userId);
  this.userId = userId;
  this.session = session;
  System.out.println("有新连接加入! 当前在线人数" + onlineNumber);
  // logger.info("有新连接加入! 当前在线人数" + onlineNumber);
  try {
   //messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
   //先给所有人发送通知,说我上线了
   Map map1 = Maps.newHashMap();
   map1.put("messageType", 1);
   map1.put("userId", userId);
   sendMessageAll(JSON.toJSonString(map1), userId);

   //把自己的信息加入到map当中去
   clients.put(userId, this);
   System.out.println("有连接关闭! 当前在线人数" + onlineNumber);
   //logger.info("有连接关闭! 当前在线人数" + clients.size());
   //给自己发一条消息:告诉自己现在都有谁在线
   Map map2 = Maps.newHashMap();
   map2.put("messageType", 3);
   //移除掉自己
   Set set = clients.keySet();
   map2.put("onlineUsers", set);
   sendMessageTo(JSON.toJSonString(map2), userId);
  } catch (IOException e) {
   System.out.println(userId + "上线的时候通知所有人发生了错误");
   //logger.info(userId+"上线的时候通知所有人发生了错误");
  }
 }

 @onError
 public void onError(Session session, Throwable error) {
  //logger.info("服务端发生了错误"+error.getMessage());
  //error.printStackTrace();
  System.out.println("服务端发生了错误:" + error.getMessage());
 }

 
 @onClose
 public void onClose() {
  onlineNumber--;
  //webSockets.remove(this);
  clients.remove(userId);
  try {
   //messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
   Map map1 = Maps.newHashMap();
   map1.put("messageType", 2);
   map1.put("onlineUsers", clients.keySet());
   map1.put("userId", userId);
   sendMessageAll(JSON.toJSonString(map1), userId);
  } catch (IOException e) {
   System.out.println(userId + "下线的时候通知所有人发生了错误");
   //logger.info(userId+"下线的时候通知所有人发生了错误");
  }
  //logger.info("有连接关闭! 当前在线人数" + onlineNumber);
  //logger.info("有连接关闭! 当前在线人数" + clients.size());
  System.out.println("有连接关闭! 当前在线人数" + onlineNumber);
 }

 
 @onMessage
 public void onMessage(String message, Session session) {
  try {
   //logger.info("来自客户端消息:" + message+"客户端的id是:"+session.getId());
   System.out.println("来自客户端消息:" + message + " | 客户端的id是:" + session.getId());
   JSonObject jsonObject = JSON.parseObject(message);
   String textMessage = jsonObject.getString("message");
   String fromuserId = jsonObject.getString("userId");
   String touserId = jsonObject.getString("to");
   //如果不是发给所有,那么就发给某一个人
   //messageType 1代表上线 2代表下线 3代表在线名单 4代表普通消息
   Map map1 = Maps.newHashMap();
   map1.put("messageType", 4);
   map1.put("textMessage", textMessage);
   map1.put("fromuserId", fromuserId);
   if (touserId.equals("All")) {
    map1.put("touserId", "所有人");
    sendMessageAll(JSON.toJSonString(map1), fromuserId);
   } else {
    map1.put("touserId", touserId);
    System.out.println("开始推送消息给" + touserId);
    sendMessageTo(JSON.toJSonString(map1), touserId);
   }
  } catch (Exception e) {
   e.printStackTrace();
   //logger.info("发生了错误了");
  }

 }

 
 public void sendMessageTo(String message, String TouserId) throws IOException {
  for (WebSocket item : clients.values()) {
   System.out.println("给指定的在线用户发送消息,在线人员名单:【" + item.userId.toString() + "】发送消息:" + message);
   if (item.userId.equals(TouserId)) {
    item.session.getAsyncRemote().sendText(message);
    break;
   }
  }
 }

 
 public void sendMessageAll(String message, String FromuserId) throws IOException {
  for (WebSocket item : clients.values()) {
   System.out.println("给所有在线用户发送给消息,在线人员名单:【" + item.userId.toString() + "】发送消息:" + message);
   item.session.getAsyncRemote().sendText(message);
  }
 }

 
 public void sendMessageAll(String message) throws IOException {
  for (WebSocket item : clients.values()) {
   System.out.println("服务器给所有在线用户发送消息,当前在线人员为【" + item.userId.toString() + "】发送消息:" + message);
   item.session.getAsyncRemote().sendText(message);
  }
 }

 
 public static synchronized int getonlineCount() {
  return onlineNumber;
 }
}

TestController.java(前端控制器)

package com.cyb.socket.websocket;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.io.IOException;

@Controller
@RequestMapping("testMethod")
public class TestController {
 @Autowired
 private WebSocket webSocket;

 
 @ResponseBody
 @GetMapping("/sendTo")
 public String sendTo(@RequestParam("userId") String userId,@RequestParam("msg") String msg) throws IOException {
  webSocket.sendMessageTo(msg,userId);
  return "推送成功";
 }

 
 @ResponseBody
 @PostMapping("/sendAll")
 public String sendAll(@RequestBody String msg) throws IOException, IOException {
  webSocket.sendMessageAll(msg);
  return "推送成功";
 }
}

SocketTask.java(轮询调度往客户端推送消息)

package com.cyb.socket.schedule;

import com.cyb.socket.websocket.WebSocket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

@Component
public class SocketTask {
 @Autowired
 private WebSocket webSocket;
 private SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS" );
 //5秒轮询一次
 @Scheduled(fixedRate = 5000)
 public void sendClientData() throws IOException {
  String msg="{"message":"你好","userId":"002","to":"All"}";
  webSocket.sendMessageAll(msg);
  System.out.println("消息推送时间:"+ sdf.format(new Date()));
 }
}

测试网页

index.html




 Test My WebSocket

 
 

TestWebSocket





 

index2.html




 Test My WebSocket

 
 

TestWebSocket





 

项目地址

链接:https://pan.baidu.com/s/1yiAXTkCjHac-F3S1HFyNJQ 提取码:53tp

功能演示

客户端给所有在线用户发消息

客户端给指定在线用户发送消息

服务器给客户端发送消息(轮询方式)

注意需要加上这些注解

演示

通过前端控制器给指定用户发送消息

演示

到此这篇关于Java中Spring Boot+Socket实现与html页面的长连接实例详解的文章就介绍到这了,更多相关Java Spring Boot+Socket实现与html页面的长连接内容请搜索考高分网以前的文章或继续浏览下面的相关文章希望大家以后多多支持考高分网!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/132938.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号