1.引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency>
2.配置websocket服务
@Configuration
public class WebSocketConfig {/*** 配置WebSocket服务* @return*/@Beanpublic ServerEndpointExporter serverEndpointExporter(){return new ServerEndpointExporter();}
}
3.启动类添加注解
@EnableWebSocket
4.websocket服务端逻辑
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.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;/*** WebSocketServer服务端*/
@Slf4j
@Component
@ServerEndpoint("/websocket/{uid}")
public class WebSocketClient {/*** 静态变量,用来记录当前在线连接数,线程安全的类。*/private static AtomicInteger onlineSessionClientCount = new AtomicInteger(0);/*** 存放所有在线的客户端*/private static Map<String, Session> onlineSessionClientMap = new ConcurrentHashMap<>();/*** 连接uid和连接会话*/private String uid;private Session session;/*** 连接建立成功调用的方法。由前端<code>new WebSocket</code>触发** @param uid 每次页面建立连接时传入到服务端的id,比如用户id等。可以自定义。* @param session 与某个客户端的连接会话,需要通过它来给客户端发送消息*/@OnOpenpublic void onOpen(@PathParam("uid") String uid, Session session) {/*** session.getId():当前session会话会自动生成一个id,从0开始累加的。*/log.info("连接建立中 ==> session_id = {}, sid = {}", session.getId(), uid);//加入 Map中。将页面的uid和session绑定或者session.getId()与session//onlineSessionIdClientMap.put(session.getId(), session);onlineSessionClientMap.put(uid, session);//在线数加1onlineSessionClientCount.incrementAndGet();this.uid = uid;this.session = session;sendToOne(uid, "连接成功");log.info("连接建立成功,当前在线数为:{} ==> 开始监听新连接:session_id = {}, sid = {},。", onlineSessionClientCount, session.getId(), uid);}/*** 连接关闭调用的方法。由前端<code>socket.close()</code>触发** @param uid* @param session*/@OnClosepublic void onClose(@PathParam("uid") String uid, Session session) {//onlineSessionIdClientMap.remove(session.getId());// 从 Map中移除onlineSessionClientMap.remove(uid);//在线数减1onlineSessionClientCount.decrementAndGet();log.info("连接关闭成功,当前在线数为:{} ==> 关闭该连接信息:session_id = {}, sid = {},。", onlineSessionClientCount, session.getId(), uid);}/*** 收到客户端消息后调用的方法。由前端<code>socket.send</code>触发* * 当服务端执行toSession.getAsyncRemote().sendText(xxx)后,前端的socket.onmessage得到监听。** @param message* @param session*/@OnMessagepublic void onMessage(String message, Session session) {/*** html界面传递来得数据格式,可以自定义.* {"sid":"user-1","message":"hello websocket"}*/log.info("接收到消息-----------------"+message);List<String> uids = session.getRequestParameterMap().get("uid");for (String uid : uids) {// 接收前端拖推送改的消息sendToOne(uid, "来自服务端的推送=====》你好前端! 我已经成功收到消息!消息数据为:" + message);}}/*** 发生错误调用的方法** @param session* @param error*/@OnErrorpublic void onError(Session session, Throwable error) {log.error("WebSocket发生错误,错误信息为:" + error.getMessage());error.printStackTrace();}/*** 群发消息** @param message 消息*/public void sendToAll(String message) {// 遍历在线map集合onlineSessionClientMap.forEach((onlineSid, toSession) -> {// 排除掉自己if (!uid.equalsIgnoreCase(onlineSid)) {log.info("服务端给客户端群发消息 ==> sid = {}, toSid = {}, message = {}", uid, onlineSid, message);toSession.getAsyncRemote().sendText(message);}});}/*** 指定发送消息** @param toUid* @param message*/public boolean sendToOne(String toUid, String message) {/** 判断发送者是否在线*/Session toSession = onlineSessionClientMap.get(toUid);if (toSession == null) {log.error("服务端给客户端发送消息 ==> toSid = {} 不存在, message = {}", toUid, message);return false;}// 异步发送log.info("服务端给客户端发送消息 ==> toSid = {}, message = {}", toUid, message);toSession.getAsyncRemote().sendText(message);return true;}}
5.service层调用推送消息方法
@Service
public class WebSocketHandler {@Resourceprivate WebSocketClient webSocketClient;public boolean sendMessageOne(String userId,String content) {boolean flag = webSocketClient.sendToOne(userId,content);return flag;}
}
6.controller层逻辑
@PostMapping("/send")public Map push2(@RequestBody PushDTO pushDTO){Map map = new HashMap();//1、参数校验,非空~if(StringUtils.isEmpty(pushDTO.getMessage()) || pushDTO.getUserId() == null || pushDTO.getPushType() == null ) {log.info("【消息推送】 参数异常");map.put("code","-1");map.put("msg","参数异常");return map;}//2、推送消息boolean flag = webSocketHandler.sendMessageOne(pushMessage.getUserId() + "", content);//3、如果推送成功,修改状态,返回正确的JSONif(flag){PushMessage updatePushMessage = new PushMessage();updatePushMessage.setId(pushMessage.getId());updatePushMessage.setPushState(PUSH_SUCCESS);
// pushMessageService.updateById(updatePushMessage);map.put("code","200");map.put("msg","成功");return map;}//4、返回用户未上线的JSONmap.put("code","500");map.put("msg","用户离线");return map;}