赞
踩
目录
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-websocket</artifactId>
- </dependency>
- @Configuration
- @EnableWebSocket
- public class WebSocketConfig {
-
- @Bean
- public ServerEndpointExporter serverEndpointExporter(){
- return new ServerEndpointExporter();
- }
-
- }
- package cn.wqk.serverwebsocket.socket;
-
- 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.Date;
- import java.util.Map;
- import java.util.Set;
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.ConcurrentMap;
- import java.util.concurrent.CopyOnWriteArraySet;
- import java.util.concurrent.atomic.AtomicInteger;
-
- /**
- * Created with IntelliJ IDEA.
- *
- * @Auther: 吴青珂
- * @Date: 2021/05/31/16:16
- * @Description:
- */
- @Component
- @Slf4j
- @ServerEndpoint("/websocket/{username}") //暴露的ws应用的路径
- public class WebSocket {
-
- /** 当前在线客户端数量(线程安全的) */
- private static AtomicInteger onlineClientNumber = new AtomicInteger(0);
-
- /** 当前在线客户端集合(线程安全的):以键值对方式存储,key是连接的编号,value是连接的对象 */
- private static Map<String ,Session> onlineClientMap = new ConcurrentHashMap<>();
-
- /**
- * 客户端与服务端连接成功
- * @param session
- * @param username
- */
- @OnOpen
- public void onOpen(Session session,@PathParam("username") String username){
- /*
- do something for onOpen
- 与当前客户端连接成功时
- */
- onlineClientNumber.incrementAndGet();//在线数+1
- onlineClientMap.put(session.getId(),session);//添加当前连接的session
- log.info("时间[{}]:与用户[{}]的连接成功,当前连接编号[{}],当前连接总数[{}]",
- new Date().toLocaleString(),
- username,
- session.getId(),
- onlineClientNumber);
- }
-
- /**
- * 客户端与服务端连接关闭
- * @param session
- * @param username
- */
- @OnClose
- public void onClose(Session session,@PathParam("username") String username){
- /*
- do something for onClose
- 与当前客户端连接关闭时
- */
- onlineClientNumber.decrementAndGet();//在线数-1
- onlineClientMap.remove(session.getId());//移除当前连接的session
- log.info("时间[{}]:与用户[{}]的连接关闭,当前连接编号[{}],当前连接总数[{}]",
- new Date().toLocaleString(),
- username,
- session.getId(),
- onlineClientNumber);
- }
-
- /**
- * 客户端与服务端连接异常
- * @param error
- * @param session
- * @param username
- */
- @OnError
- public void onError(Throwable error,Session session,@PathParam("username") String username) {
- /*
- do something for onError
- 与当前客户端连接异常时
- */
- error.printStackTrace();
- }
-
- /**
- * 客户端向服务端发送消息
- * @param message
- * @param username
- * @throws IOException
- */
- @OnMessage
- public void onMsg(Session session,String message,@PathParam("username") String username) throws IOException {
- /*
- do something for onMessage
- 收到来自当前客户端的消息时
- */
- log.info("时间[{}]:来自连接编号为[{}]的消息:[{}]",
- new Date().toLocaleString(),
- session.getId(),
- message);
- sendAllMessage(message);
- }
-
- //向所有客户端发送消息(广播)
- private void sendAllMessage(String message){
- Set<String> sessionIdSet = onlineClientMap.keySet(); //获得Map的Key的集合
- for (String sessionId : sessionIdSet) { //迭代Key集合
- Session session = onlineClientMap.get(sessionId); //根据Key得到value
- session.getAsyncRemote().sendText(message); //发送消息给客户端
- }
- }
-
- //只向当前客户端发送消息
- private void sendOneMessage(String message){
-
- }
-
- }

- package com.lyh.mp.socket;
-
- import com.lyh.mp.entity.Message;
- import com.lyh.mp.mapper.MessageMapper;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.BeansException;
- import org.springframework.context.ApplicationContext;
- import org.springframework.context.ApplicationContextAware;
- import org.springframework.stereotype.Component;
-
- import javax.websocket.*;
- import javax.websocket.server.ServerEndpoint;
- import java.io.IOException;
- import java.time.Instant;
-
- // 使用 @ServerEndpoint 注解表示此类是一个 WebSocket 端点
- // 通过 value 注解,指定 websocket 的路径
- @ServerEndpoint(value = "/channel/echo")
- @Component
- public class EchoChannel implements
- ApplicationContextAware {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(EchoChannel.class);
-
- private Session session;
-
- // 全局静态变量,保存 ApplicationContext
- private static ApplicationContext applicationContext;
- // MessageMapper.
- private MessageMapper messageMapper;
-
- // 收到消息
- @OnMessage
- public void onMessage(String message) throws IOException {
-
- /*
- 前端需要传入,发送者id,接收者id
- */
-
- Message messageA = new Message();
- messageA.setReceiverId(1L);
- messageA.setSenderId(2L);
- messageA.setMessageText(message);
- messageMapper.insert(messageA);
- LOGGER.info("[websocket] 收到消息:id={},message={}", this.session.getId(), message);
-
- if (message.equalsIgnoreCase("bye")) {
- // 由服务器主动关闭连接。状态码为 NORMAL_CLOSURE(正常关闭)。
- this.session.close(new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "Bye"));
- return;
- }
-
-
- this.session.getAsyncRemote().sendText("[" + Instant.now().toEpochMilli() + "] Hello " + message);
- }
-
- // 连接打开
- @OnOpen
- public void onOpen(Session session, EndpointConfig endpointConfig) {
- // 保存 session 到对象
- this.session = session;
-
- this.messageMapper = EchoChannel.applicationContext.getBean(MessageMapper.class);
-
-
-
- LOGGER.info("[websocket] 新的连接:id={}", this.session.getId());
-
-
- }
-
- // 连接关闭
- @OnClose
- public void onClose(CloseReason closeReason) {
- LOGGER.info("[websocket] 连接断开:id={},reason={}", this.session.getId(), closeReason);
- }
-
- // 连接异常
- @OnError
- public void onError(Throwable throwable) throws IOException {
-
- LOGGER.info("[websocket] 连接异常:id={},throwable={}", this.session.getId(), throwable.getMessage());
-
- // 关闭连接。状态码为 UNEXPECTED_CONDITION(意料之外的异常)
- this.session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, throwable.getMessage()));
- }
-
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- EchoChannel.applicationContext = applicationContext;
- }
- }

- <template>
- <div>
- <table>
- <thead>
- <tr>
- <th>消息编号</th>
- <th>发送者</th>
- <th>发送时间</th>
- <th>发送内容</th>
- </tr>
- </thead>
- <tbody>
- <tr v-for="item in messageList" :key="item.time">
- <td>{{ item.id }}</td>
- <td>{{ item.username }}</td>
- <td>{{ new Date(item.time).toLocaleTimeString() }}</td>
- <td>{{ item.message }}</td>
- </tr>
- </tbody>
- </table>
- <input
- type="text"
- v-model="sendMessage"
- placeholder="请输入你要发送的消息">
- <button @click="handleSendButton()">发送</button>
- <button @click="handleLogoutButton()">退出</button>
- </div>
- </template>
-
- <script>
-
- import {
- getUsername,
- removeUsername
- } from "@/utils/username";
-
- export default {
- name: "Home",
- data() {
- return {
- webSocketObject: null,
- username: '',
- messageList: [
-
- ],
- sendMessage: ''
- }
- },
- created() {
- //从localStorage中获得username
- this.username = getUsername()
- //如果username不存在返回到登录页面
- if (!this.username){
- this.$router.push({
- name: 'Login'
- })
- }
- //初始化WebSocket
- this.webSocketInit()
- },
- beforeDestroy() {
- this.webSocketObject.close();//在该组件销毁时关闭该连接以节约资源
- },
- methods: {
- webSocketInit(){
- const webSocketUrl = 'ws://localhost:8000/websocket/'+this.username
- this.webSocketObject = new WebSocket(webSocketUrl);
- this.webSocketObject.onopen = this.webSocketOnOpen
- this.webSocketObject.onmessage = this.webSocketOnMessage
- this.webSocketObject.onerror = this.webSocketOnError
- this.webSocketObject.onclose = this.webSocketOnClose
- },
- webSocketOnOpen(e){
- console.log('与服务端连接打开->',e)
- },
- webSocketOnMessage(e){
- console.log('来自服务端的消息->',e)
- const receiveMessage = JSON.parse(e.data);
- this.messageList.push(receiveMessage)
- },
- webSocketOnError(e){
- console.log('与服务端连接异常->',e)
- },
- webSocketOnClose(e){
- console.log('与服务端连接关闭->',e)
- },
- handleSendButton() {
- const username = this.username
- const message = this.sendMessage
- this.webSocketObject.send(JSON.stringify({
- id: 1,
- message,
- username,
- time: new Date().getTime()
- }))
- this.sendMessage = ''
- },
- handleLogoutButton(){
- removeUsername() //清除username然后断开连接
- this.webSocketObject.close();
- this.$router.push({
- name: 'Login'
- })
- }
- },
- }
- </script>
-
- <style scoped>
-
- </style>

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。