使用websocket,注入依赖service的bean为null
问题:依赖注入失败,service获取不到,提示null
这是参考代码
package com.shier.ws;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.google.gson.Gson;
import com.shier.config.HttpSessionConfig;
import com.shier.model.domain.Chat;
import com.shier.model.domain.Team;
import com.shier.model.domain.User;
import com.shier.model.request.MessageRequest;
import com.shier.model.vo.ChatMessageVO;
import com.shier.model.vo.WebSocketVO;
import com.shier.service.ChatService;
import com.shier.service.TeamService;
import com.shier.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import static com.shier.constants.ChatConstant.*;
import static com.shier.constants.UserConstants.ADMIN_ROLE;
import static com.shier.constants.UserConstants.USER_LOGIN_STATE;
/**
* WebSocket服务
*/
@Component
@Slf4j
@ServerEndpoint(value = "/websocket/{userId}/{teamId}", configurator = HttpSessionConfig.class)
public class WebSocket {
/**
* 保存队伍的连接信息
*/
private static final Map<String, ConcurrentHashMap<String, WebSocket>> ROOMS = new HashMap<>();
/**
* 线程安全的无序的集合
*/
private static final CopyOnWriteArraySet<Session> SESSIONS = new CopyOnWriteArraySet<>();
/**
* 会话池
*/
private static final Map<String, Session> SESSION_POOL = new HashMap<>(0);
/**
* 用户服务
*/
private static UserService userService;
/**
* 聊天服务
*/
private static ChatService chatService;
/**
* 团队服务
*/
private static TeamService teamService;
/**
* 房间在线人数
*/
private static int onlineCount = 0;
/**
* 当前信息
*/
private Session session;
/**
* http会话
*/
private HttpSession httpSession;
/**
* 上网数
*
* @return int
*/
public static synchronized int getOnlineCount() {
return onlineCount;
}
/**
* 添加在线计数
*/
public static synchronized void addOnlineCount() {
WebSocket.onlineCount++;
}
/**
* 子在线计数
*/
public static synchronized void subOnlineCount() {
WebSocket.onlineCount--;
}
/**
* 集热地图服务
*
* @param userService 用户服务
*/
@Resource
public void setHeatMapService(UserService userService) {
WebSocket.userService = userService;
}
/**
* 集热地图服务
*
* @param chatService 聊天服务
*/
@Resource
public void setHeatMapService(ChatService chatService) {
WebSocket.chatService = chatService;
}
/**
* 集热地图服务
*
* @param teamService 团队服务
*/
@Resource
public void setHeatMapService(TeamService teamService) {
WebSocket.teamService = teamService;
}
/**
* 队伍内群发消息
*
* @param teamId 团队id
* @param msg 消息
*/
public static void broadcast(String teamId, String msg) {
ConcurrentHashMap<String, WebSocket> map = ROOMS.get(teamId);
// keySet获取map集合key的集合 然后在遍历key即可
for (String key : map.keySet()) {
try {
WebSocket webSocket = map.get(key);
webSocket.sendMessage(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 发送消息
*
* @param message 消息
* @throws IOException ioexception
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
/**
* 开放
*
* @param session 会话
* @param userId 用户id
* @param teamId 团队id
* @param config 配置
*/
@OnOpen
public void onOpen(Session session, @PathParam(value = "userId") String userId, @PathParam(value = "teamId") String teamId, EndpointConfig config) {
try {
if (StringUtils.isBlank(userId) || "undefined".equals(userId)) {
sendError(userId, "参数有误");
return;
}
HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
User user = (User) httpSession.getAttribute(USER_LOGIN_STATE);
if (user != null) {
this.session = session;
this.httpSession = httpSession;
}
if (!"NaN".equals(teamId)) {
if (!ROOMS.containsKey(teamId)) {
ConcurrentHashMap<String, WebSocket> room = new ConcurrentHashMap<>(0);
room.put(userId, this);
ROOMS.put(String.valueOf(teamId), room);
// 在线数加1
addOnlineCount();
} else {
if (!ROOMS.get(teamId).containsKey(userId)) {
ROOMS.get(teamId).put(userId, this);
// 在线数加1
addOnlineCount();
}
}
} else {
SESSIONS.add(session);
SESSION_POOL.put(userId, session);
sendAllUsers();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 关闭
*
* @param userId 用户id
* @param teamId 团队id
* @param session 会话
*/
@OnClose
public void onClose(@PathParam("userId") String userId, @PathParam(value = "teamId") String teamId, Session session) {
try {
if (!"NaN".equals(teamId)) {
ROOMS.get(teamId).remove(userId);
if (getOnlineCount() > 0) {
subOnlineCount();
}
} else {
if (!SESSION_POOL.isEmpty()) {
SESSION_POOL.remove(userId);
SESSIONS.remove(session);
}
sendAllUsers();
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 消息
*
* @param message 消息
* @param userId 用户id
*/
@OnMessage
public void onMessage(String message, @PathParam("userId") String userId) {
if ("PING".equals(message)) {
sendOneMessage(userId, "pong");
return;
}
MessageRequest messageRequest = new Gson().fromJson(message, MessageRequest.class);
Long toId = messageRequest.getToId();
Long teamId = messageRequest.getTeamId();
String text = messageRequest.getText();
Integer chatType = messageRequest.getChatType();
User fromUser = userService.getById(userId);
Team team = teamService.getById(teamId);
if (chatType == PRIVATE_CHAT) {
// 私聊
privateChat(fromUser, toId, text, chatType);
} else if (chatType == TEAM_CHAT) {
// 队伍内聊天
teamChat(fromUser, text, team, chatType);
} else {
// 群聊
hallChat(fromUser, text, chatType);
}
}
/**
* 队伍聊天
*
* @param user 用户
* @param text 文本
* @param team 团队
* @param chatType 聊天类型
*/
private void teamChat(User user, String text, Team team, Integer chatType) {
ChatMessageVO ChatMessageVO = new ChatMessageVO();
WebSocketVO fromWebSocketVO = new WebSocketVO();
BeanUtils.copyProperties(user, fromWebSocketVO);
ChatMessageVO.setFormUser(fromWebSocketVO);
ChatMessageVO.setText(text);
ChatMessageVO.setTeamId(team.getId());
ChatMessageVO.setChatType(chatType);
ChatMessageVO.setCreateTime(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
if (user.getId() == team.getUserId() || user.getRole() == ADMIN_ROLE) {
ChatMessageVO.setIsAdmin(true);
}
User loginUser = (User) this.httpSession.getAttribute(USER_LOGIN_STATE);
if (loginUser.getId() == user.getId()) {
ChatMessageVO.setIsMy(true);
}
String toJson = new Gson().toJson(ChatMessageVO);
try {
broadcast(String.valueOf(team.getId()), toJson);
saveChat(user.getId(), null, text, team.getId(), chatType);
chatService.deleteKey(CACHE_CHAT_TEAM, String.valueOf(team.getId()));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 大厅聊天
*
* @param user 用户
* @param text 文本
* @param chatType 聊天类型
*/
private void hallChat(User user, String text, Integer chatType) {
ChatMessageVO ChatMessageVO = new ChatMessageVO();
WebSocketVO fromWebSocketVO = new WebSocketVO();
BeanUtils.copyProperties(user, fromWebSocketVO);
ChatMessageVO.setFormUser(fromWebSocketVO);
ChatMessageVO.setText(text);
ChatMessageVO.setChatType(chatType);
ChatMessageVO.setCreateTime(DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss"));
if (user.getRole() == ADMIN_ROLE) {
ChatMessageVO.setIsAdmin(true);
}
User loginUser = (User) this.httpSession.getAttribute(USER_LOGIN_STATE);
if (loginUser.getId() == user.getId()) {
ChatMessageVO.setIsMy(true);
}
String toJson = new Gson().toJson(ChatMessageVO);
sendAllMessage(toJson);
saveChat(user.getId(), null, text, null, chatType);
chatService.deleteKey(CACHE_CHAT_HALL, String.valueOf(user.getId()));
}
/**
* 私聊
*
* @param user 用户
* @param toId 为id
* @param text 文本
* @param chatType 聊天类型
*/
private void privateChat(User user, Long toId, String text, Integer chatType) {
ChatMessageVO ChatMessageVO = chatService.chatResult(user.getId(), toId, text, chatType, DateUtil.date(System.currentTimeMillis()));
User loginUser = (User) this.httpSession.getAttribute(USER_LOGIN_STATE);
if (loginUser.getId() == user.getId()) {
ChatMessageVO.setIsMy(true);
}
String toJson = new Gson().toJson(ChatMessageVO);
sendOneMessage(toId.toString(), toJson);
saveChat(user.getId(), toId, text, null, chatType);
chatService.deleteKey(CACHE_CHAT_PRIVATE, user.getId() + "" + toId);
chatService.deleteKey(CACHE_CHAT_PRIVATE, toId + "" + user.getId());
}
/**
* 保存聊天
*
* @param userId 用户id
* @param toId 为id
* @param text 文本
* @param teamId 团队id
* @param chatType 聊天类型
*/
private void saveChat(Long userId, Long toId, String text, Long teamId, Integer chatType) {
// if (chatType == PRIVATE_CHAT) {
// User user = userService.getById(userId);
// Set<Long> userIds = stringJsonListToLongSet(user.getFriendIds());
// if (!userIds.contains(toId)) {
// sendError(String.valueOf(userId), "该用户不是你的好友");
// return;
// }
// }
Chat chat = new Chat();
chat.setFromId(userId);
chat.setText(String.valueOf(text));
chat.setChatType(chatType);
chat.setCreateTime(new Date());
if (toId != null && toId > 0) {
chat.setToId(toId);
}
if (teamId != null && teamId > 0) {
chat.setTeamId(teamId);
}
chatService.save(chat);
}
/**
* 发送失败
*
* @param userId 用户id
* @param errorMessage 错误消息
*/
private void sendError(String userId, String errorMessage) {
JSONObject obj = new JSONObject();
obj.set("error", errorMessage);
sendOneMessage(userId, obj.toString());
}
/**
* 广播消息
*
* @param message 消息
*/
public void sendAllMessage(String message) {
for (Session session : SESSIONS) {
try {
if (session.isOpen()) {
synchronized (session) {
session.getBasicRemote().sendText(message);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 发送一个消息
*
* @param userId 用户编号
* @param message 消息
*/
public void sendOneMessage(String userId, String message) {
Session session = SESSION_POOL.get(userId);
if (session != null && session.isOpen()) {
try {
synchronized (session) {
session.getBasicRemote().sendText(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 给所有用户
*/
public void sendAllUsers() {
HashMap<String, List<WebSocketVO>> stringListHashMap = new HashMap<>(0);
List<WebSocketVO> WebSocketVOs = new ArrayList<>();
stringListHashMap.put("users", WebSocketVOs);
for (Serializable key : SESSION_POOL.keySet()) {
User user = userService.getById(key);
WebSocketVO WebSocketVO = new WebSocketVO();
BeanUtils.copyProperties(user, WebSocketVO);
WebSocketVOs.add(WebSocketVO);
}
sendAllMessage(JSONUtil.toJsonStr(stringListHashMap));
}
}
这是自己的代码
package com.ruoyi.webSocket;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.room.domain.Room;
import com.ruoyi.room.service.IRoomService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
@Component
@ServerEndpoint("/module/websocket/{userId}/{roomId}")
public class WebSocketServer implements ApplicationContextAware {
private static IRoomService roomService;
private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
// 保存队伍的连接信息 - 新增
private static final Map<String, ConcurrentHashMap<String, WebSocketServer>> ROOMS = new HashMap<>();
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static AtomicInteger onlineNum = new AtomicInteger();
//concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。
private static ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<>();
// 线程安全list,用来存放 在线客户端账号
public static List<String> userList = new CopyOnWriteArrayList<>();
// 连接成功
@OnOpen
public void onOpen(Session session, @PathParam(value = "userId") String userId, @PathParam(value = "roomId") String roomId) {
// 创建session给客户
sessionPools.put(userId, session);
if (!userList.contains(userId)) {
addOnlineCount();
userList.add(userId);
}
try {
if (StringUtils.isBlank(userId) || "undefined".equals(userId) ||
StringUtils.isBlank(roomId) || "undefined".equals(roomId)) {
sendError(userId, "参数有误");
return;
}
if (!ROOMS.containsKey(roomId)) {
// 房间不存在 创建房间
ConcurrentHashMap<String, WebSocketServer> room = new ConcurrentHashMap<>(0);
room.put(userId, this);
ROOMS.put(String.valueOf(roomId), room);
} else {
if (!ROOMS.get(roomId).containsKey(userId)) {
// 房间存在 客户不存在 房间加入客户
ROOMS.get(roomId).put(userId, this);
}
}
log.debug("ID为【" + userId + "】的用户加入websocket!当前在线人数为:" + onlineNum);
log.debug("当前在线:" + userList);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 关闭连接
* @param userId
*/
@OnClose
public void onClose(@PathParam(value = "userId") String userId) {
sessionPools.remove(userId);
if (userList.contains(userId)) {
userList.remove(userId);
subOnlineCount();
}
log.debug(userId + "断开webSocket连接!当前人数为" + onlineNum);
}
/**
* 消息监听 接收客户端消息
* @param message
* @throws IOException
*/
@OnMessage
public void onMessage(String message) throws IOException {
JSONObject jsonObject = JSONObject.parseObject(message);
String userId = jsonObject.getString("userId");
String roomId = jsonObject.getString("roomId");
String type = jsonObject.getString("type");
if (type.equals(MessageType.DETAIL.getType())) {
log.debug("房间详情");
try {
Room room = roomService.selectRoomById(Long.parseLong(roomId));
jsonObject.put("roomInfo", room);
ConcurrentHashMap<String, WebSocketServer> map = ROOMS.get(roomId);
// 获取玩家列表 keySet获取map集合key的集合 然后在遍历key即可
for (String key : map.keySet()) {
try {
sendToUser(key, JSONObject.toJSONString(jsonObject));
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (NumberFormatException e) {
System.out.println("转换错误: " + e.getMessage());
}
}
}
/**
* 连接错误
* @param session
* @param throwable
* @throws IOException
*/
@OnError
public void onError(Session session, Throwable throwable) throws IOException {
log.error("websocket连接错误!");
throwable.printStackTrace();
}
/**
* 发送消息
*/
public void sendMessage(Session session, String message) throws IOException, EncodeException {
if (session != null) {
synchronized (session) {
session.getBasicRemote().sendText(message);
}
}
}
/**
* 给指定用户发送信息
*/
public void sendToUser(String userId, String message) {
Session session = sessionPools.get(userId);
try {
if (session != null) {
sendMessage(session, message);
}else {
log.debug("推送用户不在线");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void addOnlineCount() {
onlineNum.incrementAndGet();
}
public static void subOnlineCount() {
onlineNum.decrementAndGet();
}
/**
* 发送失败
*
* @param userId 用户id
* @param errorMessage 错误消息
*/
private void sendError(String userId, String errorMessage) {
JSONObject obj = new JSONObject();
obj.put("error", errorMessage);
sendOneMessage(userId, obj.toString());
}
/**
* 发送一个消息
*
* @param userId 用户编号
* @param message 消息
*/
public void sendOneMessage(String userId, String message) {
Session session = sessionPools.get(userId);
if (session != null && session.isOpen()) {
try {
synchronized (session) {
session.getBasicRemote().sendText(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
修改后的代码
package com.ruoyi.webSocket;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.room.domain.Room;
import com.ruoyi.room.service.IRoomService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
@Component
@ServerEndpoint("/module/websocket/{userId}/{roomId}")
public class WebSocketServer implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static <roomService> roomService getBean(Class<roomService> beanClass) {
return context.getBean(beanClass);
}
private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
// 保存队伍的连接信息 - 新增
private static final Map<String, ConcurrentHashMap<String, WebSocketServer>> ROOMS = new HashMap<>();
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static AtomicInteger onlineNum = new AtomicInteger();
//concurrent包的线程安全Set,用来存放每个客户端对应的WebSocketServer对象。
private static ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<>();
// 线程安全list,用来存放 在线客户端账号
public static List<String> userList = new CopyOnWriteArrayList<>();
// 连接成功
@OnOpen
public void onOpen(Session session, @PathParam(value = "userId") String userId, @PathParam(value = "roomId") String roomId) {
// 创建session给客户
sessionPools.put(userId, session);
if (!userList.contains(userId)) {
addOnlineCount();
userList.add(userId);
}
try {
if (StringUtils.isBlank(userId) || "undefined".equals(userId) ||
StringUtils.isBlank(roomId) || "undefined".equals(roomId)) {
sendError(userId, "参数有误");
return;
}
if (!ROOMS.containsKey(roomId)) {
// 房间不存在 创建房间
ConcurrentHashMap<String, WebSocketServer> room = new ConcurrentHashMap<>(0);
room.put(userId, this);
ROOMS.put(String.valueOf(roomId), room);
} else {
if (!ROOMS.get(roomId).containsKey(userId)) {
// 房间存在 客户不存在 房间加入客户
ROOMS.get(roomId).put(userId, this);
}
}
log.debug("ID为【" + userId + "】的用户加入websocket!当前在线人数为:" + onlineNum);
log.debug("当前在线:" + userList);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 关闭连接
* @param userId
*/
@OnClose
public void onClose(@PathParam(value = "userId") String userId) {
sessionPools.remove(userId);
if (userList.contains(userId)) {
userList.remove(userId);
subOnlineCount();
}
log.debug(userId + "断开webSocket连接!当前人数为" + onlineNum);
}
/**
* 消息监听 接收客户端消息
* @param message
* @throws IOException
*/
@OnMessage
public void onMessage(String message) throws IOException {
JSONObject jsonObject = JSONObject.parseObject(message);
String userId = jsonObject.getString("userId");
String roomId = jsonObject.getString("roomId");
String type = jsonObject.getString("type");
if (type.equals(MessageType.DETAIL.getType())) {
log.debug("房间详情");
try {
Room room = context.getBean(IRoomService.class).selectRoomById(Long.parseLong(roomId));
jsonObject.put("roomInfo", room);
ConcurrentHashMap<String, WebSocketServer> map = ROOMS.get(roomId);
// 获取玩家列表 keySet获取map集合key的集合 然后在遍历key即可
for (String key : map.keySet()) {
try {
sendToUser(key, JSONObject.toJSONString(jsonObject));
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (NumberFormatException e) {
System.out.println("转换错误: " + e.getMessage());
}
}
}
/**
* 连接错误
* @param session
* @param throwable
* @throws IOException
*/
@OnError
public void onError(Session session, Throwable throwable) throws IOException {
log.error("websocket连接错误!");
throwable.printStackTrace();
}
/**
* 发送消息
*/
public void sendMessage(Session session, String message) throws IOException, EncodeException {
if (session != null) {
synchronized (session) {
session.getBasicRemote().sendText(message);
}
}
}
/**
* 给指定用户发送信息
*/
public void sendToUser(String userId, String message) {
Session session = sessionPools.get(userId);
try {
if (session != null) {
sendMessage(session, message);
}else {
log.debug("推送用户不在线");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void addOnlineCount() {
onlineNum.incrementAndGet();
}
public static void subOnlineCount() {
onlineNum.decrementAndGet();
}
/**
* 发送失败
*
* @param userId 用户id
* @param errorMessage 错误消息
*/
private void sendError(String userId, String errorMessage) {
JSONObject obj = new JSONObject();
obj.put("error", errorMessage);
sendOneMessage(userId, obj.toString());
}
/**
* 发送一个消息
*
* @param userId 用户编号
* @param message 消息
*/
public void sendOneMessage(String userId, String message) {
Session session = sessionPools.get(userId);
if (session != null && session.isOpen()) {
try {
synchronized (session) {
session.getBasicRemote().sendText(message);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
核心代码
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static <roomService> roomService getBean(Class<roomService> beanClass) {
return context.getBean(beanClass);
}
Room room = context.getBean(IRoomService.class).selectRoomById(Long.parseLong(roomId));
原因:执行的先后顺序吧,具体还没仔细了解
上一篇: Java ! = n
下一篇: JSONUtil I