SpringBoot和Vue2集成WebSocket,实现聊天室功能

1.加入依赖

2.后端建立socket服务端

3.前端建立客户端

后端

org.springframework.boot

spring-boot-starter-websocket

com.alibaba

fastjson

1.2.76

// 配置开启WebSocket

@Configuration

public class WebSocketConfig {

@Bean

public ServerEndpointExporter serverEndpointExporter() {

return new ServerEndpointExporter();

}

}

/**

* @author websocket服务

*/

@ServerEndpoint(value = "/imserver/{userId}")

@Component

public class WebSocketServer {

private static UserService userService;

private static RedisTemplate redisTemplate;

public static void setUserService(ApplicationContext context){

userService = context.getBean(UserServiceImpl.class);

redisTemplate = (RedisTemplate) context.getBean("redisTemplate");

}

private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);

/**

* 记录当前在线连接数

*/

public static final Map sessionMap = new ConcurrentHashMap<>();

/**

* 连接建立成功调用的方法

*/

// 当前用户

private UserVo userVo;

// 连接上服务端触发的方法

@OnOpen

public void onOpen(Session session, @PathParam("userId") String userId) {

if (StringUtils.hasText(userId)){

// 加入新用户

if (sessionMap.containsKey(userId)){

sessionMap.remove(userId);

}

sessionMap.put(userId, session);

this.userVo = userService.findById(Long.valueOf(userId));

// 统计所有在线用户

List list = new LinkedList<>();

sessionMap.forEach((userId1,session1) -> {

UserVo userVo = userService.findById(Long.valueOf(userId1));

list.add(userVo);

});

try {

// 发送给所有在线的用户,更新在线人数

sendAllMessage(JSON.toJSONString(list));

} catch (Exception e) {

e.printStackTrace();

}

log.info("有新用户加入,userId={}, 当前在线人数为:{}", userId, sessionMap.size());

}

}

/**

* 连接关闭调用的方法

*/

@OnClose

public void onClose(Session session, @PathParam("userId") String userId) {

sessionMap.remove(userId);

// 统计所有在线用户

List list = new LinkedList<>();

sessionMap.forEach((userId1,session1) -> {

UserVo userVo = userService.findById(Long.valueOf(userId1));

list.add(userVo);

});

sendAllMessage(JSON.toJSONString(list));

log.info("有一连接关闭,移除userId={}的用户session, 当前在线人数为:{}", userId, sessionMap.size());

}

/**

* 收到客户端消息后调用的方法

* 后台收到客户端发送过来的消息

* onMessage 是一个消息的中转站

* 接受 浏览器端 socket.send 发送过来的 json数据

* @param message 客户端发送过来的消息

*/

@OnMessage

public void onMessage(String message, Session session, @PathParam("userId") String userId) {

userVo = userService.findById(Long.valueOf(userId));

log.info("服务端收到用户username={},id={}的消息:{}", userVo.getNickname(),userId, message);

// 解析消息

JSONObject jsonObject1 = JSON.parseObject(message);

String toUserId = jsonObject1.getString("toUserId");

String text = jsonObject1.getString("text");

// 判断是给指定人发,还是群发

if (StringUtils.hasText(toUserId)){

// {"to": "admin", "text": "聊天文本"}

Session toSession = sessionMap.get(toUserId); // 根据 to用户名来获取 session,再通过session发送消息文本

if (toSession != null) {

// 服务器端 再把消息组装一下,组装后的消息包含发送人和发送的文本内容

// {"from": "zhang", "text": "hello"}

JSONObject jsonObject = new JSONObject();

jsonObject.put("fromUser",userVo);

jsonObject.put("toUser",userService.findById(Long.valueOf(toUserId)));

jsonObject.put("text",text);

this.sendMessage(jsonObject.toJSONString(), toSession);

log.info("发送给用户userId={},消息:{}", toUserId, jsonObject.toJSONString());

} else {

log.info("发送失败,未找到用户username={}的session", toUserId);

}

}else{

JSONObject jsonObject = new JSONObject();

jsonObject.put("fromUser",userVo);

jsonObject.put("text",text);

this.sendAllMessage(jsonObject.toJSONString());

// 将消息存入redis

redisTemplate.opsForList().rightPush("messageList",jsonObject.toJSONString());

redisTemplate.expire("messageList",60*60, TimeUnit.SECONDS); // 过期时间

log.info("发送给所有用户,消息:{}", toUserId, jsonObject.toJSONString());

}

}

@OnError

public void onError(Session session, Throwable error) {

log.error("发生错误");

error.printStackTrace();

}

/**

* 服务端发送消息给客户端

*/

private void sendMessage(String message, Session toSession) {

try {

log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);

toSession.getBasicRemote().sendText(message);

} catch (Exception e) {

log.error("服务端发送消息给客户端失败", e);

}

}

/**

* 服务端发送消息给所有客户端

*/

private void sendAllMessage(String message) {

try {

for (Session session : sessionMap.values()) {

log.info("服务端给客户端[{}]发送消息{}", session.getId(), message);

session.getBasicRemote().sendText(message);

}

} catch (Exception e) {

log.error("服务端发送消息给客户端失败", e);

}

}

}

// WebSocket服务类无法进行bean的注入,所以要自己调用ApplicationContext获取bean再注入

@SpringBootApplication

public class BlogApplication {

public static void main(String[] args) {

ConfigurableApplicationContext applicationContext = SpringApplication.run(BlogApplication.class, args);

WebSocketServer.setUserService(applicationContext);

}

}

前端

springboot集成websocket实现聊天室的功能。如有不足之处,还望大家斧正。

参考链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。