从后端java类在运行时连接到Web-Socket-Server

时间:2017-01-20 06:09:29

标签: java spring-websocket java-websocket

我使用spring实现了以下Web-Socket-Server。我们不想使用STOMP和JSocks。

@Configuration
@EnableWebSocket
public class WebSocketConfig implements WebSocketConfigurer {

  public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    registry.addHandler(new WebSocketServerHandler(), "/websocket/user/{userId}");
  }

}




@Service
public class WebSocketServerHandler extends TextWebSocketHandler {

   private List<WebSocketSession> sessions = new ArrayList<WebSocketSession>();

   @Override
   public void handleTextMessage(WebSocketSession session, TextMessage message)
        throws Exception {

        session.sendMessage(message);           
   }

   @Override
   public void afterConnectionEstablished(WebSocketSession session) throws Exception {
     sessions.add(session);
   }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
      sessions = null;
    }

}

现在我可以从前端客户端(浏览器)成功连接到该Web-Socket-Server。现在我想在运行时从我的一些java类连接到那个Web-Socket-Server,然后想要向该Web-Socket-Server发送消息。任何人都知道我该怎么办?

我添加了一个测试Rest Controller,如下所示:

 @RequestMapping(value = "/web-socket/message/{message}")
 public void sendMessage(@PathVariable("message") final String message) throws Exception {
   final String WS_URI = "ws://localhost:8080/web-socket/user/23";

   final CountDownLatch latch = new CountDownLatch(1);
   WebSocketClientHandler handler = new WebSocketClientHandler(latch);
   WebSocketClient client = new StandardWebSocketClient();
   WebSocketSession session = client.doHandshake(handler, WS_URI).get();
   session.sendMessage(new TextMessage(message));
   latch.await(5, TimeUnit.SECONDS);
   session.close();

}

我成功地能够向websocket服务器发送消息,只是第一次通过使用谷歌休息客户端调用此测试RestController。如果我需要再次发送消息,那么我必须重新启动tomcat服务器。我在这里做的有什么不对吗?

1 个答案:

答案 0 :(得分:4)

spring-websocket具有WebSocket客户端支持。基本合同是WebSocketClient。 Spring并没有实现整个WebSocket支持,但提供了一个覆盖其他实现的抽象层。常见的Spring客户端抽象是StandardWebSocketClient。一个简单的例子看起来像

public static void main(String... args) throws Exception {
    final CountDownLatch latch = new CountDownLatch(1);
    EchoHandler handler = new EchoHandler(latch);
    WebSocketClient client = new StandardWebSocketClient();
    WebSocketSession session = client.doHandshake(handler, ECHO_URL).get();
    session.sendMessage(new TextMessage("Hello World"));
    latch.await(5000, TimeUnit.SECONDS);
    session.close();
}

EchoHandler是客户端WebSocketHandler(与服务器端相同)。

public class EchoHandler extends TextWebSocketHandler {

    private final CountDownLatch latch;

    public EchoHandler(CountDownLatch latch) {
        this.latch = latch;
    }

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        System.out.println("------- received client message ------");
        System.out.println(message.getPayload());
        System.out.println("--------- end client message ---------");
        latch.countDown();
    }
}

如果在String环境中运行客户端,也可以将WebSocketClient包装在WebSocketConnectionManager中。如果需要,这将为您提供一些生命周期助手。请参阅Spring Boot sample中的示例。

就像我说的那样依赖于依赖关系,Spring并没有实现整个WebSocket客户端支持,所以你需要一个实现。如果您在支持WebSocket的服务器中运行客户端,则无需添加任何内容。支持实现应该已经在服务器的类路径中。主要支持的WebSocket实现是Jetty,Tomcat,Undertow(主要是Wildfly或独立的Undertow),Tyrus(即Glassfish,WebLogic)。

如果您在独立应用程序中运行客户端,则需要添加WebSocket实现。不幸的是,根据我的测试,没有一个实现提供完整可行的&#34;仅客户端&#34;罐。他们要么已经或已经完成了(包括服务器)实现。因此,仅使用客户端,仍然需要拉入一堆服务器罐。这是我从测试中得出的结果

所有

共同
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-websocket</artifactId>
    <version>${spring.version}</version>
</dependency>
<dependency>
    <groupId>javax.websocket</groupId>
    <artifactId>javax.websocket-api</artifactId>
    <version>${websocket.version}</version>
</dependency>

<强> Tomcat的

<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-websocket</artifactId>
    <version>${tomcat.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-core</artifactId>
    <version>${tomcat.version}</version>
</dependency>

<强>暗流

<dependency>
    <groupId>io.undertow</groupId>
    <artifactId>undertow-websockets-jsr</artifactId>
    <version>${undertow.version}</version>
</dependency>

<强>泰鲁斯

<!-- tyrus-client is pulled in by this. -->
<dependency>
    <groupId>org.glassfish.tyrus</groupId>
    <artifactId>tyrus-server</artifactId>
    <version>${tyrus.version}</version>
</dependency>

<强>码头

<dependency>
    <groupId>org.eclipse.jetty.websocket</groupId>
    <artifactId>websocket-client</artifactId>
    <version>${jetty.version}</version>
</dependency>

使用Jetty,它不使用标准的Java WebSocket API,因此StandardWebSocketClient中没有使用它。你需要做的是

JettyWebSocketClient client = new JettyWebSocketClient();
client.start();

上面的其他所有内容都是相同的。

我只是看了一下Spring源代码,看看他们使用的所有不同依赖项。您可以查看它并使用依赖项。也许有更多有效(更轻)的依赖关系组合仍然有效。以上就是我测试过的,并且能够开始工作。