8

我正在使用没有全新 JSR-356 WebSockets 支持的 Spring 3.2.5。

我想在我的@ServerEndpointWebSocket 服务器中有单例 bean 引用,它由 servlet 容器本身实例化,而不是在 Spring 上下文中。

什么是干净的方法?

我当前的解决方案:我@Service在静态字段中使用实例制作了单例 bean:

@Service
public class WebSocketSupportBean {
    private volatile static WebSocketSupportBean instance = null;

    public static WebSocketSupportBean getInstance() {
        return instance;
    }

    public WebSocketSupportBean() {
        instance = this;
    }

并且只是@ServerEndpoint通过静态方法获取它,如果返回 null 则断开用户连接(如果在服务器启动期间未创建 bean 但用户连接):

4

5 回答 5

7

您可以使用 spring framework 3.x 设置 websockets

我开发了一个小型概念验证应用程序来演示如何基于 Rossen Stoyanchev 随 spring-core 4.0 发布的 SpringConfiguration。

应用程序使用 uri 设置一个 websocket 服务器端点/wstest,它将使用一个@Autowiredspring bean 来选择一个问候词并回复一个 websocket 消息。

index.htmlwebsocket 连接由在支持 websocket 的浏览器中运行的 html 页面 ( ) 发起并发送消息。

Endpoint 注册由 ServletContextListener 在上下文初始化时进行,当端点被实例化时,它将与 spring 连接:

@WebListener
public class MyApplication implements ServletContextListener {

    private final static String SERVER_CONTAINER_ATTRIBUTE = "javax.websocket.server.ServerContainer";

    @Override
    public void contextInitialized(ServletContextEvent sce) {

        ServletContext container = sce.getServletContext();

        final ServerContainer serverContainer = (ServerContainer) container.getAttribute(SERVER_CONTAINER_ATTRIBUTE);
        try {
            serverContainer.addEndpoint(new MyEndpointConfig(MyEndpoint.class, "/wstest"));
        } catch (DeploymentException e) {
            e.printStackTrace();
        }
    }
}

端点是:

@Component
public class MyEndpoint extends Endpoint {

    @Autowired
    MyService myService;

    @Override
    public void onOpen(Session session, EndpointConfig config) {

        session.addMessageHandler(new MyMessageHandler(session));
    }


    class MyMessageHandler implements MessageHandler.Whole<String> {

        final Session session;

        public MyMessageHandler(Session session) {
            this.session = session;
        }

        @Override
        public void onMessage(String message) {
            try {
                String greeting = myService.getGreeting();
                session.getBasicRemote().sendText(greeting + ", got your message (" + message + "). Thanks ! (session: " + session.getId() + ")");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

在我的Github 页面上查看完整的源代码并准备好运行示例。

于 2014-03-20T19:26:05.087 回答
1

尝试

@ServerEndpoint(value = "/ws", configurator = SpringConfigurator.class)

并添加maven依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
</dependency>
于 2017-04-27T02:40:07.317 回答
1

您可以使您的 @ServerEndpoint 对象扩展 SpringBeanAutowiringSupport。然后让它知道在基于 Spring 的 Web 应用程序中构建的 bean,这种方式是:

  @PostConstruct
    public void init() {
        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
    }

这样@Autowired 注释将正确工作:

@Autowired MyService myService;
于 2017-06-16T09:34:13.537 回答
1

试试这个,它对我有用

@Component
@ServerEndpoint(value = "/instantMessageServer",configurator = SpringConfigurator.class)
public class InstantMessageServer{
private static IChatService chatService;
    @Autowired
    public InstantMessageServer(IChatService chatService){
        this.chatService = chatService;
    }
    public InstantMessageServer(){}
}

我在https://spring.io/blog/2013/05/23/spring-framework-4-0-m1-websocket-support上找到了这个解决方案, 但是还有一个小故障,用 @ServerEndpoint 注释的类无法获取 httpsession使用 SpringConfigurator,其中没有方法 modifyhandler 的覆盖。也许我们创建一个单独的 Configurator 扩展 SpringConfigurator 并覆盖该方法将是一种工作方式。我认为最好用 spring-websocket 和消息传递 api 构建一个实时 Web 应用程序。


public class ModifiedServerEndpointConfigurator extends SpringConfigurator{
    @Override
    public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
        HttpSession httpSession = (HttpSession) request.getHttpSession();
        sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
        super.modifyHandshake(sec, request, response);
    }
}
于 2018-02-18T02:15:30.350 回答
1

您必须在 spring 的配置中添加 bean 定义。

我发现集成 JSR 356 websocket 的解决方案@ServerEndpoint是通过 spring 关闭 Servlet 容器对 WebSocket 端点的扫描,这可以通过在 Spring 配置中注册 @Bean 来完成。到这个春天,spring STOMP websocket 不会覆盖普通的 JSR 356 websocket,它是 websocket 的一部分。

@ServerEndpoint(value="/chatMessage")
public class ChatEndpoint{
// Normal websocket body goes here.
}

在您的配置中添加 Bean:

@Configuration
public class WebsocketConfig{
  @Bean
  public ChatEndpoint chatEndpoint(){
     return new ChatEndpoint();
  }
  // main one is ServerEndpointExporter which prevents Servlet container's scan for WebSocket
  @Bean
  public ServerEndpointExporter endpointExporter(){
     return new ServerEndpointExporter();
  }
}

这一切都为你完成。但是你应该configurator = SpringConfigurator.class@ServerEndpoint. 我正在使用 Spring Websocket 4.0.0,它工作正常。你也可以看到这个链接

如果你没问题,那么也可以按照这个链接来了解概念。

请注意,通常您应该将 websocket 配置与 spring 的主要配置分开进行。

于 2018-08-15T13:30:20.360 回答