mirror of
https://gitee.com/dromara/orion-visor.git
synced 2026-06-10 11:16:57 +08:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72695af0f0 | ||
|
|
3a5b84eec4 | ||
|
|
387ed53328 | ||
|
|
c9cbc5fd55 | ||
|
|
ae03460a33 | ||
|
|
4b060a864a | ||
|
|
07e8e63ee6 | ||
|
|
ab1d4ed97f | ||
|
|
2bd7dfd5b8 | ||
|
|
c39049e5f5 | ||
|
|
5113aa63bd | ||
|
|
518fd8c839 | ||
|
|
a046faaa07 | ||
|
|
dcf25392ff | ||
|
|
7f24948efa | ||
|
|
59d9739f36 | ||
|
|
26a6d08d96 | ||
|
|
cd59c51344 |
13
README.md
13
README.md
@@ -51,12 +51,13 @@
|
||||
|
||||
## 演示环境
|
||||
|
||||
演示地址: http://101.43.254.243:1081/
|
||||
演示账号: admin/admin
|
||||
|
||||
⭐ 体验后可以点一下 `star` 这对我很重要!
|
||||
🌈 如果本项目对你有帮助请帮忙推广一下 让更多的人知道此项目!
|
||||
[github](https://github.com/lijiahangmax/orion-visor) [gitee](https://gitee.com/lijiahangmax/orion-visor)
|
||||
* 🔗 演示地址: http://101.43.254.243:1081/
|
||||
* 🔏 演示账号: admin/admin
|
||||
* ⭐ 体验后可以点一下 `star` 这对我很重要! [github](https://github.com/lijiahangmax/orion-visor) [gitee](https://gitee.com/lijiahangmax/orion-visor)
|
||||
* 🌈 如果本项目对你有帮助请帮忙推广一下 让更多的人知道此项目!
|
||||
* 🎭 演示环境部分功能不可用, 完整功能请本地部署!
|
||||
* 📛 演示环境请不要随便删除数据!
|
||||
* 📧 如果演示环境不可用请联系我!
|
||||
|
||||
## 快速开始
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
version: '3.3'
|
||||
services:
|
||||
orion-visor-service:
|
||||
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:2.0.4
|
||||
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-service:2.0.7
|
||||
ports:
|
||||
- 1081:80
|
||||
environment:
|
||||
@@ -20,7 +20,7 @@ services:
|
||||
- orion-visor-mysql
|
||||
- orion-visor-redis
|
||||
orion-visor-mysql:
|
||||
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:2.0.4
|
||||
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-mysql:2.0.7
|
||||
privileged: true
|
||||
ports:
|
||||
- 3307:3306
|
||||
@@ -34,7 +34,7 @@ services:
|
||||
- /data/orion-visor-space/docker-volumes/orion-visor-mysql/var-lib-mysql-files:/var/lib/mysql-files
|
||||
- /data/orion-visor-space/docker-volumes/orion-visor-mysql/etc-mysql:/etc/mysql
|
||||
orion-visor-redis:
|
||||
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:2.0.4
|
||||
image: registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:2.0.7
|
||||
privileged: true
|
||||
ports:
|
||||
- 6380:6379
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#/bin/bash
|
||||
version=2.0.4
|
||||
version=2.0.7
|
||||
cp -r ../../sql ./sql
|
||||
docker build -t orion-visor-mysql:${version} .
|
||||
rm -rf ./sql
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#/bin/bash
|
||||
version=2.0.4
|
||||
version=2.0.7
|
||||
docker build -t orion-visor-redis:${version} .
|
||||
docker tag orion-visor-redis:${version} registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:${version}
|
||||
docker push registry.cn-hangzhou.aliyuncs.com/lijiahangmax/orion-visor-redis:${version}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#/bin/bash
|
||||
version=2.0.4
|
||||
version=2.0.7
|
||||
mv ../../orion-visor-launch/target/orion-visor-launch.jar ./orion-visor-launch.jar
|
||||
mv ../../orion-visor-ui/dist ./dist
|
||||
docker build -t orion-visor-service:${version} .
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<url>https://github.com/lijiahangmax/orion-visor</url>
|
||||
|
||||
<properties>
|
||||
<revision>2.0.4</revision>
|
||||
<revision>2.0.7</revision>
|
||||
<spring.boot.version>2.7.17</spring.boot.version>
|
||||
<spring.boot.admin.version>2.7.15</spring.boot.admin.version>
|
||||
<flatten.maven.plugin.version>1.5.0</flatten.maven.plugin.version>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.orion.visor.framework.common.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 保留
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/6/6 15:26
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Keep {
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@ public interface AppConst extends OrionConst {
|
||||
/**
|
||||
* 同 ${orion.version} 迭代时候需要手动更改
|
||||
*/
|
||||
String VERSION = "2.0.4";
|
||||
String VERSION = "2.0.7";
|
||||
|
||||
String ORION_VISOR = "orion-visor";
|
||||
|
||||
|
||||
@@ -25,8 +25,6 @@ public interface Const extends com.orion.lang.constant.Const, FieldConst, CnCons
|
||||
|
||||
Integer DEFAULT_SORT = 10;
|
||||
|
||||
int LOGIN_HISTORY_COUNT = 30;
|
||||
|
||||
Long NONE_ID = -1L;
|
||||
|
||||
Integer DEFAULT_VERSION = 1;
|
||||
|
||||
@@ -97,4 +97,6 @@ public interface ErrorMessage {
|
||||
|
||||
String PLEASE_CHECK_HOST_SSH = "请检查主机 {} 是否存在/权限/SSH配置";
|
||||
|
||||
String CLIENT_ABORT = "手动中断";
|
||||
|
||||
}
|
||||
|
||||
@@ -14,13 +14,19 @@ import lombok.Getter;
|
||||
@AllArgsConstructor
|
||||
public enum MovePosition {
|
||||
|
||||
// 拖拽到目标元素上
|
||||
/**
|
||||
* 拖拽到目标元素上
|
||||
*/
|
||||
TOP(-1),
|
||||
|
||||
// 拖拽到目标元素中
|
||||
/**
|
||||
* 拖拽到目标元素中
|
||||
*/
|
||||
IN(0),
|
||||
|
||||
// 拖拽到目标元素下
|
||||
/**
|
||||
* 拖拽到目标元素下
|
||||
*/
|
||||
BOTTOM(1),
|
||||
|
||||
;
|
||||
|
||||
@@ -36,24 +36,47 @@ public class BannerApplicationRunner implements ApplicationRunner {
|
||||
@Value("${management.endpoints.web.base-path:''}")
|
||||
private String managementEndpoints;
|
||||
|
||||
@Value("${springdoc.api-docs.enabled}")
|
||||
private Boolean apiDocsEnabled;
|
||||
|
||||
@Value("${spring.datasource.druid.stat-view-servlet.enabled}")
|
||||
private Boolean druidConsoleEnabled;
|
||||
|
||||
@Value("#{'${management.endpoints.web.exposure.include}' != 'shutdown'}")
|
||||
private Boolean springBootActuatorEnabled;
|
||||
|
||||
@Value("${spring.boot.admin.client.enabled}")
|
||||
private Boolean springBootAdminClientEnabled;
|
||||
|
||||
@Override
|
||||
public void run(ApplicationArguments args) {
|
||||
String line = AnsiAppender.create()
|
||||
.append(AnsiForeground.BRIGHT_GREEN, ":: orion-visor-launch v" + version + " 服务已启动(" + env + ") ::\n")
|
||||
.append(AnsiForeground.BRIGHT_GREEN, ":: swagger 文档 ")
|
||||
.append(AnsiForeground.BRIGHT_BLUE, "http://127.0.0.1:" + port + "/doc.html\n")
|
||||
.append(AnsiForeground.BRIGHT_GREEN, ":: druid console ")
|
||||
.append(AnsiForeground.BRIGHT_BLUE, "http://127.0.0.1:" + port + "/druid/index.html\n")
|
||||
.append(AnsiForeground.BRIGHT_GREEN, ":: actuator endpoint ")
|
||||
.append(AnsiForeground.BRIGHT_BLUE, "http://127.0.0.1:" + port + managementEndpoints + "\n")
|
||||
.append(AnsiForeground.BRIGHT_GREEN, ":: admin console ")
|
||||
.append(AnsiForeground.BRIGHT_BLUE, "http://127.0.0.1:" + port + adminSeverContextPath + "\n")
|
||||
.append(AnsiForeground.BRIGHT_GREEN, ":: server 健康检测 ")
|
||||
.append(AnsiForeground.BRIGHT_BLUE, "curl -X GET --location \"http://127.0.0.1:" + port + apiPrefix + "/server/bootstrap/health\"")
|
||||
.toString();
|
||||
AnsiAppender appender = AnsiAppender.create()
|
||||
.append(AnsiForeground.BRIGHT_GREEN, ":: orion-visor-launch v" + version + " 服务已启动(" + env + ") ::\n");
|
||||
// swagger 地址
|
||||
if (apiDocsEnabled) {
|
||||
appender.append(AnsiForeground.BRIGHT_GREEN, ":: swagger 文档 ")
|
||||
.append(AnsiForeground.BRIGHT_BLUE, "http://127.0.0.1:" + port + "/doc.html\n");
|
||||
}
|
||||
// druid 控制台
|
||||
if (druidConsoleEnabled) {
|
||||
appender.append(AnsiForeground.BRIGHT_GREEN, ":: druid console ")
|
||||
.append(AnsiForeground.BRIGHT_BLUE, "http://127.0.0.1:" + port + "/druid/index.html\n");
|
||||
}
|
||||
// admin actuator 端点
|
||||
if (springBootActuatorEnabled) {
|
||||
appender.append(AnsiForeground.BRIGHT_GREEN, ":: actuator endpoint ")
|
||||
.append(AnsiForeground.BRIGHT_BLUE, "http://127.0.0.1:" + port + managementEndpoints + "\n");
|
||||
}
|
||||
// admin server 控制台
|
||||
if (springBootAdminClientEnabled) {
|
||||
appender.append(AnsiForeground.BRIGHT_GREEN, ":: admin console ")
|
||||
.append(AnsiForeground.BRIGHT_BLUE, "http://127.0.0.1:" + port + adminSeverContextPath + "\n");
|
||||
}
|
||||
appender.append(AnsiForeground.BRIGHT_GREEN, ":: server 健康检测 ")
|
||||
.append(AnsiForeground.BRIGHT_BLUE, "curl -X GET --location \"http://127.0.0.1:" + port + apiPrefix + "/server/bootstrap/health\"");
|
||||
Threads.start(() -> {
|
||||
Threads.sleep(1000L);
|
||||
System.out.println(line);
|
||||
System.out.println(appender);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -8,4 +8,5 @@ ${AnsiColor.BRIGHT_GREEN}:: Application Name ${AnsiColor.BLUE}${spring.appli
|
||||
${AnsiColor.BRIGHT_GREEN}:: Application Version ${AnsiColor.BLUE}${orion.version}
|
||||
${AnsiColor.BRIGHT_GREEN}:: SpringBoot Version ${AnsiColor.BLUE}${spring-boot.version}
|
||||
${AnsiColor.BRIGHT_GREEN}:: Active Profile ${AnsiColor.BLUE}${spring.profiles.active}
|
||||
${AnsiColor.BRIGHT_GREEN}:: Demo Mode ${AnsiColor.BLUE}${orion.demo}
|
||||
${AnsiColor.DEFAULT}
|
||||
@@ -72,9 +72,9 @@ public class PrettyLogPrinterInterceptor extends AbstractLogPrinterInterceptor {
|
||||
}
|
||||
Method method = invocation.getMethod();
|
||||
// 方法签名
|
||||
requestLog.append("\tmethodSign: ").append(method.getDeclaringClass().getName()).append('#')
|
||||
.append(method.getName()).append("\n");
|
||||
// 参数
|
||||
// requestLog.append("\tmethodSign: ").append(method.getDeclaringClass().getName()).append('#')
|
||||
// .append(method.getName()).append("\n");
|
||||
// 方法参数
|
||||
requestLog.append("\tparameter: ").append(this.requestToString(method, invocation.getArguments()));
|
||||
log.info(requestLog.toString());
|
||||
}
|
||||
|
||||
@@ -73,8 +73,8 @@ public class RowLogPrinterInterceptor extends AbstractLogPrinterInterceptor impl
|
||||
}
|
||||
Method method = invocation.getMethod();
|
||||
// 方法签名
|
||||
fields.put(METHOD_SIGN, method.getDeclaringClass().getName() + "#" + method.getName());
|
||||
// 参数
|
||||
// fields.put(METHOD_SIGN, method.getDeclaringClass().getName() + "#" + method.getName());
|
||||
// 方法参数
|
||||
fields.put(PARAMETER, this.requestToString(method, invocation.getArguments()));
|
||||
log.info("api请求-开始 {}", JSON.toJSONString(fields));
|
||||
fields.clear();
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.orion.visor.framework.redis.configuration.config.RedissonConfig;
|
||||
import com.orion.visor.framework.redis.core.lock.RedisLocker;
|
||||
import com.orion.visor.framework.redis.core.utils.RedisUtils;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.redisson.config.SingleServerConfig;
|
||||
import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||
@@ -14,6 +15,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
@@ -35,6 +37,7 @@ public class OrionRedisAutoConfiguration {
|
||||
* @param redisConnectionFactory factory
|
||||
* @return RedisTemplate
|
||||
*/
|
||||
@Primary
|
||||
@Bean
|
||||
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
|
||||
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
|
||||
@@ -58,6 +61,9 @@ public class OrionRedisAutoConfiguration {
|
||||
return config -> {
|
||||
config.setThreads(redissonConfig.getThreads());
|
||||
config.setNettyThreads(redissonConfig.getNettyThreads());
|
||||
// 单机配置
|
||||
SingleServerConfig single = config.useSingleServer();
|
||||
single.setConnectionMinimumIdleSize(redissonConfig.getMinimumIdleSize());
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,15 @@ public class RedissonConfig {
|
||||
*/
|
||||
private Integer nettyThreads;
|
||||
|
||||
/**
|
||||
* 最小空闲连接数
|
||||
*/
|
||||
private Integer minimumIdleSize;
|
||||
|
||||
public RedissonConfig() {
|
||||
this.threads = 16;
|
||||
this.nettyThreads = 16;
|
||||
this.minimumIdleSize = 16;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,12 @@
|
||||
"type": "java.lang.Integer",
|
||||
"description": "netty 线程数.",
|
||||
"defaultValue": "16"
|
||||
},
|
||||
{
|
||||
"name": "spring.redisson.minimum-idle-size",
|
||||
"type": "java.lang.Integer",
|
||||
"description": "最小空闲连接数.",
|
||||
"defaultValue": "16"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -23,7 +23,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -38,10 +37,9 @@ import java.util.Optional;
|
||||
* @version 1.0.0
|
||||
* @since 2022/6/21 11:22
|
||||
*/
|
||||
@Profile({"dev"})
|
||||
@ConditionalOnClass({OpenAPI.class})
|
||||
@EnableConfigurationProperties(SwaggerConfig.class)
|
||||
@ConditionalOnProperty(prefix = "springdoc.api-docs", name = "enabled", havingValue = "true", matchIfMissing = true)
|
||||
@ConditionalOnProperty(name = "springdoc.api-docs.enabled", havingValue = "true")
|
||||
@AutoConfiguration
|
||||
@AutoConfigureOrder(AutoConfigureOrderConst.FRAMEWORK_SWAGGER)
|
||||
public class OrionSwaggerAutoConfiguration {
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
package com.orion.visor.launch;
|
||||
|
||||
import com.orion.lang.utils.Strings;
|
||||
import com.orion.visor.framework.common.constant.Const;
|
||||
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* application 启动类
|
||||
@@ -14,7 +24,35 @@ import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
public class LaunchApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new SpringApplicationBuilder(LaunchApplication.class).run(args);
|
||||
new SpringApplicationBuilder(LaunchApplication.class)
|
||||
.beanNameGenerator(new CustomBeanNameGenerator())
|
||||
.run(args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义 bean 名称生成器
|
||||
*/
|
||||
public static class CustomBeanNameGenerator implements BeanNameGenerator {
|
||||
|
||||
private static final String BEAN_ANNOTATION_CLASS_NAME = "org.springframework.stereotype.Component";
|
||||
|
||||
@Override
|
||||
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
|
||||
// 兼容注解自定义名称
|
||||
if (definition instanceof AnnotatedBeanDefinition) {
|
||||
AnnotationMetadata metadata = ((AnnotatedBeanDefinition) definition).getMetadata();
|
||||
// 处理自定义 bean 名称
|
||||
return Optional.of(metadata)
|
||||
.map(s -> s.getAnnotationAttributes(BEAN_ANNOTATION_CLASS_NAME))
|
||||
.map(s -> s.get(Const.VALUE))
|
||||
.map(Object::toString)
|
||||
.filter(Strings::isNotBlank)
|
||||
.orElseGet(definition::getBeanClassName);
|
||||
} else {
|
||||
// 非注解形式默认使用默认名称
|
||||
return BeanDefinitionReaderUtils.generateBeanName(definition, registry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ spring:
|
||||
initial-size: 0
|
||||
min-idle: 1
|
||||
max-active: 5
|
||||
stat-view-servlet:
|
||||
enabled: false
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
@@ -14,6 +16,20 @@ spring:
|
||||
redisson:
|
||||
threads: 2
|
||||
netty-threads: 2
|
||||
minimum-idle-size: 2
|
||||
boot:
|
||||
admin:
|
||||
client:
|
||||
enabled: false
|
||||
server:
|
||||
enabled: false
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
enabled-by-default: false
|
||||
web:
|
||||
exposure:
|
||||
include: shutdown
|
||||
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
|
||||
@@ -10,10 +10,13 @@ spring:
|
||||
min-idle: 5
|
||||
# 最大连接池数量
|
||||
max-active: 20
|
||||
web-stat-filter:
|
||||
enabled: true
|
||||
# 控制台
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
login-username: ${DRUID_USERNAME:admin}
|
||||
login-password: ${DRUID_PASSWORD:admin}
|
||||
web-stat-filter:
|
||||
enabled: true
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
@@ -24,12 +27,23 @@ spring:
|
||||
redisson:
|
||||
threads: 4
|
||||
netty-threads: 4
|
||||
minimum-idle-size: 4
|
||||
quartz:
|
||||
properties:
|
||||
org:
|
||||
quartz:
|
||||
threadPool:
|
||||
threadCount: 10
|
||||
boot:
|
||||
admin:
|
||||
client:
|
||||
enabled: true
|
||||
server:
|
||||
enabled: true
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
enabled-by-default: true
|
||||
|
||||
springdoc:
|
||||
api-docs:
|
||||
@@ -39,6 +53,7 @@ springdoc:
|
||||
|
||||
knife4j:
|
||||
enable: false
|
||||
production: true
|
||||
|
||||
orion:
|
||||
# 是否为演示模式
|
||||
|
||||
@@ -19,6 +19,9 @@ spring:
|
||||
mvc:
|
||||
pathmatch:
|
||||
matching-strategy: ANT_PATH_MATCHER
|
||||
async:
|
||||
# 异步请求时间 30min
|
||||
request-timeout: 1800000
|
||||
datasource:
|
||||
druid:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
@@ -37,13 +40,14 @@ spring:
|
||||
# 最大生存的时间
|
||||
max-evictable-idle-time-millis: 900000
|
||||
validation-query: SELECT 1
|
||||
web-stat-filter:
|
||||
enabled: true
|
||||
# 控制台
|
||||
stat-view-servlet:
|
||||
enabled: true
|
||||
url-pattern: /druid/*
|
||||
login-username:
|
||||
login-password:
|
||||
web-stat-filter:
|
||||
enabled: true
|
||||
filter:
|
||||
stat:
|
||||
enabled: true
|
||||
@@ -85,7 +89,7 @@ spring:
|
||||
misfireThreshold: 60000
|
||||
clusterCheckinInterval: 5000
|
||||
isClustered: true
|
||||
#连接池
|
||||
# 连接池
|
||||
threadPool:
|
||||
class: org.quartz.simpl.SimpleThreadPool
|
||||
threadCount: 5
|
||||
@@ -95,12 +99,16 @@ spring:
|
||||
admin:
|
||||
context-path: /admin
|
||||
client:
|
||||
enabled: true
|
||||
url: http://127.0.0.1:${server.port}/${spring.boot.admin.context-path}
|
||||
instance:
|
||||
service-host-type: IP
|
||||
server:
|
||||
enabled: true
|
||||
|
||||
management:
|
||||
endpoints:
|
||||
enabled-by-default: true
|
||||
web:
|
||||
base-path: /actuator
|
||||
exposure:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
### 分页查询 SFTP 操作日志
|
||||
POST {{baseUrl}}/asset/host-sftp-log/query
|
||||
POST {{baseUrl}}/asset/host-sftp/query-log
|
||||
Content-Type: application/json
|
||||
Authorization: {{token}}
|
||||
|
||||
@@ -10,8 +10,12 @@ Authorization: {{token}}
|
||||
|
||||
|
||||
### 删除 SFTP 操作日志
|
||||
DELETE {{baseUrl}}/asset/host-sftp-log/delete?idList=1,2,3
|
||||
DELETE {{baseUrl}}/asset/host-sftp/delete-log?idList=1,2,3
|
||||
Authorization: {{token}}
|
||||
|
||||
|
||||
### 下载文件
|
||||
GET {{baseUrl}}/asset/host-sftp/download?channelId=123&transferToken=123
|
||||
|
||||
|
||||
###
|
||||
|
||||
@@ -5,11 +5,12 @@ import com.orion.visor.framework.biz.operator.log.core.annotation.OperatorLog;
|
||||
import com.orion.visor.framework.common.validator.group.Page;
|
||||
import com.orion.visor.framework.log.core.annotation.IgnoreLog;
|
||||
import com.orion.visor.framework.log.core.enums.IgnoreLogMode;
|
||||
import com.orion.visor.framework.web.core.annotation.IgnoreWrapper;
|
||||
import com.orion.visor.framework.web.core.annotation.RestWrapper;
|
||||
import com.orion.visor.module.asset.define.operator.HostTerminalOperatorType;
|
||||
import com.orion.visor.module.asset.entity.request.host.HostSftpLogQueryRequest;
|
||||
import com.orion.visor.module.asset.entity.vo.HostSftpLogVO;
|
||||
import com.orion.visor.module.asset.service.HostSftpLogService;
|
||||
import com.orion.visor.module.asset.service.HostSftpService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@@ -17,44 +18,60 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.PermitAll;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* SFTP 操作日志服务 api
|
||||
* SFTP 操作服务 api
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023-12-26 22:09
|
||||
*/
|
||||
@Tag(name = "asset - SFTP 操作日志服务")
|
||||
@Tag(name = "asset - SFTP 操作服务")
|
||||
@Slf4j
|
||||
@Validated
|
||||
@RestWrapper
|
||||
@RestController
|
||||
@RequestMapping("/asset/host-sftp-log")
|
||||
@RequestMapping("/asset/host-sftp")
|
||||
@SuppressWarnings({"ELValidationInJSP", "SpringElInspection"})
|
||||
public class HostSftpLogController {
|
||||
|
||||
@Resource
|
||||
private HostSftpLogService hostSftpLogService;
|
||||
private HostSftpService hostSftpService;
|
||||
|
||||
@IgnoreLog(IgnoreLogMode.RET)
|
||||
@PostMapping("/query")
|
||||
@PostMapping("/query-log")
|
||||
@Operation(summary = "分页查询 SFTP 操作日志")
|
||||
@PreAuthorize("@ss.hasAnyPermission('infra:operator-log:query', 'asset:host-sftp-log:management:query')")
|
||||
public DataGrid<HostSftpLogVO> getHostSftpLogPage(@Validated(Page.class) @RequestBody HostSftpLogQueryRequest request) {
|
||||
return hostSftpLogService.getHostSftpLogPage(request);
|
||||
return hostSftpService.getHostSftpLogPage(request);
|
||||
}
|
||||
|
||||
@OperatorLog(HostTerminalOperatorType.DELETE_SFTP_LOG)
|
||||
@DeleteMapping("/delete")
|
||||
@DeleteMapping("/delete-log")
|
||||
@Operation(summary = "删除 SFTP 操作日志")
|
||||
@Parameter(name = "idList", description = "idList", required = true)
|
||||
@PreAuthorize("@ss.hasAnyPermission('infra:operator-log:delete', 'asset:host-sftp-log:management:delete')")
|
||||
public Integer deleteHostSftpLog(@RequestParam("idList") List<Long> idList) {
|
||||
return hostSftpLogService.deleteHostSftpLog(idList);
|
||||
return hostSftpService.deleteHostSftpLog(idList);
|
||||
}
|
||||
|
||||
@PermitAll
|
||||
@IgnoreWrapper
|
||||
@IgnoreLog(IgnoreLogMode.RET)
|
||||
@GetMapping("/download")
|
||||
@Operation(summary = "下载文件")
|
||||
@Parameter(name = "channelId", description = "channelId", required = true)
|
||||
@Parameter(name = "transferToken", description = "transferToken", required = true)
|
||||
public StreamingResponseBody downloadWithTransferToken(@RequestParam("channelId") String channelId,
|
||||
@RequestParam("transferToken") String transferToken,
|
||||
HttpServletResponse response) {
|
||||
return hostSftpService.downloadWithTransferToken(channelId, transferToken, response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.orion.visor.module.asset.handler.host.config.model;
|
||||
|
||||
import com.orion.visor.framework.common.handler.data.model.GenericsDataModel;
|
||||
import com.orion.visor.framework.common.security.UpdatePasswordAction;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -24,61 +23,86 @@ import javax.validation.constraints.Size;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "HostSftpConfig", description = "主机 SSH 配置")
|
||||
public class HostSshConfigModel implements GenericsDataModel, UpdatePasswordAction {
|
||||
|
||||
/**
|
||||
* ssh 端口
|
||||
*/
|
||||
@NotNull
|
||||
@Range(min = 1, max = 65535)
|
||||
@Schema(description = "ssh 端口")
|
||||
private Integer port;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
@Size(max = 128)
|
||||
@Schema(description = "用户名")
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 认证方式
|
||||
*/
|
||||
@NotBlank
|
||||
@Size(max = 12)
|
||||
@Schema(description = "认证方式")
|
||||
private String authType;
|
||||
|
||||
/**
|
||||
* 系统类型
|
||||
*/
|
||||
@NotBlank
|
||||
@Size(max = 12)
|
||||
@Schema(description = "系统类型")
|
||||
private String osType;
|
||||
|
||||
@Schema(description = "密码")
|
||||
/**
|
||||
* 密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
@Schema(description = "身份id")
|
||||
/**
|
||||
* 身份id
|
||||
*/
|
||||
private Long identityId;
|
||||
|
||||
@Schema(description = "密钥id")
|
||||
/**
|
||||
* 密钥id
|
||||
*/
|
||||
private Long keyId;
|
||||
|
||||
/**
|
||||
* 连接超时时间
|
||||
*/
|
||||
@NotNull
|
||||
@Range(min = 0, max = 100000)
|
||||
@Schema(description = "连接超时时间")
|
||||
private Integer connectTimeout;
|
||||
|
||||
/**
|
||||
* SSH输出编码
|
||||
*/
|
||||
@NotBlank
|
||||
@Size(max = 12)
|
||||
@Schema(description = "SSH输出编码")
|
||||
private String charset;
|
||||
|
||||
/**
|
||||
* 文件名称编码
|
||||
*/
|
||||
@NotBlank
|
||||
@Size(max = 12)
|
||||
@Schema(description = "文件名称编码")
|
||||
private String fileNameCharset;
|
||||
|
||||
/**
|
||||
* 文件内容编码
|
||||
*/
|
||||
@NotBlank
|
||||
@Size(max = 12)
|
||||
@Schema(description = "文件内容编码")
|
||||
private String fileContentCharset;
|
||||
|
||||
@Schema(description = "是否使用新密码 仅参数")
|
||||
/**
|
||||
* 是否使用新密码 仅参数
|
||||
*/
|
||||
private Boolean useNewPassword;
|
||||
|
||||
@Schema(description = "是否已设置密码 仅返回")
|
||||
/**
|
||||
* 是否已设置密码 仅返回
|
||||
*/
|
||||
private Boolean hasPassword;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.orion.visor.module.asset.handler.host.exec.command;
|
||||
|
||||
import com.orion.visor.module.asset.define.AssetThreadPools;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.dto.ExecCommandDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.handler.ExecTaskHandler;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.model.ExecCommandDTO;
|
||||
|
||||
/**
|
||||
* 批量执行命令执行器
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
package com.orion.visor.module.asset.handler.host.exec.command.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 批量执行启动主机对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/3/11 15:46
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "ExecCommandHostDTO", description = "批量执行启动主机对象")
|
||||
public class ExecCommandHostDTO {
|
||||
|
||||
@Schema(description = "hostLogId")
|
||||
private Long hostLogId;
|
||||
|
||||
@Schema(description = "hostId")
|
||||
private Long hostId;
|
||||
|
||||
@Schema(description = "主机名称")
|
||||
private String hostName;
|
||||
|
||||
@Schema(description = "主机地址")
|
||||
private String hostAddress;
|
||||
|
||||
@Schema(description = "日志文件路径")
|
||||
private String logPath;
|
||||
|
||||
@Schema(description = "脚本路径")
|
||||
private String scriptPath;
|
||||
|
||||
@Schema(description = "执行命令")
|
||||
private String command;
|
||||
|
||||
@Schema(description = "主机用户")
|
||||
private String username;
|
||||
|
||||
@Schema(description = "命令编码")
|
||||
private String charset;
|
||||
|
||||
@Schema(description = "文件名称编码")
|
||||
private String fileNameCharset;
|
||||
|
||||
@Schema(description = "文件内容编码")
|
||||
private String fileContentCharset;
|
||||
|
||||
}
|
||||
@@ -20,8 +20,8 @@ import com.orion.visor.framework.common.file.FileClient;
|
||||
import com.orion.visor.module.asset.dao.ExecHostLogDAO;
|
||||
import com.orion.visor.module.asset.entity.domain.ExecHostLogDO;
|
||||
import com.orion.visor.module.asset.enums.ExecHostStatusEnum;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.dto.ExecCommandDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.dto.ExecCommandHostDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.model.ExecCommandDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.model.ExecCommandHostDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.log.manager.ExecLogManager;
|
||||
import com.orion.visor.module.asset.service.HostTerminalService;
|
||||
import lombok.Getter;
|
||||
|
||||
@@ -9,8 +9,8 @@ import com.orion.lang.utils.time.Dates;
|
||||
import com.orion.net.host.ssh.ExitCode;
|
||||
import com.orion.visor.framework.common.constant.Const;
|
||||
import com.orion.visor.module.asset.enums.ExecHostStatusEnum;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.dto.ExecCommandDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.dto.ExecCommandHostDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.model.ExecCommandDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.model.ExecCommandHostDTO;
|
||||
|
||||
/**
|
||||
* 命令执行器 ansi 日志输出
|
||||
|
||||
@@ -2,8 +2,8 @@ package com.orion.visor.module.asset.handler.host.exec.command.handler;
|
||||
|
||||
import com.orion.lang.support.timeout.TimeoutChecker;
|
||||
import com.orion.lang.support.timeout.TimeoutEndpoint;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.dto.ExecCommandDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.dto.ExecCommandHostDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.model.ExecCommandDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.model.ExecCommandHostDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,9 +18,9 @@ import com.orion.visor.module.asset.define.message.ExecMessageDefine;
|
||||
import com.orion.visor.module.asset.entity.domain.ExecLogDO;
|
||||
import com.orion.visor.module.asset.enums.ExecHostStatusEnum;
|
||||
import com.orion.visor.module.asset.enums.ExecStatusEnum;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.dto.ExecCommandDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.dto.ExecCommandHostDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.manager.ExecTaskManager;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.model.ExecCommandDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.model.ExecCommandHostDTO;
|
||||
import com.orion.visor.module.infra.api.SystemMessageApi;
|
||||
import com.orion.visor.module.infra.entity.dto.message.SystemMessageDTO;
|
||||
import lombok.Getter;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.exec.command.dto;
|
||||
package com.orion.visor.module.asset.handler.host.exec.command.model;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -19,31 +18,46 @@ import java.util.List;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "ExecCommandDTO", description = "批量执行启动对象")
|
||||
public class ExecCommandDTO {
|
||||
|
||||
@Schema(description = "logId")
|
||||
/**
|
||||
* logId
|
||||
*/
|
||||
private Long logId;
|
||||
|
||||
@Schema(description = "用户id")
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "用户名")
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
@Schema(description = "执行描述")
|
||||
/**
|
||||
* 执行描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
@Schema(description = "执行序列")
|
||||
/**
|
||||
* 执行序列
|
||||
*/
|
||||
private Integer execSeq;
|
||||
|
||||
@Schema(description = "超时时间")
|
||||
/**
|
||||
* 超时时间
|
||||
*/
|
||||
private Integer timeout;
|
||||
|
||||
@Schema(description = "是否使用脚本执行")
|
||||
/**
|
||||
* 是否使用脚本执行
|
||||
*/
|
||||
private Boolean scriptExec;
|
||||
|
||||
@Schema(description = "执行主机")
|
||||
/**
|
||||
* 执行主机
|
||||
*/
|
||||
private List<ExecCommandHostDTO> hosts;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.orion.visor.module.asset.handler.host.exec.command.model;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 批量执行启动主机对象
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/3/11 15:46
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ExecCommandHostDTO {
|
||||
|
||||
/**
|
||||
* hostLogId
|
||||
*/
|
||||
private Long hostLogId;
|
||||
|
||||
/**
|
||||
* hostId
|
||||
*/
|
||||
private Long hostId;
|
||||
|
||||
/**
|
||||
* 主机名称
|
||||
*/
|
||||
private String hostName;
|
||||
|
||||
/**
|
||||
* 主机地址
|
||||
*/
|
||||
private String hostAddress;
|
||||
|
||||
/**
|
||||
* 日志文件路径
|
||||
*/
|
||||
private String logPath;
|
||||
|
||||
/**
|
||||
* 脚本路径
|
||||
*/
|
||||
private String scriptPath;
|
||||
|
||||
/**
|
||||
* 执行命令
|
||||
*/
|
||||
private String command;
|
||||
|
||||
/**
|
||||
* 主机用户
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 命令编码
|
||||
*/
|
||||
private String charset;
|
||||
|
||||
/**
|
||||
* 文件名称编码
|
||||
*/
|
||||
private String fileNameCharset;
|
||||
|
||||
/**
|
||||
* 文件内容编码
|
||||
*/
|
||||
private String fileContentCharset;
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.exec.log;
|
||||
|
||||
import com.orion.visor.framework.common.annotation.Keep;
|
||||
import com.orion.visor.framework.common.constant.ExtraFieldConst;
|
||||
import com.orion.visor.framework.common.file.FileClient;
|
||||
import com.orion.visor.framework.websocket.core.utils.WebSockets;
|
||||
@@ -29,6 +30,7 @@ import javax.annotation.Resource;
|
||||
@Component
|
||||
public class ExecLogTailHandler extends AbstractWebSocketHandler {
|
||||
|
||||
@Keep
|
||||
@Resource
|
||||
private FileClient logsFileClient;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.extra.model;
|
||||
|
||||
import com.orion.visor.framework.common.handler.data.model.GenericsDataModel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -18,13 +17,16 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "HostLabelExtraModel", description = "主机拓展信息 - 标签模型")
|
||||
public class HostLabelExtraModel implements GenericsDataModel {
|
||||
|
||||
@Schema(description = "别名")
|
||||
/**
|
||||
* 别名
|
||||
*/
|
||||
private String alias;
|
||||
|
||||
@Schema(description = "颜色")
|
||||
/**
|
||||
* 颜色
|
||||
*/
|
||||
private String color;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.extra.model;
|
||||
|
||||
import com.orion.visor.framework.common.handler.data.model.GenericsDataModel;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -18,19 +17,26 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "HostExtraSshModel", description = "主机拓展信息 - ssh 模型")
|
||||
public class HostSshExtraModel implements GenericsDataModel {
|
||||
|
||||
@Schema(description = "认证方式")
|
||||
/**
|
||||
* 认证方式
|
||||
*/
|
||||
private String authType;
|
||||
|
||||
@Schema(description = "认证方式")
|
||||
/**
|
||||
* 认证方式
|
||||
*/
|
||||
private String username;
|
||||
|
||||
@Schema(description = "主机密钥")
|
||||
/**
|
||||
* 主机密钥
|
||||
*/
|
||||
private Long keyId;
|
||||
|
||||
@Schema(description = "主机身份")
|
||||
/**
|
||||
* 主机身份
|
||||
*/
|
||||
private Long identityId;
|
||||
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package com.orion.visor.module.asset.handler.host.terminal;
|
||||
|
||||
import com.orion.visor.module.asset.define.AssetThreadPools;
|
||||
import com.orion.visor.module.asset.handler.host.terminal.enums.InputTypeEnum;
|
||||
import com.orion.visor.module.asset.handler.host.terminal.manager.TerminalManager;
|
||||
import com.orion.visor.module.asset.handler.host.terminal.manager.HostTerminalManager;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.socket.CloseStatus;
|
||||
@@ -24,7 +24,7 @@ import javax.annotation.Resource;
|
||||
public class TerminalMessageDispatcher extends AbstractWebSocketHandler {
|
||||
|
||||
@Resource
|
||||
private TerminalManager terminalManager;
|
||||
private HostTerminalManager hostTerminalManager;
|
||||
|
||||
@Override
|
||||
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
|
||||
@@ -65,7 +65,7 @@ public class TerminalMessageDispatcher extends AbstractWebSocketHandler {
|
||||
String id = session.getId();
|
||||
log.info("TerminalMessageDispatcher-afterConnectionClosed id: {}, code: {}, reason: {}", id, status.getCode(), status.getReason());
|
||||
// 关闭会话
|
||||
terminalManager.closeSession(id);
|
||||
hostTerminalManager.closeSession(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
|
||||
import com.orion.visor.framework.common.constant.ErrorMessage;
|
||||
import com.orion.visor.framework.websocket.core.utils.WebSockets;
|
||||
import com.orion.visor.module.asset.handler.host.terminal.enums.OutputTypeEnum;
|
||||
import com.orion.visor.module.asset.handler.host.terminal.manager.TerminalManager;
|
||||
import com.orion.visor.module.asset.handler.host.terminal.manager.HostTerminalManager;
|
||||
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalConfig;
|
||||
import com.orion.visor.module.asset.handler.host.terminal.session.ITerminalSession;
|
||||
@@ -27,7 +27,7 @@ import java.util.Map;
|
||||
public abstract class AbstractTerminalHandler<T extends TerminalBasePayload> implements ITerminalHandler<T> {
|
||||
|
||||
@Resource
|
||||
protected TerminalManager terminalManager;
|
||||
protected HostTerminalManager hostTerminalManager;
|
||||
|
||||
@Resource
|
||||
private OperatorLogFrameworkService operatorLogFrameworkService;
|
||||
@@ -75,7 +75,7 @@ public abstract class AbstractTerminalHandler<T extends TerminalBasePayload> imp
|
||||
String channelId = channel.getId();
|
||||
String sessionId = payload.getSessionId();
|
||||
// 获取会话并且设置参数
|
||||
ITerminalSession session = terminalManager.getSession(channelId, sessionId);
|
||||
ITerminalSession session = hostTerminalManager.getSession(channelId, sessionId);
|
||||
if (session != null) {
|
||||
TerminalConfig config = session.getConfig();
|
||||
extra.put(OperatorLogs.HOST_ID, config.getHostId());
|
||||
|
||||
@@ -30,7 +30,7 @@ public class SftpChangeModHandler extends AbstractTerminalHandler<SftpChangeModR
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 获取会话
|
||||
String sessionId = payload.getSessionId();
|
||||
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
|
||||
ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
|
||||
String path = payload.getPath();
|
||||
Integer mod = payload.getMod();
|
||||
log.info("SftpChangeModHandler-handle start sessionId: {}, path: {}, mod: {}", sessionId, path, mod);
|
||||
|
||||
@@ -30,7 +30,7 @@ public class SftpDownloadFlatDirectoryHandler extends AbstractTerminalHandler<Sf
|
||||
public void handle(WebSocketSession channel, SftpDownloadFlatDirectoryRequest payload) {
|
||||
// 获取会话
|
||||
String sessionId = payload.getSessionId();
|
||||
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
|
||||
ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
|
||||
String[] paths = payload.getPath().split("\\|");
|
||||
log.info("SftpDownloadFlatDirectoryHandler-handle start sessionId: {}, paths: {}", sessionId, Arrays.toString(paths));
|
||||
Exception ex = null;
|
||||
|
||||
@@ -25,7 +25,7 @@ public class SftpGetContentHandler extends AbstractTerminalHandler<SftpBaseReque
|
||||
public void handle(WebSocketSession channel, SftpBaseRequest payload) {
|
||||
// 获取会话
|
||||
String sessionId = payload.getSessionId();
|
||||
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
|
||||
ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
|
||||
String path = payload.getPath();
|
||||
log.info("SftpGetContentHandler-handle start sessionId: {}, path: {}", sessionId, path);
|
||||
String content = Const.EMPTY;
|
||||
|
||||
@@ -31,7 +31,7 @@ public class SftpListHandler extends AbstractTerminalHandler<SftpListRequest> {
|
||||
public void handle(WebSocketSession channel, SftpListRequest payload) {
|
||||
// 获取会话
|
||||
String sessionId = payload.getSessionId();
|
||||
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
|
||||
ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
|
||||
String path = payload.getPath();
|
||||
log.info("SftpListHandler-handle start sessionId: {}, path: {}", sessionId, path);
|
||||
Exception ex = null;
|
||||
|
||||
@@ -30,7 +30,7 @@ public class SftpMakeDirectoryHandler extends AbstractTerminalHandler<SftpBaseRe
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 获取会话
|
||||
String sessionId = payload.getSessionId();
|
||||
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
|
||||
ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
|
||||
String path = payload.getPath();
|
||||
log.info("SftpMakeDirectoryHandler-handle start sessionId: {}, path: {}", sessionId, path);
|
||||
Exception ex = null;
|
||||
|
||||
@@ -30,7 +30,7 @@ public class SftpMoveHandler extends AbstractTerminalHandler<SftpMoveRequest> {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 获取会话
|
||||
String sessionId = payload.getSessionId();
|
||||
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
|
||||
ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
|
||||
String path = payload.getPath();
|
||||
String target = payload.getTarget();
|
||||
log.info("SftpMoveHandler-handle start sessionId: {}, path: {}, target: {}", sessionId, path, target);
|
||||
|
||||
@@ -31,7 +31,7 @@ public class SftpRemoveHandler extends AbstractTerminalHandler<SftpBaseRequest>
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 获取会话
|
||||
String sessionId = payload.getSessionId();
|
||||
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
|
||||
ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
|
||||
String[] paths = payload.getPath().split("\\|");
|
||||
log.info("SftpRemoveHandler-handle start sessionId: {}, path: {}", sessionId, Arrays.toString(paths));
|
||||
Exception ex = null;
|
||||
|
||||
@@ -30,7 +30,7 @@ public class SftpSetContentHandler extends AbstractTerminalHandler<SftpSetConten
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 获取会话
|
||||
String sessionId = payload.getSessionId();
|
||||
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
|
||||
ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
|
||||
String path = payload.getPath();
|
||||
log.info("SftpSetContentHandler-handle start sessionId: {}, path: {}", sessionId, path);
|
||||
Exception ex = null;
|
||||
|
||||
@@ -30,7 +30,7 @@ public class SftpTouchHandler extends AbstractTerminalHandler<SftpBaseRequest> {
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 获取会话
|
||||
String sessionId = payload.getSessionId();
|
||||
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
|
||||
ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
|
||||
String path = payload.getPath();
|
||||
log.info("SftpTouchHandler-handle start sessionId: {}, path: {}", sessionId, path);
|
||||
Exception ex = null;
|
||||
|
||||
@@ -30,7 +30,7 @@ public class SftpTruncateHandler extends AbstractTerminalHandler<SftpBaseRequest
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 获取会话
|
||||
String sessionId = payload.getSessionId();
|
||||
ISftpSession session = terminalManager.getSession(channel.getId(), sessionId);
|
||||
ISftpSession session = hostTerminalManager.getSession(channel.getId(), sessionId);
|
||||
String path = payload.getPath();
|
||||
log.info("SftpTruncateHandler-handle start sessionId: {}, path: {}", sessionId, path);
|
||||
Exception ex = null;
|
||||
|
||||
@@ -20,7 +20,7 @@ public class SshInputHandler extends AbstractTerminalHandler<SshInputRequest> {
|
||||
@Override
|
||||
public void handle(WebSocketSession channel, SshInputRequest payload) {
|
||||
// 获取会话
|
||||
ISshSession session = terminalManager.getSession(channel.getId(), payload.getSessionId());
|
||||
ISshSession session = hostTerminalManager.getSession(channel.getId(), payload.getSessionId());
|
||||
// 处理输入
|
||||
session.write(payload.getCommand());
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public class SshResizeHandler extends AbstractTerminalHandler<SshResizeRequest>
|
||||
@Override
|
||||
public void handle(WebSocketSession channel, SshResizeRequest payload) {
|
||||
// 获取会话
|
||||
ISshSession session = terminalManager.getSession(channel.getId(), payload.getSessionId());
|
||||
ISshSession session = hostTerminalManager.getSession(channel.getId(), payload.getSessionId());
|
||||
// 修改大小
|
||||
session.resize(payload.getCols(), payload.getRows());
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ public class TerminalCheckHandler extends AbstractTerminalHandler<TerminalCheckR
|
||||
* @return 是否存在
|
||||
*/
|
||||
private boolean checkSession(WebSocketSession channel, TerminalCheckRequest payload) {
|
||||
ITerminalSession session = terminalManager.getSession(channel.getId(), payload.getSessionId());
|
||||
ITerminalSession session = hostTerminalManager.getSession(channel.getId(), payload.getSessionId());
|
||||
if (session != null) {
|
||||
this.sendCheckFailedMessage(channel, payload, ErrorMessage.SESSION_PRESENT);
|
||||
return true;
|
||||
|
||||
@@ -20,7 +20,7 @@ public class TerminalCloseHandler extends AbstractTerminalHandler<TerminalBasePa
|
||||
public void handle(WebSocketSession channel, TerminalBasePayload payload) {
|
||||
log.info("TerminalCloseHandler-handle start sessionId: {}", payload.getSessionId());
|
||||
// 关闭会话
|
||||
terminalManager.closeSession(channel.getId(), payload.getSessionId());
|
||||
hostTerminalManager.closeSession(channel.getId(), payload.getSessionId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ public class TerminalConnectHandler extends AbstractTerminalHandler<TerminalConn
|
||||
// 连接主机
|
||||
ITerminalSession session = this.connect(sessionId, connect, channel, payload);
|
||||
// 添加会话到 manager
|
||||
terminalManager.addSession(session);
|
||||
hostTerminalManager.addSession(session);
|
||||
} catch (Exception e) {
|
||||
ex = e;
|
||||
// 修改连接状态为失败
|
||||
|
||||
@@ -26,7 +26,7 @@ public class TerminalPingHandler extends AbstractTerminalHandler<TerminalBasePay
|
||||
// 发送 pong
|
||||
this.send(channel, OutputTypeEnum.PONG.getType());
|
||||
// 活跃 terminal
|
||||
Map<String, ITerminalSession> sessions = terminalManager.getSession(channel.getId());
|
||||
Map<String, ITerminalSession> sessions = hostTerminalManager.getSession(channel.getId());
|
||||
if (!Maps.isEmpty(sessions)) {
|
||||
for (ITerminalSession session : sessions.values()) {
|
||||
session.keepAlive();
|
||||
|
||||
@@ -10,14 +10,14 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 终端管理器
|
||||
* 主机终端管理器
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/1/3 11:35
|
||||
*/
|
||||
@Component
|
||||
public class TerminalManager {
|
||||
public class HostTerminalManager {
|
||||
|
||||
/**
|
||||
* 会话存储器
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
@@ -17,13 +16,16 @@ import lombok.experimental.SuperBuilder;
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "TerminalBasePayload", description = "终端基础 payload")
|
||||
public class TerminalBasePayload {
|
||||
|
||||
@Schema(description = "会话id")
|
||||
/**
|
||||
* 会话id
|
||||
*/
|
||||
private String sessionId;
|
||||
|
||||
@Schema(description = "消息类型")
|
||||
/**
|
||||
* 消息类型
|
||||
*/
|
||||
private String type;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model;
|
||||
|
||||
import com.orion.visor.framework.desensitize.core.annotation.DesensitizeObject;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -18,35 +16,51 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@DesensitizeObject
|
||||
@Schema(name = "TerminalConfig", description = "主机终端连接参数")
|
||||
public class TerminalConfig {
|
||||
|
||||
@Schema(description = "logId")
|
||||
/**
|
||||
* logId
|
||||
*/
|
||||
private Long logId;
|
||||
|
||||
@Schema(description = "主机id")
|
||||
/**
|
||||
* 主机id
|
||||
*/
|
||||
private Long hostId;
|
||||
|
||||
@Schema(description = "主机名称")
|
||||
/**
|
||||
* 主机名称
|
||||
*/
|
||||
private String hostName;
|
||||
|
||||
@Schema(description = "主机地址")
|
||||
/**
|
||||
* 主机地址
|
||||
*/
|
||||
private String address;
|
||||
|
||||
@Schema(description = "cols")
|
||||
/**
|
||||
* cols
|
||||
*/
|
||||
private Integer cols;
|
||||
|
||||
@Schema(description = "rows")
|
||||
/**
|
||||
* rows
|
||||
*/
|
||||
private Integer rows;
|
||||
|
||||
@Schema(description = "SSH输出编码")
|
||||
/**
|
||||
* SSH输出编码
|
||||
*/
|
||||
private String charset;
|
||||
|
||||
@Schema(description = "文件名称编码")
|
||||
/**
|
||||
* 文件名称编码
|
||||
*/
|
||||
private String fileNameCharset;
|
||||
|
||||
@Schema(description = "文件内容编码")
|
||||
/**
|
||||
* 文件内容编码
|
||||
*/
|
||||
private String fileContentCharset;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.request;
|
||||
|
||||
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -20,10 +19,11 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "SftpBaseRequest", description = "sftp 基础请求 实体对象")
|
||||
public class SftpBaseRequest extends TerminalBasePayload {
|
||||
|
||||
@Schema(description = "path")
|
||||
/**
|
||||
* path
|
||||
*/
|
||||
private String path;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -21,10 +20,11 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "SftpChangeModRequest", description = "sftp 修改文件权限 实体对象")
|
||||
public class SftpChangeModRequest extends SftpBaseRequest {
|
||||
|
||||
@Schema(description = "10进制的8进制 权限")
|
||||
/**
|
||||
* 10进制的8进制 权限
|
||||
*/
|
||||
private Integer mod;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -21,10 +20,11 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "SftpDownloadDirectoryFlatRequest", description = "sftp 下载文件夹展开文件 实体对象")
|
||||
public class SftpDownloadFlatDirectoryRequest extends SftpBaseRequest {
|
||||
|
||||
@Schema(description = "当前路径")
|
||||
/**
|
||||
* 当前路径
|
||||
*/
|
||||
private String currentPath;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -21,10 +20,11 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "SftpListRequest", description = "sftp 列表请求 实体对象")
|
||||
public class SftpListRequest extends SftpBaseRequest {
|
||||
|
||||
@Schema(description = "是否显示隐藏文件")
|
||||
/**
|
||||
* 是否显示隐藏文件
|
||||
*/
|
||||
private Integer showHiddenFile;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -21,10 +20,11 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "SftpMoveRequest", description = "sftp 移动文件 实体对象")
|
||||
public class SftpMoveRequest extends SftpBaseRequest {
|
||||
|
||||
@Schema(description = "target")
|
||||
/**
|
||||
* target
|
||||
*/
|
||||
private String target;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.request;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -21,10 +20,11 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "SftpSetContentRequest", description = "sftp 设置文件内容 实体对象")
|
||||
public class SftpSetContentRequest extends SftpBaseRequest {
|
||||
|
||||
@Schema(description = "content")
|
||||
/**
|
||||
* content
|
||||
*/
|
||||
private String content;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.request;
|
||||
|
||||
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -22,10 +21,11 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "SshInputRequest", description = "ssh 输入请求 实体对象")
|
||||
public class SshInputRequest extends TerminalBasePayload {
|
||||
|
||||
@Schema(description = "command")
|
||||
/**
|
||||
* command
|
||||
*/
|
||||
private String command;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.request;
|
||||
|
||||
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -22,13 +21,16 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "SshResizeRequest", description = "ssh 修改大小请求 实体对象")
|
||||
public class SshResizeRequest extends TerminalBasePayload {
|
||||
|
||||
@Schema(description = "列数")
|
||||
/**
|
||||
* 列数
|
||||
*/
|
||||
private Integer cols;
|
||||
|
||||
@Schema(description = "行数")
|
||||
/**
|
||||
* 行数
|
||||
*/
|
||||
private Integer rows;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.request;
|
||||
|
||||
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -22,13 +21,16 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "TerminalConnectRequest", description = "主机连接检查请求 实体对象")
|
||||
public class TerminalCheckRequest extends TerminalBasePayload {
|
||||
|
||||
@Schema(description = "主机id")
|
||||
/**
|
||||
* 主机id
|
||||
*/
|
||||
private Long hostId;
|
||||
|
||||
@Schema(description = "连接类型")
|
||||
/**
|
||||
* 连接类型
|
||||
*/
|
||||
private String connectType;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.request;
|
||||
|
||||
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -22,16 +21,21 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "TerminalConnectRequest", description = "终端连接请求 实体对象")
|
||||
public class TerminalConnectRequest extends TerminalBasePayload {
|
||||
|
||||
@Schema(description = "伪终端类型")
|
||||
/**
|
||||
* 伪终端类型
|
||||
*/
|
||||
private String terminalType;
|
||||
|
||||
@Schema(description = "列数")
|
||||
/**
|
||||
* 列数
|
||||
*/
|
||||
private Integer cols;
|
||||
|
||||
@Schema(description = "行数")
|
||||
/**
|
||||
* 行数
|
||||
*/
|
||||
private Integer rows;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.response;
|
||||
|
||||
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -20,13 +19,16 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "SftpBaseResponse", description = "sftp 基础响应 实体对象")
|
||||
public class SftpBaseResponse extends TerminalBasePayload {
|
||||
|
||||
@Schema(description = "结果")
|
||||
/**
|
||||
* 结果
|
||||
*/
|
||||
private Integer result;
|
||||
|
||||
@Schema(description = "消息")
|
||||
/**
|
||||
* 消息
|
||||
*/
|
||||
private String msg;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.response;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -19,13 +18,16 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "SftpDownloadFlatDirectoryResponse", description = "sftp 下载文件夹展开文件 实体对象")
|
||||
public class SftpDownloadFlatDirectoryResponse extends SftpBaseResponse {
|
||||
|
||||
@Schema(description = "currentPath")
|
||||
/**
|
||||
* currentPath
|
||||
*/
|
||||
private String currentPath;
|
||||
|
||||
@Schema(description = "body")
|
||||
/**
|
||||
* body
|
||||
*/
|
||||
private String body;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.response;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
@@ -19,37 +18,56 @@ import java.util.Date;
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "SftpFileResponse", description = "sftp 文件响应 实体对象")
|
||||
public class SftpFileVO {
|
||||
|
||||
@Schema(description = "名称")
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
@Schema(description = "绝对路径")
|
||||
/**
|
||||
* 绝对路径
|
||||
*/
|
||||
private String path;
|
||||
|
||||
@Schema(description = "文件后缀")
|
||||
/**
|
||||
* 文件后缀
|
||||
*/
|
||||
private String suffix;
|
||||
|
||||
@Schema(description = "文件大小(byte)")
|
||||
/**
|
||||
* 文件大小(byte)
|
||||
*/
|
||||
private Long size;
|
||||
|
||||
@Schema(description = "属性")
|
||||
/**
|
||||
* 属性
|
||||
*/
|
||||
private String attr;
|
||||
|
||||
@Schema(description = "是否为目录")
|
||||
/**
|
||||
* 是否为目录
|
||||
*/
|
||||
private Boolean isDir;
|
||||
|
||||
@Schema(description = "10进制表现的8进制权限")
|
||||
/**
|
||||
* 10进制表现的8进制权限
|
||||
*/
|
||||
private Integer permission;
|
||||
|
||||
@Schema(description = "用户id")
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private Integer uid;
|
||||
|
||||
@Schema(description = "组id")
|
||||
/**
|
||||
* 组id
|
||||
*/
|
||||
private Integer gid;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
private Date modifyTime;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.response;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -19,13 +18,16 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "SftpGetContentResponse", description = "sftp 获取内容响应 实体对象")
|
||||
public class SftpGetContentResponse extends SftpBaseResponse {
|
||||
|
||||
@Schema(description = "path")
|
||||
/**
|
||||
* path
|
||||
*/
|
||||
private String path;
|
||||
|
||||
@Schema(description = "content")
|
||||
/**
|
||||
* content
|
||||
*/
|
||||
private String content;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.response;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -19,13 +18,16 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "SftpListResponse", description = "sftp 列表响应 实体对象")
|
||||
public class SftpListResponse extends SftpBaseResponse {
|
||||
|
||||
@Schema(description = "path")
|
||||
/**
|
||||
* path
|
||||
*/
|
||||
private String path;
|
||||
|
||||
@Schema(description = "body")
|
||||
/**
|
||||
* body
|
||||
*/
|
||||
private String body;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.response;
|
||||
|
||||
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -20,10 +19,11 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "SshOutputResponse", description = "ssh 输出响应 实体对象")
|
||||
public class SshOutputResponse extends TerminalBasePayload {
|
||||
|
||||
@Schema(description = "body")
|
||||
/**
|
||||
* body
|
||||
*/
|
||||
private String body;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.response;
|
||||
|
||||
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -20,13 +19,16 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "TerminalCheckResponse", description = "主机连接检查响应 实体对象")
|
||||
public class TerminalCheckResponse extends TerminalBasePayload {
|
||||
|
||||
@Schema(description = "检查结果")
|
||||
/**
|
||||
* 检查结果
|
||||
*/
|
||||
private Integer result;
|
||||
|
||||
@Schema(description = "错误信息")
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
private String msg;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.response;
|
||||
|
||||
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -20,13 +19,16 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "TerminalCloseResponse", description = "主机连接关闭响应 实体对象")
|
||||
public class TerminalCloseResponse extends TerminalBasePayload {
|
||||
|
||||
@Schema(description = "是否为强制关闭")
|
||||
/**
|
||||
* 是否为强制关闭
|
||||
*/
|
||||
private Integer forceClose;
|
||||
|
||||
@Schema(description = "关闭信息")
|
||||
/**
|
||||
* 关闭信息
|
||||
*/
|
||||
private String msg;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.terminal.model.response;
|
||||
|
||||
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalBasePayload;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
@@ -20,13 +19,16 @@ import lombok.experimental.SuperBuilder;
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Schema(name = "TerminalConnectResponse", description = "终端连接响应 实体对象")
|
||||
public class TerminalConnectResponse extends TerminalBasePayload {
|
||||
|
||||
@Schema(description = "检查结果")
|
||||
/**
|
||||
* 检查结果
|
||||
*/
|
||||
private Integer result;
|
||||
|
||||
@Schema(description = "错误信息")
|
||||
/**
|
||||
* 错误信息
|
||||
*/
|
||||
private String msg;
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON;
|
||||
import com.orion.lang.utils.io.Streams;
|
||||
import com.orion.visor.module.asset.handler.host.transfer.handler.ITransferHandler;
|
||||
import com.orion.visor.module.asset.handler.host.transfer.handler.TransferHandler;
|
||||
import com.orion.visor.module.asset.handler.host.transfer.manager.HostTransferManager;
|
||||
import com.orion.visor.module.asset.handler.host.transfer.model.TransferOperatorRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@@ -13,7 +14,7 @@ import org.springframework.web.socket.TextMessage;
|
||||
import org.springframework.web.socket.WebSocketSession;
|
||||
import org.springframework.web.socket.handler.AbstractWebSocketHandler;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* sftp 传输消息处理器
|
||||
@@ -26,24 +27,30 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
@Component
|
||||
public class TransferMessageDispatcher extends AbstractWebSocketHandler {
|
||||
|
||||
private final ConcurrentHashMap<String, ITransferHandler> handlers = new ConcurrentHashMap<>();
|
||||
@Resource
|
||||
private HostTransferManager hostTransferManager;
|
||||
|
||||
@Override
|
||||
public void afterConnectionEstablished(WebSocketSession session) {
|
||||
log.info("TransferMessageHandler-afterConnectionEstablished id: {}", session.getId());
|
||||
// 添加处理器
|
||||
hostTransferManager.putHandler(session.getId(), new TransferHandler(session));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleTextMessage(WebSocketSession session, TextMessage message) {
|
||||
// 获取处理器
|
||||
ITransferHandler handler = handlers.computeIfAbsent(session.getId(), s -> new TransferHandler(session));
|
||||
ITransferHandler handler = hostTransferManager.getHandler(session.getId());
|
||||
// 处理消息
|
||||
handler.handleMessage(JSON.parseObject(message.getPayload(), TransferOperatorRequest.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
|
||||
handlers.get(session.getId()).putContent(message.getPayload().array());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterConnectionEstablished(WebSocketSession session) {
|
||||
log.info("TransferMessageHandler-afterConnectionEstablished id: {}", session.getId());
|
||||
// 获取处理器
|
||||
ITransferHandler handler = hostTransferManager.getHandler(session.getId());
|
||||
// 添加数据
|
||||
handler.putContent(message.getPayload().array());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,7 +63,7 @@ public class TransferMessageDispatcher extends AbstractWebSocketHandler {
|
||||
String id = session.getId();
|
||||
log.info("TransferMessageHandler-afterConnectionClosed id: {}, code: {}, reason: {}", id, status.getCode(), status.getReason());
|
||||
// 关闭会话
|
||||
Streams.close(handlers.remove(id));
|
||||
Streams.close(hostTransferManager.removeHandler(id));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,9 +30,9 @@ public enum TransferOperatorType {
|
||||
UPLOAD_ERROR(TransferOperatorType.UPLOAD, "uploadError"),
|
||||
|
||||
/**
|
||||
* 开始下载
|
||||
* 初始化下载
|
||||
*/
|
||||
DOWNLOAD_START(TransferOperatorType.DOWNLOAD, "downloadStart"),
|
||||
DOWNLOAD_INIT(TransferOperatorType.DOWNLOAD, "downloadInit"),
|
||||
|
||||
/**
|
||||
* 中断下载
|
||||
@@ -45,7 +45,7 @@ public enum TransferOperatorType {
|
||||
|
||||
public static final String DOWNLOAD = "DOWNLOAD";
|
||||
|
||||
private final String operator;
|
||||
private final String kind;
|
||||
|
||||
private final String type;
|
||||
|
||||
|
||||
@@ -34,6 +34,16 @@ public enum TransferReceiverType {
|
||||
*/
|
||||
UPLOAD_ERROR("uploadError"),
|
||||
|
||||
/**
|
||||
* 开始下载
|
||||
*/
|
||||
DOWNLOAD_START("downloadStart"),
|
||||
|
||||
/**
|
||||
* 下载进度
|
||||
*/
|
||||
DOWNLOAD_PROGRESS("downloadProgress"),
|
||||
|
||||
/**
|
||||
* 下载完成
|
||||
*/
|
||||
|
||||
@@ -2,6 +2,9 @@ package com.orion.visor.module.asset.handler.host.transfer.handler;
|
||||
|
||||
import com.orion.lang.able.SafeCloseable;
|
||||
import com.orion.visor.module.asset.handler.host.transfer.model.TransferOperatorRequest;
|
||||
import com.orion.visor.module.asset.handler.host.transfer.session.IDownloadSession;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 传输处理器定义
|
||||
@@ -26,4 +29,11 @@ public interface ITransferHandler extends SafeCloseable {
|
||||
*/
|
||||
void putContent(byte[] content);
|
||||
|
||||
/**
|
||||
* 获取 token sessions
|
||||
*
|
||||
* @return token sessions
|
||||
*/
|
||||
Map<String, IDownloadSession> getTokenSessions();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.transfer.handler;
|
||||
|
||||
import com.orion.lang.id.UUIds;
|
||||
import com.orion.lang.utils.Exceptions;
|
||||
import com.orion.lang.utils.io.Streams;
|
||||
import com.orion.net.host.SessionStore;
|
||||
@@ -14,6 +15,7 @@ import com.orion.visor.module.asset.handler.host.transfer.model.TransferOperator
|
||||
import com.orion.visor.module.asset.handler.host.transfer.session.*;
|
||||
import com.orion.visor.module.asset.handler.host.transfer.utils.TransferUtils;
|
||||
import com.orion.visor.module.asset.service.HostTerminalService;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.socket.WebSocketSession;
|
||||
|
||||
@@ -45,10 +47,14 @@ public class TransferHandler implements ITransferHandler {
|
||||
*/
|
||||
private final ConcurrentHashMap<String, ITransferHostSession> sessions;
|
||||
|
||||
@Getter
|
||||
private final ConcurrentHashMap<String, IDownloadSession> tokenSessions;
|
||||
|
||||
public TransferHandler(WebSocketSession channel) {
|
||||
this.channel = channel;
|
||||
this.userId = WebSockets.getAttr(channel, ExtraFieldConst.USER_ID);
|
||||
this.sessions = new ConcurrentHashMap<>();
|
||||
this.tokenSessions = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,9 +79,11 @@ public class TransferHandler implements ITransferHandler {
|
||||
// 上传失败
|
||||
((IUploadSession) currentSession).uploadError();
|
||||
break;
|
||||
case DOWNLOAD_START:
|
||||
case DOWNLOAD_INIT:
|
||||
// 开始下载
|
||||
((IDownloadSession) currentSession).startDownload(payload.getPath());
|
||||
String token = UUIds.random32();
|
||||
tokenSessions.put(token, (IDownloadSession) currentSession);
|
||||
((IDownloadSession) currentSession).downloadInit(payload.getPath(), token);
|
||||
break;
|
||||
case DOWNLOAD_ABORT:
|
||||
// 中断下载
|
||||
@@ -100,7 +108,7 @@ public class TransferHandler implements ITransferHandler {
|
||||
*/
|
||||
private boolean getAndInitSession(TransferOperatorRequest payload, TransferOperatorType type) {
|
||||
Long hostId = payload.getHostId();
|
||||
String sessionKey = hostId + "_" + type.getOperator();
|
||||
String sessionKey = hostId + "_" + type.getKind();
|
||||
try {
|
||||
// 获取会话
|
||||
ITransferHostSession session = sessions.get(sessionKey);
|
||||
@@ -109,10 +117,10 @@ public class TransferHandler implements ITransferHandler {
|
||||
HostTerminalConnectDTO connectInfo = hostTerminalService.getTerminalConnectInfo(this.userId, hostId);
|
||||
SessionStore sessionStore = hostTerminalService.openSessionStore(connectInfo);
|
||||
// 打开会话并初始化
|
||||
if (TransferOperatorType.UPLOAD.equals(type.getOperator())) {
|
||||
if (TransferOperatorType.UPLOAD.equals(type.getKind())) {
|
||||
// 上传操作
|
||||
session = new UploadSession(connectInfo, sessionStore, this.channel);
|
||||
} else if (TransferOperatorType.DOWNLOAD.equals(type.getOperator())) {
|
||||
} else if (TransferOperatorType.DOWNLOAD.equals(type.getKind())) {
|
||||
// 下载操作
|
||||
session = new DownloadSession(connectInfo, sessionStore, this.channel);
|
||||
} else {
|
||||
@@ -136,6 +144,7 @@ public class TransferHandler implements ITransferHandler {
|
||||
public void close() {
|
||||
log.info("TransferHandler.close channelId: {}", channel.getId());
|
||||
sessions.values().forEach(Streams::close);
|
||||
tokenSessions.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.orion.visor.module.asset.handler.host.transfer.manager;
|
||||
|
||||
import com.orion.visor.module.asset.handler.host.transfer.handler.ITransferHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 主机传输管理器
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2024/6/4 17:58
|
||||
*/
|
||||
@Component
|
||||
public class HostTransferManager {
|
||||
|
||||
private final ConcurrentHashMap<String, ITransferHandler> handlers = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 添加处理器
|
||||
*
|
||||
* @param id id
|
||||
* @param handler handler
|
||||
*/
|
||||
public void putHandler(String id, ITransferHandler handler) {
|
||||
handlers.put(id, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取处理器
|
||||
*
|
||||
* @param id id
|
||||
* @return handler
|
||||
*/
|
||||
public ITransferHandler getHandler(String id) {
|
||||
return handlers.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除处理器
|
||||
*
|
||||
* @param id id
|
||||
* @return handler
|
||||
*/
|
||||
public ITransferHandler removeHandler(String id) {
|
||||
return handlers.remove(id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.transfer.model;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -17,13 +16,16 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "SftpFileBackupParams", description = "sftp 文件备份参数")
|
||||
public class SftpFileBackupParams {
|
||||
|
||||
@Schema(description = "文件名称")
|
||||
/**
|
||||
* 文件名称
|
||||
*/
|
||||
private String fileName;
|
||||
|
||||
@Schema(description = "时间戳")
|
||||
/**
|
||||
* 时间戳
|
||||
*/
|
||||
private Long timestamp;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.transfer.model;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -17,16 +16,21 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "FileOperatorRequest", description = "文件操作请求 实体对象")
|
||||
public class TransferOperatorRequest {
|
||||
|
||||
@Schema(description = "上传路径")
|
||||
/**
|
||||
* 文件路径
|
||||
*/
|
||||
private String path;
|
||||
|
||||
@Schema(description = "type")
|
||||
/**
|
||||
* type
|
||||
*/
|
||||
private String type;
|
||||
|
||||
@Schema(description = "主机id")
|
||||
/**
|
||||
* 主机id
|
||||
*/
|
||||
private Long hostId;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.transfer.model;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -17,19 +16,41 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "FileOperatorResponse", description = "文件操作响应 实体对象")
|
||||
public class TransferOperatorResponse {
|
||||
|
||||
@Schema(description = "type")
|
||||
/**
|
||||
* channelId
|
||||
*/
|
||||
private String channelId;
|
||||
|
||||
/**
|
||||
* type
|
||||
*/
|
||||
private String type;
|
||||
|
||||
@Schema(description = "主机id")
|
||||
/**
|
||||
* 主机id
|
||||
*/
|
||||
private Long hostId;
|
||||
|
||||
@Schema(description = "是否成功")
|
||||
/**
|
||||
* 是否成功
|
||||
*/
|
||||
private Boolean success;
|
||||
|
||||
@Schema(description = "消息")
|
||||
/**
|
||||
* 传输的大小
|
||||
*/
|
||||
private Integer currentSize;
|
||||
|
||||
/**
|
||||
* transferToken
|
||||
*/
|
||||
private String transferToken;
|
||||
|
||||
/**
|
||||
* 消息
|
||||
*/
|
||||
private String msg;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.orion.visor.module.asset.handler.host.transfer.session;
|
||||
|
||||
import com.orion.lang.define.wrapper.Ref;
|
||||
import com.orion.lang.utils.Threads;
|
||||
import com.orion.lang.utils.Valid;
|
||||
import com.orion.lang.utils.io.Streams;
|
||||
@@ -12,11 +13,13 @@ import com.orion.visor.module.asset.define.operator.HostTerminalOperatorType;
|
||||
import com.orion.visor.module.asset.entity.dto.HostTerminalConnectDTO;
|
||||
import com.orion.visor.module.asset.handler.host.transfer.enums.TransferReceiverType;
|
||||
import com.orion.visor.module.asset.handler.host.transfer.utils.TransferUtils;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.socket.BinaryMessage;
|
||||
import org.springframework.web.socket.WebSocketSession;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* 下载会话实现
|
||||
@@ -28,6 +31,9 @@ import java.io.InputStream;
|
||||
@Slf4j
|
||||
public class DownloadSession extends TransferHostSession implements IDownloadSession {
|
||||
|
||||
@Getter
|
||||
private String path;
|
||||
|
||||
private InputStream inputStream;
|
||||
|
||||
public DownloadSession(HostTerminalConnectDTO connectInfo, SessionStore sessionStore, WebSocketSession channel) {
|
||||
@@ -35,7 +41,8 @@ public class DownloadSession extends TransferHostSession implements IDownloadSes
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDownload(String path) {
|
||||
public void downloadInit(String path, String token) {
|
||||
this.path = path;
|
||||
String channelId = channel.getId();
|
||||
try {
|
||||
log.info("DownloadSession.startDownload open start channelId: {}, path: {}", channelId, path);
|
||||
@@ -54,39 +61,17 @@ public class DownloadSession extends TransferHostSession implements IDownloadSes
|
||||
}
|
||||
// 打开输入流
|
||||
this.inputStream = executor.openInputStream(path);
|
||||
// 响应开始下载
|
||||
TransferUtils.sendMessage(this.channel, TransferReceiverType.DOWNLOAD_START, null, e -> {
|
||||
e.setChannelId(channelId);
|
||||
e.setTransferToken(token);
|
||||
});
|
||||
log.info("DownloadSession.startDownload open success channelId: {}, path: {}", channelId, path);
|
||||
} catch (Exception e) {
|
||||
log.error("DownloadSession.startDownload open error channelId: {}, path: {}", channelId, path, e);
|
||||
// 响应结果
|
||||
// 响应下载失败
|
||||
TransferUtils.sendMessage(this.channel, TransferReceiverType.DOWNLOAD_ERROR, e);
|
||||
return;
|
||||
}
|
||||
// 异步读取文件内容
|
||||
AssetThreadPools.TERMINAL_OPERATOR.execute(() -> {
|
||||
Exception ex = null;
|
||||
try {
|
||||
byte[] buffer = new byte[Const.BUFFER_KB_32];
|
||||
int len;
|
||||
// 响应文件内容
|
||||
while (this.inputStream != null && (len = this.inputStream.read(buffer)) != -1) {
|
||||
this.channel.sendMessage(new BinaryMessage(buffer, 0, len, true));
|
||||
}
|
||||
log.info("DownloadSession.download finish channelId: {}, path: {}", channelId, path);
|
||||
} catch (Exception e) {
|
||||
log.error("DownloadSession.download error channelId: {}, path: {}", channelId, path, e);
|
||||
ex = e;
|
||||
}
|
||||
// 关闭等待 jsch 内部处理
|
||||
Threads.sleep(100);
|
||||
this.closeStream();
|
||||
Threads.sleep(100);
|
||||
// 响应结果
|
||||
if (ex == null) {
|
||||
TransferUtils.sendMessage(this.channel, TransferReceiverType.DOWNLOAD_FINISH, null);
|
||||
} else {
|
||||
TransferUtils.sendMessage(this.channel, TransferReceiverType.DOWNLOAD_ERROR, ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,9 +81,72 @@ public class DownloadSession extends TransferHostSession implements IDownloadSes
|
||||
this.closeStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeTo(OutputStream outputStream) {
|
||||
String channelId = channel.getId();
|
||||
Ref<Exception> ex = new Ref<>();
|
||||
try {
|
||||
byte[] buffer = new byte[Const.BUFFER_KB_32];
|
||||
int len;
|
||||
int i = 0;
|
||||
int size = 0;
|
||||
// 响应文件内容
|
||||
while (this.inputStream != null && (len = this.inputStream.read(buffer)) != -1) {
|
||||
outputStream.write(buffer, 0, len);
|
||||
size += len;
|
||||
// 不要每次都 flush 和 send > 1mb
|
||||
if (i == 32) {
|
||||
i = 0;
|
||||
}
|
||||
// 首次触发
|
||||
if (i == 0) {
|
||||
this.flushAndSendProgress(outputStream, size);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// 最后一次也要 flush
|
||||
if (i != 0) {
|
||||
this.flushAndSendProgress(outputStream, size);
|
||||
}
|
||||
log.info("DownloadSession.download finish channelId: {}, path: {}", channelId, path);
|
||||
} catch (Exception e) {
|
||||
log.error("DownloadSession.download error channelId: {}, path: {}", channelId, path, e);
|
||||
ex.set(e);
|
||||
}
|
||||
// 异步关闭
|
||||
AssetThreadPools.TERMINAL_OPERATOR.execute(() -> {
|
||||
// 关闭等待 jsch 内部处理
|
||||
Threads.sleep(100);
|
||||
this.closeStream();
|
||||
Threads.sleep(100);
|
||||
// 响应结果
|
||||
Exception e = ex.getValue();
|
||||
if (e == null) {
|
||||
TransferUtils.sendMessage(this.channel, TransferReceiverType.DOWNLOAD_FINISH, null);
|
||||
} else {
|
||||
TransferUtils.sendMessage(this.channel, TransferReceiverType.DOWNLOAD_ERROR, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷流 & 发送进度
|
||||
*
|
||||
* @param outputStream outputStream
|
||||
* @param size size
|
||||
* @throws IOException IOException
|
||||
*/
|
||||
private void flushAndSendProgress(OutputStream outputStream, int size) throws IOException {
|
||||
// flush
|
||||
outputStream.flush();
|
||||
// send
|
||||
TransferUtils.sendMessage(this.channel, TransferReceiverType.DOWNLOAD_PROGRESS, null, e -> e.setCurrentSize(size));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void closeStream() {
|
||||
// 关闭 inputStream 可能会被阻塞 ???...??? 只能关闭 executor
|
||||
this.path = null;
|
||||
Streams.close(this.executor);
|
||||
this.executor = null;
|
||||
this.inputStream = null;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.orion.visor.module.asset.handler.host.transfer.session;
|
||||
|
||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||
|
||||
/**
|
||||
* 下载会话定义
|
||||
*
|
||||
@@ -7,18 +9,26 @@ package com.orion.visor.module.asset.handler.host.transfer.session;
|
||||
* @version 1.0.0
|
||||
* @since 2024/2/22 22:25
|
||||
*/
|
||||
public interface IDownloadSession {
|
||||
public interface IDownloadSession extends StreamingResponseBody {
|
||||
|
||||
/**
|
||||
* 开始下载
|
||||
* 初始化下载
|
||||
*
|
||||
* @param path path
|
||||
* @param path path
|
||||
* @param token token
|
||||
*/
|
||||
void startDownload(String path);
|
||||
void downloadInit(String path, String token);
|
||||
|
||||
/**
|
||||
* 停止下载
|
||||
*/
|
||||
void abortDownload();
|
||||
|
||||
/**
|
||||
* 获取下载文件路径
|
||||
*
|
||||
* @return path
|
||||
*/
|
||||
String getPath();
|
||||
|
||||
}
|
||||
|
||||
@@ -6,8 +6,11 @@ import com.orion.visor.framework.common.constant.ErrorMessage;
|
||||
import com.orion.visor.framework.websocket.core.utils.WebSockets;
|
||||
import com.orion.visor.module.asset.handler.host.transfer.enums.TransferReceiverType;
|
||||
import com.orion.visor.module.asset.handler.host.transfer.model.TransferOperatorResponse;
|
||||
import org.apache.catalina.connector.ClientAbortException;
|
||||
import org.springframework.web.socket.WebSocketSession;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* 传输工具类
|
||||
*
|
||||
@@ -28,11 +31,26 @@ public class TransferUtils {
|
||||
* @param ex ex
|
||||
*/
|
||||
public static void sendMessage(WebSocketSession channel, TransferReceiverType type, Exception ex) {
|
||||
sendMessage(channel, type, ex, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*
|
||||
* @param channel channel
|
||||
* @param type type
|
||||
* @param ex ex
|
||||
* @param filler filler
|
||||
*/
|
||||
public static void sendMessage(WebSocketSession channel, TransferReceiverType type, Exception ex, Consumer<TransferOperatorResponse> filler) {
|
||||
TransferOperatorResponse resp = TransferOperatorResponse.builder()
|
||||
.type(type.getType())
|
||||
.success(ex == null)
|
||||
.msg(TransferUtils.getErrorMessage(ex))
|
||||
.build();
|
||||
if (filler != null) {
|
||||
filler.accept(resp);
|
||||
}
|
||||
WebSockets.sendText(channel, JSON.toJSONString(resp));
|
||||
}
|
||||
|
||||
@@ -45,9 +63,10 @@ public class TransferUtils {
|
||||
public static String getErrorMessage(Exception ex) {
|
||||
if (ex == null) {
|
||||
return null;
|
||||
}
|
||||
if (ex instanceof InvalidArgumentException) {
|
||||
} else if (ex instanceof InvalidArgumentException) {
|
||||
return ex.getMessage();
|
||||
} else if (ex instanceof ClientAbortException) {
|
||||
return ErrorMessage.CLIENT_ABORT;
|
||||
}
|
||||
return ErrorMessage.OPERATE_ERROR;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.orion.visor.module.asset.handler.host.upload.dto;
|
||||
package com.orion.visor.module.asset.handler.host.upload.model;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
@@ -17,22 +16,31 @@ import lombok.NoArgsConstructor;
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Schema(name = "FileUploadFileItemDTO", description = "文件上传文件对象")
|
||||
public class FileUploadFileItemDTO {
|
||||
|
||||
@Schema(description = "id")
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "fileId")
|
||||
/**
|
||||
* fileId
|
||||
*/
|
||||
private String fileId;
|
||||
|
||||
@Schema(description = "远程路径")
|
||||
/**
|
||||
* 远程路径
|
||||
*/
|
||||
private String remotePath;
|
||||
|
||||
@Schema(description = "当前大小")
|
||||
/**
|
||||
* 当前大小
|
||||
*/
|
||||
private Long current;
|
||||
|
||||
@Schema(description = "状态")
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
}
|
||||
@@ -15,8 +15,8 @@ import com.orion.visor.module.asset.entity.domain.UploadTaskDO;
|
||||
import com.orion.visor.module.asset.entity.domain.UploadTaskFileDO;
|
||||
import com.orion.visor.module.asset.enums.UploadTaskFileStatusEnum;
|
||||
import com.orion.visor.module.asset.enums.UploadTaskStatusEnum;
|
||||
import com.orion.visor.module.asset.handler.host.upload.dto.FileUploadFileItemDTO;
|
||||
import com.orion.visor.module.asset.handler.host.upload.manager.FileUploadTaskManager;
|
||||
import com.orion.visor.module.asset.handler.host.upload.model.FileUploadFileItemDTO;
|
||||
import com.orion.visor.module.asset.handler.host.upload.uploader.FileUploader;
|
||||
import com.orion.visor.module.asset.handler.host.upload.uploader.IFileUploader;
|
||||
import com.orion.visor.module.asset.service.UploadTaskService;
|
||||
|
||||
@@ -16,7 +16,7 @@ import com.orion.visor.module.asset.entity.domain.UploadTaskFileDO;
|
||||
import com.orion.visor.module.asset.entity.dto.HostTerminalConnectDTO;
|
||||
import com.orion.visor.module.asset.enums.HostSshOsTypeEnum;
|
||||
import com.orion.visor.module.asset.enums.UploadTaskFileStatusEnum;
|
||||
import com.orion.visor.module.asset.handler.host.upload.dto.FileUploadFileItemDTO;
|
||||
import com.orion.visor.module.asset.handler.host.upload.model.FileUploadFileItemDTO;
|
||||
import com.orion.visor.module.asset.service.HostTerminalService;
|
||||
import com.orion.visor.module.asset.service.UploadTaskService;
|
||||
import com.orion.visor.module.asset.utils.SftpUtils;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.orion.visor.module.asset.handler.host.upload.uploader;
|
||||
|
||||
import com.orion.lang.able.SafeCloseable;
|
||||
import com.orion.visor.module.asset.handler.host.upload.dto.FileUploadFileItemDTO;
|
||||
import com.orion.visor.module.asset.handler.host.upload.model.FileUploadFileItemDTO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -3,17 +3,19 @@ package com.orion.visor.module.asset.service;
|
||||
import com.orion.lang.define.wrapper.DataGrid;
|
||||
import com.orion.visor.module.asset.entity.request.host.HostSftpLogQueryRequest;
|
||||
import com.orion.visor.module.asset.entity.vo.HostSftpLogVO;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* SFTP 操作日志 服务类
|
||||
* SFTP 操作 服务类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
* @since 2023-12-26 22:09
|
||||
*/
|
||||
public interface HostSftpLogService {
|
||||
public interface HostSftpService {
|
||||
|
||||
/**
|
||||
* 分页查询 SFTP 操作日志
|
||||
@@ -31,4 +33,16 @@ public interface HostSftpLogService {
|
||||
*/
|
||||
Integer deleteHostSftpLog(List<Long> idList);
|
||||
|
||||
/**
|
||||
* 通过 transferToken 下载
|
||||
*
|
||||
* @param channelId channelId
|
||||
* @param transferToken transferToken
|
||||
* @param response response
|
||||
* @return body
|
||||
*/
|
||||
StreamingResponseBody downloadWithTransferToken(String channelId,
|
||||
String transferToken,
|
||||
HttpServletResponse response);
|
||||
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import com.orion.lang.utils.json.matcher.ReplacementFormatter;
|
||||
import com.orion.lang.utils.json.matcher.ReplacementFormatters;
|
||||
import com.orion.lang.utils.time.Dates;
|
||||
import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
|
||||
import com.orion.visor.framework.common.annotation.Keep;
|
||||
import com.orion.visor.framework.common.constant.Const;
|
||||
import com.orion.visor.framework.common.constant.ErrorMessage;
|
||||
import com.orion.visor.framework.common.constant.PathConst;
|
||||
@@ -36,8 +37,8 @@ import com.orion.visor.module.asset.entity.vo.ExecLogVO;
|
||||
import com.orion.visor.module.asset.enums.*;
|
||||
import com.orion.visor.module.asset.handler.host.config.model.HostSshConfigModel;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.ExecTaskExecutors;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.dto.ExecCommandDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.dto.ExecCommandHostDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.model.ExecCommandDTO;
|
||||
import com.orion.visor.module.asset.handler.host.exec.command.model.ExecCommandHostDTO;
|
||||
import com.orion.visor.module.asset.service.AssetAuthorizedDataService;
|
||||
import com.orion.visor.module.asset.service.ExecCommandService;
|
||||
import com.orion.visor.module.asset.service.HostConfigService;
|
||||
@@ -67,6 +68,7 @@ public class ExecCommandServiceImpl implements ExecCommandService {
|
||||
|
||||
private static final int DESC_OMIT = 60;
|
||||
|
||||
@Keep
|
||||
@Resource
|
||||
private FileClient logsFileClient;
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.orion.lang.utils.collect.Lists;
|
||||
import com.orion.lang.utils.io.Files1;
|
||||
import com.orion.lang.utils.io.Streams;
|
||||
import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
|
||||
import com.orion.visor.framework.common.annotation.Keep;
|
||||
import com.orion.visor.framework.common.constant.Const;
|
||||
import com.orion.visor.framework.common.constant.ErrorMessage;
|
||||
import com.orion.visor.framework.common.constant.PathConst;
|
||||
@@ -80,6 +81,7 @@ public class ExecLogServiceImpl implements ExecLogService {
|
||||
@Resource
|
||||
private HostConfigService hostConfigService;
|
||||
|
||||
@Keep
|
||||
@Resource
|
||||
private FileClient logsFileClient;
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ import com.orion.visor.module.asset.entity.request.host.HostConnectLogQueryReque
|
||||
import com.orion.visor.module.asset.entity.vo.HostConnectLogVO;
|
||||
import com.orion.visor.module.asset.enums.HostConnectStatusEnum;
|
||||
import com.orion.visor.module.asset.enums.HostConnectTypeEnum;
|
||||
import com.orion.visor.module.asset.handler.host.terminal.manager.TerminalManager;
|
||||
import com.orion.visor.module.asset.handler.host.terminal.manager.HostTerminalManager;
|
||||
import com.orion.visor.module.asset.handler.host.terminal.model.TerminalConfig;
|
||||
import com.orion.visor.module.asset.handler.host.terminal.session.ITerminalSession;
|
||||
import com.orion.visor.module.asset.service.HostConnectLogService;
|
||||
@@ -49,7 +49,7 @@ public class HostConnectLogServiceImpl implements HostConnectLogService {
|
||||
private HostConnectLogDAO hostConnectLogDAO;
|
||||
|
||||
@Resource
|
||||
private TerminalManager terminalManager;
|
||||
private HostTerminalManager hostTerminalManager;
|
||||
|
||||
@Override
|
||||
public Long create(HostConnectTypeEnum type, HostConnectLogCreateRequest request) {
|
||||
@@ -84,7 +84,7 @@ public class HostConnectLogServiceImpl implements HostConnectLogService {
|
||||
@Override
|
||||
public List<HostConnectLogVO> getHostConnectSessions(HostConnectLogQueryRequest request) {
|
||||
// 查询全部
|
||||
List<Long> idList = terminalManager.getChannelSessions()
|
||||
List<Long> idList = hostTerminalManager.getChannelSessions()
|
||||
.values()
|
||||
.stream()
|
||||
.map(ConcurrentHashMap::values)
|
||||
@@ -204,7 +204,7 @@ public class HostConnectLogServiceImpl implements HostConnectLogService {
|
||||
OperatorLogs.add(OperatorLogs.HOST_NAME, record.getHostName());
|
||||
// 获取会话
|
||||
HostConnectLogExtraDTO extra = JSON.parseObject(record.getExtraInfo(), HostConnectLogExtraDTO.class);
|
||||
ITerminalSession session = terminalManager.getSession(extra.getChannelId(), extra.getSessionId());
|
||||
ITerminalSession session = hostTerminalManager.getSession(extra.getChannelId(), extra.getSessionId());
|
||||
if (session != null) {
|
||||
// 关闭会话
|
||||
session.forceOffline();
|
||||
|
||||
@@ -2,26 +2,37 @@ package com.orion.visor.module.asset.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.orion.lang.constant.StandardContentType;
|
||||
import com.orion.lang.define.wrapper.DataGrid;
|
||||
import com.orion.lang.utils.Arrays1;
|
||||
import com.orion.lang.utils.Strings;
|
||||
import com.orion.lang.utils.io.Files1;
|
||||
import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
|
||||
import com.orion.visor.framework.common.constant.Const;
|
||||
import com.orion.visor.framework.common.constant.ErrorMessage;
|
||||
import com.orion.visor.framework.common.constant.ExtraFieldConst;
|
||||
import com.orion.visor.module.asset.convert.HostSftpLogConvert;
|
||||
import com.orion.visor.module.asset.define.operator.HostTerminalOperatorType;
|
||||
import com.orion.visor.module.asset.entity.request.host.HostSftpLogQueryRequest;
|
||||
import com.orion.visor.module.asset.entity.vo.HostSftpLogVO;
|
||||
import com.orion.visor.module.asset.service.HostSftpLogService;
|
||||
import com.orion.visor.module.asset.handler.host.transfer.handler.ITransferHandler;
|
||||
import com.orion.visor.module.asset.handler.host.transfer.manager.HostTransferManager;
|
||||
import com.orion.visor.module.asset.handler.host.transfer.session.IDownloadSession;
|
||||
import com.orion.visor.module.asset.service.HostSftpService;
|
||||
import com.orion.visor.module.infra.api.OperatorLogApi;
|
||||
import com.orion.visor.module.infra.entity.dto.operator.OperatorLogQueryDTO;
|
||||
import com.orion.web.servlet.web.Servlets;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* SFTP 操作日志 服务实现类
|
||||
* SFTP 操作 服务实现类
|
||||
*
|
||||
* @author Jiahang Li
|
||||
* @version 1.0.0
|
||||
@@ -29,11 +40,14 @@ import java.util.List;
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class HostSftpLogServiceImpl implements HostSftpLogService {
|
||||
public class HostSftpServiceImpl implements HostSftpService {
|
||||
|
||||
@Resource
|
||||
private OperatorLogApi operatorLogApi;
|
||||
|
||||
@Resource
|
||||
private HostTransferManager hostTransferManager;
|
||||
|
||||
@Override
|
||||
public DataGrid<HostSftpLogVO> getHostSftpLogPage(HostSftpLogQueryRequest request) {
|
||||
// 查询
|
||||
@@ -62,6 +76,25 @@ public class HostSftpLogServiceImpl implements HostSftpLogService {
|
||||
return effect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StreamingResponseBody downloadWithTransferToken(String channelId, String transferToken, HttpServletResponse response) {
|
||||
// 获取会话
|
||||
IDownloadSession session = Optional.ofNullable(channelId)
|
||||
.map(hostTransferManager::getHandler)
|
||||
.map(ITransferHandler::getTokenSessions)
|
||||
.map(s -> s.remove(transferToken))
|
||||
.orElse(null);
|
||||
// 响应会话
|
||||
if (session == null) {
|
||||
Servlets.setContentType(response, StandardContentType.TEXT_HTML);
|
||||
Servlets.setCharset(response, Const.UTF_8);
|
||||
return outputStream -> outputStream.write(Strings.bytes(ErrorMessage.SESSION_ABSENT));
|
||||
}
|
||||
// 响应文件
|
||||
Servlets.setAttachmentHeader(response, Files1.getFileName(session.getPath()));
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建查询对象
|
||||
*
|
||||
@@ -12,6 +12,7 @@ import com.orion.lang.utils.collect.Maps;
|
||||
import com.orion.lang.utils.io.Files1;
|
||||
import com.orion.lang.utils.time.Dates;
|
||||
import com.orion.visor.framework.biz.operator.log.core.utils.OperatorLogs;
|
||||
import com.orion.visor.framework.common.annotation.Keep;
|
||||
import com.orion.visor.framework.common.constant.Const;
|
||||
import com.orion.visor.framework.common.constant.ErrorMessage;
|
||||
import com.orion.visor.framework.common.file.FileClient;
|
||||
@@ -37,7 +38,7 @@ import com.orion.visor.module.asset.enums.HostConfigTypeEnum;
|
||||
import com.orion.visor.module.asset.enums.UploadTaskFileStatusEnum;
|
||||
import com.orion.visor.module.asset.enums.UploadTaskStatusEnum;
|
||||
import com.orion.visor.module.asset.handler.host.upload.FileUploadTasks;
|
||||
import com.orion.visor.module.asset.handler.host.upload.dto.FileUploadFileItemDTO;
|
||||
import com.orion.visor.module.asset.handler.host.upload.model.FileUploadFileItemDTO;
|
||||
import com.orion.visor.module.asset.handler.host.upload.manager.FileUploadTaskManager;
|
||||
import com.orion.visor.module.asset.handler.host.upload.task.IFileUploadTask;
|
||||
import com.orion.visor.module.asset.handler.host.upload.uploader.IFileUploader;
|
||||
@@ -86,6 +87,7 @@ public class UploadTaskServiceImpl implements UploadTaskService {
|
||||
@Resource
|
||||
private FileUploadTaskManager fileUploadTaskManager;
|
||||
|
||||
@Keep
|
||||
@Resource
|
||||
private FileClient localFileClient;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.orion.visor.module.asset.task;
|
||||
import com.orion.lang.utils.Strings;
|
||||
import com.orion.lang.utils.io.Files1;
|
||||
import com.orion.lang.utils.time.Dates;
|
||||
import com.orion.visor.framework.common.annotation.Keep;
|
||||
import com.orion.visor.framework.common.file.FileClient;
|
||||
import com.orion.visor.framework.common.utils.LockerUtils;
|
||||
import com.orion.visor.module.asset.dao.ExecHostLogDAO;
|
||||
@@ -37,6 +38,7 @@ public class ExecLogFileAutoClearTask {
|
||||
@Resource
|
||||
private AppExecLogConfig appExecLogConfig;
|
||||
|
||||
@Keep
|
||||
@Resource
|
||||
private FileClient logsFileClient;
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user