1.依赖导入

pom.xml


          
          
<!-- WebSocket 支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<!-- 文件上传解析器 -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.3</version>
</dependency>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

2.websocket后端配置

2.1WebSSHWebSocketConfig.java

          
          
@Configuration
@EnableWebSocket
public class WebSSHWebSocketConfig implements WebSocketConfigurer {
@Autowired
WebSSHWebSocketHandler webSSHWebSocketHandler;
@Override
public void registerWebSocketHandlers( WebSocketHandlerRegistry webSocketHandlerRegistry) {
//socket通道
//指定处理器和路径
webSocketHandlerRegistry. addHandler( webSSHWebSocketHandler, "/api/v1/webssh")
. addInterceptors( new WebSocketInterceptor())
. setAllowedOrigins( "*");
}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.

3.​处理器(Handler)和拦截器(Interceptor)的实现

3.1WebSSHWebSocketHandler.java

          
          
@Component
public class WebSSHWebSocketHandler implements WebSocketHandler {
@Autowired
private WebSSHService webSSHService;
private Logger logger = LoggerFactory. getLogger( WebSSHWebSocketHandler. class);

private static boolean bRunFlag;

private static List < AppInfo > appInfo;

@Override
public void afterConnectionEstablished( WebSocketSession webSocketSession) throws Exception {
logger. info( "用户:{},连接WebSSH", webSocketSession. getAttributes(). get( ConstantPool. USER_UUID_KEY));
//调用初始化连接
webSSHService. initConnection( webSocketSession);
}


public void close(){
bRunFlag = false;
}

/**
* @Description: 收到消息的回调
* @Param: [webSocketSession, webSocketMessage]
* @return: void
* @Author:
* @Date: 2020/8/10
*/
@Override
public void handleMessage( WebSocketSession webSocketSession, WebSocketMessage <?> webSocketMessage) throws Exception {
if ( webSocketMessage instanceof TextMessage) {
logger. info( "用户:{},发送命令:{}", webSocketSession. getAttributes(). get( ConstantPool. USER_UUID_KEY), webSocketMessage. toString());
//调用service接收消息
webSSHService. recvHandle((( TextMessage) webSocketMessage). getPayload(), webSocketSession);
} else if ( webSocketMessage instanceof BinaryMessage) {

} else if ( webSocketMessage instanceof PongMessage) {

} else {
System. out. println( "Unexpected WebSocket message type: " + webSocketMessage);
}
}

/**
* @Description: 出现错误的回调
* @Param: [webSocketSession, throwable]
* @return: void
* @Author:
* @Date: 2020/8/10
*/
@Override
public void handleTransportError( WebSocketSession webSocketSession, Throwable throwable) throws Exception {
logger. error( "数据传输错误:" + throwable. getMessage());
}

/**
* @Description: 连接关闭的回调
* @Param: [webSocketSession, closeStatus]
* @return: void
* @Author:
* @Date: 2020/8/10
*/
@Override
public void afterConnectionClosed( WebSocketSession webSocketSession, CloseStatus closeStatus) throws Exception {
logger. info( "用户:{}断开webssh连接", String. valueOf( webSocketSession. getAttributes(). get( ConstantPool. USER_UUID_KEY)));
//调用service关闭连接
webSSHService. close( webSocketSession);
}

@Override
public boolean supportsPartialMessages() {
return false;
}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
3.2WebSocketInterceptor.java

          
          
public class WebSocketInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake( ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map < String, Object > map) throws Exception {
if ( serverHttpRequest instanceof ServletServerHttpRequest) {
ServletServerHttpRequest request = ( ServletServerHttpRequest) serverHttpRequest;
//生成一个UUID
String uuid = UUID. randomUUID(). toString(). replace( "-", "");
//将uuid放到websocketsession中
map. put( ConstantPool. USER_UUID_KEY, uuid);
return true;
} else {
return false;
}
}

@Override
public void afterHandshake( ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {

}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 1.

4.WebSSH的业务逻辑实现(核心)

4.1WebSSHService.java

          
          
public interface WebSSHService {
public void setAppMap( Map < String, Map < String, Object >> map);

public Map < String, Map < String, Object >> getAppMap();


public void handleMsg ( PushMessage message);

public void setSwitch();


/**
* @Description: 初始化ssh连接
* @Param:
* @return:
* @Author:
* @Date:
*/
public void initConnection( WebSocketSession session);

/**
* @Description: 处理客户段发的数据
* @Param:
* @return:
* @Author:
* @Date:
*/
public void recvHandle( String buffer, WebSocketSession session);

/**
* @Description: 数据写回前端 for websocket
* @Param:
* @return:
* @Author:
* @Date:
*/
public void sendMessage( WebSocketSession session, byte[] buffer) throws IOException;

/**
* @Description: 关闭连接
* @Param:
* @return:
* @Author:
* @Date:
*/
public void close( WebSocketSession session);
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.

          
          
@Override
public void sendMessage( WebSocketSession session, byte[] buffer) throws IOException {
session. sendMessage( new TextMessage( buffer));
}
@Override
public void close( WebSocketSession session) {
String userId = String. valueOf( session. getAttributes(). get( ConstantPool. USER_UUID_KEY));
SSHConnectInfo sshConnectInfo = ( SSHConnectInfo) sshMap. get( userId);
if ( sshConnectInfo != null) {
//断开连接
if ( sshConnectInfo. getChannel() != null)
{
sshConnectInfo. getChannel(). disconnect();
}
//map中移除
sshMap. remove( userId);
}
}
/**
* @Description: 将消息转发到终端
* @Param: [channel, data]
* @return: void
* @Author:
* @Date:
*/
private void transToSSH( Channel channel, String command) throws IOException {
if ( channel != null) {
OutputStream outputStream = channel. getOutputStream();
outputStream. write( command. getBytes());
outputStream. flush();
}
}
@Override
public void recvHandle( String buffer, WebSocketSession session) {
ObjectMapper objectMapper = new ObjectMapper();
WebSSHData webSSHData = null;
try {
webSSHData = objectMapper. readValue( buffer, WebSSHData. class);
if( null == webSSHData || null == webSSHData. getAppId()){
logger. error( "传入数据为空或没有传appId");
session. sendMessage( new TextMessage( "传入数据为空或没有传appId"));
return;
}
} catch ( IOException e) {
logger. error( "Json转换异常");
logger. error( "异常信息:{}", e. getMessage());
return;
}
String appId = webSSHData. getAppId();
if( StringUtils. isEmpty( appId)){
close( session);
}
//设置appId
bRunFlag = true;
while ( bRunFlag){
//前端关闭会话、应该退出
if( null == session || ! session. isOpen()){
break;
}

//收到消息不用sleep
try{
if( bReceiveFlag){
if( null != appMap. get( appId)){
sendMsg( session, appId);
}
bReceiveFlag = false;
} else{
if( null != appMap. get( appId)){
sendMsg( session, appId);
}
Thread. sleep( 5000);
}
} catch ( IOException e){
e. printStackTrace();
}
catch ( InterruptedException e) {
e. printStackTrace();
}
}
//TODO
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.

5.在线平台测试功能

#yyds干货盘点#一个简单的websocket示例_ide