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

How to create a Websocket SessionManager that are reachable from other classes

我正在开发一个带有 WebSocket 的应用程序,我想将客户端 ID 和会话保存到管理器中,但是当我还希望能够从另一个服务器访问它时,我很难理解如何正确地做到这一点 class 自动装配。

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);
    }
        ....
        ....
        ....
        ....

}

来自另一个 class:

public class DoSomething       {

        @Autowired
        WebsocketServerEndpoint serverEndpoint;

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

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

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

据我所知,如果无论如何我都想“自动装配”,有两种可能的方法。

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

但是,当我想实例化“public static final ClientsManager manageClients = new ClientsManager();”

时,这是如何工作的?

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

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

  1. 创建beand首先创建一个Configurationclass,然后在里面创建一个Beand或Beans

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

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

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

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

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

    @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();
        }
    }
    

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