websocket的使用
依赖包
<!--实时通信的依赖包-->
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
开发一个服务端程序用来广播消息
实体类
package com.seecen.ws;
/**
* Author: CalcYu
* Date: 2019/8/12
*/
public class Message {
//-1: 群聊 2:私聊 0:系统 999:特殊操作
private int type;
//内容
private String content;
//私聊接收者
private Integer toUser;
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Integer getToUser() {
return toUser;
}
public void setToUser(Integer toUser) {
this.toUser = toUser;
}
}
特效实体类
package com.seecen.ws;
/**
* Author: CalcYu
* Date: 2019/8/13
*/
public class Msg {
/**
* 1:系统上/下线消息
* 4:用户文本消息
* 5:收到用户抖动消息
* 6:收到用户撤回消息
*/
private int type;
private String username;
private int messageId;
private String content;
public Msg() {
}
public Msg(int type, String username, int messageId, String content) {
this.type = type;
this.username = username;
this.messageId = messageId;
this.content = content;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getMessageId() {
return messageId;
}
public void setMessageId(int messageId) {
this.messageId = messageId;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
给websocket服务定义一个连接的地址
package com.seecen.ws;
import com.alibaba.fastjson.JSON;
import com.seecen.controller.LoginController;
import com.seecen.entity.User;
import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* Author: CalcYu
* Date: 2019/8/9
* 1.客户端建立连接
* 2.客户端断开连接
* 3.客户端发送消息
*/
//给websocket服务定义一个连接的地址
//ws:localhost:8080/my_chat
@ServerEndpoint(value = "/my_chat", configurator = GetHttpSession.class)
public class ChatServer {
//声明一个集合来保存客户断程序,建立连接或断开连接都是并发操作
private static CopyOnWriteArraySet<ChatServer> clients = new CopyOnWriteArraySet<>();
private Session session;
//每个ChatServer绑定一个User对象
private User user;
/**
* 当建立连接执行
* 创建连接时会创建一个session对象
* 每个客户端会创建 一个ChatServer对象 每个对象有一个session
*/
@OnOpen
public void onOpen(Session session, EndpointConfig config) {
this.session = session;
clients.add(this);
//从配置文件中获取httpSession对象及User对象
HttpSession httpSession = (HttpSession)
config.getUserProperties().get(HttpSession.class.getName());
//获取httpSession中的User对象
User user = (User) httpSession.getAttribute(LoginController.USER_INFO);
this.user = user;
System.out.println("有新的连接加入,当前在线人数为:" + clients.size());
}
/**
* 当断开连接执行
*/
@OnClose
public void onClose() {
clients.remove(this);
System.out.println("有一个用户退出,当前在线人数为:" + clients.size());
}
/**
* 当发送消息执行
*
* @param msg
*/
@OnMessage
public void onMessage(String msg) {
//传递比较丰富的消息可以采用json
//如果给客户端主动发送消息
//广播
//把字符串还原成对象
Message message = JSON.parseObject(msg, Message.class);
//当类型为-1时 群聊,把消息content广播给所有在线用户
if (message.getType() == -1) {
for (ChatServer chat : clients) {
try {
//<p style="color: green">群聊消息</p>
String html = "<p style='color: green'>%s</p>";
chat.getSession().getBasicRemote().sendText(String.format(html,message.getContent()));
} catch (IOException e) {
e.printStackTrace();
}
}
} else if (message.getType() == 2) {
//私聊
// 遍历集合找到对应用户进行推送(问题:并不知道哪个ChatServer对象是哪个用户)
for (ChatServer c : clients) {
if (c.getUser().getUserId().intValue() == message.getToUser()) {
// 张三对李四说:晚上吃什么?
//<p style="color: red">私聊消息</p>
String html = "<p style='color: red'>%s</p>";
String content = this.user.getUserName() + "对" + c.getUser().getUserName() + ":" + message.getContent();
try {
c.getSession().getBasicRemote().sendText(String.format(html, content));
//给自己发送消息
this.getSession().getBasicRemote().sendText(String.format(html, content));
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
}
}
//当websocket出错会执行
@OnError
public void onError(Throwable e){
e.printStackTrace();
}
public User getUser() {
return user;
}
//只能读取不能修改
public Session getSession() {
return session;
}
}
开发一个客户端程序用来发送和接收消息
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.main {
width: 350px;
margin: 0 auto;
}
.main #msgBox {
width: 100%;
height: 300px;
}
</style>
</head>
<body>
<div class="main">
<div id="msgBox" ></div>
<select name="" id="user">
<option value="-1">所有人</option>
<option value="3">张三</option>
<option value="6">李四</option>
</select>
<input type="text" id="inputTxt">
<input type="button" id="sendBtn" value="发送">
</div>
<script src="/js/jquery.min.js"></script>
<script>
//字面量的方式传递一个对象
var obj = {userName: "1111", userPsw: "123"};
var obj2 = new Object();
obj2.userName = "123123";
//把js对象转换成字符串
var jsonStr = JSON.stringify(obj);
//把字符串转换成对象
var jsObj = JSON.parse(jsonStr);
//同时打印多个变量值
console.log(obj, obj2, jsonStr, jsObj);
//当页面加载完成连接服务器程序
var url = "ws://localhost:8866/my_chat";
var ws = new WebSocket(url);
if (ws) {
//采用监听的方式来绑定回调函数
ws.onopen = function (event) {
console.log("连接服务器成功");
$("#msgBox").append("连接服务器成功\n");
}
ws.onclose = function (event) {
$("#msgBox").append("服务器连接中断\n");
}
ws.onmessage = function (event) {
$("#msgBox").append(event.data + "\n");
}
//主动给服务器发送消息
$("#sendBtn").click(function () {
var msg = $("#inputTxt").val();
if (msg) {
var msgType = $("#user").val();
if (msgType == -1) {
//发送给所有人
var msgObj = {type: -1, content: msg};
ws.send(JSON.stringify(msgObj));
} else {
//私聊
var msgObj = {type: 2, content: msg, toUser: msgType};
ws.send(JSON.stringify(msgObj))
}
}
})
} else {
alert("浏览器版本过低,不支持websocket协议");
}
</script>
</body>
</html>
websocket使用细节
- 如何通过json传递信息
- 如何把json字符串还原回一个对象
依赖包
fastjson (阿里巴巴开源的)
<!--json转换依赖包--> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.31</version> </dependency>
JSON api
toJSONString 方法
parseObject 方法
parseArray 方法
html里面转换
js中进行互转
JSON.stringify(obj);
JSON.parse(jsonStr);
WebSocket中如何获取HttpSession对象中的User
增加终端配置文件
package com.seecen.ws;
import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
/**
* Author: CalcYu
* Date: 2019/8/12
* 自定义终端配置文件获取httpSession中的对象
*/
public class GetHttpSession extends ServerEndpointConfig.Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
//获取httpSession对象,保存至终端配置文件的用户属性中
HttpSession session = (HttpSession) request.getHttpSession();
if (session != null) {
sec.getUserProperties().put(HttpSession.class.getName(), session);
}
}
}
web.xml中可以设置websocket文本缓存大小
<!--设置websocket文本缓存大小-->
<context-param>
<param-name>org.apache.tomcat.websocket.textBufferSize</param-name>
<param-value>5242800</param-value>
</context-param>
bug怎么这么多!