学习了怎么实现webSocket:1.在src目录下新建ChatEntpoint.java类
import java.io.IOException;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value = “/websocket/chat”)
public class ChatEntpoint {
private static final String GUEST_PREFIX=“访客”;
private static final AtomicInteger connectionIds = new AtomicInteger(0);
//定义一个集合,用于保存所有接入的WebSocket客户端
private static final Set clientSet = new CopyOnWriteArraySet<>();
//定义一个成员变量,记录WebSocket客户端的聊天昵称
private final String nickname;
//定义一个成员变量,记录与WebSocket之间的会话
private Session session;
public ChatEntpoint() {
nickname=GUEST_PREFIX+connectionIds.getAndIncrement();
}
//当客户端连接进来时自动激发该方法
@OnOpen
public void start(Session session) {
this.session = session;
//将WebSocket客户端会话添加到集合中
clientSet.add(this);
String message = String.format("【%s %s】", nickname,"加入了!");
//发送消息
broadcast(message);
}
//当客户端断开连接时自动激发该方法
@OnClose
public void end() {
clientSet.remove(this);
String message = String.format("【%s %s】", nickname,"离开了!");
//发送消息
broadcast(message);
}
//当收到客户端消息时自动激发该方法
@OnMessage
public void incoming(String message) {
String filterMessage = String.format("【%s %s】", nickname,filter(message));
broadcast(filterMessage);
}
//当客户端通信发生错误时
@OnError
public void onError(Throwable t)throws Throwable {
System.out.println("WebSocket服务器端报错"+t);
}
//实现广播消息的工具方法
public static void broadcast(String msg) {
//遍历服务器关联的所有客户端
for(ChatEntpoint client:clientSet) {
try {
synchronized(client) {
//发送消息
client.session.getBasicRemote().sendText(msg);
}
}catch(IOException e) {
System.out.println("聊天错误,向客户端 "+client+" 发送消息出现错误");
clientSet.remove(client);
try {
client.session.close();
}catch(IOException el) {}
String message = String.format("【%s %s】", client.nickname,"已经断开了连接!");
}
}
}
//定义一个工具方法,用于对字符串中的HTML字符标签进行转义
private static String filter(String message) {
if(null == message) {
return null;
}
char content[] = new char[message.length()];
message.getChars(0, message.length(), content, 0);
StringBuilder result = new StringBuilder(content.length+50);
for(int i=0;i<content.length;i++) {
//控制对尖括号等特殊字符进行转义
switch(content[i]) {
case '<':
result.append("<");
break;
case '>':
result.append(">");
break;
case '&':
result.append("&");
break;
case '"':
result.append(""");
break;
default:
result.append(content[i]);
break;
}
}
return (result.toString());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
2.在webContent下新建chat.html文件
以及webSocket和tomcat得关系:伴随着HTML5推出的WebSocket,真正实现了Web的实时通信,使B/S模式具备了C/S模式的实时通信能力。WebSocket的工作流程是这样的:浏览器通过JavaScript向服务端发出建立WebSocket连接的请求,在WebSocket连接建立成功后,客户端和服务端就可以通过 TCP连接传输数据。因为WebSocket连接本质上是TCP连接,不需要每次传输都带上重复的头部数据,所以它的数据传输量比轮询小了很多。本文不详细地介绍WebSocket规范,主要介绍下WebSocket在Java Web中的实现。
Tomcat自7.0.5版本开始支持WebSocket,并且实现了Java WebSocket规范(JSR356 ),而在7.0.5版本之前(7.0.2版本之后)则采用自定义API,即WebSocketServlet。本文使用的是Tomcat9.0.6版本
————————————————
版权声明:本文为优快云博主「qq_39686941」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/qq_39686941/article/details/104958717
学习了java set类:Interface Set 不包含重复元素的集合,并且最多一个空元素。
1.参数类型
E - 由此集合维护的元素的类型
2.Set接口除了继承自Collection接口的所有构造函数的合同以及add,equals和hashCode方法的合同。
3.
Class CopyOnWriteArraySet:
1.构造方法:CopyOnWriteArraySet():创建一个空集。
一、Session简单介绍
在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。(用的时候需要导入包import javax.websocket.Session;)
详细见https://www.cnblogs.com/xdp-gacl/p/3855702.html
二
java.util.concurrent.atomic原子操作类包里面提供了一组原子变量类。其基本的特性就是在多线程环境下,当有多个线程同时执行这些类的实例包含的方法时,具有排他性,即当某个线程进入方法,执行其中的指令时,不会被其他线程打断,而别的线程就像自旋锁一样,一直等到该方法执行完成,才由JVM从等待队列中选择一个另一个线程进入,这只是一种逻辑上的理解。实际上是借助硬件的相关指令来实现的,不会阻塞线程(或者说只是在硬件级别上阻塞了)。可以对基本数据、数组中的基本数据、对类中的基本数据进行操作。原子变量类相当于一种泛化的volatile变量,能够支持原子的和有条件的读-改-写操作。
————————————————
版权声明:本文为优快云博主「May的博客」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/lmb55/article/details/79547685
三
@OnOpen:
WebSocket.onopen属性定义一个事件处理程序,当WebSocket 的连接状态readyState 变为“OPEN”时调用;这意味着当前连接已经准备好发送和接受数据。这个事件处理程序通过 事件(建立连接时)触发。
参考https://www.cnblogs.com/wgp13x/p/3812579.html