问题:
为了分析问题,我不得不编写一个简单的Java Web套接字客户端站点代码,并使用基于stomp的Web套接字代理连接到服务器端基于Spring的应用程序。
解决方案:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.rnd</groupId>
<artifactId>SockWebsocketClient</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.5</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>9.0.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.2.RELEASE</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>5.0.7.RELEASE</version>
</dependency>
</dependencies>
</project>
Sock JS客户端
它是主要的班级,是做基础工作的简单班级。 由于当今大多数Web套接字都打算使用SSL,因此尝试通过创建虚拟TrustManager来传递信任管理器问题。
此代码的输入是您要订阅的主题字符串。
另外,不要在运行前更改代码中的<URL>字符串,指向您的Web套接字url。
package com.client;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.messaging.converter.SimpleMessageConverter;
import org.springframework.messaging.converter.StringMessageConverter;
import org.springframework.messaging.simp.stomp.StompHeaders;
import org.springframework.web.socket.WebSocketHttpHeaders;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import org.springframework.web.socket.messaging.WebSocketStompClient;
import org.springframework.web.socket.sockjs.client.Transport;
import org.springframework.web.socket.sockjs.client.WebSocketTransport;
import org.springframework.web.socket.sockjs.frame.Jackson2SockJsMessageCodec;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class SockJsClient {
public static void main(String[] args) {
try {
StandardWebSocketClient simpleWebSocketClient = new StandardWebSocketClient();
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
Map<String, Object> properties = new HashMap<>();
properties.put("org.apache.tomcat.websocket.SSL_CONTEXT", sc);
simpleWebSocketClient.setUserProperties(properties);
List<Transport> transports = new ArrayList();
transports.add(new WebSocketTransport(simpleWebSocketClient));
org.springframework.web.socket.sockjs.client.SockJsClient sockJsClient = new org.springframework.web.socket.sockjs.client.SockJsClient(transports);
sockJsClient.setMessageCodec(new Jackson2SockJsMessageCodec());
WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);
stompClient.setMessageConverter(new MessageConverter() {
@Override
public Object fromMessage(Message<?> message, Class<?> aClass) {
return new String((byte[])message.getPayload());
}
@Override
public Message<?> toMessage(Object o, MessageHeaders messageHeaders) {
return null;
}
});
// url : pointing to websocket as sockJs first tries to get info by sending a HTTP request
// and then sends an upgrade request to ws or wss. So your url should be some thing like htttp://
URI stompUrlEndpoint = new URI("<url>");
WebSocketHttpHeaders handshakeHeaders = new WebSocketHttpHeaders();
StompHeaders connectHeaders = new StompHeaders();
/*Can set connection header like login , passcode in connectHeaders */
stompClient.connect(stompUrlEndpoint.toString(), handshakeHeaders, connectHeaders, new SessionHandler(args[0]), new Object[0]);
Thread.sleep(30000);
stompClient.stop();
} catch (Exception e) {
e.printStackTrace();
}
}
}
会话处理程序
每个套接字连接都需要一个会话处理程序,这里是一个用于处理连接设置和传入消息的会话处理程序。
package com.client;
import org.springframework.messaging.simp.stomp.StompCommand;
import org.springframework.messaging.simp.stomp.StompFrameHandler;
import org.springframework.messaging.simp.stomp.StompHeaders;
import org.springframework.messaging.simp.stomp.StompSession;
import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter;
import java.lang.reflect.Type;
public class SessionHandler extends StompSessionHandlerAdapter {
private final String topicName ;
public SessionHandler(String topicName) {
this.topicName = topicName;
}
@Override
public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
this.subscribeTo(session);
}
@Override
public void handleException(StompSession session,StompCommand command,StompHeaders headers,byte[] payload,Throwable exception ) {
exception.printStackTrace();
}
public void handleFrame(StompHeaders headers, Object payload) {
System.out.println(payload.toString());
}
@Override
public void handleTransportError(StompSession session, Throwable exception) {
exception.printStackTrace();
}
private void subscribeTo(StompSession session) {
StompHeaders headers = new StompHeaders();
headers.add("id","websocket-session-standalone-0");
headers.add("destination",topicName);
session.subscribe(headers, new StompFrameHandler() {
@Override
public Type getPayloadType(StompHeaders stompHeaders) {
return String.class;
}
@Override
public void handleFrame(StompHeaders stompHeaders, Object o) {
System.out.println( " Message is " +
o.toString()
);
}
});
}
}
翻译自: https://www.javacodegeeks.com/2019/08/web-socket-java-client-stomp-spring-server-side.html