一、导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
二、新建websocket配置
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.session.StandardSessionFacade;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
/**
* @author 736421789@qq.com
* @date 2020/1/23 12:19
*/
@Component
@Slf4j
public class WebSocketConfig extends ServerEndpointConfig.Configurator{
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
StandardSessionFacade ssf = (StandardSessionFacade) request.getHttpSession();
if (ssf != null) {
HttpSession httpSession = (HttpSession) request.getHttpSession();
//关键操作
sec.getUserProperties().put("sessionId", httpSession.getId());
log.info("获取到的SessionID:" + httpSession.getId());
}
super.modifyHandshake(sec, request, response);
}
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
三、新建websocket配置类,由于还没有想好吧消息存储到其他地方,暂时用map存储,后续想到办法会更新
import cn.suse.edu.wasterecovery.utils.BasesUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* @author 736421789@qq.com
* @date 2020/1/23 12:21
*/
@Component
@ServerEndpoint("/webSocket/{username}")
@Slf4j
public class WebSocket {
/**
* 在线人数
*/
public static int onlineNumber = 0;
/**
* 以用户的姓名为key,WebSocket为对象保存起来
*/
private static Map<String, WebSocket> clients = new ConcurrentHashMap<String, WebSocket>();
/**
* 设置为静态的 公用一个消息map ConcurrentMap为线程安全的map HashMap不安全
*/
private static ConcurrentMap<String, List<Map>> messageMap=new ConcurrentHashMap<>();
/**
* 会话
*/
private Session session;
/**
* 用户名称
*/
private String username;
/**
* 建立连接
*
* @param session
*/
@OnOpen
public void onOpen(@PathParam("username") String username, Session session) throws IOException, InterruptedException {
onlineNumber++;
log.info("现在来连接的客户id:"+session.getId()+"用户名:"+username);
this.username = username;
this.session = session;
clients.put(username, this);
log.info("有新连接加入! 当前在线人数" + onlineNumber);
log.info("存储的列队消息:{}",messageMap);
List<Map> userMessage = messageMap.get(username);
if(!BasesUtil.isEmpty(userMessage)){
for (int i = userMessage.size() - 1; i >= 0; i--) {
Map messages =userMessage.get(i);
String o = (String) messages.get(username);
sendMessageTo(o,username);
Thread.sleep(10000);
}
messageMap.remove(username);
}
}
@OnError
public void onError(Session session, Throwable error) {
log.info("服务端发生了错误"+error.getMessage());
error.printStackTrace();
}
/**
* 连接关闭
*/
@OnClose
public void onClose()
{
onlineNumber--;
clients.remove(username);
log.info("{}连接关闭! 当前在线人数{}",username, onlineNumber);
}
/**
* 收到客户端的消息
*
* @param message 消息
* @param session 会话
*/
@OnMessage
public void onMessage(String message, Session session)
{
log.info("来自客户端消息:" + message+"客户端的id是:"+session.getId());
}
public void sendMessageTo(String message, String ToUserName) throws IOException {
for (WebSocket item : clients.values()) {
if (item.username.equals(ToUserName) ) {
item.session.getAsyncRemote().sendText(message);
return;
}else {
List<Map> objects=new ArrayList<>();
Map<String,String> amp=new HashMap<>();
if(!BasesUtil.isEmpty(messageMap.get(ToUserName))){
List list= messageMap.get(ToUserName);
log.info("有待发送的消息,继续存储");
amp.put(ToUserName,message);
list.add(amp);
return;
}else {
//该用户发的离线消息的集合
amp.put(ToUserName,message);
objects.add(amp);
messageMap.put(ToUserName, objects );
log.info("用户不在线保存信息");
return;
}
}
}
}
public void sendMessageAll(String message) throws IOException {
for (WebSocket item : clients.values()) {
item.session.getAsyncRemote().sendText(message);
}
}
/**
* 获取消息列队
* @return
*/
public ConcurrentMap<String, List<Map>> getMessageMap(){
return messageMap;
}
/**
* 获取用户消息
* @param username
* @return
*/
public List<Map> getuserMessageMap(String username){
return messageMap.get(username);
}
/**
* 删除用户消息
* @param username
*/
public void delMessageMap(String username){
messageMap.remove(username);
}
public static synchronized int getOnlineCount() {
return onlineNumber;
}
}
四、新建一个消息实体类
import lombok.Data;
/**
* @author 736421789@qq.com
* @date 2020/3/3 10:08
*/
@Data
public class TemporaryInformation {
/**
* 发送时间
*/
private String sendTime;
/**
* 发送内容
*/
private String message;
private String title;
}
五、controller测试
@GetMapping("contactUs")
public void GetContactUs(String ToUserName) throws IOException {
TemporaryInformation temporaryInformation = new TemporaryInformation();
temporaryInformation.setTitle("消息实时推送服务");
temporaryInformation.setSendTime(DateUtil.getCurrentDate());
temporaryInformation.setMessage("尊敬的用户你好:您附近有新订单,请注意查看!");
//Result.toJsonPObject():把消息转换成自己定义的json格式
webSocketService.sendMessageTo(Result.toJsonPObject(temporaryInformation),ToUserName);
}
希望大佬勿喷,java学习中,后续更新更多