赞
踩
WebSocket简单来讲就是在客户端与服务端之间建立一个长连接,实现端对端的直接通信,连接保持期间可以双发互相发送数据(双工通信)
WebSocket测试网站:http://www.websocket-test.com/
下面三步照着做就可以了,主要需要自己根据要求定制的再第三步
第一步:引入WebSocket依赖
<!--websocket-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
第二步:配置WebSocketConfig
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
第三步:创建WebSocketServer
主要需要自己根据项目修改的内容,其他基本不需要修改:
①websocket接口@ServerEndpoint(value = “/ws/{userId}”)和对应的路径参数的使用
②onMessage中的接收客户端请求信息的内容
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; import com.len.bmbhome.client.*; import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer; import org.bmbhome.service.UserDataService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; @Slf4j //自行设置连接接口的url,下方接收的参数userId也可以自行修改 @ServerEndpoint(value = "/ws/{userId}") @Component public class WebSocketServer { private Long userId; private Session session; //记录所有的WebSocketServer private static CopyOnWriteArrayList<WebSocketServer> webSocketSet = new CopyOnWriteArrayList<>(); public Session getSession() { return this.session; } public Long getUserId(){ return this.userId; } /** * 连接建立成功调用的方法 */ @OnOpen public void onOpen(Session session, @PathParam(value = "userId") Long userId) { log.info("有连接加入:" + userId); this.userId = userId; this.session = session; webSocketSet.add(this); } /** * 收到客户端消息后调用的方法 */ @OnMessage public void onMessage(String message, Session session) { try { log.info("来自客户端的消息:{}", message); //添加一些自己接收到客户端发送的数据的一些处理 } catch (Exception e) { log.error("接收用户消息出错了:", e); } } /** * 连接关闭时调用的方法 */ @OnClose public void OnClose() { log.info("退出用户userId" + this.userId); webSocketSet.remove(this); } /** * 向指定的session发送数据 */ private void sendMessage(Session session, String message) { try { session.getBasicRemote().sendText(message); } catch (IOException e) { log.error("消息发送失败", e); } } /** * 群发消息,即对每一个session都进行发送 */ private void sendMessageToAll(String message) throws IOException { for (WebSocketServer webSocketServer : webSocketSet) { webSocketServer.getSession().getBasicRemote().sendText(message); } } /** * 向指定userId用户发送信息 * 利用遍历的方法,判断userId是否匹配 */ private void sendMessgaeByUserId(Long userId,String message) throws IOException { for (WebSocketServer webSocketServer : webSocketSet) { if(webSocketServer.getUserId() == userId){ webSocketServer.getSession().getBasicRemote().sendText(message); } } } /** * 主动断开连接 */ public void close() throws IOException { //主动断开连接 this.session.close(); this.onClose(); } }
补充:
①客户端也要通过实现websocket才能进行通信,而不是使用原始的http协议
②sendMessage可以发送map、collection等等数据,但是要通过先转json,再转string。
客户端接收到string后,转换为json
以发送Map数据为例
Map<String,Object> map = new HashMap<>();
map.put("userName","lnz");
map.put("userId","199");
map.put("gsr","10");
sendMessage(this.session,JSONObject.toJSON(map).toString());
实例测试:
①服务端从客户端接收用户的各种健康数据(步数、皮肤电等等),并保存到数据库中
②服务端向客户端发送数据
传递JSON格式数据{”type":“xx”,xxx},利用onMessage中switch来判断type进行接收还是发送数据
type = 2、3时,进行保存数据到服务器
type=100时,进行服务器向客户端发送数据
package org.bmbhome.config; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.TypeReference; import com.len.bmbhome.client.*; import com.sun.scenario.effect.impl.sw.sse.SSEBlend_SRC_OUTPeer; import org.bmbhome.service.UserDataService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; @Slf4j @ServerEndpoint(value = "/ws/{userId}") @Component public class WebSocketServer { private Long userId; private Session session; //记录所有的WebSocketServer // 因为同一个userId可能有多个接入所以不可以使用Map<userId,WebSocketServer>或Map<userId,Session>这样的容器 //这边可以自行设计存储的容器,但注意要为static private static CopyOnWriteArrayList<WebSocketServer> webSocketSet = new CopyOnWriteArrayList<>(); private static UserDataService userDataService; @Autowired public void setUserDataService(UserDataService userDataService) { WebSocketServer.userDataService = userDataService; } public Session getSession() { return this.session; } public Long getUserId(){ return this.userId; } /** * 连接建立成功调用的方法 */ @OnOpen public void onOpen(Session session, @PathParam(value = "userId") Long userId) { log.info("有连接加入:" + userId); this.userId = userId; this.session = session; webSocketSet.add(this); } /** * 收到客户端消息后调用的方法 */ @OnMessage public void onMessage(String message, Session session) { try { log.info("来自客户端的消息:{}", message); int type = JSON.parseObject(message).getInteger("type"); System.out.println(type); JSONObject jsonObject = JSONObject.parseObject(message); switch (type) { /** * 步数统计 * json格式: {"type":"2",data:"xxx"} */ case 2: MessageDTO<StepDTO> stepDTOMessageDTO = new MessageDTO<>(); stepDTOMessageDTO.setType(jsonObject.getInteger("type")); StepDTO stepDTO = new StepDTO(); stepDTO.setCount(jsonObject.getLong("data")); stepDTOMessageDTO.setData(stepDTO); System.out.println(stepDTOMessageDTO.getType()); System.out.println(stepDTOMessageDTO.getData()); userDataService.saveUserStep(userId, stepDTOMessageDTO); break; /** * 皮肤电数据信息 * json格式: {"type":"3","data":"xxx"} */ case 3: GsrDTO gsrDTO = new GsrDTO(); gsrDTO.setSensorValue(jsonObject.getInteger("data")); userDataService.saveUserGsr(userId, gsrDTO); System.out.println(gsrDTO); break; /** * 用户请求数据 * 测试服务器向客户端发送数据 * json格式: {"type":"100"} */ case 100: sendMessage(this.session,"恭喜你以及获得到数据"); sendMessgaeByUserId(3L,"3号你很容易被选中"); Map<String,Object> map = new HashMap<>(); map.put("userName","lnz"); map.put("userId","199"); map.put("gsr","10"); sendMessage(this.session,JSONObject.toJSON(map).toString()); break; default: log.error("未知消息类型"); } } catch (Exception e) { log.error("接收用户消息出错了:", e); } } @OnClose public void OnClose() { log.info("退出用户userId" + this.userId); webSocketSet.remove(this); } /** * 向指定的session发送数据 */ private void sendMessage(Session session, String message) { try { session.getBasicRemote().sendText(message); } catch (IOException e) { log.error("消息发送失败", e); } } /** * 群发消息,即对每一个session都进行发送 */ private void sendMessageToAll(String message) throws IOException { for (WebSocketServer webSocketServer : webSocketSet) { webSocketServer.getSession().getBasicRemote().sendText(message); } } /** * 向指定userId用户发送信息 * 利用遍历的方法 */ private void sendMessgaeByUserId(Long userId,String message) throws IOException { for (WebSocketServer webSocketServer : webSocketSet) { if(webSocketServer.getUserId() == userId){ webSocketServer.getSession().getBasicRemote().sendText(message); } } } }
请求服务器发送数据测试:
向服务器发送数据测试:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。