[fix] change

This commit is contained in:
wujiawei
2024-05-29 10:46:07 +08:00
parent 2a0f58f0d1
commit 617e214bd9
307 changed files with 27 additions and 27 deletions

View File

@ -0,0 +1,22 @@
FROM registry.cn-hangzhou.aliyuncs.com/wu-lazy/wu-framework-parent:jdk-17.0.7-x64
MAINTAINER wujiawei <1207537021@qq.com>
RUN echo "Asia/Shanghai" > /etc/timezone
ENV APP_JAR_NAME=$APP_NAME \
JAVA_OPTS="-Xms512m -Xmx1024m -Djava.security.egd=file:/dev/./urandom" \
PARAMS=""
COPY target/*.jar /app.jar
ENTRYPOINT exec java -server $JAVA_OPTS -jar /app.jar $PARAMS

View File

@ -0,0 +1,16 @@
FROM alpine
MAINTAINER wujiawei <1207537021@qq.com>
RUN echo "Asia/Shanghai" > /etc/timezone
COPY target/lazy-cloud-heartbeat-client /native-app
ENTRYPOINT ["/bin/sh" ,"-c", "exec ./native-app"]

View File

@ -0,0 +1,55 @@
#### 构建native 镜像
```shell
mvn clean compile
mvn spring-boot:process-aot -Pnative
mvn native:build -Pnative
```
### 构建docker镜像
```shell
docker build -t docker-registry.wujiawei.com/lazy/lazy-under-cloud-heartbeat-client:lazy-2.4.2-native-SNAPSHOT_latest -f Native-Dockerfile .
docker push docker-registry.wujiawei.com/lazy/lazy-under-cloud-heartbeat-client:lazy-2.4.2-native-SNAPSHOT_latest
```
## BUILD IMAGE
```shell
#docker login --username=1207537021@qq.com registry.cn-hangzhou.aliyuncs.com
docker build -t registry.cn-hangzhou.aliyuncs.com/wu-lazy/wu-smart-agent-network-heartbeat-client:server-jdk17-master .
docker push registry.cn-hangzhou.aliyuncs.com/wu-lazy/wu-smart-agent-network-heartbeat-client:server-jdk17-master
```
### run
```shell
docker run -d -it --name client -e spring.lazy.netty.inet-host=124.222.48.62 -e spring.lazy.netty.inet-port=30676 -e spring.lazy.netty.client-id=node1 registry.cn-hangzhou.aliyuncs.com/wu-lazy/wu-smart-agent-network-heartbeat-client:server-jdk17-master
```
```shell
gu install native-image
gu list
mvn native:build
```
```shell
mvn clean native:compile -Pnative
```
```RUN
docker run -d -it -p 18080:18080 --name wu-smart-agent-network-heartbeat-client registry.cn-hangzhou.aliyuncs.com/wu-lazy/wu-smart-agent-network-heartbeat-client:server-jdk17-master
http://127.0.0.1:18080/swagger-ui/index.html
```

View File

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>top.wu2020</groupId>
<artifactId>wu-smart-agent-network</artifactId>
<version>1.2.6-JDK17-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>wu-lazy-cloud-heartbeat-client</artifactId>
<description>云下心跳客户端</description>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<!-- 通用心跳包 -->
<dependency>
<groupId>top.wu2020</groupId>
<artifactId>wu-lazy-cloud-heartbeat-common</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.50</version>
</dependency>
<dependency>
<groupId>top.wu2020</groupId>
<artifactId>wu-framework-web-spring-starter</artifactId>
</dependency>
<!-- h2数据库驱动 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>top.wu2020</groupId>
<artifactId>wu-database-lazy-plus-starter</artifactId>
</dependency>
</dependencies>
<repositories>
<repository>
<id>maven_central</id>
<name>Maven Central</name>
<url>https://repo.maven.apache.org/maven2/</url>
</repository>
</repositories>
</project>

View File

@ -0,0 +1,9 @@
package org.framework.smart.agent.network.heartbeat.client;
import org.springframework.context.annotation.ComponentScan;
import org.wu.framework.lazy.orm.core.stereotype.LazyScan;
@ComponentScan(basePackages = "org.framework.smart.agent.network.heartbeat.client")
@LazyScan(scanBasePackages = "org.framework.smart.agent.network.heartbeat.client.infrastructure.entity")
public class EnableHeartbeatClientAutoConfiguration {
}

View File

@ -0,0 +1,54 @@
package org.framework.smart.agent.network.heartbeat.client.application;
import org.framework.smart.agent.network.heartbeat.client.netty.event.ClientChangeEvent;
/**
* 客户端状态变更事件
* @see ClientChangeEvent
*/
@Deprecated
public interface ClientChangeApplication {
/**
* 推送客户端在线
*/
void clientOnLine(String clientId);
/**
* 推送客户端在线
* @param clientId 客户端
* @param inetHost 服务端ip
* @param inetPort 服务端端口
*/
void clientOnLine(String inetHost, int inetPort,String clientId);
/**
* 推送客户端离线
*/
void clientOffLine(String clientId);
/**
* 推送客户端离线
* @param clientId 客户端
* @param inetHost 服务端ip
* @param inetPort 服务端端口
*/
void clientOffLine(String inetHost, int inetPort,String clientId);
/**
* 暂存开启
*
* @param clientId 租户ID
*/
void stagingOpen(String clientId);
/**
* 暂存关闭
*
* @param clientId 客户端ID 对应的租户
*/
void stagingClose(String clientId);
}

View File

@ -0,0 +1,128 @@
package org.framework.smart.agent.network.heartbeat.client.application;
import org.wu.framework.web.response.Result;
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesRemoveCommand;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesStoryCommand;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesUpdateCommand;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesQueryListCommand;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesQueryOneCommand;
import org.framework.smart.agent.network.heartbeat.client.application.dto.LazyNettyServerPropertiesDTO;
import java.util.List;
import org.wu.framework.lazy.orm.database.lambda.domain.LazyPage;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyApplication
**/
public interface LazyNettyServerPropertiesApplication {
/**
* describe 新增服务端配置信息
*
* @param lazyNettyServerPropertiesStoryCommand 新增服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息新增后领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
Result<LazyNettyServerProperties> story(LazyNettyServerPropertiesStoryCommand lazyNettyServerPropertiesStoryCommand);
/**
* describe 批量新增服务端配置信息
*
* @param lazyNettyServerPropertiesStoryCommandList 批量新增服务端配置信息
* @return {@link Result<List<LazyNettyServerProperties>>} 服务端配置信息新增后领域对象集合
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
Result<List<LazyNettyServerProperties>> batchStory(List<LazyNettyServerPropertiesStoryCommand> lazyNettyServerPropertiesStoryCommandList);
/**
* describe 更新服务端配置信息
*
* @param lazyNettyServerPropertiesUpdateCommand 更新服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
Result<LazyNettyServerProperties> updateOne(LazyNettyServerPropertiesUpdateCommand lazyNettyServerPropertiesUpdateCommand);
/**
* describe 查询单个服务端配置信息
*
* @param lazyNettyServerPropertiesQueryOneCommand 查询单个服务端配置信息
* @return {@link Result<LazyNettyServerPropertiesDTO>} 服务端配置信息DTO对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
Result<LazyNettyServerPropertiesDTO> findOne(LazyNettyServerPropertiesQueryOneCommand lazyNettyServerPropertiesQueryOneCommand);
/**
* describe 查询多个服务端配置信息
*
* @param lazyNettyServerPropertiesQueryListCommand 查询多个服务端配置信息
* @return {@link Result <List<LazyNettyServerPropertiesDTO>>} 服务端配置信息DTO对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
Result<List<LazyNettyServerPropertiesDTO>> findList(LazyNettyServerPropertiesQueryListCommand lazyNettyServerPropertiesQueryListCommand);
/**
* describe 分页查询多个服务端配置信息
*
* @param lazyNettyServerPropertiesQueryListCommand 分页查询多个服务端配置信息
* @return {@link Result <LazyPage<LazyNettyServerPropertiesDTO>>} 分页服务端配置信息DTO对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
Result<LazyPage<LazyNettyServerPropertiesDTO>> findPage(int size, int current, LazyNettyServerPropertiesQueryListCommand lazyNettyServerPropertiesQueryListCommand);
/**
* describe 删除服务端配置信息
*
* @param lazyNettyServerPropertiesRemoveCommand 删除服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
Result<LazyNettyServerProperties> remove(LazyNettyServerPropertiesRemoveCommand lazyNettyServerPropertiesRemoveCommand);
/**
* 启动socket
*
* @param lazyNettyServerProperties 配置
*/
void starterOneClientSocket(LazyNettyServerProperties lazyNettyServerProperties);
/**
* 启动所有 配置的socket
*/
void starterAllClientSocket();
/**
* 关闭 客户端socket
* @param needCloseLazyNettyServerProperties 配置
*/
void destroyOneClientSocket(LazyNettyServerProperties needCloseLazyNettyServerProperties);
/**
* 关闭 客户端socket
*/
void destroyClientSocket();
}

View File

@ -0,0 +1,93 @@
package org.framework.smart.agent.network.heartbeat.client.application.assembler;
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesRemoveCommand;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesStoryCommand;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesUpdateCommand;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesQueryListCommand;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesQueryOneCommand;
import org.framework.smart.agent.network.heartbeat.client.application.dto.LazyNettyServerPropertiesDTO;
import org.mapstruct.factory.Mappers;
import org.mapstruct.Mapper;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyAssembler
**/
@Mapper
public interface LazyNettyServerPropertiesDTOAssembler {
/**
* describe MapStruct 创建的代理对象
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
LazyNettyServerPropertiesDTOAssembler INSTANCE = Mappers.getMapper(LazyNettyServerPropertiesDTOAssembler.class);
/**
* describe 应用层存储入参转换成 领域对象
*
* @param lazyNettyServerPropertiesStoryCommand 保存服务端配置信息对象
* @return {@link LazyNettyServerProperties} 服务端配置信息领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
LazyNettyServerProperties toLazyNettyServerProperties(LazyNettyServerPropertiesStoryCommand lazyNettyServerPropertiesStoryCommand);
/**
* describe 应用层更新入参转换成 领域对象
*
* @param lazyNettyServerPropertiesUpdateCommand 更新服务端配置信息对象
* @return {@link LazyNettyServerProperties} 服务端配置信息领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
LazyNettyServerProperties toLazyNettyServerProperties(LazyNettyServerPropertiesUpdateCommand lazyNettyServerPropertiesUpdateCommand);
/**
* describe 应用层查询入参转换成 领域对象
*
* @param lazyNettyServerPropertiesQueryOneCommand 查询单个服务端配置信息对象参数
* @return {@link LazyNettyServerProperties} 服务端配置信息领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
LazyNettyServerProperties toLazyNettyServerProperties(LazyNettyServerPropertiesQueryOneCommand lazyNettyServerPropertiesQueryOneCommand);
/**
* describe 应用层查询入参转换成 领域对象
*
* @param lazyNettyServerPropertiesQueryListCommand 查询集合服务端配置信息对象参数
* @return {@link LazyNettyServerProperties} 服务端配置信息领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
LazyNettyServerProperties toLazyNettyServerProperties(LazyNettyServerPropertiesQueryListCommand lazyNettyServerPropertiesQueryListCommand);
/**
* describe 应用层删除入参转换成 领域对象
*
* @param lazyNettyServerPropertiesRemoveCommand 删除服务端配置信息对象参数
* @return {@link LazyNettyServerProperties} 服务端配置信息领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
LazyNettyServerProperties toLazyNettyServerProperties(LazyNettyServerPropertiesRemoveCommand lazyNettyServerPropertiesRemoveCommand);
/**
* describe 持久层领域对象转换成DTO对象
*
* @param lazyNettyServerProperties 服务端配置信息领域对象
* @return {@link LazyNettyServerPropertiesDTO} 服务端配置信息DTO对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
LazyNettyServerPropertiesDTO fromLazyNettyServerProperties(LazyNettyServerProperties lazyNettyServerProperties);
}

View File

@ -0,0 +1,77 @@
package org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties;
import lombok.Data;
import lombok.experimental.Accessors;
import io.swagger.v3.oas.annotations.media.Schema;
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
import java.lang.String;
import java.time.LocalDateTime;
import java.lang.Integer;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyQueryListCommand
**/
@Data
@Accessors(chain = true)
@Schema(title = "lazy_netty_server_properties_query_List_command",description = "服务端配置信息")
public class LazyNettyServerPropertiesQueryListCommand {
/**
*
* 客户身份ID
*/
@Schema(description ="客户身份ID",name ="clientId",example = "")
private String clientId;
/**
*
* 状态(on_line、off_line)
*/
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
private NettyClientStatus connectStatus;
/**
*
* 创建时间
*/
@Schema(description ="创建时间",name ="createTime",example = "")
private LocalDateTime createTime;
/**
*
* 服务端host
*/
@Schema(description ="服务端host",name ="inetHost",example = "")
private String inetHost;
/**
*
* 服务端端口
*/
@Schema(description ="服务端端口",name ="inetPort",example = "")
private Integer inetPort;
/**
*
* 类型配置、DB
*/
@Schema(description ="类型配置、DB",name ="type",example = "")
private PropertiesType type;
/**
*
* 更新时间
*/
@Schema(description ="更新时间",name ="updateTime",example = "")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,76 @@
package org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties;
import lombok.Data;
import lombok.experimental.Accessors;
import io.swagger.v3.oas.annotations.media.Schema;
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
import java.lang.String;
import java.time.LocalDateTime;
import java.lang.Integer;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyQueryOneCommand
**/
@Data
@Accessors(chain = true)
@Schema(title = "lazy_netty_server_properties_query_one_command",description = "服务端配置信息")
public class LazyNettyServerPropertiesQueryOneCommand {
/**
*
* 客户身份ID
*/
@Schema(description ="客户身份ID",name ="clientId",example = "")
private String clientId;
/**
*
* 状态(on_line、off_line)
*/
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
private NettyClientStatus connectStatus;
/**
*
* 创建时间
*/
@Schema(description ="创建时间",name ="createTime",example = "")
private LocalDateTime createTime;
/**
*
* 服务端host
*/
@Schema(description ="服务端host",name ="inetHost",example = "")
private String inetHost;
/**
*
* 服务端端口
*/
@Schema(description ="服务端端口",name ="inetPort",example = "")
private Integer inetPort;
/**
*
* 类型配置、DB
*/
@Schema(description ="类型配置、DB",name ="type",example = "")
private PropertiesType type;
/**
*
* 更新时间
*/
@Schema(description ="更新时间",name ="updateTime",example = "")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,77 @@
package org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties;
import lombok.Data;
import lombok.experimental.Accessors;
import io.swagger.v3.oas.annotations.media.Schema;
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
import java.lang.String;
import java.time.LocalDateTime;
import java.lang.Integer;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyRemoveCommand
**/
@Data
@Accessors(chain = true)
@Schema(title = "lazy_netty_server_properties_remove_command",description = "服务端配置信息")
public class LazyNettyServerPropertiesRemoveCommand {
/**
*
* 客户身份ID
*/
@Schema(description ="客户身份ID",name ="clientId",example = "")
private String clientId;
/**
*
* 状态(on_line、off_line)
*/
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
private NettyClientStatus connectStatus;
/**
*
* 创建时间
*/
@Schema(description ="创建时间",name ="createTime",example = "")
private LocalDateTime createTime;
/**
*
* 服务端host
*/
@Schema(description ="服务端host",name ="inetHost",example = "")
private String inetHost;
/**
*
* 服务端端口
*/
@Schema(description ="服务端端口",name ="inetPort",example = "")
private Integer inetPort;
/**
*
* 类型配置、DB
*/
@Schema(description ="类型配置、DB",name ="type",example = "")
private PropertiesType type;
/**
*
* 更新时间
*/
@Schema(description ="更新时间",name ="updateTime",example = "")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,76 @@
package org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties;
import lombok.Data;
import lombok.experimental.Accessors;
import io.swagger.v3.oas.annotations.media.Schema;
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
import java.lang.String;
import java.time.LocalDateTime;
import java.lang.Integer;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyStoryCommand
**/
@Data
@Accessors(chain = true)
@Schema(title = "lazy_netty_server_properties_story_command",description = "服务端配置信息")
public class LazyNettyServerPropertiesStoryCommand {
/**
*
* 客户身份ID
*/
@Schema(description ="客户身份ID",name ="clientId",example = "")
private String clientId;
/**
*
* 状态(on_line、off_line)
*/
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
private NettyClientStatus connectStatus;
/**
*
* 创建时间
*/
@Schema(description ="创建时间",name ="createTime",example = "")
private LocalDateTime createTime;
/**
*
* 服务端host
*/
@Schema(description ="服务端host",name ="inetHost",example = "")
private String inetHost;
/**
*
* 服务端端口
*/
@Schema(description ="服务端端口",name ="inetPort",example = "")
private Integer inetPort;
/**
*
* 类型配置、DB
*/
@Schema(description ="类型配置、DB",name ="type",example = "")
private PropertiesType type;
/**
*
* 更新时间
*/
@Schema(description ="更新时间",name ="updateTime",example = "")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,76 @@
package org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties;
import lombok.Data;
import lombok.experimental.Accessors;
import io.swagger.v3.oas.annotations.media.Schema;
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
import java.lang.String;
import java.time.LocalDateTime;
import java.lang.Integer;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyUpdateCommand
**/
@Data
@Accessors(chain = true)
@Schema(title = "lazy_netty_server_properties_update_command",description = "服务端配置信息")
public class LazyNettyServerPropertiesUpdateCommand {
/**
*
* 客户身份ID
*/
@Schema(description ="客户身份ID",name ="clientId",example = "")
private String clientId;
/**
*
* 状态(on_line、off_line)
*/
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
private NettyClientStatus connectStatus;
/**
*
* 创建时间
*/
@Schema(description ="创建时间",name ="createTime",example = "")
private LocalDateTime createTime;
/**
*
* 服务端host
*/
@Schema(description ="服务端host",name ="inetHost",example = "")
private String inetHost;
/**
*
* 服务端端口
*/
@Schema(description ="服务端端口",name ="inetPort",example = "")
private Integer inetPort;
/**
*
* 类型配置、DB
*/
@Schema(description ="类型配置、DB",name ="type",example = "")
private PropertiesType type;
/**
*
* 更新时间
*/
@Schema(description ="更新时间",name ="updateTime",example = "")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,76 @@
package org.framework.smart.agent.network.heartbeat.client.application.dto;
import lombok.Data;
import lombok.experimental.Accessors;
import io.swagger.v3.oas.annotations.media.Schema;
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
import java.lang.String;
import java.time.LocalDateTime;
import java.lang.Integer;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyDTO
**/
@Data
@Accessors(chain = true)
@Schema(title = "lazy_netty_server_properties_command_dto",description = "服务端配置信息")
public class LazyNettyServerPropertiesDTO {
/**
*
* 客户身份ID
*/
@Schema(description ="客户身份ID",name ="clientId",example = "")
private String clientId;
/**
*
* 状态(on_line、off_line)
*/
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
private NettyClientStatus connectStatus;
/**
*
* 创建时间
*/
@Schema(description ="创建时间",name ="createTime",example = "")
private LocalDateTime createTime;
/**
*
* 服务端host
*/
@Schema(description ="服务端host",name ="inetHost",example = "")
private String inetHost;
/**
*
* 服务端端口
*/
@Schema(description ="服务端端口",name ="inetPort",example = "")
private Integer inetPort;
/**
*
* 类型配置、DB
*/
@Schema(description ="类型配置、DB",name ="type",example = "")
private PropertiesType type;
/**
*
* 更新时间
*/
@Schema(description ="更新时间",name ="updateTime",example = "")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,270 @@
package org.framework.smart.agent.network.heartbeat.client.application.impl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.client.application.LazyNettyServerPropertiesApplication;
import org.framework.smart.agent.network.heartbeat.client.application.assembler.LazyNettyServerPropertiesDTOAssembler;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.*;
import org.framework.smart.agent.network.heartbeat.client.application.dto.LazyNettyServerPropertiesDTO;
import org.framework.smart.agent.network.heartbeat.client.config.NettyClientProperties;
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerPropertiesRepository;
import org.framework.smart.agent.network.heartbeat.client.netty.event.ClientChangeEvent;
import org.framework.smart.agent.network.heartbeat.client.netty.socket.NettyClientSocket;
import org.framework.smart.agent.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
import org.wu.framework.core.NormalUsedString;
import org.wu.framework.database.lazy.web.plus.stereotype.LazyApplication;
import org.wu.framework.lazy.orm.database.lambda.domain.LazyPage;
import org.wu.framework.web.response.Result;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyApplicationImpl
**/
@Slf4j
@LazyApplication
public class LazyNettyServerPropertiesApplicationImpl implements LazyNettyServerPropertiesApplication {
@Resource
LazyNettyServerPropertiesRepository lazyNettyServerPropertiesRepository;
@Resource
private ClientChangeEvent clientChangeEvent;
@Resource
private List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList; // 处理服务端发送过来的数据类型
@Resource
private NettyClientProperties nettyClientProperties;// 默认配置文件配置
// 缓存连接socket
private final ConcurrentHashMap<LazyNettyServerProperties, NettyClientSocket> cacheNettyClientSocketMap = new ConcurrentHashMap<>();
public static final ThreadPoolExecutor NETTY_CLIENT_EXECUTOR =
new ThreadPoolExecutor(20, 50, 200, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(1));
/**
* describe 新增服务端配置信息
*
* @param lazyNettyServerPropertiesStoryCommand 新增服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息新增后领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Override
public Result<LazyNettyServerProperties> story(LazyNettyServerPropertiesStoryCommand lazyNettyServerPropertiesStoryCommand) {
LazyNettyServerProperties lazyNettyServerProperties = LazyNettyServerPropertiesDTOAssembler.INSTANCE.toLazyNettyServerProperties(lazyNettyServerPropertiesStoryCommand);
// 如果状态正在运行中直接忽略
lazyNettyServerPropertiesRepository.exists(lazyNettyServerProperties)
.accept(exists -> {
if (!exists) {
starterOneClientSocket(lazyNettyServerProperties);
}
});
lazyNettyServerProperties.setType(PropertiesType.DB);
return lazyNettyServerPropertiesRepository.story(lazyNettyServerProperties);
}
/**
* describe 批量新增服务端配置信息
*
* @param lazyNettyServerPropertiesStoryCommandList 批量新增服务端配置信息
* @return {@link Result<List<LazyNettyServerProperties>>} 服务端配置信息新增后领域对象集合
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Override
public Result<List<LazyNettyServerProperties>> batchStory(List<LazyNettyServerPropertiesStoryCommand> lazyNettyServerPropertiesStoryCommandList) {
List<LazyNettyServerProperties> lazyNettyServerPropertiesList = lazyNettyServerPropertiesStoryCommandList.stream().map(LazyNettyServerPropertiesDTOAssembler.INSTANCE::toLazyNettyServerProperties).collect(Collectors.toList());
return lazyNettyServerPropertiesRepository.batchStory(lazyNettyServerPropertiesList);
}
/**
* describe 更新服务端配置信息
*
* @param lazyNettyServerPropertiesUpdateCommand 更新服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Override
public Result<LazyNettyServerProperties> updateOne(LazyNettyServerPropertiesUpdateCommand lazyNettyServerPropertiesUpdateCommand) {
LazyNettyServerProperties lazyNettyServerProperties = LazyNettyServerPropertiesDTOAssembler.INSTANCE.toLazyNettyServerProperties(lazyNettyServerPropertiesUpdateCommand);
return lazyNettyServerPropertiesRepository.story(lazyNettyServerProperties);
}
/**
* describe 查询单个服务端配置信息
*
* @param lazyNettyServerPropertiesQueryOneCommand 查询单个服务端配置信息
* @return {@link Result<LazyNettyServerPropertiesDTO>} 服务端配置信息DTO对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Override
public Result<LazyNettyServerPropertiesDTO> findOne(LazyNettyServerPropertiesQueryOneCommand lazyNettyServerPropertiesQueryOneCommand) {
LazyNettyServerProperties lazyNettyServerProperties = LazyNettyServerPropertiesDTOAssembler.INSTANCE.toLazyNettyServerProperties(lazyNettyServerPropertiesQueryOneCommand);
return lazyNettyServerPropertiesRepository.findOne(lazyNettyServerProperties).convert(LazyNettyServerPropertiesDTOAssembler.INSTANCE::fromLazyNettyServerProperties);
}
/**
* describe 查询多个服务端配置信息
*
* @param lazyNettyServerPropertiesQueryListCommand 查询多个服务端配置信息
* @return {@link Result<List<LazyNettyServerPropertiesDTO>>} 服务端配置信息DTO对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Override
public Result<List<LazyNettyServerPropertiesDTO>> findList(LazyNettyServerPropertiesQueryListCommand lazyNettyServerPropertiesQueryListCommand) {
LazyNettyServerProperties lazyNettyServerProperties = LazyNettyServerPropertiesDTOAssembler.INSTANCE.toLazyNettyServerProperties(lazyNettyServerPropertiesQueryListCommand);
return lazyNettyServerPropertiesRepository.findList(lazyNettyServerProperties).convert(lazyNettyServerPropertiess -> lazyNettyServerPropertiess.stream().map(LazyNettyServerPropertiesDTOAssembler.INSTANCE::fromLazyNettyServerProperties).collect(Collectors.toList()));
}
/**
* describe 分页查询多个服务端配置信息
*
* @param lazyNettyServerPropertiesQueryListCommand 分页查询多个服务端配置信息
* @return {@link Result<LazyPage<LazyNettyServerPropertiesDTO>>} 分页服务端配置信息DTO对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Override
public Result<LazyPage<LazyNettyServerPropertiesDTO>> findPage(int size, int current, LazyNettyServerPropertiesQueryListCommand lazyNettyServerPropertiesQueryListCommand) {
LazyNettyServerProperties lazyNettyServerProperties = LazyNettyServerPropertiesDTOAssembler.INSTANCE.toLazyNettyServerProperties(lazyNettyServerPropertiesQueryListCommand);
return lazyNettyServerPropertiesRepository.findPage(size, current, lazyNettyServerProperties).convert(page -> page.convert(LazyNettyServerPropertiesDTOAssembler.INSTANCE::fromLazyNettyServerProperties));
}
/**
* describe 删除服务端配置信息
*
* @param lazyNettyServerPropertiesRemoveCommand 删除服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Override
public Result<LazyNettyServerProperties> remove(LazyNettyServerPropertiesRemoveCommand lazyNettyServerPropertiesRemoveCommand) {
LazyNettyServerProperties lazyNettyServerProperties = LazyNettyServerPropertiesDTOAssembler.INSTANCE.toLazyNettyServerProperties(lazyNettyServerPropertiesRemoveCommand);
// 关闭连接
destroyOneClientSocket(lazyNettyServerProperties);
return lazyNettyServerPropertiesRepository.remove(lazyNettyServerProperties);
}
/**
* 启动socket
*
* @param lazyNettyServerProperties 配置
*/
@Override
public void starterOneClientSocket(LazyNettyServerProperties lazyNettyServerProperties) {
boolean enabled = nettyClientProperties.isEnabled();
if (enabled) {
String inetHost = lazyNettyServerProperties.getInetHost();
Integer inetPort = lazyNettyServerProperties.getInetPort();
String clientId = lazyNettyServerProperties.getClientId();
NettyClientSocket nettyClientSocket = new
NettyClientSocket(inetHost, inetPort, clientId,
NormalUsedString.DEFAULT,
clientChangeEvent, handleChannelTypeAdvancedList);
cacheNettyClientSocketMap.put(lazyNettyServerProperties, nettyClientSocket);
// 更新状态为运行中
lazyNettyServerProperties.setConnectStatus(NettyClientStatus.RUNNING);
lazyNettyServerPropertiesRepository.story(lazyNettyServerProperties);
Thread thread = new Thread(() -> {
try {
nettyClientSocket.newConnect2Server();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
// 当前服务连接Netty客户端:{},Netty端口:{}
log.info("Current service connection Netty client: {}, Netty port: {}", inetHost, inetPort);
NETTY_CLIENT_EXECUTOR.execute(thread);
}
}
/**
* 启动所有 配置的socket
*/
@Override
public void starterAllClientSocket() {
boolean enabled = nettyClientProperties.isEnabled();
if (enabled) {
// 查询所有配置
lazyNettyServerPropertiesRepository.findList(new LazyNettyServerProperties()).accept(lazyNettyServerPropertiesDTOS -> {
for (LazyNettyServerProperties nettyServerProperties : lazyNettyServerPropertiesDTOS) {
starterOneClientSocket(nettyServerProperties);
}
});
}
}
/**
* 关闭 客户端socket
*
* @param needCloseLazyNettyServerProperties 配置
*/
@Override
public void destroyOneClientSocket(LazyNettyServerProperties needCloseLazyNettyServerProperties) {
// 关闭指定socket
cacheNettyClientSocketMap.forEach(((nettyServerProperties, nettyClientSocket) -> {
String clientId = nettyServerProperties.getClientId();
String inetHost = nettyServerProperties.getInetHost();
Integer inetPort = nettyServerProperties.getInetPort();
String needCloseInetHost = needCloseLazyNettyServerProperties.getInetHost();
Integer needCloseInetPort = needCloseLazyNettyServerProperties.getInetPort();
String needCloseClientId = needCloseLazyNettyServerProperties.getClientId();
if (Objects.equals(clientId, needCloseClientId)
&& Objects.equals(inetPort, needCloseInetPort)
&& Objects.equals(inetHost, needCloseInetHost)) {
nettyClientSocket.shutdown();
// 关闭客户端:{}与服务端连接:{}:{}
log.warn("Close client: {} Connect to server: {}: {}", clientId, inetHost, inetPort);
}
}));
}
/**
* 关闭 客户端socket
*/
@Override
public void destroyClientSocket() {
// 关闭socket
cacheNettyClientSocketMap.forEach(((nettyServerProperties, nettyClientSocket) -> {
nettyClientSocket.shutdown();
String clientId = nettyServerProperties.getClientId();
String inetHost = nettyServerProperties.getInetHost();
Integer inetPort = nettyServerProperties.getInetPort();
// 关闭客户端:{}与服务端连接:{}:{}
log.warn("Close client: {} Connect to server: {}: {}", clientId, inetHost, inetPort);
}));
}
}

View File

@ -0,0 +1,82 @@
package org.framework.smart.agent.network.heartbeat.client.config;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.client.netty.socket.NettyClientSocket;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.framework.smart.agent.network.heartbeat.client.netty.event.ClientChangeEvent;
import org.framework.smart.agent.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
import org.wu.framework.core.NormalUsedString;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* description 自动配置
*
* @author 吴佳伟
* @date 2023/09/12 18:22
* @see InitConfig
*/
@Deprecated
@Slf4j
public class ClientAutoConfiguration implements CommandLineRunner {
private final NettyClientProperties nettyClientProperties;
private final ClientChangeEvent clientChangeEvent;
private final List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList; // 处理服务端发送过来的数据类型
public static final ThreadPoolExecutor NETTY_CLIENT_EXECUTOR = new ThreadPoolExecutor(1, 1, 200, TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<>(1));
public ClientAutoConfiguration(NettyClientProperties nettyClientProperties,
ClientChangeEvent clientChangeEvent,
List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
this.nettyClientProperties = nettyClientProperties;
this.clientChangeEvent = clientChangeEvent;
this.handleChannelTypeAdvancedList = handleChannelTypeAdvancedList;
}
@Bean(destroyMethod = "shutdown")
public NettyClientSocket nettyClientSocket() {
String inetHost = nettyClientProperties.getInetHost();
int inetPort = nettyClientProperties.getInetPort();
String clientId = nettyClientProperties.getClientId();
return new NettyClientSocket(inetHost, inetPort, clientId, NormalUsedString.DEFAULT, clientChangeEvent, handleChannelTypeAdvancedList);
}
/**
* @param args
* @throws Exception
*/
@Override
public void run(String... args) throws Exception {
String inetHost = nettyClientProperties.getInetHost();
int inetPort = nettyClientProperties.getInetPort();
String clientId = nettyClientProperties.getClientId();
NettyClientSocket nettyClientSocket = new NettyClientSocket(
inetHost, inetPort,
clientId, NormalUsedString.DEFAULT,
clientChangeEvent, handleChannelTypeAdvancedList);
Thread thread = new Thread(() -> {
try {
nettyClientSocket.newConnect2Server();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
log.info("当前服务连接Netty客户端:{},Netty端口:{}", inetHost, inetPort);
NETTY_CLIENT_EXECUTOR.execute(thread);
}
}

View File

@ -0,0 +1,89 @@
package org.framework.smart.agent.network.heartbeat.client.config;
import org.framework.smart.agent.network.heartbeat.client.netty.advanced.*;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Role;
import org.framework.smart.agent.network.heartbeat.client.netty.event.ClientChangeEvent;
import org.framework.smart.agent.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
import java.util.List;
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@ConditionalOnProperty(prefix = NettyClientProperties.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
public class HeartbeatClientConfiguration {
/**
* 服务端 处理客户端心跳
*
* @return ClientHandleChannelHeartbeatTypeAdvanced
*/
@Bean
public ClientHandleChannelHeartbeatTypeAdvanced clientChannelHeartbeatTypeAdvanced() {
return new ClientHandleChannelHeartbeatTypeAdvanced();
}
/**
* 处理 客户端代理的真实端口自动读写
*
* @return ClientHandleDistributeSingleClientRealAutoReadConnectTypeAdvanced
*/
@Bean
public ClientHandleDistributeSingleClientRealAutoReadConnectTypeAdvanced handleDistributeSingleClientRealAutoReadConnectTypeAdvanced() {
return new ClientHandleDistributeSingleClientRealAutoReadConnectTypeAdvanced();
}
/**
* 处理 接收服务端发送过来的聊天信息
*
* @return ClientHandleDistributeSingleClientMessageTypeAdvanced
*/
@Bean
public ClientHandleDistributeSingleClientMessageTypeAdvanced handleDistributeSingleClientMessageTypeAdvanced() {
return new ClientHandleDistributeSingleClientMessageTypeAdvanced();
}
@Bean
public ClientHandleDistributeSingleClientRealCloseVisitorTypeAdvanced handleDistributeSingleClientRealCloseVisitorTypeAdvanced() {
return new ClientHandleDistributeSingleClientRealCloseVisitorTypeAdvanced();
}
@Bean
public ClientReportHandleChannelTransferTypeAdvancedHandleDistribute handleChannelTransferTypeAdvancedHandleDistribute(NettyClientProperties nettyClientProperties) {
return new ClientReportHandleChannelTransferTypeAdvancedHandleDistribute(nettyClientProperties);
}
@Bean
public HandleDistributeConnectSuccessNotificationTypeAdvancedHandle handleDistributeConnectSuccessNotificationTypeAdvancedHandle(ClientChangeEvent clientChangeEvent) {
return new HandleDistributeConnectSuccessNotificationTypeAdvancedHandle(clientChangeEvent);
}
@Bean
public HandleClientChannelActiveAdvanced handleClientChannelActiveAdvanced(NettyClientProperties nettyClientProperties) {
return new HandleClientChannelActiveAdvanced(nettyClientProperties);
}
@Bean
public HandleDistributeDisconnectTypeAdvancedHandle handleDistributeDisconnectTypeAdvancedHandle(ClientChangeEvent clientChangeEvent) {
return new HandleDistributeDisconnectTypeAdvancedHandle(clientChangeEvent);
}
@Bean
public HandleDistributeStagingClosedTypeAdvanced handleDistributeStagingClosedTypeAdvanced() {
return new HandleDistributeStagingClosedTypeAdvanced();
}
@Bean
public HandleDistributeStagingOpenedTypeAdvanced handleDistributeStagingOpenedTypeAdvanced() {
return new HandleDistributeStagingOpenedTypeAdvanced();
}
@Bean
public ClientHandleDistributeSingleClientRealConnectTypeAdvanced clientHandleDistributeSingleClientRealConnectTypeAdvanced(NettyClientProperties nettyClientProperties,
List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
return new ClientHandleDistributeSingleClientRealConnectTypeAdvanced(nettyClientProperties, handleChannelTypeAdvancedList);
}
}

View File

@ -0,0 +1,87 @@
package org.framework.smart.agent.network.heartbeat.client.config;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.client.application.LazyNettyServerPropertiesApplication;
import org.framework.smart.agent.network.heartbeat.client.infrastructure.entity.LazyNettyServerPropertiesDO;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Role;
import org.wu.framework.lazy.orm.database.lambda.stream.lambda.LazyLambdaStream;
import org.wu.framework.lazy.orm.database.lambda.stream.wrapper.LazyWrappers;
import java.util.Objects;
/**
* 初始化配置
*/
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
@Slf4j
@Configuration
public class InitConfig implements CommandLineRunner, DisposableBean {
private final NettyClientProperties nettyClientProperties;
private final LazyLambdaStream lazyLambdaStream;
private final LazyNettyServerPropertiesApplication lazyNettyServerPropertiesApplication;
public InitConfig(NettyClientProperties nettyClientProperties, LazyLambdaStream lazyLambdaStream, LazyNettyServerPropertiesApplication lazyNettyServerPropertiesApplication) {
this.nettyClientProperties = nettyClientProperties;
this.lazyLambdaStream = lazyLambdaStream;
this.lazyNettyServerPropertiesApplication = lazyNettyServerPropertiesApplication;
}
@Override
public void run(String... args) throws Exception {
try {
// 存储配置到db
initDb2Config();
// 启动客户端连接
lazyNettyServerPropertiesApplication.starterAllClientSocket();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 存储配置到db
*/
public void initDb2Config() {
String clientId = nettyClientProperties.getClientId();
String inetHost = nettyClientProperties.getInetHost();
int inetPort = nettyClientProperties.getInetPort();
if (Objects.isNull(clientId) ||
Objects.isNull(inetHost)) {
log.warn("配置信息为空,请通过页面添加配置信息:{}", nettyClientProperties);
return;
}
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = new LazyNettyServerPropertiesDO();
lazyNettyServerPropertiesDO.setClientId(clientId);
lazyNettyServerPropertiesDO.setInetHost(inetHost);
lazyNettyServerPropertiesDO.setInetPort(inetPort);
lazyNettyServerPropertiesDO.setType(PropertiesType.CONFIG);
lazyNettyServerPropertiesDO.setIsDeleted(false);
// 根据服务端端口、port 唯一性验证
boolean exists = lazyLambdaStream.exists(LazyWrappers.<LazyNettyServerPropertiesDO>lambdaWrapper()
.eq(LazyNettyServerPropertiesDO::getInetHost, inetHost)
.eq(LazyNettyServerPropertiesDO::getInetPort, inetPort)
.eq(LazyNettyServerPropertiesDO::getClientId, clientId)
);
if (!exists) {
lazyLambdaStream.insert(lazyNettyServerPropertiesDO);
}
}
/**
* 程序关闭后执行
*/
@Override
public void destroy() {
lazyNettyServerPropertiesApplication.destroyClientSocket();
}
}

View File

@ -0,0 +1,36 @@
package org.framework.smart.agent.network.heartbeat.client.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* netty 客户服务端地址配置属性
*/
@ConfigurationProperties(prefix = NettyClientProperties.PREFIX, ignoreUnknownFields = true)
@Configuration
@Data
public class NettyClientProperties {
public static final String PREFIX = "spring.lazy.netty.client";
/**
* 服务端地址 如127.0.0.1
*/
private String inetHost;
/**
* 服务端端口 如7001
*/
private int inetPort;
/**
* 服务端path
*/
private String inetPath = "lazy-cloud-heartbeat-server";
/**
* 客户端ID 如1024
*/
private String clientId;
/**
* 是否开启 默认是
*/
private boolean enabled = true;
}

View File

@ -0,0 +1,14 @@
package org.framework.smart.agent.network.heartbeat.client.config;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 属性类型
*/
@AllArgsConstructor
@Getter
public enum PropertiesType {
DB,
CONFIG
}

View File

@ -0,0 +1,141 @@
package org.framework.smart.agent.network.heartbeat.client.controller;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import org.wu.framework.web.spring.EasyController;
import org.springframework.web.bind.annotation.*;
import org.wu.framework.web.response.Result;
import org.wu.framework.web.response.ResultFactory;
import org.springframework.beans.factory.annotation.Autowired;
import jakarta.annotation.Resource;
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesRemoveCommand;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesStoryCommand;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesUpdateCommand;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesQueryListCommand;
import org.framework.smart.agent.network.heartbeat.client.application.command.lazy.netty.server.properties.LazyNettyServerPropertiesQueryOneCommand;
import org.framework.smart.agent.network.heartbeat.client.application.LazyNettyServerPropertiesApplication;
import org.framework.smart.agent.network.heartbeat.client.application.dto.LazyNettyServerPropertiesDTO;
import java.util.List;
import org.wu.framework.lazy.orm.database.lambda.domain.LazyPage;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyController
**/
@Tag(name = "服务端配置信息提供者")
@EasyController("/v1/api/lazy/netty/server/properties")
public class LazyNettyServerPropertiesProvider {
@Resource
private LazyNettyServerPropertiesApplication lazyNettyServerPropertiesApplication;
/**
* describe 新增服务端配置信息
*
* @param lazyNettyServerPropertiesStoryCommand 新增服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息新增后领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Operation(summary = "新增服务端配置信息")
@PostMapping("/story")
public Result<LazyNettyServerProperties> story(@RequestBody LazyNettyServerPropertiesStoryCommand lazyNettyServerPropertiesStoryCommand){
return lazyNettyServerPropertiesApplication.story(lazyNettyServerPropertiesStoryCommand);
}
/**
* describe 批量新增服务端配置信息
*
* @param lazyNettyServerPropertiesStoryCommandList 批量新增服务端配置信息
* @return {@link Result<List<LazyNettyServerProperties>>} 服务端配置信息新增后领域对象集合
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Operation(summary = "批量新增服务端配置信息")
@PostMapping("/batchStory")
public Result<List<LazyNettyServerProperties>> batchStory(@RequestBody List<LazyNettyServerPropertiesStoryCommand> lazyNettyServerPropertiesStoryCommandList){
return lazyNettyServerPropertiesApplication.batchStory(lazyNettyServerPropertiesStoryCommandList);
}
/**
* describe 更新服务端配置信息
*
* @param lazyNettyServerPropertiesUpdateCommand 更新服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Operation(summary = "更新服务端配置信息")
@PutMapping("/updateOne")
public Result<LazyNettyServerProperties> updateOne(@RequestBody LazyNettyServerPropertiesUpdateCommand lazyNettyServerPropertiesUpdateCommand){
return lazyNettyServerPropertiesApplication.updateOne(lazyNettyServerPropertiesUpdateCommand);
}
/**
* describe 查询单个服务端配置信息
*
* @param lazyNettyServerPropertiesQueryOneCommand 查询单个服务端配置信息
* @return {@link Result<LazyNettyServerPropertiesDTO>} 服务端配置信息DTO对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Operation(summary = "查询单个服务端配置信息")
@GetMapping("/findOne")
public Result<LazyNettyServerPropertiesDTO> findOne(@ModelAttribute LazyNettyServerPropertiesQueryOneCommand lazyNettyServerPropertiesQueryOneCommand){
return lazyNettyServerPropertiesApplication.findOne(lazyNettyServerPropertiesQueryOneCommand);
}
/**
* describe 查询多个服务端配置信息
*
* @param lazyNettyServerPropertiesQueryListCommand 查询多个服务端配置信息
* @return {@link Result<List<LazyNettyServerPropertiesDTO>>} 服务端配置信息DTO对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Operation(summary = "查询多个服务端配置信息")
@GetMapping("/findList")
public Result<List<LazyNettyServerPropertiesDTO>> findList(@ModelAttribute LazyNettyServerPropertiesQueryListCommand lazyNettyServerPropertiesQueryListCommand){
return lazyNettyServerPropertiesApplication.findList(lazyNettyServerPropertiesQueryListCommand);
}
/**
* describe 分页查询多个服务端配置信息
*
* @param lazyNettyServerPropertiesQueryListCommand 分页查询多个服务端配置信息
* @return {@link Result<LazyPage<LazyNettyServerPropertiesDTO>>} 分页服务端配置信息DTO对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Operation(summary = "分页查询多个服务端配置信息")
@GetMapping("/findPage")
public Result<LazyPage<LazyNettyServerPropertiesDTO>> findPage(@Parameter(description ="分页大小") @RequestParam(defaultValue = "10", value = "size") int size,
@Parameter(description ="当前页数") @RequestParam(defaultValue = "1", value = "current") int current,@ModelAttribute LazyNettyServerPropertiesQueryListCommand lazyNettyServerPropertiesQueryListCommand){
return lazyNettyServerPropertiesApplication.findPage(size,current,lazyNettyServerPropertiesQueryListCommand);
}
/**
* describe 删除服务端配置信息
*
* @param lazyNettyServerPropertiesRemoveCommand 删除服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Operation(summary = "删除服务端配置信息")
@DeleteMapping("/remove")
public Result<LazyNettyServerProperties> remove(@ModelAttribute LazyNettyServerPropertiesRemoveCommand lazyNettyServerPropertiesRemoveCommand){
return lazyNettyServerPropertiesApplication.remove(lazyNettyServerPropertiesRemoveCommand);
}
}

View File

@ -0,0 +1,76 @@
package org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties;
import lombok.Data;
import lombok.experimental.Accessors;
import io.swagger.v3.oas.annotations.media.Schema;
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
import java.lang.String;
import java.time.LocalDateTime;
import java.lang.Integer;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyDomain
**/
@Data
@Accessors(chain = true)
@Schema(title = "lazy_netty_server_properties",description = "服务端配置信息")
public class LazyNettyServerProperties {
/**
*
* 客户身份ID
*/
@Schema(description ="客户身份ID",name ="clientId",example = "")
private String clientId;
/**
*
* 状态(on_line、off_line)
*/
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
private NettyClientStatus connectStatus;
/**
*
* 创建时间
*/
@Schema(description ="创建时间",name ="createTime",example = "")
private LocalDateTime createTime;
/**
*
* 服务端host
*/
@Schema(description ="服务端host",name ="inetHost",example = "")
private String inetHost;
/**
*
* 服务端端口
*/
@Schema(description ="服务端端口",name ="inetPort",example = "")
private Integer inetPort;
/**
*
* 类型配置、DB
*/
@Schema(description ="类型配置、DB",name ="type",example = "")
private PropertiesType type;
/**
*
* 更新时间
*/
@Schema(description ="更新时间",name ="updateTime",example = "")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,118 @@
package org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties;
import org.wu.framework.web.response.Result;
import org.wu.framework.web.response.ResultFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
import java.util.List;
import org.wu.framework.lazy.orm.database.lambda.domain.LazyPage;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyDomainRepository
**/
public interface LazyNettyServerPropertiesRepository {
/**
* describe 新增服务端配置信息
*
* @param lazyNettyServerProperties 新增服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息新增后领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
Result<LazyNettyServerProperties> story(LazyNettyServerProperties lazyNettyServerProperties);
/**
* describe 批量新增服务端配置信息
*
* @param lazyNettyServerPropertiesList 批量新增服务端配置信息
* @return {@link Result<List<LazyNettyServerProperties>>} 服务端配置信息新增后领域对象集合
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
Result<List<LazyNettyServerProperties>> batchStory(List<LazyNettyServerProperties> lazyNettyServerPropertiesList);
/**
* describe 查询单个服务端配置信息
*
* @param lazyNettyServerProperties 查询单个服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息DTO对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
Result<LazyNettyServerProperties> findOne(LazyNettyServerProperties lazyNettyServerProperties);
/**
* describe 查询多个服务端配置信息
*
* @param lazyNettyServerProperties 查询多个服务端配置信息
* @return {@link Result<List<LazyNettyServerProperties>>} 服务端配置信息DTO对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
Result<List<LazyNettyServerProperties>> findList(LazyNettyServerProperties lazyNettyServerProperties);
/**
* describe 分页查询多个服务端配置信息
*
* @param size 当前页数
* @param current 当前页
* @param lazyNettyServerProperties 分页查询多个服务端配置信息
* @return {@link Result<LazyPage<LazyNettyServerProperties>>} 分页服务端配置信息领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
Result<LazyPage<LazyNettyServerProperties>> findPage(int size,int current,LazyNettyServerProperties lazyNettyServerProperties);
/**
* describe 删除服务端配置信息
*
* @param lazyNettyServerProperties 删除服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
Result<LazyNettyServerProperties> remove(LazyNettyServerProperties lazyNettyServerProperties);
/**
* describe 是否存在服务端配置信息
*
* @param lazyNettyServerProperties 是否存在服务端配置信息
* @return {@link Result<Boolean>} 服务端配置信息是否存在
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
Result<Boolean> exists(LazyNettyServerProperties lazyNettyServerProperties);
/**
* 客户端连接服务端状态在线
* @param lazyNettyServerProperties 数据
*/
void onLine(LazyNettyServerProperties lazyNettyServerProperties);
/**
* 推送客户端离线
* @param lazyNettyServerProperties 数据
*/
void offLine(LazyNettyServerProperties lazyNettyServerProperties);
}

View File

@ -0,0 +1,48 @@
package org.framework.smart.agent.network.heartbeat.client.infrastructure.converter;
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
import org.framework.smart.agent.network.heartbeat.client.infrastructure.entity.LazyNettyServerPropertiesDO;
import org.mapstruct.factory.Mappers;
import org.mapstruct.Mapper;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyInfrastructureConverter
**/
@Mapper
public interface LazyNettyServerPropertiesConverter {
/**
* describe MapStruct 创建的代理对象
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
LazyNettyServerPropertiesConverter INSTANCE = Mappers.getMapper(LazyNettyServerPropertiesConverter.class);
/**
* describe 实体对象 转换成领域对象
*
* @param lazyNettyServerPropertiesDO 服务端配置信息实体对象
* @return {@link LazyNettyServerProperties} 服务端配置信息领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
LazyNettyServerProperties toLazyNettyServerProperties(LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO);
/**
* describe 领域对象 转换成实体对象
*
* @param lazyNettyServerProperties 服务端配置信息领域对象
* @return {@link LazyNettyServerPropertiesDO} 服务端配置信息实体对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
LazyNettyServerPropertiesDO fromLazyNettyServerProperties(LazyNettyServerProperties lazyNettyServerProperties);
}

View File

@ -0,0 +1,97 @@
package org.framework.smart.agent.network.heartbeat.client.infrastructure.entity;
import lombok.Data;
import lombok.experimental.Accessors;
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
import org.wu.framework.lazy.orm.core.stereotype.LazyTableIndex;
import org.wu.framework.core.stereotype.LayerField;
import org.wu.framework.core.stereotype.LayerField.LayerFieldType;
import org.wu.framework.lazy.orm.core.stereotype.LazyTable;
import org.wu.framework.lazy.orm.core.stereotype.LazyTableField;
import org.wu.framework.lazy.orm.core.stereotype.*;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema;
import java.lang.String;
import java.time.LocalDateTime;
import java.lang.Integer;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyInfrastructureEntity
**/
@Data
@Accessors(chain = true)
@LazyTable(tableName = "lazy_netty_server_properties",comment = "服务端配置信息")
@Schema(title = "lazy_netty_server_properties",description = "服务端配置信息")
public class LazyNettyServerPropertiesDO {
/**
*
* 客户身份ID
*/
@Schema(description ="客户身份ID",name ="clientId",example = "")
@LazyTableFieldUnique(name="client_id",comment="客户身份ID",columnType="varchar(255)")
private String clientId;
/**
*
* 状态(on_line、off_line)
*/
@Schema(description ="状态(on_line、off_line)",name ="connectStatus",example = "")
@LazyTableField(name="connect_status",comment="状态(on_line、off_line)",columnType="varchar(255)")
private NettyClientStatus connectStatus;
/**
*
* 创建时间
*/
@Schema(description ="创建时间",name ="createTime",example = "")
@LazyTableField(name="create_time",comment="创建时间")
private LocalDateTime createTime;
/**
*
* 服务端host
*/
@Schema(description ="服务端host",name ="inetHost",example = "")
@LazyTableFieldUnique(name="inet_host",comment="服务端host",columnType="varchar(255)")
private String inetHost;
/**
*
* 服务端端口
*/
@Schema(description ="服务端端口",name ="inetPort",example = "")
@LazyTableFieldUnique(name="inet_port",comment="服务端端口",columnType="int")
private Integer inetPort;
/**
*
* 是否删除
*/
@Schema(description ="是否删除",name ="isDeleted",example = "")
@LazyTableField(name="is_deleted",comment="是否删除")
private Boolean isDeleted;
/**
*
* 类型配置、DB
*/
@Schema(description ="类型配置、DB",name ="type",example = "")
@LazyTableField(name="type",comment="类型配置、DB",columnType="varchar(255)")
private PropertiesType type;
/**
*
* 更新时间
*/
@Schema(description ="更新时间",name ="updateTime",example = "")
@LazyTableField(name="update_time",comment="更新时间")
private LocalDateTime updateTime;
}

View File

@ -0,0 +1,15 @@
package org.framework.smart.agent.network.heartbeat.client.infrastructure.mapper;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyInfrastructureMapper
**/
public interface LazyNettyServerPropertiesMapper {
}

View File

@ -0,0 +1,213 @@
package org.framework.smart.agent.network.heartbeat.client.infrastructure.persistence;
import org.framework.smart.agent.network.heartbeat.client.config.PropertiesType;
import org.framework.smart.agent.network.heartbeat.client.infrastructure.entity.LazyNettyServerPropertiesDO;
import org.framework.smart.agent.network.heartbeat.client.infrastructure.converter.LazyNettyServerPropertiesConverter;
import org.framework.smart.agent.network.heartbeat.client.infrastructure.mapper.LazyNettyServerPropertiesMapper;
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerPropertiesRepository;
import org.springframework.stereotype.Repository;
import java.util.stream.Collectors;
import org.wu.framework.lazy.orm.database.lambda.stream.wrapper.LazyWrappers;
import org.wu.framework.web.response.Result;
import org.wu.framework.web.response.ResultFactory;
import jakarta.annotation.Resource;
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
import org.wu.framework.lazy.orm.database.lambda.stream.lambda.LazyLambdaStream;
import java.util.List;
import org.wu.framework.lazy.orm.database.lambda.domain.LazyPage;
/**
* describe 服务端配置信息
*
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
* @see org.wu.framework.lazy.orm.core.persistence.reverse.lazy.ddd.DefaultDDDLazyInfrastructurePersistence
**/
@Repository
public class LazyNettyServerPropertiesRepositoryImpl implements LazyNettyServerPropertiesRepository {
@Resource
LazyLambdaStream lazyLambdaStream;
/**
* describe 新增服务端配置信息
*
* @param lazyNettyServerProperties 新增服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息新增后领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Override
public Result<LazyNettyServerProperties> story(LazyNettyServerProperties lazyNettyServerProperties) {
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
String inetHost = lazyNettyServerPropertiesDO.getInetHost();
Integer inetPort = lazyNettyServerPropertiesDO.getInetPort();
String clientId = lazyNettyServerPropertiesDO.getClientId();
lazyNettyServerPropertiesDO.setIsDeleted(false);
// 查询 ip、端口、客户端
boolean exists = lazyLambdaStream.exists(LazyWrappers.<LazyNettyServerPropertiesDO>lambdaWrapper()
.eq(LazyNettyServerPropertiesDO::getInetHost, inetHost)
.eq(LazyNettyServerPropertiesDO::getInetPort, inetPort)
.eq(LazyNettyServerPropertiesDO::getClientId, clientId)
);
if (exists) {
// 更新
lazyLambdaStream.update(lazyNettyServerPropertiesDO, LazyWrappers.<LazyNettyServerPropertiesDO>lambdaWrapper()
.eq(LazyNettyServerPropertiesDO::getInetHost, inetHost)
.eq(LazyNettyServerPropertiesDO::getInetPort, inetPort)
.eq(LazyNettyServerPropertiesDO::getClientId, clientId)
);
} else {
lazyLambdaStream.insert(lazyNettyServerPropertiesDO);
}
return ResultFactory.successOf();
}
/**
* describe 批量新增服务端配置信息
*
* @param lazyNettyServerPropertiesList 批量新增服务端配置信息
* @return {@link Result<List<LazyNettyServerProperties>>} 服务端配置信息新增后领域对象集合
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Override
public Result<List<LazyNettyServerProperties>> batchStory(List<LazyNettyServerProperties> lazyNettyServerPropertiesList) {
List<LazyNettyServerPropertiesDO> lazyNettyServerPropertiesDOList = lazyNettyServerPropertiesList.stream().map(LazyNettyServerPropertiesConverter.INSTANCE::fromLazyNettyServerProperties).collect(Collectors.toList());
lazyLambdaStream.upsert(lazyNettyServerPropertiesDOList);
return ResultFactory.successOf();
}
/**
* describe 查询单个服务端配置信息
*
* @param lazyNettyServerProperties 查询单个服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Override
public Result<LazyNettyServerProperties> findOne(LazyNettyServerProperties lazyNettyServerProperties) {
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
LazyNettyServerProperties lazyNettyServerPropertiesOne = lazyLambdaStream
.selectOne(
LazyWrappers.lambdaWrapperBean(lazyNettyServerPropertiesDO)
.eq(LazyNettyServerPropertiesDO::getIsDeleted,false)
, LazyNettyServerProperties.class);
return ResultFactory.successOf(lazyNettyServerPropertiesOne);
}
/**
* describe 查询多个服务端配置信息
*
* @param lazyNettyServerProperties 查询多个服务端配置信息
* @return {@link Result<List<LazyNettyServerProperties>>} 服务端配置信息领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Override
public Result<List<LazyNettyServerProperties>> findList(LazyNettyServerProperties lazyNettyServerProperties) {
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
List<LazyNettyServerProperties> lazyNettyServerPropertiesList = lazyLambdaStream.selectList(
LazyWrappers.lambdaWrapperBean(lazyNettyServerPropertiesDO)
.eq(LazyNettyServerPropertiesDO::getIsDeleted, false)
, LazyNettyServerProperties.class);
return ResultFactory.successOf(lazyNettyServerPropertiesList);
}
/**
* describe 分页查询多个服务端配置信息
*
* @param size 当前页数
* @param current 当前页
* @param lazyNettyServerProperties 分页查询多个服务端配置信息
* @return {@link Result<LazyPage<LazyNettyServerProperties>>} 分页服务端配置信息领域对象
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Override
public Result<LazyPage<LazyNettyServerProperties>> findPage(int size, int current, LazyNettyServerProperties lazyNettyServerProperties) {
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
LazyPage<LazyNettyServerProperties> lazyPage = new LazyPage<>(current, size);
LazyPage<LazyNettyServerProperties> lazyNettyServerPropertiesLazyPage = lazyLambdaStream.selectPage(
LazyWrappers
.lambdaWrapperBean(lazyNettyServerPropertiesDO)
.eq(LazyNettyServerPropertiesDO::getIsDeleted, false)
, lazyPage, LazyNettyServerProperties.class);
return ResultFactory.successOf(lazyNettyServerPropertiesLazyPage);
}
/**
* describe 删除服务端配置信息
*
* @param lazyNettyServerProperties 删除服务端配置信息
* @return {@link Result<LazyNettyServerProperties>} 服务端配置信息
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Override
public Result<LazyNettyServerProperties> remove(LazyNettyServerProperties lazyNettyServerProperties) {
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
lazyLambdaStream.delete(LazyWrappers.lambdaWrapperBean(lazyNettyServerPropertiesDO));
return ResultFactory.successOf();
}
/**
* describe 是否存在服务端配置信息
*
* @param lazyNettyServerProperties 服务端配置信息领域对象
* @return {@link Result<Boolean>} 是否存在 true 存在false 不存在
* @author Jia wei Wu
* @date 2024/04/03 03:00 下午
**/
@Override
public Result<Boolean> exists(LazyNettyServerProperties lazyNettyServerProperties) {
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
Boolean exists = lazyLambdaStream.exists(LazyWrappers.lambdaWrapperBean(lazyNettyServerPropertiesDO));
return ResultFactory.successOf(exists);
}
/**
* 客户端连接服务端状态在线
*
* @param lazyNettyServerProperties 数据
*/
@Override
public void onLine(LazyNettyServerProperties lazyNettyServerProperties) {
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
lazyLambdaStream.update(lazyNettyServerPropertiesDO,LazyWrappers.<LazyNettyServerPropertiesDO>lambdaWrapper()
.eq(LazyNettyServerPropertiesDO::getInetPort,lazyNettyServerPropertiesDO.getInetPort())
.eq(LazyNettyServerPropertiesDO::getInetHost,lazyNettyServerPropertiesDO.getInetHost())
.eq(LazyNettyServerPropertiesDO::getClientId,lazyNettyServerPropertiesDO.getClientId())
);
}
/**
* 推送客户端离线
*
* @param lazyNettyServerProperties 数据
*/
@Override
public void offLine(LazyNettyServerProperties lazyNettyServerProperties) {
LazyNettyServerPropertiesDO lazyNettyServerPropertiesDO = LazyNettyServerPropertiesConverter.INSTANCE.fromLazyNettyServerProperties(lazyNettyServerProperties);
lazyLambdaStream.update(lazyNettyServerPropertiesDO,LazyWrappers.<LazyNettyServerPropertiesDO>lambdaWrapper()
.eq(LazyNettyServerPropertiesDO::getInetPort,lazyNettyServerPropertiesDO.getInetPort())
.eq(LazyNettyServerPropertiesDO::getInetHost,lazyNettyServerPropertiesDO.getInetHost())
.eq(LazyNettyServerPropertiesDO::getClientId,lazyNettyServerPropertiesDO.getClientId())
);
}
}

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.framework.smart.agent.network.heartbeat.client.infrastructure.mapper.LazyNettyServerPropertiesMapper">
<resultMap id="BaseResultMap" type="org.framework.smart.agent.network.heartbeat.client.infrastructure.entity.LazyNettyServerPropertiesDO">
<id column="id" property="id" />
<result column="create_time" property="createTime" />
<result column="update_time" property="updateTime" />
<result column="is_deleted" property="isDeleted" />
<result column="inet_host" property="inetHost" />
<result column="inet_port" property="inetPort" />
<result column="client_id" property="clientId" />
<result column="type" property="type" />
<result column="connect_status" property="connectStatus" />
</resultMap>
</mapper>

View File

@ -0,0 +1,29 @@
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
import io.netty.channel.Channel;
import org.framework.smart.agent.network.heartbeat.common.MessageType;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.advanced.AbstractHandleChannelHeartbeatTypeAdvanced;
/**
* 服务端 处理客户端心跳
* TYPE_HEARTBEAT
*/
public class ClientHandleChannelHeartbeatTypeAdvanced extends AbstractHandleChannelHeartbeatTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param channel 当前通道
* @param msg 通道数据
*/
@Override
public void doHandler(Channel channel, NettyProxyMsg msg) {
NettyProxyMsg hb = new NettyProxyMsg();
hb.setType(MessageType.TYPE_HEARTBEAT);
// channel.writeAndFlush(hb);
}
}

View File

@ -0,0 +1,26 @@
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeSingleClientMessageTypeAdvanced;
/**
* 接收服务端发送过来的聊天信息
*/
@Slf4j
public class ClientHandleDistributeSingleClientMessageTypeAdvanced extends AbstractHandleDistributeSingleClientMessageTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param channel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
byte[] clientId = nettyProxyMsg.getClientId();
byte[] data = nettyProxyMsg.getData();
log.info("接收客户端:{},发送过来的聊天信息:{}", new String(clientId), new String(data));
}
}

View File

@ -0,0 +1,29 @@
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.NettyRealIdContext;
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeSingleClientRealAutoReadConnectTypeAdvanced;
@Slf4j
public class ClientHandleDistributeSingleClientRealAutoReadConnectTypeAdvanced extends AbstractHandleDistributeSingleClientRealAutoReadConnectTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param channel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
// 获取访客ID
byte[] visitorId = nettyProxyMsg.getVisitorId();
// 获取访客对应的真实代理通道
Channel realChannel = NettyRealIdContext.getReal(visitorId);
if (realChannel != null) {
realChannel.config().setOption(ChannelOption.AUTO_READ, true);
}
}
}

View File

@ -0,0 +1,26 @@
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.common.NettyCommunicationIdContext;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.NettyRealIdContext;
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeSingleClientRealCloseVisitorTypeAdvanced;
@Slf4j
public class ClientHandleDistributeSingleClientRealCloseVisitorTypeAdvanced extends AbstractHandleDistributeSingleClientRealCloseVisitorTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param channel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
// 关闭代理的真实通道
byte[] visitorId = nettyProxyMsg.getVisitorId();
NettyRealIdContext.clear(visitorId);
NettyCommunicationIdContext.clear(visitorId);
}
}

View File

@ -0,0 +1,56 @@
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.client.config.NettyClientProperties;
import org.framework.smart.agent.network.heartbeat.client.netty.socket.NettyClientRealSocket;
import org.framework.smart.agent.network.heartbeat.common.InternalNetworkPenetrationRealClient;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeSingleClientRealConnectTypeAdvanced;
import java.util.List;
/**
* 客户端创建真实代理同奥
*/
@Slf4j
public class ClientHandleDistributeSingleClientRealConnectTypeAdvanced extends AbstractHandleDistributeSingleClientRealConnectTypeAdvanced<NettyProxyMsg> {
private final NettyClientProperties nettyClientProperties;// 服务端地址信息
private final List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList;
public ClientHandleDistributeSingleClientRealConnectTypeAdvanced(NettyClientProperties nettyClientProperties, List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
this.nettyClientProperties = nettyClientProperties;
this.handleChannelTypeAdvancedList = handleChannelTypeAdvancedList;
}
/**
* 处理当前数据
*
* @param channel 当前通道
* @param msg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg msg) {
// 创建真实端口监听
byte[] clientIdBytes = msg.getClientId();
byte[] visitorPort = msg.getVisitorPort();
byte[] clientTargetIp = msg.getClientTargetIp();
byte[] clientTargetPort = msg.getClientTargetPort();
byte[] visitorIdBytes = msg.getVisitorId();
InternalNetworkPenetrationRealClient internalNetworkPenetrationRealClient =
InternalNetworkPenetrationRealClient
.builder()
.clientId(new String(clientIdBytes))
.visitorPort(Integer.valueOf(new String(visitorPort)))
.clientTargetIp(new String(clientTargetIp))
.clientTargetPort(Integer.valueOf(new String(clientTargetPort)))
.visitorId(new String(visitorIdBytes))
.build();
// 绑定真实服务端口
NettyClientRealSocket.buildRealServer(internalNetworkPenetrationRealClient, nettyClientProperties, handleChannelTypeAdvancedList);
}
}

View File

@ -0,0 +1,58 @@
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.client.config.NettyClientProperties;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.NettyRealIdContext;
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeChannelTransferTypeAdvanced;
import org.framework.smart.agent.network.heartbeat.common.enums.MessageTypeEnums;
/**
* 服务端处理客户端数据传输
*
* @see MessageTypeEnums#DISTRIBUTE_CLIENT_TRANSFER
*/
@Slf4j
public class ClientReportHandleChannelTransferTypeAdvancedHandleDistribute extends AbstractHandleDistributeChannelTransferTypeAdvanced<NettyProxyMsg> {
private final NettyClientProperties nettyClientProperties;
public ClientReportHandleChannelTransferTypeAdvancedHandleDistribute(NettyClientProperties nettyClientProperties) {
this.nettyClientProperties = nettyClientProperties;
}
/**
* 处理当前数据
*
* @param channel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
public void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
log.debug("接收到服务端需要内网穿透的数据:{}" , nettyProxyMsg);
String clientId = nettyClientProperties.getClientId();
byte[] visitorPort = nettyProxyMsg.getVisitorPort();
byte[] clientTargetIp = nettyProxyMsg.getClientTargetIp();
byte[] clientTargetPort = nettyProxyMsg.getClientTargetPort();
byte[] visitorId = nettyProxyMsg.getVisitorId();
// 真实服务通道
Channel realChannel = NettyRealIdContext.getReal(new String(visitorId));
if (realChannel == null) {
log.error("无法获取访客:{} 真实服务", new String(visitorId));
return;
}
// 把数据转到真实服务
ByteBuf buf = channel.config().getAllocator().buffer(nettyProxyMsg.getData().length);
buf.writeBytes(nettyProxyMsg.getData());
realChannel.writeAndFlush(buf);
}
}

View File

@ -0,0 +1,34 @@
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
import io.netty.channel.Channel;
import org.framework.smart.agent.network.heartbeat.client.config.NettyClientProperties;
import org.framework.smart.agent.network.heartbeat.common.ChannelContext;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleClientChannelActiveAdvanced;
import org.framework.smart.agent.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
/**
* 客户端通道 is active
*/
public class HandleClientChannelActiveAdvanced extends AbstractHandleClientChannelActiveAdvanced<NettyProxyMsg> {
private final NettyClientProperties nettyClientProperties;
public HandleClientChannelActiveAdvanced(NettyClientProperties nettyClientProperties) {
this.nettyClientProperties = nettyClientProperties;
}
/**
* 处理当前数据
*
* @param channel 当前通道
* @param nettyProxyMsg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg nettyProxyMsg) {
// 缓存当前通道
byte[] clientIdByte = nettyProxyMsg.getClientId();
String clientId = new String(clientIdByte);
ChannelContext.push(channel, clientId);
ChannelAttributeKeyUtils.buildClientId(channel, clientId);
}
}

View File

@ -0,0 +1,44 @@
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.client.netty.event.ClientChangeEvent;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeConnectSuccessNotificationTypeAdvancedHandle;
import java.util.List;
/**
* 客户端连接成功通知
*/
@Slf4j
public class HandleDistributeConnectSuccessNotificationTypeAdvancedHandle extends AbstractHandleDistributeConnectSuccessNotificationTypeAdvancedHandle<NettyProxyMsg> {
private final ClientChangeEvent clientChangeEvent;
public HandleDistributeConnectSuccessNotificationTypeAdvancedHandle(ClientChangeEvent clientChangeEvent) {
this.clientChangeEvent = clientChangeEvent;
}
/**
* 处理当前数据
*
* @param channel 当前通道
* @param msg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg msg) {
// 客户端ID{},客户端:{}连接成功
log.warn("Client ID: {}, Client Data : {} Connection successful", new String(msg.getClientId()), new String(msg.getData()));
// 存储其他客户端状态
List<String> clientIdList = JSONObject.parseArray(new String(msg.getData()), String.class);
for (String tenantId : clientIdList) {
clientChangeEvent.clientOnLine(tenantId);
}
}
}

View File

@ -0,0 +1,43 @@
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.client.netty.event.ClientChangeEvent;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeDisconnectTypeAdvancedHandle;
/**
* 服务端处理客户端断开连接处理
* TYPE_DISCONNECT
*/
@Slf4j
public class HandleDistributeDisconnectTypeAdvancedHandle extends AbstractHandleDistributeDisconnectTypeAdvancedHandle<NettyProxyMsg> {
private final ClientChangeEvent clientChangeEvent;
public HandleDistributeDisconnectTypeAdvancedHandle(ClientChangeEvent clientChangeEvent) {
this.clientChangeEvent = clientChangeEvent;
}
/**
* 处理当前数据
*
* @param channel 当前通道
* @param msg 通道数据
*/
@Override
public void doHandler(Channel channel, NettyProxyMsg msg) {
// 服务下线
byte[] data = msg.getData();
byte[] clientId = msg.getClientId();
String tenantId = new String(clientId);
//客户端:{}下线
log.warn("Client: {} Offline", tenantId);
clientChangeEvent.clientOffLine(tenantId);
}
}

View File

@ -0,0 +1,30 @@
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeStagingClosedTypeAdvanced;
/**
* 服务端下发暂存关闭消息处理
*/
@Slf4j
public class HandleDistributeStagingClosedTypeAdvanced extends AbstractHandleDistributeStagingClosedTypeAdvanced<NettyProxyMsg> {
/**
* 处理当前数据
*
* @param channel 当前通道
* @param msg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg msg) {
String clientId = new String(msg.getClientId());
log.info("客户端:{}离线暂存关闭", clientId);
// 修改redis 客户端暂存状态
// String stagingStatusKey = StagingConfigKeyConstant.getStagingStatusKey(clientId);
// stringRedisTemplate.opsForValue().set(stagingStatusKey, StagingStatus.CLOSED.name());
}
}

View File

@ -0,0 +1,34 @@
package org.framework.smart.agent.network.heartbeat.client.netty.advanced;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.advanced.client.AbstractHandleDistributeStagingOpenedTypeAdvanced;
/**
* 服务端下发暂存开启消息处理
*/
@Slf4j
public class HandleDistributeStagingOpenedTypeAdvanced extends AbstractHandleDistributeStagingOpenedTypeAdvanced<NettyProxyMsg> {
public HandleDistributeStagingOpenedTypeAdvanced() {
}
/**
* 处理当前数据
*
* @param channel 当前通道
* @param msg 通道数据
*/
@Override
protected void doHandler(Channel channel, NettyProxyMsg msg) {
String clientId = new String(msg.getClientId());
//客户端:{}离线暂存开启
log.warn("Client: {} Offline temporary storage enabled", new String(msg.getClientId()));
// 修改redis 客户端暂存状态
// String stagingStatusKey = StagingConfigKeyConstant.getStagingStatusKey(clientId);
// stringRedisTemplate.opsForValue().set(stagingStatusKey, StagingStatus.OPENED.name());
}
}

View File

@ -0,0 +1,52 @@
package org.framework.smart.agent.network.heartbeat.client.netty.event;
/**
* 客户端状态变更事件
*/
public interface ClientChangeEvent {
/**
* 推送客户端在线
*/
void clientOnLine(String clientId);
/**
* 推送客户端在线
* @param clientId 客户端
* @param inetHost 服务端ip
* @param inetPort 服务端端口
* @param serverId 服务端ID
*/
void clientOnLine(String inetHost, int inetPort,String serverId ,String clientId);
/**
* 推送客户端离线
*/
void clientOffLine(String clientId);
/**
* 推送客户端离线
*
* @param inetHost 服务端ip
* @param inetPort 服务端端口
* @param serverId 服务端ID
* @param clientId 客户端
*/
void clientOffLine(String inetHost, int inetPort,String serverId,String clientId);
/**
* 暂存开启
*
* @param clientId 租户ID
*/
void stagingOpen(String clientId);
/**
* 暂存关闭
*
* @param clientId 客户端ID 对应的租户
*/
void stagingClose(String clientId);
}

View File

@ -0,0 +1,131 @@
package org.framework.smart.agent.network.heartbeat.client.netty.event;
import jakarta.annotation.Resource;
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerProperties;
import org.framework.smart.agent.network.heartbeat.client.domain.model.lazy.netty.server.properties.LazyNettyServerPropertiesRepository;
import org.framework.smart.agent.network.heartbeat.common.enums.NettyClientStatus;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Component
public class DefaultClientChangeEventImpl implements ClientChangeEvent {
@Resource
private LazyNettyServerPropertiesRepository lazyNettyServerPropertiesRepository;
// private final StringRedisTemplate stringRedisTemplate;
// private final RedisProviderTemplate redisProviderTemplate;
//
// public DefaultClientChangeEvent1Impl(StringRedisTemplate stringRedisTemplate, RedisProviderTemplate redisProviderTemplate) {
// this.stringRedisTemplate = stringRedisTemplate;
// this.redisProviderTemplate = redisProviderTemplate;
// }
/**
* 推送客户端在线
*/
@Override
public void clientOnLine(String clientId) {
// // 获取当前客户端ID
// if (ObjectUtils.isEmpty(clientId)) {
// clientId = stringRedisTemplate.opsForValue().get(ClientConfigKeyUtils.CLIENT_ID_KEY);
// }
// String clientStatusKey = ClientConfigKeyUtils.getClientStatusKey(clientId);
// // 如果可以已经在线状态不推送
// stringRedisTemplate.opsForValue().set(clientStatusKey, NettyClientStatus.ON_LINE.name());
// ClientOnLineState clientOnLineState = new ClientOnLineState();
// clientOnLineState.setClientId(clientId);
// clientOnLineState.setOnLineState(NettyClientStatus.ON_LINE.name());
// // 暂存扫描触发
// redisProviderTemplate.send(RedisChannelConstant.REDIS_CLIENT_ONLINE_OR_OFFLINE_CHANNEL,clientOnLineState);
}
/**
* 推送客户端在线
*
* @param inetHost 服务端ip
* @param inetPort 服务端端口
* @param serverId 服务端ID
* @param clientId 客户端
*/
@Override
public void clientOnLine(String inetHost, int inetPort, String serverId, String clientId) {
LazyNettyServerProperties lazyNettyServerProperties = new LazyNettyServerProperties();
lazyNettyServerProperties.setClientId(clientId);
lazyNettyServerProperties.setInetHost(inetHost);
lazyNettyServerProperties.setInetPort(inetPort);
lazyNettyServerProperties.setConnectStatus(NettyClientStatus.ON_LINE);
lazyNettyServerPropertiesRepository.onLine(lazyNettyServerProperties);
// 更改状态未在线
clientOnLine(clientId);
}
/**
* 推送客户端离线
*/
@Override
public void clientOffLine(String clientId) {
// if (ObjectUtils.isEmpty(clientId)) {
// clientId = stringRedisTemplate.opsForValue().get(ClientConfigKeyUtils.CLIENT_ID_KEY);
// }
// String clientStatusKey = ClientConfigKeyUtils.getClientStatusKey(clientId);
// // 离线状态
// stringRedisTemplate.opsForValue().set(clientStatusKey, NettyClientStatus.OFF_LINE.name());
// // 暂存状态
// stagingOpen(clientId);
// // 暂存扫描触发
// ClientOnLineState clientOnLineState = new ClientOnLineState();
// clientOnLineState.setClientId(clientId);
// clientOnLineState.setOnLineState(NettyClientStatus.OFF_LINE.name());
// redisProviderTemplate.send(RedisChannelConstant.REDIS_CLIENT_ONLINE_OR_OFFLINE_CHANNEL,clientOnLineState);
}
/**
* 推送客户端离线
*
* @param inetHost 服务端ip
* @param inetPort 服务端端口
* @param serverId
* @param clientId 客户端
*/
@Override
public void clientOffLine(String inetHost, int inetPort, String serverId, String clientId) {
LazyNettyServerProperties lazyNettyServerProperties = new LazyNettyServerProperties();
lazyNettyServerProperties.setClientId(clientId);
lazyNettyServerProperties.setInetHost(inetHost);
lazyNettyServerProperties.setInetPort(inetPort);
lazyNettyServerProperties.setConnectStatus(NettyClientStatus.OFF_LINE);
lazyNettyServerPropertiesRepository.offLine(lazyNettyServerProperties);
clientOffLine(clientId);
}
@Override
public void stagingOpen(String clientId) {
// String stagingStatusKey = StagingConfigKeyConstant.getStagingStatusKey(clientId);
// stringRedisTemplate.opsForValue().set(stagingStatusKey, StagingStatus.OPENED.name());
}
/**
* 暂存关闭
*
* @param clientId 租户ID
*/
@Override
public void stagingClose(String clientId) {
// if (clientId == null) {
// clientId = stringRedisTemplate.opsForValue().get(ClientConfigKeyUtils.CLIENT_ID_KEY);
// }
// String stagingStatusKey = StagingConfigKeyConstant.getStagingStatusKey(clientId);
// stringRedisTemplate.opsForValue().set(stagingStatusKey, StagingStatus.CLOSED.name());
}
}

View File

@ -0,0 +1,45 @@
package org.framework.smart.agent.network.heartbeat.client.netty.filter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import org.framework.smart.agent.network.heartbeat.client.netty.handler.NettyClientHandler;
import org.framework.smart.agent.network.heartbeat.client.netty.socket.NettyClientSocket;
import org.framework.smart.agent.network.heartbeat.common.adapter.ChannelTypeAdapter;
import org.framework.smart.agent.network.heartbeat.common.decoder.NettyProxyMsgDecoder;
import org.framework.smart.agent.network.heartbeat.common.encoder.NettyProxyMsgEncoder;
public class NettyClientFilter extends ChannelInitializer<SocketChannel> {
private final ChannelTypeAdapter channelTypeAdapter;
private final NettyClientSocket nettyClientSocket;
public NettyClientFilter(ChannelTypeAdapter channelTypeAdapter, NettyClientSocket nettyClientSocket) {
this.channelTypeAdapter = channelTypeAdapter;
this.nettyClientSocket = nettyClientSocket;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
/* * 解码和编码,应和服务端一致 * */
// pipeline.addLast(new NettyMsgDecoder(Integer.MAX_VALUE, 0, 4, -4, 0));
// pipeline.addLast(new NettMsgEncoder());
// 解码、编码
pipeline.addLast(new NettyProxyMsgDecoder(Integer.MAX_VALUE, 0, 4, -4, 0));
pipeline.addLast(new NettyProxyMsgEncoder());
// pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
//入参说明: 读超时时间、写超时时间、所有类型的超时时间、时间格式
//因为服务端设置的超时时间是5秒所以设置4秒
pipeline.addLast(new IdleStateHandler(0, 4, 0));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("doHandler", new NettyClientHandler(channelTypeAdapter, nettyClientSocket)); //客户端的逻辑
}
}

View File

@ -0,0 +1,30 @@
package org.framework.smart.agent.network.heartbeat.client.netty.filter;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import org.framework.smart.agent.network.heartbeat.client.netty.handler.NettyClientRealHandler;
public class NettyClientRealFilter extends ChannelInitializer<SocketChannel> {
/**
* This method will be called once the {@link Channel} was registered. After the method returns this instance
* will be removed from the {@link ChannelPipeline} of the {@link Channel}.
*
* @param ch the {@link Channel} which was registered.
* @throws Exception is thrown if an error occurs. In that case it will be handled by
* {@link #exceptionCaught(ChannelHandlerContext, Throwable)} which will by default connectionClose
* the {@link Channel}.
*/
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new NettyClientRealHandler());
// // 解码、编码
// pipeline.addLast(new NettyProxyMsgDecoder(Integer.MAX_VALUE, 0, 4, -4, 0));
// pipeline.addLast(new NettMsgEncoder());
// pipeline.addLast(new NettyProxyMsgDecoder(Integer.MAX_VALUE, 0, 4, -4, 0));
// pipeline.addLast(new NettyProxyMsgEncoder());
}
}

View File

@ -0,0 +1,42 @@
package org.framework.smart.agent.network.heartbeat.client.netty.filter;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import org.framework.smart.agent.network.heartbeat.client.netty.handler.NettyClientVisitorRealHandler;
import org.framework.smart.agent.network.heartbeat.common.adapter.ChannelTypeAdapter;
import org.framework.smart.agent.network.heartbeat.common.decoder.NettyProxyMsgDecoder;
import org.framework.smart.agent.network.heartbeat.common.encoder.NettyProxyMsgEncoder;
/**
* netty 客户端连接真实服服务端访客拦截器
*/
public class NettyClientVisitorRealFilter extends ChannelInitializer<SocketChannel> {
private final ChannelTypeAdapter channelTypeAdapter;
public NettyClientVisitorRealFilter(ChannelTypeAdapter channelTypeAdapter) {
this.channelTypeAdapter = channelTypeAdapter;
}
/**
* This method will be called once the {@link Channel} was registered. After the method returns this instance
* will be removed from the {@link ChannelPipeline} of the {@link Channel}.
*
* @param ch the {@link Channel} which was registered.
* @throws Exception is thrown if an error occurs. In that case it will be handled by
* {@link #exceptionCaught(ChannelHandlerContext, Throwable)} which will by default connectionClose
* the {@link Channel}.
*/
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// // 解码、编码
// pipeline.addLast(new NettyProxyMsgDecoder(Integer.MAX_VALUE, 0, 4, -4, 0));
// pipeline.addLast(new NettMsgEncoder());
pipeline.addLast(new NettyProxyMsgDecoder(Integer.MAX_VALUE, 0, 4, -4, 0));
pipeline.addLast(new NettyProxyMsgEncoder());
pipeline.addLast(new NettyClientVisitorRealHandler(channelTypeAdapter));
}
}

View File

@ -0,0 +1,24 @@
package org.framework.smart.agent.network.heartbeat.client.netty.handler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import java.util.Date;
public class HeartBeatClientHandler extends ChannelInboundHandlerAdapter {
private final int lossConnectCount = 0;
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
System.out.println("客户端循环心跳监测发送: " + new Date());
if (evt instanceof IdleStateEvent event) {
if (event.state() == IdleState.WRITER_IDLE) {
ctx.writeAndFlush("biubiu");
}
}
}
}

View File

@ -0,0 +1,121 @@
package org.framework.smart.agent.network.heartbeat.client.netty.handler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.EventLoop;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.client.netty.socket.NettyClientSocket;
import org.framework.smart.agent.network.heartbeat.common.MessageType;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.adapter.ChannelTypeAdapter;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.concurrent.TimeUnit;
/**
* description
*
* @author 吴佳伟
* @date 2023/09/13 10:29
*/
@Slf4j
public class NettyClientHandler extends SimpleChannelInboundHandler<NettyProxyMsg> {
private final ChannelTypeAdapter channelTypeAdapter;
private final NettyClientSocket nettyClientSocket;
public NettyClientHandler(ChannelTypeAdapter channelTypeAdapter, NettyClientSocket nettyClientSocket) {
this.channelTypeAdapter = channelTypeAdapter;
this.nettyClientSocket = nettyClientSocket;
}
/**
* @param ctx the {@link ChannelHandlerContext} which this {@link SimpleChannelInboundHandler}
* belongs to
* @param msg the message to handle
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, NettyProxyMsg msg) {
// log.info("第" + count + "次" + ",客户端接受的消息:" + msg);
// log.info("第" + count + "次" + ",客户端接受的消息内容:" + new String(msg.getData()));
// count++;
// 接收服务端、或者是代理端的信息
Channel channel = ctx.channel();
// log.info("type:{},clientId:{},data:{}",msg.getMysqlType(),new String(msg.getClientId()),new String(msg.getData()));
channelTypeAdapter.handler(channel, msg);
}
/**
* 建立连接时
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// 建立连接时
log.info("When establishing a connection{}" , new Date());
ctx.fireChannelActive();
String clientId = nettyClientSocket.getClientId();
// 处理客户端连接成功
Channel channel = ctx.channel();
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setType(MessageType.CLIENT_CHANNEL_ACTIVE);
nettyMsg.setClientId(clientId);
channelTypeAdapter.handler(channel, nettyMsg);
}
/**
* 关闭连接时
*/
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
//服务端主动关闭当前客户端连接时
log.info("When the server actively closes the current client connection{}" , new Date());
final EventLoop eventLoop = ctx.channel().eventLoop();
eventLoop.schedule(() -> {
try {
nettyClientSocket.newConnect2Server();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}, 1L, TimeUnit.SECONDS);
super.channelInactive(ctx);
}
/**
* 心跳请求处理 * 每4秒发送一次心跳请求; *
*/
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object obj) throws Exception {
if (obj instanceof IdleStateEvent event) {
if (IdleState.WRITER_IDLE.equals(event.state())) { //如果写通道处于空闲状态,就发送心跳命令
String clientId = nettyClientSocket.getClientId();
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setType(MessageType.TYPE_HEARTBEAT);
nettyMsg.setData(clientId.getBytes(StandardCharsets.UTF_8));
nettyMsg.setClientId(clientId.getBytes(StandardCharsets.UTF_8));
ctx.writeAndFlush(nettyMsg);// 发送心跳数据
} else if (event.state() == IdleState.WRITER_IDLE) { // 如果检测到写空闲状态,关闭连接
// 离线、暂存通知
String clientId = nettyClientSocket.getClientId();
Channel channel = ctx.channel();
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setType(MessageType.DISTRIBUTE_CLIENT_DISCONNECTION_NOTIFICATION);
nettyMsg.setClientId(clientId.getBytes(StandardCharsets.UTF_8));
channelTypeAdapter.handler(channel, nettyMsg);
ctx.close();
}
} else {
super.userEventTriggered(ctx, obj);
}
}
}

View File

@ -0,0 +1,85 @@
package org.framework.smart.agent.network.heartbeat.client.netty.handler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.common.MessageType;
import org.framework.smart.agent.network.heartbeat.common.NettyCommunicationIdContext;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
/**
* 来自客户端 真实服务器返回的数据请求
*/
@Slf4j
public class NettyClientRealHandler extends SimpleChannelInboundHandler<ByteBuf> {
@Override
public void channelRead0(ChannelHandlerContext ctx, ByteBuf buf) throws Exception {
// 客户端发送真实数据到代理了
byte[] bytes = new byte[buf.readableBytes()];
buf.readBytes(bytes);
log.debug("接收客户端真实服务数据:{}", new String(bytes));
String visitorId = ChannelAttributeKeyUtils.getVisitorId(ctx.channel());
Integer visitorPort = ChannelAttributeKeyUtils.getVisitorPort(ctx.channel());
String clientId = ChannelAttributeKeyUtils.getClientId(ctx.channel());
// 访客通信通道 上报服务端代理完成
Channel visitorChannel = NettyCommunicationIdContext.getVisitor(visitorId);
NettyProxyMsg returnMessage = new NettyProxyMsg();
returnMessage.setType(MessageType.REPORT_CLIENT_TRANSFER);
returnMessage.setVisitorId(visitorId);
returnMessage.setClientId(clientId);
returnMessage.setVisitorPort(visitorPort);
returnMessage.setData(bytes);
visitorChannel.writeAndFlush(returnMessage);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
String clientId = ChannelAttributeKeyUtils.getClientId(ctx.channel());
String visitorId = ChannelAttributeKeyUtils.getVisitorId(ctx.channel());
// 客户端真实通信通道
Channel visitor = NettyCommunicationIdContext.getVisitor(visitorId);
if (visitor != null) {
// 上报关闭这个客户端的访客通道
NettyProxyMsg closeVisitorMsg = new NettyProxyMsg();
closeVisitorMsg.setType(MessageType.REPORT_SINGLE_CLIENT_CLOSE_VISITOR);
closeVisitorMsg.setVisitorId(visitorId);
visitor.writeAndFlush(closeVisitorMsg);
}
super.channelInactive(ctx);
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
// String vid = ctx.channel().attr(Constant.VID).get();
// if (StringUtil.isNullOrEmpty(vid)) {
// super.channelWritabilityChanged(ctx);
// return;
// }
// Channel proxyChannel = Constant.vpc.get(vid);
// if (proxyChannel != null) {
// proxyChannel.config().setOption(ChannelOption.AUTO_READ, ctx.channel().isWritable());
// }
super.channelWritabilityChanged(ctx);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
super.exceptionCaught(ctx, cause);
}
}

View File

@ -0,0 +1,66 @@
package org.framework.smart.agent.network.heartbeat.client.netty.handler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.common.ChannelContext;
import org.framework.smart.agent.network.heartbeat.common.MessageType;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.adapter.ChannelTypeAdapter;
import org.framework.smart.agent.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
/**
* 客户端访客通信通道 处理器
*/
@Slf4j
public class NettyClientVisitorRealHandler extends SimpleChannelInboundHandler<NettyProxyMsg> {
private final ChannelTypeAdapter channelTypeAdapter;
public NettyClientVisitorRealHandler(ChannelTypeAdapter channelTypeAdapter) {
this.channelTypeAdapter = channelTypeAdapter;
}
@Override
public void channelRead0(ChannelHandlerContext ctx, NettyProxyMsg nettyProxyMsg) throws Exception {
Channel channel = ctx.channel();
channelTypeAdapter.handler(channel, nettyProxyMsg);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
String clientId = ChannelAttributeKeyUtils.getClientId(ctx.channel());
String visitorId = ChannelAttributeKeyUtils.getVisitorId(ctx.channel());
// 关闭访客
ChannelContext.ClientChannel clientChannel = ChannelContext.get(clientId);
if (clientChannel != null) {
Channel channel = clientChannel.getChannel();
// 上报关闭这个客户端的访客通道
NettyProxyMsg closeVisitorMsg = new NettyProxyMsg();
closeVisitorMsg.setType(MessageType.REPORT_SINGLE_CLIENT_CLOSE_VISITOR);
closeVisitorMsg.setVisitorId(visitorId);
channel.writeAndFlush(closeVisitorMsg);
}
super.channelInactive(ctx);
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception {
super.channelWritabilityChanged(ctx);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
super.exceptionCaught(ctx, cause);
}
}

View File

@ -0,0 +1,53 @@
//package org.framework.smart.agent.network.heartbeat.client.netty.listener;
//
//
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.stereotype.Component;
//import org.framework.smart.agent.network.heartbeat.client.netty.config.NettyClientProperties;
//import org.framework.smart.agent.network.heartbeat.client.rpc.StagingNoticeApiRpc;
//import org.framework.smart.agent.network.heartbeat.common.constant.RedisChannelConstant;
//
///**
// * 客户端暂存开启、关闭通知
// *
// * @see RedisChannelConstant#REDIS_CLIENT_STAGING_OPENED_OR_CLOSED_CHANNEL
// */
//@Slf4j
//@Component
//public class ClientStagingOpenedOrClosedListener {
//
// private final StagingNoticeApiRpc stagingNoticeApiRpc;
// private final NettyClientProperties nettyServerProperties;
//
//
// public ClientStagingOpenedOrClosedListener(StagingNoticeApiRpc stagingNoticeApiRpc, NettyClientProperties nettyServerProperties) {
// this.stagingNoticeApiRpc = stagingNoticeApiRpc;
// this.nettyServerProperties = nettyServerProperties;
//
// }
//
//// /**
//// * 使用redis监听注解监听数据
//// *
//// * @param consumerRecord 客户端暂存开启、关闭通知
//// */
//// @EasyRedisListener(topics = RedisChannelConstant.REDIS_CLIENT_STAGING_OPENED_OR_CLOSED_CHANNEL)
//// public void subscription(ConsumerRecord<String, ClientStagingRedisChannelBo> consumerRecord, Acknowledgment acknowledgment) {
//// ClientStagingRedisChannelBo payload = consumerRecord.payload();
//// String clientId = payload.getClientId();
//// // 如果客户端ID为空默认当前客户端
//// if (ObjectUtils.isEmpty(clientId)) {
//// clientId = nettyServerProperties.getClientId();
//// }
//// StagingStatus stagingStatus = payload.getStagingStatus();
//// log.info("客户端:【{}】暂存:【{}】通知", clientId, stagingStatus);
////
////
//// if (StagingStatus.OPENED.equals(stagingStatus)) {
//// stagingNoticeApiRpc.stagingOpened(clientId);
//// } else if (StagingStatus.CLOSED.equals(stagingStatus)) {
//// stagingNoticeApiRpc.stagingClosed(clientId);
//// }
//// acknowledgment.acknowledge();
//// }
//}

View File

@ -0,0 +1,183 @@
package org.framework.smart.agent.network.heartbeat.client.netty.socket;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.client.config.NettyClientProperties;
import org.framework.smart.agent.network.heartbeat.client.netty.filter.NettyClientRealFilter;
import org.framework.smart.agent.network.heartbeat.client.netty.filter.NettyClientVisitorRealFilter;
import org.framework.smart.agent.network.heartbeat.common.*;
import org.framework.smart.agent.network.heartbeat.common.adapter.ChannelTypeAdapter;
import org.framework.smart.agent.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
import org.framework.smart.agent.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 客户端连接真实服务
*/
@Slf4j
public class NettyClientRealSocket {
static EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
/**
* 连接真实服务
*
* @param internalNetworkPenetrationRealClient 访客信息
* @param nettyClientProperties 服务端地址信息
*/
public static void buildRealServer(InternalNetworkPenetrationRealClient internalNetworkPenetrationRealClient,
NettyClientProperties nettyClientProperties,
List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
buildNewRealServer(internalNetworkPenetrationRealClient, nettyClientProperties, handleChannelTypeAdvancedList);
}
/**
* @param internalNetworkPenetrationRealClient 访客信息
* @param nettyClientProperties 服务端地址信息
*/
private static void buildNewRealServer(InternalNetworkPenetrationRealClient internalNetworkPenetrationRealClient,
NettyClientProperties nettyClientProperties,
List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
try {
String clientId = internalNetworkPenetrationRealClient.getClientId();
String clientTargetIp = internalNetworkPenetrationRealClient.getClientTargetIp();
Integer clientTargetPort = internalNetworkPenetrationRealClient.getClientTargetPort();
Integer visitorPort = internalNetworkPenetrationRealClient.getVisitorPort();
String visitorId = internalNetworkPenetrationRealClient.getVisitorId();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
.handler(new NettyClientRealFilter());
bootstrap.connect(clientTargetIp, clientTargetPort).addListener((ChannelFutureListener) future -> {
if (future.isSuccess()) {
// 客户端链接真实服务成功 设置自动读写false 等待访客连接成功后设置成true
Channel realChannel = future.channel();
realChannel.config().setOption(ChannelOption.AUTO_READ, false);
log.info("访客通过 客户端:【{}】,绑定本地服务,IP:{},端口:{} 新建通道成功", clientId, clientTargetIp, clientTargetPort);
// 客户端真实通道
NettyRealIdContext.pushReal(realChannel, visitorId);
// 绑定访客ID到当前真实通道属性
ChannelAttributeKeyUtils.buildVisitorId(realChannel, visitorId);
ChannelAttributeKeyUtils.buildClientId(realChannel, clientId);
ChannelAttributeKeyUtils.buildVisitorPort(realChannel, visitorPort);
// 通知服务端访客连接成功
// 新建一个通道处理
newVisitorConnect2Server(internalNetworkPenetrationRealClient, nettyClientProperties, handleChannelTypeAdvancedList);
// 是否等 服务端相应访客通道已经可以自动读写
// realChannel.config().setOption(ChannelOption.AUTO_READ, true);
// 模拟发送
String byteData = "GET /swagger-ui/index.html HTTP/1.1\n" +
"Host: 127.0.0.1:19080\n" +
"Connection: keep-alive\n" +
"Cache-Control: max-age=0\n" +
"sec-ch-ua: \"Not_A Brand\";v=\"8\", \"Chromium\";v=\"120\", \"Google Chrome\";v=\"120\"\n" +
"sec-ch-ua-mobile: ?0\n" +
"sec-ch-ua-platform: \"macOS\"\n" +
"Upgrade-Insecure-Requests: 1\n" +
"User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36\n" +
"Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\n" +
"Sec-Fetch-Site: none\n" +
"Sec-Fetch-Mode: navigate\n" +
"Sec-Fetch-User: ?1\n" +
"Sec-Fetch-Dest: document\n" +
"Accept-Encoding: gzip, deflate, br\n" +
"Accept-Language: zh-CN,zh;q=0.9\n" +
"Cookie: XXL_JOB_LOGIN_IDENTITY=7b226964223a312c22757365726e616d65223a2261646d696e222c2270617373776f7264223a226531306164633339343962613539616262653536653035376632306638383365222c22726f6c65223a312c227065726d697373696f6e223a6e756c6c7d; Hm_lvt_173e771eef816c412396d2cb4fe2d632=1703040917\n";
// ChannelContext.ClientChannel clientChannel = ChannelContext.get(String.valueOf(visitorPort).getBytes(StandardCharsets.UTF_8));
// Channel channel = clientChannel.getChannel();
// channel.writeAndFlush(byteData.getBytes(StandardCharsets.UTF_8));
// future.channel().attr(Constant.VID).set(internalNetworkPenetrationRealClient);
// Constant.vrc.put(internalNetworkPenetrationRealClient, future.channel());
// ProxySocket.connectProxyServer(internalNetworkPenetrationRealClient);
} else {
log.error("客户:【{}】,无法连接当前网络内的目标IP【{}】,目标端口:【{}】", clientId, clientTargetIp, clientTargetPort);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建访客连接服务端
*
* @param internalNetworkPenetrationRealClient 内网穿透信息
* @param nettyClientProperties 服务端配置信息
* @param handleChannelTypeAdvancedList 处理器适配器
* @throws InterruptedException 异常
*/
protected static void newVisitorConnect2Server(InternalNetworkPenetrationRealClient internalNetworkPenetrationRealClient,
NettyClientProperties nettyClientProperties,
List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) throws InterruptedException {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup)
.channel(NioSocketChannel.class)
.handler(new NettyClientVisitorRealFilter(new ChannelTypeAdapter(handleChannelTypeAdvancedList)))
;
String inetHost = nettyClientProperties.getInetHost();
int inetPort = nettyClientProperties.getInetPort();
// local client id
String clientId = nettyClientProperties.getClientId();
String visitorId = internalNetworkPenetrationRealClient.getVisitorId();
Integer visitorPort = internalNetworkPenetrationRealClient.getVisitorPort();
String clientTargetIp = internalNetworkPenetrationRealClient.getClientTargetIp();
Integer clientTargetPort = internalNetworkPenetrationRealClient.getClientTargetPort();
String visitorClientId = internalNetworkPenetrationRealClient.getClientId();
// 客户端新建访客通道 连接服务端IP:{},连接服务端端口:{}
log.info("Client creates a new visitor channel to connect to server IP: {}, connecting to server port: {}", inetHost, inetPort);
ChannelFuture future = bootstrap.connect(inetHost, inetPort);
// 使用的客户端ID:{}
log.info("Client ID used: {}" , visitorClientId);
future.addListener((ChannelFutureListener) futureListener -> {
Channel channel = futureListener.channel();
if (futureListener.isSuccess()) {
NettyProxyMsg myMsg = new NettyProxyMsg();
myMsg.setType(MessageType.REPORT_SINGLE_CLIENT_REAL_CONNECT);
myMsg.setClientId(visitorClientId);
myMsg.setVisitorPort(visitorPort);
myMsg.setClientTargetIp(clientTargetIp);
myMsg.setClientTargetPort(clientTargetPort);
myMsg.setVisitorId(visitorId);
channel.writeAndFlush(myMsg);
// 绑定客户端真实通信通道
NettyCommunicationIdContext.pushVisitor(channel, visitorId);
ChannelAttributeKeyUtils.buildVisitorId(channel, visitorId);
ChannelAttributeKeyUtils.buildClientId(channel, visitorClientId);
// 客户端真实通道自动读写打开
Channel visitor = NettyRealIdContext.getReal(visitorId);
visitor.config().setOption(ChannelOption.AUTO_READ, true);
} else {
log.info("每隔2s重连....");
// 离线
channel.eventLoop().schedule(() -> {
try {
newVisitorConnect2Server(internalNetworkPenetrationRealClient, nettyClientProperties, handleChannelTypeAdvancedList);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, 2, TimeUnit.SECONDS);
}
});
}
}

View File

@ -0,0 +1,122 @@
package org.framework.smart.agent.network.heartbeat.client.netty.socket;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.framework.smart.agent.network.heartbeat.client.netty.event.ClientChangeEvent;
import org.framework.smart.agent.network.heartbeat.client.netty.filter.NettyClientFilter;
import org.framework.smart.agent.network.heartbeat.common.MessageType;
import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
import org.framework.smart.agent.network.heartbeat.common.NettyServerContext;
import org.framework.smart.agent.network.heartbeat.common.adapter.ChannelTypeAdapter;
import org.framework.smart.agent.network.heartbeat.common.advanced.HandleChannelTypeAdvanced;
import org.framework.smart.agent.network.heartbeat.common.utils.ChannelAttributeKeyUtils;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* 客户端连接服务端
*/
@Slf4j
public class NettyClientSocket {
private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
/**
* 服务端host
*/
private final String inetHost;
/**
* 服务端端口
*/
private final int inetPort;
/**
* 当前客户端id
*/
@Getter
private final String clientId;
/**
* 当前连接的服务端ID
*/
private final String serverId;
/**
* 客户端状态变更事件
*/
@Getter
private final ClientChangeEvent clientChangeEvent;
private final List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList; // 处理服务端发送过来的数据类型
public NettyClientSocket(String inetHost, int inetPort, String clientId, String serverId, ClientChangeEvent clientChangeEvent, List<HandleChannelTypeAdvanced> handleChannelTypeAdvancedList) {
this.inetHost = inetHost;
this.inetPort = inetPort;
this.clientId = clientId;
this.serverId = serverId;
this.clientChangeEvent = clientChangeEvent;
this.handleChannelTypeAdvancedList = handleChannelTypeAdvancedList;
}
public void newConnect2Server() throws InterruptedException {
newConnect2Server(inetHost, inetPort, clientId, serverId, clientChangeEvent);
}
protected void newConnect2Server(String inetHost, int inetPort, String clientId, String serverId, ClientChangeEvent clientChangeEvent) throws InterruptedException {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventLoopGroup)
.channel(NioSocketChannel.class)
.handler(new NettyClientFilter(new ChannelTypeAdapter(handleChannelTypeAdvancedList), this))
;
log.info("use clientId:{} connect to server IP:{},server port :{}", clientId, inetHost, inetPort);
ChannelFuture future = bootstrap.connect(inetHost, inetPort);
// 客户端连接服务端的channel
Channel serviceChannel = future.channel();
future.addListener((ChannelFutureListener) futureListener -> {
if (futureListener.isSuccess()) {
log.info("clientId:{},connect to server IP:{},server port :{} isSuccess ", clientId, inetHost, inetPort);
// 告诉服务端这条连接是client的连接
NettyProxyMsg nettyMsg = new NettyProxyMsg();
nettyMsg.setType(MessageType.REPORT_CLIENT_CONNECT_SUCCESS);
nettyMsg.setClientId(clientId);
nettyMsg.setData((clientId).getBytes());
ChannelAttributeKeyUtils.buildClientId(serviceChannel, clientId);
serviceChannel.writeAndFlush(nettyMsg);
NettyServerContext.pushServerEndpointChannel(serverId, clientId, serviceChannel);
// 在线 客户端注册服务端成功
clientChangeEvent.clientOnLine(inetHost, inetPort,serverId, clientId);
} else {
log.warn("Reconnect every 2 seconds....");
// 离线
NettyServerContext.removeServerEndpointChannels(serverId, clientId);
clientChangeEvent.clientOffLine(inetHost, inetPort,serverId, clientId);
futureListener.channel().eventLoop().schedule(() -> {
try {
newConnect2Server(inetHost, inetPort, clientId, serverId, clientChangeEvent);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, 2, TimeUnit.SECONDS);
}
});
}
/**
* 关闭连接
*/
public void shutdown() {
if ((eventLoopGroup != null) && (!eventLoopGroup.isShutdown())) {
eventLoopGroup.shutdownGracefully();
}
}
}

View File

@ -0,0 +1,65 @@
//package org.framework.smart.agent.network.heartbeat.client.rpc;
//
//import org.wu.framework.database.lazy.web.plus.stereotype.LazyRpc;
//import org.wu.framework.web.response.Result;
//import org.wu.framework.web.response.ResultFactory;
//import io.netty.channel.Channel;
//import org.framework.smart.agent.network.heartbeat.common.ChannelContext;
//import org.framework.smart.agent.network.heartbeat.common.MessageType;
//import org.framework.smart.agent.network.heartbeat.common.NettyProxyMsg;
//
//import java.nio.charset.StandardCharsets;
//import java.util.List;
//
//@LazyRpc
//public class StagingNoticeApiRpc {
//
//
// /**
// * 前提当前客户端曾经有过离线、而后上线了,但是呢现在有暂存的数据,因此暂存是打开的,所以这个时候可以通知服务端让其告知其他客户户我暂存了
// * 通知自己暂存了
// *
// * @param clientId 租户ID
// * @return
// */
// public Result<Void> stagingOpened(String clientId) {
// List<ChannelContext.ClientChannel> clientChannels = ChannelContext.get();
// for (ChannelContext.ClientChannel clientChannel : clientChannels) {
// // 上报 当前通道暂存开启了
// Channel channel = clientChannel.getChannel();
//
// NettyProxyMsg nettyMsg = new NettyProxyMsg();
// nettyMsg.setType(MessageType.REPORT_CLIENT_STAGING_OPENED);
// nettyMsg.setData((clientId
// .getBytes(StandardCharsets.UTF_8)));
// nettyMsg.setClientId((clientId
// .getBytes(StandardCharsets.UTF_8)));
// channel.writeAndFlush(nettyMsg);
// }
//
// return ResultFactory.successOf();
// }
//
// /**
// * 暂存恢复
// *
// * @param clientId 租户ID
// * @return
// */
// public Result<Void> stagingClosed(String clientId) {
// List<ChannelContext.ClientChannel> clientChannels = ChannelContext.get();
// for (ChannelContext.ClientChannel clientChannel : clientChannels) {
// // 上报 当前通道暂存关闭了
// Channel channel = clientChannel.getChannel();
// NettyProxyMsg nettyMsg = new NettyProxyMsg();
// nettyMsg.setType(MessageType.REPORT_CLIENT_STAGING_CLOSED);
// nettyMsg.setData((clientId
// .getBytes(StandardCharsets.UTF_8)));
// nettyMsg.setClientId((clientId
// .getBytes(StandardCharsets.UTF_8)));
// channel.writeAndFlush(nettyMsg);
// }
//
// return ResultFactory.successOf();
// }
//}

View File

@ -0,0 +1,65 @@
package org.framework.smart.agent.network.heartbeat.client.ui;
import org.springframework.context.annotation.Configuration;
import org.wu.framework.web.ui.LazyUI;
/**
* netty 客户端本地UI
*/
@Configuration
public class NettyClientLocalLazyUI implements LazyUI {
public static final String UI_URL = "/netty-client-local-ui/**";
public static final String UI_URL_INDEX = "/netty-client-local-ui/index.html";
public static final String CLASSPATH = "classpath:/netty-client-local-ui/v1/";
/**
* 是否支持 default false
* <p>
* pathPatterns 格式 /acw-client-ui/**
* locations 格式 classpath:/acw-local-client/v1/
* </p>
*
* @return true、false
*/
@Override
public boolean support() {
return true;
}
/**
* @return UI 描述
*/
@Override
public String desc() {
return "Netty 本地客户端 UI";
}
/**
* @return UI 访问的path
* 例如:/acw-client-ui/**
*/
@Override
public String pathPatterns() {
return UI_URL;
}
/**
* 返回页面首页地址
*
* @return String
* 例如 /acw-client-ui/index.html
*/
@Override
public String index() {
return UI_URL_INDEX;
}
/**
* @return 文件资源
* 例如classpath:/acw-local-client/v1/
*/
@Override
public String locations() {
return CLASSPATH;
}
}

View File

@ -0,0 +1,6 @@
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.framework.smart.agent.network.heartbeat.client.EnableHeartbeatClientAutoConfiguration,\
org.framework.smart.agent.network.heartbeat.client.config.NettyClientProperties,\
org.framework.smart.agent.network.heartbeat.client.config.InitConfig,\
org.framework.smart.agent.network.heartbeat.client.config.HeartbeatClientConfiguration

View File

@ -0,0 +1,4 @@
org.framework.smart.agent.network.heartbeat.client.EnableHeartbeatClientAutoConfiguration
org.framework.smart.agent.network.heartbeat.client.config.NettyClientProperties
org.framework.smart.agent.network.heartbeat.client.config.InitConfig
org.framework.smart.agent.network.heartbeat.client.config.HeartbeatClientConfiguration

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="./favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Java 使用 Lazy ORM 网络穿透客户端!</title>
<script type="module" crossorigin src="assets/index-BTaJShFE.js"></script>
<link rel="stylesheet" crossorigin href="./assets/index-C9GutiFy.css">
</head>
<body>
<div id="app"></div>
</body>
</html>