WebScoket
WebSocket全双工通信协议,在客户端和服务端建立连接后,可以持续双向通信,和HTTP同属于应用层协议,并且都依赖于传输层的TCP/IP协议。
建立连接
在双向通信之前,必须通过握手建立连接。Websocket通过 HTTP/1.1 协议的101状态码进行握手,首先客户端(如浏览器)发出带有特殊消息头(Upgrade、Connection)的请求到服务器,服务器判断是否支持升级,支持则返回响应状态码101,表示协议升级成功,对于WebSocket就是握手成功。
成功后服务器对其进行响,之后客户端与服务端就可以进行双向通信
优点
1、减少控制开销
2、实时性强。由于是全双工通信,服务端可以随时给客户端发送消息
3、更好的二进制支持
4、支持扩展
5、更好的压缩效果
代码
1、导入spring-boot-starter-websocket依赖
2、创建配置类 实例化ServerEndpointExporter
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter(){
return new ServerEndpointExporter();
}
}
3、创建WebScoket服务
@ServerEndpoint(value = "/demo/chat",configurator = GetHttpSessionConfigurator.class)
@Component
public class WebSocket {
//存储每一个客户端对象对应的 WebSocket对象
private static Map<String ,WebSocket> onlineUsers= new ConcurrentHashMap<>();
//可以发送消息给指定的用户
private Session session;
private HttpSession httpSession;
//链接建立时调用
@OnOpen
public void onOpen(Session session, EndpointConfig config){
this.session=session;
HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
this.httpSession=httpSession;
String studentName = (String) httpSession.getAttribute("studentName");
String studentId = (String) httpSession.getAttribute("studentId");
System.out.println("studentName======"+studentName);
System.out.println("studentId======"+studentId);
//将当前对象存储起来
onlineUsers.put(studentName,this);
//将当前在线用户名推送给所有客户端
}
//接收到客户端发送的数据时调用
@OnMessage
public void onMessage(String message,Session session) {
ObjectMapper mapper=new ObjectMapper();
try {
//将字符串转化为对象
Message mes = mapper.readValue(message, Message.class);
//要发给谁
String toStudentName = mes.getToStudentName();
String data = mes.getMessage();
//谁发送的
String studentName = (String) httpSession.getAttribute("studentName");
String resultMessage = MessageUtils.getMessage(studentName, data);
System.out.println("resultMessage======"+resultMessage);
onlineUsers.get(toStudentName).session.getBasicRemote().sendText(resultMessage);
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//链接关闭时调用
@OnClose
public void onClose(Session session){
}
public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
HttpSession httpSession = (HttpSession) request.getHttpSession();
sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
}
}