如何创建可从其他类访问的 Websocket SessionManager

发布于 2025-01-09 22:01:08 字数 2147 浏览 0 评论 0原文

我正在开发一个带有 WebSocket 的应用程序,并希望将客户端 ID 和会话保存到管理器,但当我还希望能够使用自动装配从另一个类访问此内容时,很难理解如何正确执行此操作。

public class Client {

    private String id;
    private Session session;
    private MessageHandler handler;  

    Client(String id, Session session, MessageHandler handler) {
        this.id = id;
        this.session = session;
        this.handler = handler;
    }
}

public class ClientsManager {

    private Set<Client> clientSet = new CopyOnWriteArraySet<>();

    public Set<Client> getClients() {
        return this.clientSet;
    } 

    public void addClient(Client client) {
        this.clientSet.add(client);
    }

    public void removeClient(Client client) {
        clientSet.remove(client);
    }
}  

                    

public class WebsocketServerEndpoint         {

    public static final ClientsManager manageClients = new ClientsManager();

    @OnOpen
    public void onOpen(Session session, @PathParam("connectId") String connectId) throws IOException, EncodeException {

        MessageHandler messageHandler = new MessageHandler();
        Client client = new Client(connectId, session, messageHandler);
        this.client = client;
        manageClients.addClient(client);
    }
        ....
        ....
        ....
        ....

}

来自另一个班级:

public class DoSomething       {

        @Autowired
        WebsocketServerEndpoint serverEndpoint;

        public String doSomething()  {
        int numberOfClients = serverEndpoint.getClients().size()
        return numberOfClients;
       }
}

据我了解。这是不正确的,您不应该自动装配静态字段等。

当我在 DoSomething 类中调试 serverEndpoint: null 时,我可以看到,但如果我有一个已连接的客户端,我会得到 1 个已连接的客户端,依此类推。 当我这样做时,我将在 DoSomething 课程中获得正确数量的客户。 我是否只是误解了这一点并且它像我所做的那样起作用? 或者我应该怎么做? 他们是编写我的 Client 和 ClientsManager 类的更好方法吗?

我读到,如果我想“自动装配”,无论如何有两种可能的方法。

  1. 使用构造函数 @Autowired 对于静态字段
  2. 使用 @PostConstruct 将值设置为静态字段

但是当我想实例化“public static Final ClientsManager manageClients = new ClientsManager();”时,这是如何工作的

抱歉我的愚蠢问题,但我觉得我不完全理解这一点。

I am working on an application with a WebSocket and want to save the clients id and session to a manager but have difficulties to understand how to do this correct when I also want to be able to reach this from another class with autowire.

public class Client {

    private String id;
    private Session session;
    private MessageHandler handler;  

    Client(String id, Session session, MessageHandler handler) {
        this.id = id;
        this.session = session;
        this.handler = handler;
    }
}

public class ClientsManager {

    private Set<Client> clientSet = new CopyOnWriteArraySet<>();

    public Set<Client> getClients() {
        return this.clientSet;
    } 

    public void addClient(Client client) {
        this.clientSet.add(client);
    }

    public void removeClient(Client client) {
        clientSet.remove(client);
    }
}  

                    

public class WebsocketServerEndpoint         {

    public static final ClientsManager manageClients = new ClientsManager();

    @OnOpen
    public void onOpen(Session session, @PathParam("connectId") String connectId) throws IOException, EncodeException {

        MessageHandler messageHandler = new MessageHandler();
        Client client = new Client(connectId, session, messageHandler);
        this.client = client;
        manageClients.addClient(client);
    }
        ....
        ....
        ....
        ....

}

From another class:

public class DoSomething       {

        @Autowired
        WebsocketServerEndpoint serverEndpoint;

        public String doSomething()  {
        int numberOfClients = serverEndpoint.getClients().size()
        return numberOfClients;
       }
}

As I understand. This is not correct and you should not autowire static fields and so.

I can see when I debug that serverEndpoint: null in my DoSomething class but I get 1 connected client if I have one connected and so on.
When I do like this I will get the right number of clients in DoSomething class.
Have I just misunderstood this and it works as I have done?
or how should I do instead?
Is their a better way to write my Client and ClientsManager classes?

What I have read that if I would like to "Autowire" anyway there is two possible ways.

  1. Using Constructor @Autowired For Static Field
  2. Using @PostConstruct to set the value to Static Field

But how does this work when I would like to instantiate "public static final ClientsManager manageClients = new ClientsManager();"

Sorry for my stupid question but I feel I do not fully understand this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

酸甜透明夹心 2025-01-16 22:01:08

如果您想了解有关此主题的更多信息,请搜索 Spring 依赖注入,但我写了一个简短的总结。
为了能够 @Autowire 组件,您必须创建 @Bean 或 @Service 或 @Component。

  1. 创建bean首先创建一个Configuration类,以及里面的一个或多个Bean。

    <前><代码>@配置
    公共类配置{

    @Value("${configuration.property.name}")
    字符串用户名;

    @豆
    公共 WebsocketServerEndpoint ebsocketServerEndpoint () {
    返回新的 WebsocketServerEndpoint();
    }

    }

@Value 不是必需的,只需使用此注释就可以从 spring application.properties 文件中获取属性名称。

之后,您已经创建了类的 @Bean 实例,它被注册为单例类。您可以从应用程序中的任何位置获取这一副本类,只需自动装配它即可。

或者基于用户构造函数的依赖注入。 (@Autowired 不是首选)。

  1. 不要创建bean,只需将@Component注释添加到您想要Autowire的类中,但我显示了构造函数注入。

    <前><代码>@Component
    公共类WebsocketServerEndpoint {
    公共字符串测试(){
    返回“测试”;
    }
    }

    @RestController
    公共类DoSomething {

    私有最终WebsocketServerEndpoint websocketHandler;

    公共 DoSomething(WebsocketServerEndpoint websocketHandler) {
    this.websocketHandler = websocketHandler;
    }

    @GetMapping(值=“/测试”)
    公共字符串测试(){
    返回 websocketHandler.test();
    }
    }

您甚至可以使用curl GET 请求测试此端点。 卷曲http://localhost:8080/test

If you would like to understand more about this topic search for Spring Dependency injection, but I write a short summary.
To be able to @Autowire a component you have to create a @Bean or @Service or @Component.

  1. Creating beands first create a Configuration class, and a Beand or Beans inside.

    @Configuration
    public class Configuration {
    
           @Value("${configuration.property.name}")
           String username;
    
           @Bean
           public WebsocketServerEndpoint ebsocketServerEndpoint () {
              return new WebsocketServerEndpoint();
           }
    
    }
    

@Value is not necessaty just good to mention with this annotation you can get a property name from spring application.properties file.

After this point you have created a @Bean instance of your class it is registered as a singleton class. You can get this one copy class from anywhere in your application you just have to, autowire it.

Or user construcor based dependency injection. ( @Autowired is not prefered).

  1. Dont create beans just add @Component annotation to your class that you want to Autowire but I show a constructor injection.

    @Component
    public class WebsocketServerEndpoint {
        public String test(){
            return "test";
        }
    }
    
    @RestController
    public class DoSomething {
    
        private final WebsocketServerEndpoint websocketHandler;
    
        public DoSomething(WebsocketServerEndpoint websocketHandler) {
            this.websocketHandler = websocketHandler;
        }
    
        @GetMapping(value = "/test")
        public String test() {
            return websocketHandler.test();
        }
    }
    

You can even test this endpoint with a curl GET request. curl http://localhost:8080/test

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文