携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第9天,点击查看活动详情
2.2. 通过继承AbstractwebSocketHandler实现
上面注解的版本感觉比较好理解,但是感觉不是很懂原理,所以想通过继承AbstractwebSocketHandler实现一下
-
WebSocketConfig配置通过实现
WebSocketConfigurer配置类,重写registerWebSocketHandlers方法,注册自定义的WebSocketHandler的实现类MyWebSocketHandler,并指定类对应的websocket访问的ServerEndpoint为/webSocket。 通过@EnableWebSocket注解,启动spring-boot-starter-websocket的自动化配置。@Configuration public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) { webSocketHandlerRegistry.addHandler(new MyWebSocketHandler(), "webSocket"); } @Bean public ThreadPoolTaskScheduler taskScheduler(TaskSchedulerBuilder builder) { return builder.build(); } }我直接在这个类里面配置了
ThreadPoolTaskScheduler之前是没有这个bean的,但是定时任务有bug,我就浅配了一下,虽然不太懂为什么,反正与WebSocket冲突了 -
配置hander
由于我们配置类中定义了
MyWebSocketHandler的类,是websoket用于收发消息的@Component public class MyWebSocketHandler extends AbstractWebSocketHandler { /** * 建立 WebSocket 连接 * * @param session * @throws Exception */ @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { WebSocketManager.add(session.getId(), session); } @Override protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { String payload = message.getPayload(); session.sendMessage(new TextMessage(payload + LocalDateTime.now())); } /** * 发送二进制消息 * * @param session * @param message * @throws Exception */ @Override protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) throws Exception { System.out.println("发送二进制消息"); } /** * 异常处理 * * @param session * @param exception * @throws Exception */ @Override public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception { WebSocketManager.removeAndClose(session.getId()); } /** * 关闭连接 * * @param session * @param status * @throws Exception */ @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { WebSocketManager.removeAndClose(session.getId()); } }afterConnectionEstablished方法是在socket连接成功后被触发,同原生注解里的@OnOpen功能。afterConnectionClosed方法是在socket连接关闭后被触发,同原生注解里的@OnClose功能。handleTextMessage方法是在客户端发送普通文件信息时触发,同原生注解里的@OnMessage功能。handleBinaryMessage方法是在客户端发送二进制信息时触发,同原生注解里的@OnMessage功能。handleTransportError方法同原生注解里的@OnError。- ...
-
配置WebSocket的管理器
public class WebSocketManager { // 保存 session 连接的地方 public static ConcurrentHashMap<String, WebSocketSession> SESSION_POOL = new ConcurrentHashMap<>(); /** * 添加 session * * @param key * @param session */ public static void add(String key, WebSocketSession session) { SESSION_POOL.put(key, session); } /** * 删除并返回 session * * @param key * @return */ public static WebSocketSession remove(String key) { return SESSION_POOL.remove(key); } /** * 关闭连接的操作 * * @param key */ public static void removeAndClose(String key) { WebSocketSession session = remove(key); if (session != null) { try { session.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 获得 session * * @param key * @return */ public static WebSocketSession get(String key) { return SESSION_POOL.get(key); } }用于增加和移除连接进入WebSocket的客户端
-
发送消息以及他的实现类
public interface WebSocketService { /** * 给客户端发送消息 * @param session * @param text * @throws IOException */ public void sendMsg(WebSocketSession session, String text) throws IOException; /** * 给客户端广播消息 * @param text * @throws IOException */ public void broadcastMsg(String text) throws IOException; }实现,这里我直接用时间代替查数据库了
@Service public class WebSocketServiceImpl implements WebSocketService { public void sendMsg(WebSocketSession session, String text) throws IOException { System.out.println(text); session.sendMessage(new TextMessage(text)); } public void broadcastMsg(String text) throws IOException { for (WebSocketSession session : WebSocketManager.SESSION_POOL.values()) { session.sendMessage(new TextMessage(text)); } } } -
定时任务
这个怎么写其实都ok的
@Component public class MsgJob { @Autowired private WebSocketService webSocketService; @Scheduled(cron = "0/3 * * * * *") public void run() throws IOException { System.out.println(WebSocketManager.SESSION_POOL.size()); webSocketService.broadcastMsg(LocalDateTime.now().toString()); } } -
主启动
@SpringBootApplication(scanBasePackages = {"com.he.websocket2"}) @EnableScheduling @EnableWebSocket public class WebSocketMain { public static void main(String[] args) { SpringApplication.run(WebSocketMain.class, args); } }这里需要注意的是
@EnableWebSocket用于开启WebSocket,不过确实和schedule有问题,暂且不管他,等以后学深入再看 -
前端页面和之前的一样,懒得修改了
运行测试,没有问题