Java注释和websocket—为什么使用注释而不是传统方法?
请看我贴在下面的代码。仅供参考,这来自Oracle网站的websocket示例: 我的问题是,这是怎么回事?!--特别是Java注释和websocket—为什么使用注释而不是传统方法?,java,netbeans,websocket,annotations,Java,Netbeans,Websocket,Annotations,请看我贴在下面的代码。仅供参考,这来自Oracle网站的websocket示例: 我的问题是,这是怎么回事?!--特别是MyWhiteboard的broadcastFigure功能。它不是一个被重写的抽象函数,也不是传统意义上的另一个类的“注册”。我看到它的唯一方式是当编译器看到@OnMessage注释时,它会在收到新消息时将broadcastFigure调用插入到编译代码中。但在调用此函数之前,它将通过FiguredCoder类在接收的数据中流动-基于注释@ServerEndpoint中指定
MyWhiteboard
的broadcastFigure
功能。它不是一个被重写的抽象函数,也不是传统意义上的另一个类的“注册”。我看到它的唯一方式是当编译器看到@OnMessage
注释时,它会在收到新消息时将broadcastFigure
调用插入到编译代码中。但在调用此函数之前,它将通过FiguredCoder
类在接收的数据中流动-基于注释@ServerEndpoint
中指定的解码器。在broadcastFigure
中,当调用sendObject
时,编译器将根据注释@ServerEndpoint
中指定的内容插入对FigureEncoder
的引用。这准确吗
如果是这样的话,为什么这个实现使用注释以这种方式进行操作?在研究这一点之前,我希望有一个抽象的OnMessage
函数需要重写,并为编码器和解码器提供显式注册函数。为什么websocket实现不使用这种“传统”方法,而是通过注释来实现呢
多谢各位
Mywhiteboard.java:
@ServerEndpoint(value = "/whiteboardendpoint", encoders = {FigureEncoder.class}, decoders = {FigureDecoder.class})
public class MyWhiteboard {
private static Set<Session> peers = Collections.synchronizedSet(new HashSet<Session>());
@OnMessage
public void broadcastFigure(Figure figure, Session session) throws IOException, EncodeException {
System.out.println("broadcastFigure: " + figure);
for (Session peer : peers) {
if (!peer.equals(session)) {
peer.getBasicRemote().sendObject(figure);
}
}
}
@OnError
public void onError(Throwable t) {
}
@OnClose
public void onClose(Session peer) {
peers.remove(peer);
}
@OnOpen
public void onOpen(Session peer) {
peers.add(peer);
}
}
@ServerEndpoint(value=“/whiteboardendpoint”,编码器={FigureEncoder.class},解码器={FigureDecoder.class})
公共类MyWhiteboard{
private static Set peers=Collections.synchronizedSet(new HashSet());
@OnMessage
public void broadcastFigure(Figure Figure,Session Session)抛出IOException,EncodeException{
System.out.println(“广播数字:+数字);
用于(会话对等方:对等方){
如果(!peer.equals(会话)){
peer.getBasicRemote().sendObject(图);
}
}
}
@一个错误
公共作废登记员(可丢弃的t){
}
@一次
公共void onClose(会话对等方){
删除(peer);
}
@奥诺彭
公共开放(会话对等){
peers.add(peer);
}
}
FigureEncoder.java
public class FigureEncoder implements Encoder.Text<Figure> {
@Override
public String encode(Figure figure) throws EncodeException {
return figure.getJson().toString();
}
@Override
public void init(EndpointConfig config) {
System.out.println("init");
}
@Override
public void destroy() {
System.out.println("destroy");
}
}
公共类figueencoder实现编码器.Text{
@凌驾
公共字符串编码(见图)引发EncodeException异常{
返回figure.getJson().toString();
}
@凌驾
公共void init(EndpointConfig配置){
System.out.println(“init”);
}
@凌驾
公共空间销毁(){
系统输出打印(“销毁”);
}
}
FigureCoder.java:
public class FigureDecoder implements Decoder.Text<Figure> {
@Override
public Figure decode(String string) throws DecodeException {
JsonObject jsonObject = Json.createReader(new StringReader(string)).readObject();
return new Figure(jsonObject);
}
@Override
public boolean willDecode(String string) {
try {
Json.createReader(new StringReader(string)).readObject();
return true;
} catch (JsonException ex) {
ex.printStackTrace();
return false;
}
}
@Override
public void init(EndpointConfig config) {
System.out.println("init");
}
@Override
public void destroy() {
System.out.println("destroy");
}
}
公共类figuredcoder实现解码器.Text{
@凌驾
公众人物解码(字符串)引发解码异常{
JsonObject JsonObject=Json.createReader(新的StringReader(string)).readObject();
返回新图形(jsonObject);
}
@凌驾
公共布尔值willDecode(字符串){
试一试{
createReader(新的StringReader(string)).readObject();
返回true;
}捕获(JsonException ex){
例如printStackTrace();
返回false;
}
}
@凌驾
公共void init(EndpointConfig配置){
System.out.println(“init”);
}
@凌驾
公共空间销毁(){
系统输出打印(“销毁”);
}
}
注释有其优点和缺点,关于选择创建基于注释的API而不是使用接口的(你怎么说)“传统”API,有很多话要说。我不想谈这个,因为你会在网上找到很多战争
正确使用注释可以提供关于类/方法职责的更好信息。许多人更喜欢注释,因此注释已成为一种趋势,并被广泛使用
现在,让我们回到你的问题:
为什么这个实现使用注释这样做?在看这个之前,我希望有一个抽象的OnMessage函数需要重写,并为编码器和解码器提供显式注册函数。为什么websocket实现不使用这种“传统”方法,而是通过注释来实现呢
实际上他们没有。注释只是使用API提供的一种方式。如果你不喜欢,那么你可以用老办法。以下是JSR-356规范:
创建端点主要有两种方法。第一种方法是实施某些
Java WebSocket API中具有处理端点生命周期所需行为的API类,
使用和发送消息、发布自身或连接到对等方。通常,本规范将参考以下内容:
作为编程端点的端点类型。第二种方法是装饰一个普通的旧Java对象
(POJO)使用来自JavaWebSocket API的某些注释。然后实现采用这些
注释类并在运行时创建适当的对象,以将POJO部署为websocket端点。
通常,此规范将此类端点称为
带注释的端点
同样,人们更喜欢使用注释,这是大多数教程都会用到的,但是如果你想使用注释,也可以不使用注释。其他地方有代码使用反射查找OnMessage注释。谢谢immibis。是的,我就是这么想的。但是,从设计的角度来看,为什么您认为他们这样做,而不是要求我们重写显式OnMessage方法?我试图理解设计原理。再次谢谢,太好了。我跟进了你所说的:编程端点与带注释端点,这是一个有趣的讨论。干杯。人们更喜欢使用注释?真正地这种方法防止您使用编译时类型检查