WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
特点:它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话,属于服务器推送技术的一种。
在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
整合springboot + 一个群发消息、群组消息的demo
- 引入pom文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
- 启动类上加注解@EnableWebSocket
@EnableScheduling
@EnableWebSocket
@MapperScan(basePackages = "com.XX.dao")
@SpringBootApplication
public class Start {
public static void main(String[] args) {
SpringApplication.run(Start.class, args);
}
}
-
在application.properties文件内修改端口号
#server server.port=8002
-
建配置类WebSocketConfig
@Configuration public class WebSocketConfig implements WebSocketConfigurer { @Autowired private MyMessageHandler handler; @Autowired private MyHandShakeInterceptor interceptor; @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry webSocketHandlerRegistry) { webSocketHandlerRegistry.addHandler(handler, "/WSSERVER").addInterceptors(interceptor).setAllowedOrigins("*"); } }
-
写一个握手拦截器
@Component public class MyHandShakeInterceptor implements HandshakeInterceptor { @Autowired private UserService userService; @Override public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception { ServletServerHttpRequest servletServerHttpRequest = (ServletServerHttpRequest) serverHttpRequest; HttpServletRequest req = servletServerHttpRequest.getServletRequest(); User user = (User) req.getSession().getAttribute("user"); map.put("user", userService.getUserMapper().selectByPrimaryKey(user.getId())); return true; } @Override public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) { // } }
-
写一个消息处理器
@Component public class MyMessageHandler extends TextWebSocketHandler { //客户端列表 private Map<String, WebSocketSession> clients = new ConcurrentHashMap<String, WebSocketSession>(); public Map<String, WebSocketSession> getClients() { return clients; } @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { clients.put(session.getId(), session); System.out.println("建立连接:" + session.getId()); } @Override public void handleMessage(WebSocketSession session, final WebSocketMessage<?> message) throws Exception { String p = message.getPayload().toString(); User user = (User) session.getAttributes().get("user"); System.out.println("收到消息:" + user.getAccount() + ":" + p); MyMsg myMsg = JSONObject.parseObject(p, MyMsg.class); myMsg.setCreatetime(new Date()); myMsg.setSender(user.getAccount()); //全体推送 if (myMsg.getType().equals("all")) { myMsg.setReceiver("all"); clients.entrySet().forEach(o -> { try { TextMessage textMessage = new TextMessage(JSON.toJSONString(myMsg)); o.getValue().sendMessage(textMessage); } catch (IOException e) { e.printStackTrace(); } }); //群组推送 } else if (myMsg.getType().equals("grp")) { myMsg.setReceiver(user.getGrp()); clients.entrySet().stream().filter(o -> { User u = (User) o.getValue().getAttributes().get("user"); return u.getGrp().equals(myMsg.getReceiver()); }).forEach(o -> { try { TextMessage textMessage = new TextMessage(JSON.toJSONString(myMsg)); o.getValue().sendMessage(textMessage); } catch (IOException e) { e.printStackTrace(); } }); } } @Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { clients.remove(session.getId()); System.out.println("断开连接:" + session.getId()); } }
-
客户端页面
<body class="bg-a"> <div class="container-fluid h-100" id="app"> <div class="row"> <div class="col text-center bg-warning text-white shadow">websocket</div> </div> <div class="mt-2 h-75 border" id="chatbox" style="overflow: auto;"> <div class="m-1" v-for="msg in msgs"> <div>{{msg.sender}}->{{msg.receiver}}-{{msg.createtime|filterDate}}</div> <div>{{msg.content}}</div> </div> </div> <div class="form-inline mt-2"> <select id="type" class="form-control form-control-sm"> <option value="all">:全体</option> <option value="grp">:群组</option> <option value="prv">:用户</option> </select> <input id="msg" type="text" class="form-control form-control-sm ml-1"/> <button class="btn btn-sm btn-outline-success ml-1" onclick="sendMsg();">发送</button> </div> </div> <script th:inline="javascript"> //ws var url = "ws://" + location.host + "/WSSERVER"; var ws = new WebSocket(url); //app var app = new Vue({ el: "#app", data: {msgs: []}, filters: { filterDate: function (val) { return $.msfmt.todate(val, true, 8); } } }); //sendMsg function sendMsg() { var msg = { content: $("#msg").val(), type: $("#type").val() } ws.send(JSON.stringify(msg)); layer.msg("发送成功"); $("#msg").val(""); } //ws-onmessage ws.onmessage = function (e) { app.msgs.push($.parseJSON(e.data)); } </script> </body>