Java注释和websocket—为什么使用注释而不是传统方法?

Java注释和websocket—为什么使用注释而不是传统方法?,java,netbeans,websocket,annotations,Java,Netbeans,Websocket,Annotations,请看我贴在下面的代码。仅供参考,这来自Oracle网站的websocket示例: 我的问题是,这是怎么回事?!--特别是MyWhiteboard的broadcastFigure功能。它不是一个被重写的抽象函数,也不是传统意义上的另一个类的“注册”。我看到它的唯一方式是当编译器看到@OnMessage注释时,它会在收到新消息时将broadcastFigure调用插入到编译代码中。但在调用此函数之前,它将通过FiguredCoder类在接收的数据中流动-基于注释@ServerEndpoint中指定

请看我贴在下面的代码。仅供参考,这来自Oracle网站的websocket示例:

我的问题是,这是怎么回事?!--特别是
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方法?我试图理解设计原理。再次谢谢,太好了。我跟进了你所说的:编程端点与带注释端点,这是一个有趣的讨论。干杯。人们更喜欢使用注释?真正地这种方法防止您使用编译时类型检查