初始化
This commit is contained in:
commit
b356735d72
284
pom.xml
Normal file
284
pom.xml
Normal file
@ -0,0 +1,284 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<!-- 项目基本信息 -->
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>xml-to-txt-service</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
|
||||
<!-- 父项目 -->
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
|
||||
<!-- 属性配置 -->
|
||||
<properties>
|
||||
<!-- 基本属性 -->
|
||||
<java.version>21</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
|
||||
<!-- 依赖版本管理 -->
|
||||
<commins-fileupload.version>1.6.0</commins-fileupload.version>
|
||||
<mybatis-flex.version>1.9.3</mybatis-flex.version>
|
||||
<swagger.version>2.2.0</swagger.version>
|
||||
<h2.version>2.2.224</h2.version>
|
||||
<sqlite.version>3.45.1.0</sqlite.version>
|
||||
<lombok.version>1.18.30</lombok.version>
|
||||
<hutool.version>5.8.27</hutool.version>
|
||||
<json.version>20231013</json.version>
|
||||
<fastjson2.version>2.0.49</fastjson2.version>
|
||||
<knife4j.version>4.5.0</knife4j.version>
|
||||
<bean-searcher.version>4.3.0</bean-searcher.version>
|
||||
<mapstruct-plus.version>1.4.0</mapstruct-plus.version>
|
||||
<easy-trans.version>3.0.5</easy-trans.version>
|
||||
<modelmapper.version>2.3.9</modelmapper.version>
|
||||
<tika.version>2.8.0</tika.version>
|
||||
<jinjia2.version>2.8.1</jinjia2.version>
|
||||
<velocity.version>1.7</velocity.version>
|
||||
</properties>
|
||||
|
||||
<!-- 依赖管理 - 强制规范 -->
|
||||
<dependencies>
|
||||
|
||||
<!-- 项目基本依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.aspectj</groupId>
|
||||
<artifactId>aspectjweaver</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 文件上传 -->
|
||||
<dependency>
|
||||
<groupId>commons-fileupload</groupId>
|
||||
<artifactId>commons-fileupload</artifactId>
|
||||
<version>${commins-fileupload.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 代码简化与基础工具箱 -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.dataformat</groupId>
|
||||
<artifactId>jackson-dataformat-xml</artifactId>
|
||||
<version>${jackson-bom.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson-bom.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.alibaba.fastjson2</groupId>
|
||||
<artifactId>fastjson2-extension</artifactId>
|
||||
<version>${fastjson2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>${gson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
<artifactId>json</artifactId>
|
||||
<version>${json.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- API文档 -->
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||
<version>${knife4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 数据库相关依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>${sqlite.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>${h2.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- ORM框架 -->
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-spring-boot3-starter</artifactId>
|
||||
<version>${mybatis-flex.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.zhxu</groupId>
|
||||
<artifactId>bean-searcher-boot-starter</artifactId>
|
||||
<version>${bean-searcher.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.modelmapper</groupId>
|
||||
<artifactId>modelmapper</artifactId>
|
||||
<version>${modelmapper.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 翻译工具 -->
|
||||
<dependency>
|
||||
<groupId>com.fhs-opensource</groupId>
|
||||
<artifactId>easy-trans-spring-boot-starter</artifactId>
|
||||
<version>${easy-trans.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fhs-opensource</groupId>
|
||||
<artifactId>easy-trans-mybatis-flex-extend</artifactId>
|
||||
<version>${easy-trans.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 文件编码工具 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-core</artifactId>
|
||||
<version>${tika.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-parsers-standard-package</artifactId>
|
||||
<version>${tika.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 模板:JinJia2 -->
|
||||
<dependency>
|
||||
<groupId>com.hubspot.jinjava</groupId>
|
||||
<artifactId>jinjava</artifactId>
|
||||
<version>${jinjia2.version}</version>
|
||||
</dependency>
|
||||
<!-- 模板:freemarker -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||
</dependency>
|
||||
<!-- 模板:thymeleaf -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
<!-- 模板:velocity -->
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity</artifactId>
|
||||
<version>${velocity.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity-engine-core</artifactId>
|
||||
<version>2.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity-tools</artifactId>
|
||||
<version>2.0</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<!-- 测试依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<includes>
|
||||
<include>**/**/*.j2</include>
|
||||
<include>**/*.xml</include>
|
||||
</includes>
|
||||
<filtering>false</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>aliyun</id>
|
||||
<name>aliyun</name>
|
||||
<url>https://maven.aliyun.com/repository/public</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>aliyun</id>
|
||||
<name>aliyun</name>
|
||||
<url>https://maven.aliyun.com/repository/public</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
</project>
|
52
src/main/java/com/example/demo/Application.java
Normal file
52
src/main/java/com/example/demo/Application.java
Normal file
@ -0,0 +1,52 @@
|
||||
package com.example.demo;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.modelmapper.ModelMapper;
|
||||
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
|
||||
import io.swagger.v3.oas.annotations.info.Info;
|
||||
import io.swagger.v3.oas.annotations.info.License;
|
||||
|
||||
/**
|
||||
* XML解析器应用程序主类
|
||||
* Spring Boot应用程序的入口点
|
||||
*
|
||||
* @author system
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@MapperScan("com.example.demo.parser.mapper") // 扫描Mapper接口
|
||||
@OpenAPIDefinition(
|
||||
info = @Info(
|
||||
title = "XML解析器API文档",
|
||||
description = "XML文件解析并转化为TXT服务项目的API接口文档",
|
||||
version = "1.0",
|
||||
license = @License(
|
||||
name = "Apache 2.0",
|
||||
url = "http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||
)
|
||||
)
|
||||
)
|
||||
public class Application {
|
||||
|
||||
/**
|
||||
* 应用程序入口方法
|
||||
*
|
||||
* @param args 命令行参数
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置ModelMapper用于DTO、Entity和VO之间的转换
|
||||
*
|
||||
* @return ModelMapper实例
|
||||
*/
|
||||
@Bean
|
||||
public ModelMapper modelMapper() {
|
||||
return new ModelMapper();
|
||||
}
|
||||
}
|
160
src/main/java/com/example/demo/common/config/CacheConfig.java
Normal file
160
src/main/java/com/example/demo/common/config/CacheConfig.java
Normal file
@ -0,0 +1,160 @@
|
||||
package com.example.demo.common.config;
|
||||
|
||||
import com.example.demo.common.constant.GlobalConstants;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 缓存配置类
|
||||
* 配置H2内存缓存,用于缓存解析规则和映射规则等数据
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
public class CacheConfig {
|
||||
|
||||
/**
|
||||
* 配置缓存管理器
|
||||
* 使用ConcurrentMapCacheManager作为缓存管理器,提供基于内存的缓存实现
|
||||
*
|
||||
* @return ConcurrentMapCacheManager实例
|
||||
*/
|
||||
@Bean
|
||||
public ConcurrentMapCacheManager cacheManager() {
|
||||
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
|
||||
|
||||
// 预定义的缓存名称
|
||||
cacheManager.setCacheNames(Arrays.asList(
|
||||
GlobalConstants.Cache.CACHE_KEY_PARSE_RULE,
|
||||
GlobalConstants.Cache.CACHE_KEY_MAPPER_RULE,
|
||||
"system_config",
|
||||
"user_session"
|
||||
));
|
||||
|
||||
// 设置默认缓存配置
|
||||
cacheManager.setAllowNullValues(false);
|
||||
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建一个简单的缓存包装器,支持过期时间
|
||||
*
|
||||
* @param <K> 缓存键类型
|
||||
* @param <V> 缓存值类型
|
||||
* @return 带过期时间的缓存
|
||||
*/
|
||||
@Bean
|
||||
public <K, V> CacheWrapper<K, V> cacheWrapper() {
|
||||
return new CacheWrapper<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 带过期时间的缓存包装器
|
||||
*
|
||||
* @param <K> 缓存键类型
|
||||
* @param <V> 缓存值类型
|
||||
*/
|
||||
public static class CacheWrapper<K, V> {
|
||||
|
||||
private final ConcurrentHashMap<K, CacheEntry<V>> cache = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* 存储值到缓存,使用默认过期时间
|
||||
*
|
||||
* @param key 缓存键
|
||||
* @param value 缓存值
|
||||
*/
|
||||
public void put(K key, V value) {
|
||||
put(key, value, GlobalConstants.Cache.DEFAULT_CACHE_EXPIRE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 存储值到缓存,指定过期时间
|
||||
*
|
||||
* @param key 缓存键
|
||||
* @param value 缓存值
|
||||
* @param expireTime 过期时间(秒)
|
||||
*/
|
||||
public void put(K key, V value, long expireTime) {
|
||||
long expireAt = System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(expireTime);
|
||||
cache.put(key, new CacheEntry<>(value, expireAt));
|
||||
}
|
||||
|
||||
/**
|
||||
* 从缓存中获取值
|
||||
*
|
||||
* @param key 缓存键
|
||||
* @return 缓存值,如果不存在或已过期则返回null
|
||||
*/
|
||||
public V get(K key) {
|
||||
CacheEntry<V> entry = cache.get(key);
|
||||
if (entry == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 检查是否过期
|
||||
if (System.currentTimeMillis() > entry.getExpireAt()) {
|
||||
cache.remove(key);
|
||||
return null;
|
||||
}
|
||||
|
||||
return entry.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 从缓存中删除值
|
||||
*
|
||||
* @param key 缓存键
|
||||
*/
|
||||
public void remove(K key) {
|
||||
cache.remove(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空缓存
|
||||
*/
|
||||
public void clear() {
|
||||
cache.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存大小
|
||||
*
|
||||
* @return 缓存中的条目数量
|
||||
*/
|
||||
public int size() {
|
||||
return cache.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存条目内部类
|
||||
*
|
||||
* @param <T> 条目值类型
|
||||
*/
|
||||
private static class CacheEntry<T> {
|
||||
private final T value;
|
||||
private final long expireAt;
|
||||
|
||||
public CacheEntry(T value, long expireAt) {
|
||||
this.value = value;
|
||||
this.expireAt = expireAt;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public long getExpireAt() {
|
||||
return expireAt;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
//package com.example.demo.common.config;
|
||||
//
|
||||
//import lombok.RequiredArgsConstructor;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.boot.CommandLineRunner;
|
||||
//import org.springframework.core.io.ClassPathResource;
|
||||
//import org.springframework.jdbc.datasource.init.ScriptUtils;
|
||||
//import org.springframework.stereotype.Component;
|
||||
//
|
||||
//import javax.sql.DataSource;
|
||||
//import java.sql.Connection;
|
||||
//
|
||||
///**
|
||||
// * 数据库初始化配置
|
||||
// * 应用启动时自动执行数据库脚本
|
||||
// *
|
||||
// * @author system
|
||||
// * @version 1.0
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Component
|
||||
//@RequiredArgsConstructor
|
||||
//public class DatabaseInitializer implements CommandLineRunner {
|
||||
//
|
||||
// private final DataSource dataSource;
|
||||
//
|
||||
// /**
|
||||
// * 应用启动时执行数据库初始化
|
||||
// *
|
||||
// * @param args 命令行参数
|
||||
// * @throws Exception 异常
|
||||
// */
|
||||
// @Override
|
||||
// public void run(String... args) throws Exception {
|
||||
// log.info("开始初始化数据库...");
|
||||
//
|
||||
// try (Connection connection = dataSource.getConnection()) {
|
||||
// // 执行数据库初始化脚本
|
||||
// ClassPathResource schemaResource = new ClassPathResource("schema.sql");
|
||||
// ScriptUtils.executeSqlScript(connection, schemaResource);
|
||||
//
|
||||
// log.info("数据库初始化完成");
|
||||
// } catch (Exception e) {
|
||||
// log.error("数据库初始化失败: {}", e.getMessage(), e);
|
||||
// throw new RuntimeException("数据库初始化失败", e);
|
||||
// }
|
||||
// log.info("应用启动成功....");
|
||||
// }
|
||||
//}
|
@ -0,0 +1,70 @@
|
||||
package com.example.demo.common.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.jdbc.datasource.init.DataSourceInitializer;
|
||||
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* H2数据源配置类
|
||||
* 配置缓存数据库H2的数据源和初始化
|
||||
*
|
||||
* @author system
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
public class H2DataSourceConfig {
|
||||
|
||||
private final static String baseURL = "script/h2/";
|
||||
|
||||
/**
|
||||
* 配置H2数据源属性
|
||||
*
|
||||
* @return DataSourceProperties H2数据源属性
|
||||
*/
|
||||
@Bean
|
||||
@ConfigurationProperties("spring.datasource.h2")
|
||||
public DataSourceProperties h2DataSourceProperties() {
|
||||
return new DataSourceProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建H2数据源
|
||||
*
|
||||
* @return DataSource H2数据源
|
||||
*/
|
||||
@Bean
|
||||
@ConfigurationProperties("spring.datasource.h2.hikari")
|
||||
public DataSource h2DataSource() {
|
||||
return h2DataSourceProperties().initializeDataSourceBuilder().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* H2数据库初始化器
|
||||
* 仅在spring.sql.init.h2.enabled=true时启用
|
||||
*
|
||||
* @return DataSourceInitializer 数据库初始化器
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnProperty(prefix = "spring.sql.init.h2", name = "enabled", havingValue = "true")
|
||||
public DataSourceInitializer h2DataSourceInitializer() {
|
||||
DataSourceInitializer initializer = new DataSourceInitializer();
|
||||
initializer.setDataSource(h2DataSource());
|
||||
|
||||
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
|
||||
// 先执行cache-schema.sql创建缓存表结构
|
||||
populator.addScript(new ClassPathResource(baseURL + "h2-schema.sql"));
|
||||
// 再执行cache-data.sql插入缓存数据
|
||||
populator.addScript(new ClassPathResource(baseURL + "h2-data.sql"));
|
||||
populator.setContinueOnError(true);
|
||||
|
||||
initializer.setDatabasePopulator(populator);
|
||||
return initializer;
|
||||
}
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
package com.example.demo.common.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Primary;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.jdbc.datasource.init.DataSourceInitializer;
|
||||
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* SQLite数据源配置类
|
||||
* 配置主数据库SQLite的数据源和初始化
|
||||
*
|
||||
* @author system
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
public class SqliteDataSourceConfig {
|
||||
|
||||
private final static String baseURL = "script/sqlite/";
|
||||
|
||||
/**
|
||||
* 配置SQLite数据源属性
|
||||
*
|
||||
* @return DataSourceProperties SQLite数据源属性
|
||||
*/
|
||||
@Bean
|
||||
@Primary
|
||||
@ConfigurationProperties("spring.datasource.sqlite")
|
||||
public DataSourceProperties sqliteDataSourceProperties() {
|
||||
return new DataSourceProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建SQLite数据源
|
||||
*
|
||||
* @return DataSource SQLite数据源
|
||||
*/
|
||||
@Bean
|
||||
@Primary
|
||||
@ConfigurationProperties("spring.datasource.sqlite.hikari")
|
||||
public DataSource sqliteDataSource() {
|
||||
return sqliteDataSourceProperties().initializeDataSourceBuilder().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* SQLite数据库初始化器
|
||||
* 仅在spring.sql.init.sqlite.enabled=true时启用
|
||||
*
|
||||
* @return DataSourceInitializer 数据库初始化器
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnProperty(prefix = "spring.sql.init.sqlite", name = "enabled", havingValue = "true")
|
||||
public DataSourceInitializer sqliteDataSourceInitializer() {
|
||||
DataSourceInitializer initializer = new DataSourceInitializer();
|
||||
initializer.setDataSource(sqliteDataSource());
|
||||
|
||||
ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
|
||||
// 先执行schema.sql创建表结构
|
||||
populator.addScript(new ClassPathResource(baseURL + "sqlite-schema.sql"));
|
||||
// 再执行data.sql插入数据
|
||||
populator.addScript(new ClassPathResource(baseURL + "sqlite-data.sql"));
|
||||
populator.setContinueOnError(true);
|
||||
|
||||
initializer.setDatabasePopulator(populator);
|
||||
return initializer;
|
||||
}
|
||||
}
|
@ -0,0 +1,77 @@
|
||||
package com.example.demo.common.config.orm;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* Bean Searcher配置类
|
||||
* 配置Bean Searcher框架,用于高级查询功能
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Configuration
|
||||
public class BeanSearcherConfig {
|
||||
|
||||
/**
|
||||
* 由于Bean Searcher框架会自动配置,这里仅做占位配置
|
||||
* 实际项目中可根据需要添加自定义配置
|
||||
*/
|
||||
// 注意:实际使用时需要引入正确的Bean Searcher依赖并使用正确的包名
|
||||
// 例如:import cn.beansearcher.config.SearcherConfig;
|
||||
// import cn.beansearcher.interceptor.InterceptorChain;
|
||||
|
||||
/*
|
||||
@Bean
|
||||
public SearcherConfig searcherConfig(InterceptorChain interceptorChain) {
|
||||
SearcherConfig config = new SearcherConfig();
|
||||
|
||||
// 配置默认的页码(从1开始)
|
||||
config.setDefaultPage(1);
|
||||
|
||||
// 配置默认的每页记录数
|
||||
config.setDefaultSize(10);
|
||||
|
||||
// 配置最大每页记录数
|
||||
config.setMaxSize(1000);
|
||||
|
||||
// 配置是否允许多表查询
|
||||
config.setAllowMultiTable(true);
|
||||
|
||||
// 配置是否允许模糊查询
|
||||
config.setAllowLike(true);
|
||||
|
||||
// 配置模糊查询的默认模式(LEFT, RIGHT, BOTH)
|
||||
config.setDefaultLikeMode("BOTH");
|
||||
|
||||
// 配置是否允许排序
|
||||
config.setAllowOrderby(true);
|
||||
|
||||
// 配置拦截器链
|
||||
config.setInterceptorChain(interceptorChain);
|
||||
|
||||
// 配置是否显示SQL日志
|
||||
config.setShowSql(true);
|
||||
|
||||
// 配置是否格式化SQL日志
|
||||
config.setFormatSql(true);
|
||||
|
||||
// 配置是否显示参数
|
||||
config.setShowParams(true);
|
||||
|
||||
// 配置是否显示执行时间
|
||||
config.setShowExecuteTime(true);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public InterceptorChain interceptorChain() {
|
||||
InterceptorChain chain = new InterceptorChain();
|
||||
|
||||
// 这里可以添加自定义拦截器
|
||||
// chain.addInterceptor(new MyInterceptor());
|
||||
|
||||
return chain;
|
||||
}
|
||||
*/
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.example.demo.common.config.springdoc;
|
||||
|
||||
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
|
||||
import io.swagger.v3.oas.annotations.info.Info;
|
||||
import io.swagger.v3.oas.annotations.info.License;
|
||||
import io.swagger.v3.oas.annotations.servers.Server;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* OpenAPI配置类
|
||||
* 配置Swagger/OpenAPI文档生成
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Configuration
|
||||
@OpenAPIDefinition(
|
||||
info = @Info(
|
||||
title = "XML解析转TXT服务API文档",
|
||||
description = "提供XML文件解析并转换为TXT文件的服务接口",
|
||||
version = "1.0.0",
|
||||
license = @License(
|
||||
name = "Apache 2.0",
|
||||
url = "http://www.apache.org/licenses/LICENSE-2.0"
|
||||
)
|
||||
),
|
||||
servers = {
|
||||
@Server(
|
||||
url = "/xml-parser",
|
||||
description = "本地开发环境"
|
||||
)
|
||||
}
|
||||
)
|
||||
public class OpenApiConfig {
|
||||
// 这里可以添加更多OpenAPI配置
|
||||
// 例如安全配置、全局参数等
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package com.example.demo.common.config.tika.config;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.tika.Tika;
|
||||
import org.apache.tika.config.TikaConfig;
|
||||
import org.apache.tika.detect.Detector;
|
||||
import org.apache.tika.exception.TikaException;
|
||||
import org.apache.tika.parser.AutoDetectParser;
|
||||
import org.apache.tika.parser.Parser;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Tika配置类
|
||||
*
|
||||
* <p>该类负责配置和初始化Apache Tika组件,用于文档内容检测和解析。
|
||||
* 通过加载自定义的tika-config.xml配置文件来定制Tika的行为。</p>
|
||||
*
|
||||
* <p>使用示例:</p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* // 自动注入Tika实例
|
||||
* @Autowired
|
||||
* private Tika tika;
|
||||
*
|
||||
* // 使用Tika检测文件类型
|
||||
* String fileType = tika.detect(file);
|
||||
*
|
||||
* // 使用Tika解析文件内容
|
||||
* String content = tika.parseToString(file);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*
|
||||
* @see Tika
|
||||
* @see TikaConfig
|
||||
* @see Detector
|
||||
* @see Parser
|
||||
*/
|
||||
@Configuration
|
||||
@RequiredArgsConstructor
|
||||
public class MyTikaConfig {
|
||||
|
||||
/**
|
||||
* Spring资源加载器,用于加载类路径下的配置文件
|
||||
*/
|
||||
private final ResourceLoader resourceLoader;
|
||||
|
||||
/**
|
||||
* 创建并配置Tika实例
|
||||
*
|
||||
* <p>该方法会从类路径下加载tika-config.xml配置文件,基于该配置创建TikaConfig,
|
||||
* 然后获取配置中的检测器(Detector)和解析器(Parser),最终构建Tika实例。</p>
|
||||
*
|
||||
* <p>配置文件的预期位置:src/main/resources/tika-config.xml</p>
|
||||
*
|
||||
* @return 配置好的Tika实例,可用于文件类型检测和内容解析
|
||||
* @throws TikaException 当Tika配置处理过程中发生错误时抛出
|
||||
* @throws IOException 当读取配置文件发生I/O错误时抛出
|
||||
* @throws SAXException 当解析XML配置文件发生错误时抛出
|
||||
*
|
||||
* @see TikaConfig
|
||||
* @see Detector
|
||||
* @see AutoDetectParser
|
||||
*
|
||||
* @example 使用自定义配置的Tika实例
|
||||
* <pre>
|
||||
* {@code
|
||||
* Tika tika = myTikaConfig.tika();
|
||||
* String mimeType = tika.detect(new File("document.pdf"));
|
||||
* String content = tika.parseToString(new File("document.pdf"));
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
@Bean
|
||||
public Tika tika() throws TikaException, IOException, SAXException {
|
||||
// 从类路径加载Tika配置文件
|
||||
Resource resource = resourceLoader.getResource("classpath:tika-config.xml");
|
||||
InputStream inputStream = resource.getInputStream();
|
||||
|
||||
// 基于配置文件创建Tika配置
|
||||
TikaConfig config = new TikaConfig(inputStream);
|
||||
|
||||
// 从配置中获取文件类型检测器
|
||||
Detector detector = config.getDetector();
|
||||
|
||||
// 创建自动检测解析器,使用自定义配置
|
||||
Parser autoDetectParser = new AutoDetectParser(config);
|
||||
|
||||
// 构建并返回Tika实例,组合检测器和解析器
|
||||
return new Tika(detector, autoDetectParser);
|
||||
}
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package com.example.demo.common.config.tika.handle;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.tika.detect.AutoDetectReader;
|
||||
import org.apache.tika.exception.TikaException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* 文件字符集检测工具类
|
||||
* <p>
|
||||
* 该类使用Apache Tika库的AutoDetectReader自动检测输入流的字符集编码。
|
||||
* 主要用于识别文件或数据流的字符集,如UTF-8、GBK、ISO-8859-1等。
|
||||
* </p>
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Slf4j
|
||||
public class FileCharsetCheck {
|
||||
|
||||
/**
|
||||
* 检测输入流的字符集编码
|
||||
* <p>
|
||||
* 该方法通过分析输入流的前几个字节来自动识别字符集编码。
|
||||
* 如果检测过程中发生异常,将记录错误日志并返回null。
|
||||
* </p>
|
||||
*
|
||||
* <p><b>注意:</b>该方法会读取输入流的起始部分内容,但不会重置流的位置。
|
||||
* 调用者需要自行处理输入流的位置重置或重新创建输入流。</p>
|
||||
*
|
||||
* <p><b>使用示例:</b></p>
|
||||
* <pre>{@code
|
||||
* InputStream inputStream = new FileInputStream("example.txt");
|
||||
* String charset = FileCharsetCheck.check(inputStream);
|
||||
* if (charset != null) {
|
||||
* System.out.println("文件编码: " + charset);
|
||||
* } else {
|
||||
* System.out.println("编码检测失败");
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @param input 要检测的输入流,不能为null
|
||||
* @return 检测到的字符集名称(如"UTF-8"),如果检测失败则返回null
|
||||
* @throws IllegalArgumentException 如果输入流为null
|
||||
*
|
||||
* @see AutoDetectReader
|
||||
* @see Charset
|
||||
*/
|
||||
public static String check(InputStream input) {
|
||||
if (input == null) {
|
||||
throw new IllegalArgumentException("输入流不能为null");
|
||||
}
|
||||
|
||||
try {
|
||||
Charset charset = new AutoDetectReader(input).getCharset();
|
||||
return charset.name();
|
||||
} catch (IOException | TikaException e) {
|
||||
log.error("解析文件编码异常!", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
package com.example.demo.common.config.tika.handle;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.tika.Tika;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 文件类型检查工具类
|
||||
* 使用Apache Tika库检测文件真实类型,防止文件类型欺骗攻击
|
||||
* 通过白名单机制限制可上传的文件类型,增强系统安全性
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Slf4j
|
||||
public class FileTypeCheck {
|
||||
|
||||
/**
|
||||
* 允许的文件类型白名单
|
||||
* 包含办公文档、图片、媒体文件、数据文件等常见安全文件类型
|
||||
*/
|
||||
private static final List<String> WHITE_LIST = new ArrayList<>(16);
|
||||
|
||||
static {
|
||||
/* 办公文件 */
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_XLS);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_XLSX);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_DOC);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_DOCX);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_PPT);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_PPTX);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_PDF);
|
||||
/* 图片 */
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_SVG);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_ICO);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_PNG);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_JPEG);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_GIF);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_BMP);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_WEBP);
|
||||
/* 媒体 */
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_MP3);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_MP4);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_WAV);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_AVI);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_MOV);
|
||||
/* 可执行文件或安装包 */
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_EXE);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_MSI);
|
||||
/* 常用格式化数据文件 */
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_TXT);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_JSON);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_XML);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_CSV);
|
||||
/* 压缩包 */
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_7Z);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_RAR);
|
||||
WHITE_LIST.add(FileTypeConst.FILE_TYPE_ZIP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过文件名和输入流检查文件类型
|
||||
* 使用Tika库检测文件的真实MIME类型,并与白名单进行比对
|
||||
* 如果文件类型不在白名单中,将抛出RuntimeException
|
||||
*
|
||||
* @param fileName 文件名(用于创建临时文件)
|
||||
* @param inputStream 文件输入流
|
||||
* @throws RuntimeException 当文件类型不在白名单中时抛出
|
||||
*/
|
||||
public static void getFileTypeByFileName(final String fileName, InputStream inputStream) {
|
||||
Tika defaultTika = new Tika();
|
||||
String fileType;
|
||||
// 创建临时文件用于类型检测
|
||||
final File file = new File(fileName);
|
||||
try {
|
||||
// 将输入流复制到临时文件
|
||||
FileUtils.copyInputStreamToFile(inputStream, file);
|
||||
// 使用Tika检测文件真实类型
|
||||
fileType = defaultTika.detect(file);
|
||||
|
||||
// 检查文件类型是否在白名单中
|
||||
if (!WHITE_LIST.contains(fileType)) {
|
||||
throw new RuntimeException("请上传正确的文件类型!!!");
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("getFileTypeByFileName exception:", e);
|
||||
} finally {
|
||||
// 清理临时文件
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过MultipartFile检查文件类型
|
||||
* 适用于Spring MVC文件上传场景
|
||||
*
|
||||
* @param fileName 文件名
|
||||
* @param mFile Spring MultipartFile对象
|
||||
*/
|
||||
public static void getFileTypeByFileName(final String fileName, MultipartFile mFile) {
|
||||
try {
|
||||
// 调用重载方法,使用MultipartFile的输入流
|
||||
getFileTypeByFileName(fileName, mFile.getInputStream());
|
||||
} catch (IOException e) {
|
||||
log.error("getFileTypeByFileName exception:", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,368 @@
|
||||
package com.example.demo.common.config.tika.handle;
|
||||
|
||||
/**
|
||||
* 文件类型常量类
|
||||
* <p>
|
||||
* 该类定义了常见的文件MIME类型常量,用于文件上传、下载、验证等场景。
|
||||
* 所有常量均为标准的MIME类型字符串。
|
||||
* 参考了标准MIME类型定义及常见文件格式:cite[2]:cite[9]。
|
||||
* </p>
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
public class FileTypeConst {
|
||||
|
||||
/* 电子文档与数据文件 */
|
||||
|
||||
/**
|
||||
* Excel 97-2003 工作表格式 (.xls)
|
||||
*/
|
||||
public static final String FILE_TYPE_XLS = "application/vnd.ms-excel";
|
||||
|
||||
/**
|
||||
* Excel 2007及以上 工作表格式 (.xlsx)
|
||||
*/
|
||||
public static final String FILE_TYPE_XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
|
||||
|
||||
/**
|
||||
* Word 97-2003 文档格式 (.doc)
|
||||
*/
|
||||
public static final String FILE_TYPE_DOC = "application/msword";
|
||||
|
||||
/**
|
||||
* Word 2007及以上 文档格式 (.docx)
|
||||
*/
|
||||
public static final String FILE_TYPE_DOCX = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
|
||||
|
||||
/**
|
||||
* PowerPoint 97-2003 演示文稿格式 (.ppt)
|
||||
*/
|
||||
public static final String FILE_TYPE_PPT = "application/vnd.ms-powerpoint";
|
||||
|
||||
/**
|
||||
* PowerPoint 2007及以上 演示文稿格式 (.pptx)
|
||||
*/
|
||||
public static final String FILE_TYPE_PPTX = "application/vnd.openxmlformats-officedocument.presentationml.presentation";
|
||||
|
||||
/**
|
||||
* Adobe PDF 文档格式 (.pdf)
|
||||
*/
|
||||
public static final String FILE_TYPE_PDF = "application/pdf";
|
||||
|
||||
/**
|
||||
* JSON 数据格式 (.json)
|
||||
*/
|
||||
public static final String FILE_TYPE_JSON = "application/json";
|
||||
|
||||
/**
|
||||
* XML 数据格式 (.xml)
|
||||
*/
|
||||
public static final String FILE_TYPE_XML = "application/xml";
|
||||
|
||||
/**
|
||||
* 纯文本文件格式 (.txt)
|
||||
*/
|
||||
public static final String FILE_TYPE_TXT = "text/plain";
|
||||
|
||||
/**
|
||||
* CSV 逗号分隔值文件格式 (.csv)
|
||||
*/
|
||||
public static final String FILE_TYPE_CSV = "text/csv";
|
||||
|
||||
/**
|
||||
* HTML 网页文件格式 (.html, .htm)
|
||||
*/
|
||||
public static final String FILE_TYPE_HTML = "text/html";
|
||||
|
||||
/**
|
||||
* CSS 样式表文件格式 (.css)
|
||||
*/
|
||||
public static final String FILE_TYPE_CSS = "text/css";
|
||||
|
||||
/* 压缩文件 */
|
||||
|
||||
/**
|
||||
* ZIP 压缩文件格式 (.zip)
|
||||
*/
|
||||
public static final String FILE_TYPE_ZIP = "application/zip";
|
||||
|
||||
/**
|
||||
* RAR 压缩文件格式 (.rar)
|
||||
*/
|
||||
public static final String FILE_TYPE_RAR = "application/vnd.rar";
|
||||
|
||||
/**
|
||||
* 7-Zip 压缩文件格式 (.7z)
|
||||
*/
|
||||
public static final String FILE_TYPE_7Z = "application/x-7z-compressed";
|
||||
|
||||
/**
|
||||
* GZIP 压缩文件格式 (.gz)
|
||||
*/
|
||||
public static final String FILE_TYPE_GZ = "application/gzip";
|
||||
|
||||
/**
|
||||
* TAR 归档文件格式 (.tar)
|
||||
*/
|
||||
public static final String FILE_TYPE_TAR = "application/x-tar";
|
||||
|
||||
/* 可执行文件与安装包 */
|
||||
|
||||
/**
|
||||
* Windows 可执行程序格式 (.exe)
|
||||
*/
|
||||
public static final String FILE_TYPE_EXE = "application/x-msdownload";
|
||||
|
||||
/**
|
||||
* Windows 安装包格式 (.msi)
|
||||
*/
|
||||
public static final String FILE_TYPE_MSI = "application/x-msi";
|
||||
|
||||
/**
|
||||
* Android 应用安装包格式 (.apk)
|
||||
*/
|
||||
public static final String FILE_TYPE_APK = "application/vnd.android.package-archive";
|
||||
|
||||
/**
|
||||
* Debian/Ubuntu 系统安装包格式 (.deb)
|
||||
*/
|
||||
public static final String FILE_TYPE_DEB = "application/vnd.debian.binary-package";
|
||||
|
||||
/**
|
||||
* Red Hat/CentOS 系统安装包格式 (.rpm)
|
||||
*/
|
||||
public static final String FILE_TYPE_RPM = "application/x-rpm";
|
||||
|
||||
/**
|
||||
* macOS 磁盘映像文件格式 (.dmg)
|
||||
*/
|
||||
public static final String FILE_TYPE_DMG = "application/x-apple-diskimage";
|
||||
|
||||
/**
|
||||
* Java 归档文件格式 (.jar)
|
||||
*/
|
||||
public static final String FILE_TYPE_JAR = "application/java-archive";
|
||||
|
||||
/* 图片与图形文件 */
|
||||
|
||||
/**
|
||||
* JPEG 图像格式 (.jpg, .jpeg)
|
||||
*/
|
||||
public static final String FILE_TYPE_JPEG = "image/jpeg";
|
||||
|
||||
/**
|
||||
* PNG 图像格式 (.png)
|
||||
*/
|
||||
public static final String FILE_TYPE_PNG = "image/png";
|
||||
|
||||
/**
|
||||
* GIF 图像格式 (.gif)
|
||||
*/
|
||||
public static final String FILE_TYPE_GIF = "image/gif";
|
||||
|
||||
/**
|
||||
* BMP 位图格式 (.bmp)
|
||||
*/
|
||||
public static final String FILE_TYPE_BMP = "image/bmp";
|
||||
|
||||
/**
|
||||
* WebP 图像格式 (.webp)
|
||||
*/
|
||||
public static final String FILE_TYPE_WEBP = "image/webp";
|
||||
|
||||
/**
|
||||
* TIFF 高质量图像格式 (.tiff, .tif)
|
||||
*/
|
||||
public static final String FILE_TYPE_TIFF = "image/tiff";
|
||||
|
||||
/**
|
||||
* ICO 图标文件格式 (.ico)
|
||||
*/
|
||||
public static final String FILE_TYPE_ICO = "image/x-icon";
|
||||
|
||||
/**
|
||||
* SVG 矢量图形格式 (.svg) - 标准MIME类型为 image/svg+xml:cite[2]
|
||||
*/
|
||||
public static final String FILE_TYPE_SVG = "image/svg+xml";
|
||||
|
||||
/**
|
||||
* HEIC/HEIF 高效图像文件格式 (.heic, .heif)
|
||||
*/
|
||||
public static final String FILE_TYPE_HEIC = "image/heic";
|
||||
|
||||
/* 音频文件 */
|
||||
|
||||
/**
|
||||
* MP3 音频格式 (.mp3)
|
||||
*/
|
||||
public static final String FILE_TYPE_MP3 = "audio/mpeg";
|
||||
|
||||
/**
|
||||
* WAV 音频格式 (.wav)
|
||||
*/
|
||||
public static final String FILE_TYPE_WAV = "audio/wav";
|
||||
|
||||
/**
|
||||
* AAC 高级音频编码格式 (.aac)
|
||||
*/
|
||||
public static final String FILE_TYPE_AAC = "audio/aac";
|
||||
|
||||
/**
|
||||
* OGG 音频格式 (.ogg, .oga)
|
||||
*/
|
||||
public static final String FILE_TYPE_OGG_AUDIO = "audio/ogg";
|
||||
|
||||
/**
|
||||
* FLAC 无损音频格式 (.flac)
|
||||
*/
|
||||
public static final String FILE_TYPE_FLAC = "audio/flac";
|
||||
|
||||
/**
|
||||
* MIDI 音乐文件格式 (.mid, .midi)
|
||||
*/
|
||||
public static final String FILE_TYPE_MIDI = "audio/midi";
|
||||
|
||||
/* 视频文件 */
|
||||
|
||||
/**
|
||||
* MP4 视频格式 (.mp4)
|
||||
*/
|
||||
public static final String FILE_TYPE_MP4 = "video/mp4";
|
||||
|
||||
/**
|
||||
* AVI 音频视频交错格式 (.avi)
|
||||
*/
|
||||
public static final String FILE_TYPE_AVI = "video/x-msvideo";
|
||||
|
||||
/**
|
||||
* MOV QuickTime 视频格式 (.mov)
|
||||
*/
|
||||
public static final String FILE_TYPE_MOV = "video/quicktime";
|
||||
|
||||
/**
|
||||
* WebM 开放网络媒体格式 (.webm)
|
||||
*/
|
||||
public static final String FILE_TYPE_WEBM = "video/webm";
|
||||
|
||||
/**
|
||||
* MPEG-1/2 视频格式 (.mpeg, .mpg)
|
||||
*/
|
||||
public static final String FILE_TYPE_MPEG = "video/mpeg";
|
||||
|
||||
/**
|
||||
* WMV Windows Media 视频格式 (.wmv)
|
||||
*/
|
||||
public static final String FILE_TYPE_WMV = "video/x-ms-wmv";
|
||||
|
||||
/**
|
||||
* FLV Flash 视频格式 (.flv)
|
||||
*/
|
||||
public static final String FILE_TYPE_FLV = "video/x-flv";
|
||||
|
||||
/**
|
||||
* 3GPP 多媒体容器格式 (.3gp)
|
||||
*/
|
||||
public static final String FILE_TYPE_3GP = "video/3gpp";
|
||||
|
||||
/* 脚本与源代码文件 */
|
||||
|
||||
/**
|
||||
* JavaScript 文件格式 (.js)
|
||||
*/
|
||||
public static final String FILE_TYPE_JS = "application/javascript";
|
||||
|
||||
/**
|
||||
* TypeScript 文件格式 (.ts) - 通常作为文本处理
|
||||
*/
|
||||
public static final String FILE_TYPE_TS = "application/typescript";
|
||||
|
||||
/**
|
||||
* Python 脚本文件格式 (.py)
|
||||
*/
|
||||
public static final String FILE_TYPE_PY = "text/x-python";
|
||||
|
||||
/**
|
||||
* Java 源代码文件格式 (.java)
|
||||
*/
|
||||
public static final String FILE_TYPE_JAVA = "text/x-java-source";
|
||||
|
||||
/**
|
||||
* C/C++ 头文件格式 (.h)
|
||||
*/
|
||||
public static final String FILE_TYPE_H = "text/x-c";
|
||||
|
||||
/**
|
||||
* C/C++ 源文件格式 (.c, .cpp)
|
||||
*/
|
||||
public static final String FILE_TYPE_C = "text/x-c";
|
||||
|
||||
/**
|
||||
* PHP 脚本文件格式 (.php)
|
||||
*/
|
||||
public static final String FILE_TYPE_PHP = "application/x-php";
|
||||
|
||||
/**
|
||||
* Shell 脚本文件格式 (.sh)
|
||||
*/
|
||||
public static final String FILE_TYPE_SH = "application/x-sh";
|
||||
|
||||
/**
|
||||
* PowerShell 脚本文件格式 (.ps1)
|
||||
*/
|
||||
public static final String FILE_TYPE_PS1 = "application/x-powershell";
|
||||
|
||||
/**
|
||||
* Batch 批处理文件格式 (.bat) - 通常作为文本处理
|
||||
*/
|
||||
public static final String FILE_TYPE_BAT = "application/x-msdownload";
|
||||
|
||||
/* 字体文件 */
|
||||
|
||||
/**
|
||||
* TrueType 字体格式 (.ttf)
|
||||
*/
|
||||
public static final String FILE_TYPE_TTF = "font/ttf";
|
||||
|
||||
/**
|
||||
* OpenType 字体格式 (.otf)
|
||||
*/
|
||||
public static final String FILE_TYPE_OTF = "font/otf";
|
||||
|
||||
/**
|
||||
* Web Open Font 格式 (.woff)
|
||||
*/
|
||||
public static final String FILE_TYPE_WOFF = "font/woff";
|
||||
|
||||
/**
|
||||
* Web Open Font 格式 2.0 (.woff2)
|
||||
*/
|
||||
public static final String FILE_TYPE_WOFF2 = "font/woff2";
|
||||
|
||||
/* 其他文件类型 */
|
||||
|
||||
/**
|
||||
* 电子邮件格式 (.eml)
|
||||
*/
|
||||
public static final String FILE_TYPE_EML = "message/rfc822";
|
||||
|
||||
/**
|
||||
* iCalendar 日历文件格式 (.ics)
|
||||
*/
|
||||
public static final String FILE_TYPE_ICS = "text/calendar";
|
||||
|
||||
/**
|
||||
* SQL 数据库转储文件格式 (.sql)
|
||||
*/
|
||||
public static final String FILE_TYPE_SQL = "application/sql";
|
||||
|
||||
/**
|
||||
* 电子书 EPUB 格式 (.epub)
|
||||
*/
|
||||
public static final String FILE_TYPE_EPUB = "application/epub+zip";
|
||||
|
||||
/**
|
||||
* 虚拟磁盘文件格式 (.iso)
|
||||
*/
|
||||
public static final String FILE_TYPE_ISO = "application/x-iso9660-image";
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
package com.example.demo.common.constant;
|
||||
|
||||
/**
|
||||
* 系统常量类
|
||||
* 定义系统中使用的各种常量,包括错误码、文件类型、状态码等
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
public class GlobalConstants {
|
||||
|
||||
/** 否 */
|
||||
public static final String N = "0";
|
||||
|
||||
/** 是 */
|
||||
public static final String Y = "1";
|
||||
|
||||
// ==================== 文件相关常量 ==================== //
|
||||
|
||||
public static class FileExtensionType {
|
||||
|
||||
/**
|
||||
* XML文件扩展名
|
||||
*/
|
||||
public static final String FILE_EXTENSION_XML = ".xml";
|
||||
|
||||
/**
|
||||
* TXT文件扩展名
|
||||
*/
|
||||
public static final String FILE_EXTENSION_TXT = ".txt";
|
||||
|
||||
}
|
||||
|
||||
public static class FileStatus {
|
||||
|
||||
/**
|
||||
* 文件上传状态:已上传
|
||||
*/
|
||||
public static final String FILE_STATUS_UPLOADED = "uploaded";
|
||||
|
||||
/**
|
||||
* 文件状态:已解析
|
||||
*/
|
||||
public static final String FILE_STATUS_PARSED = "parsed";
|
||||
|
||||
/**
|
||||
* 文件状态:已转换
|
||||
*/
|
||||
public static final String FILE_STATUS_CONVERTED = "converted";
|
||||
|
||||
}
|
||||
|
||||
// ==================== XML解析相关常量 ==================== //
|
||||
|
||||
public static class XMLTagType {
|
||||
|
||||
/**
|
||||
* XML标签类型:根节点
|
||||
*/
|
||||
public static final String XML_TAG_TYPE_ROOT = "root";
|
||||
|
||||
/**
|
||||
* XML标签类型:普通节点
|
||||
*/
|
||||
public static final String XML_TAG_TYPE_NODE = "node";
|
||||
|
||||
/**
|
||||
* XML标签类型:叶子节点
|
||||
*/
|
||||
public static final String XML_TAG_TYPE_LEAF = "leaf";
|
||||
|
||||
/**
|
||||
* XML属性:label
|
||||
*/
|
||||
public static final String XML_ATTR_LABEL = "label";
|
||||
|
||||
/**
|
||||
* XML属性:isNull
|
||||
*/
|
||||
public static final String XML_ATTR_IS_NULL = "isNull";
|
||||
|
||||
/**
|
||||
* XML属性:node
|
||||
*/
|
||||
public static final String XML_ATTR_NODE = "node";
|
||||
|
||||
}
|
||||
|
||||
// ==================== 通用状态常量 ==================== //
|
||||
|
||||
public static class Status {
|
||||
|
||||
/**
|
||||
* 未删除状态
|
||||
*/
|
||||
public static final String NOT_DELETED = "0";
|
||||
|
||||
/**
|
||||
* 已删除状态
|
||||
*/
|
||||
public static final String DELETED = "1";
|
||||
|
||||
/**
|
||||
* 启用状态
|
||||
*/
|
||||
public static final String ENABLED = "1";
|
||||
|
||||
/**
|
||||
* 禁用状态
|
||||
*/
|
||||
public static final String DISABLED = "0";
|
||||
|
||||
}
|
||||
|
||||
// ==================== 字符集常量 ==================== //
|
||||
|
||||
public static class Charset {
|
||||
|
||||
/**
|
||||
* UTF-8字符集
|
||||
*/
|
||||
public static final String CHARSET_UTF8 = "UTF-8";
|
||||
|
||||
}
|
||||
|
||||
// ==================== 路径常量 ==================== //
|
||||
|
||||
public static class Path {
|
||||
|
||||
/**
|
||||
* 路径分隔符
|
||||
*/
|
||||
public static final String PATH_SEPARATOR = "/";
|
||||
|
||||
/**
|
||||
* Windows路径分隔符
|
||||
*/
|
||||
public static final String WINDOWS_PATH_SEPARATOR = "\\";
|
||||
|
||||
}
|
||||
|
||||
// ==================== 缓存相关常量 ==================== //
|
||||
|
||||
public static class Cache {
|
||||
|
||||
/**
|
||||
* 解析规则缓存键前缀
|
||||
*/
|
||||
public static final String CACHE_KEY_PARSE_RULE = "parse_rule:";
|
||||
|
||||
/**
|
||||
* 映射规则缓存键前缀
|
||||
*/
|
||||
public static final String CACHE_KEY_MAPPER_RULE = "mapper_rule:";
|
||||
|
||||
/**
|
||||
* 默认缓存过期时间(秒)
|
||||
*/
|
||||
public static final long DEFAULT_CACHE_EXPIRE = 3600L;
|
||||
|
||||
}
|
||||
|
||||
}
|
58
src/main/java/com/example/demo/common/domain/BaseDTO.java
Normal file
58
src/main/java/com/example/demo/common/domain/BaseDTO.java
Normal file
@ -0,0 +1,58 @@
|
||||
package com.example.demo.common.domain;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 基础数据传输对象
|
||||
* 所有DTO类的基类,用于数据在不同层之间的传递
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Schema(description = "基础数据传输对象")
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BaseDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Schema(description = "ID")
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Schema(description = "创建时间")
|
||||
private Date createdTime;
|
||||
|
||||
/**
|
||||
* 创建人ID
|
||||
*/
|
||||
@Schema(description = "创建人ID")
|
||||
private String createdId;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@Schema(description = "更新时间")
|
||||
private Date updatedTime;
|
||||
|
||||
/**
|
||||
* 更新人ID
|
||||
*/
|
||||
@Schema(description = "更新人ID")
|
||||
private String updatedId;
|
||||
}
|
104
src/main/java/com/example/demo/common/domain/BaseEntity.java
Normal file
104
src/main/java/com/example/demo/common/domain/BaseEntity.java
Normal file
@ -0,0 +1,104 @@
|
||||
package com.example.demo.common.domain;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Id;
|
||||
import com.mybatisflex.annotation.KeyType;
|
||||
import com.mybatisflex.core.keygen.KeyGenerators;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 基础实体类
|
||||
* 所有数据库实体类的基类,包含通用字段和注解
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Schema(description = "基础实体类")
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BaseEntity implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Id(keyType = KeyType.Generator, value = KeyGenerators.uuid)
|
||||
@Schema(description = "ID")
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 命名空间
|
||||
*/
|
||||
@Schema(description = "命名空间")
|
||||
private String nameSpace;
|
||||
|
||||
/**
|
||||
* 排序字段
|
||||
*/
|
||||
@Schema(description = "排序字段")
|
||||
private String sortName;
|
||||
|
||||
/**
|
||||
* 是否删除(0:未删除,1:已删除)
|
||||
*/
|
||||
@Column(isLogicDelete = true)
|
||||
@Schema(description = "是否删除")
|
||||
private String isDelete;
|
||||
|
||||
/**
|
||||
* 乐观锁版本号
|
||||
*/
|
||||
@Column(version = true)
|
||||
@Schema(description = "乐观锁版本号")
|
||||
private Integer revision;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@Column(onInsertValue = "now()")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description = "创建时间")
|
||||
private Date createdTime;
|
||||
|
||||
/**
|
||||
* 创建人ID
|
||||
*/
|
||||
@Schema(description = "创建人ID")
|
||||
private String createdId;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@Column(onUpdateValue = "now()", onInsertValue = "now()")
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description = "更新时间")
|
||||
private Date updatedTime;
|
||||
|
||||
/**
|
||||
* 更新人ID
|
||||
*/
|
||||
@Schema(description = "更新人ID")
|
||||
private String updatedId;
|
||||
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@Schema(description = "租户ID")
|
||||
private String tenantId;
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
package com.example.demo.common.domain;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import cn.zhxu.bs.bean.DbField;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 基础查询数据传输对象
|
||||
* 所有查询DTO类的基类,用于封装查询条件
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Schema(description = "基础查询数据传输对象")
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BaseQueryDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 模糊查询
|
||||
*/
|
||||
@Schema(description = "模糊查询")
|
||||
private String fuzzy;
|
||||
|
||||
/**
|
||||
* 分页参数:当前页码
|
||||
*/
|
||||
@Builder.Default
|
||||
@Schema(description = "当前页码")
|
||||
private Integer pageNum = 1;
|
||||
|
||||
/**
|
||||
* 分页参数:每页条数
|
||||
*/
|
||||
@Builder.Default
|
||||
@Schema(description = "每页条数")
|
||||
private Integer pageSize = 10;
|
||||
|
||||
/**
|
||||
* 排序字段
|
||||
*/
|
||||
@Schema(description = "排序字段")
|
||||
private String sortField;
|
||||
|
||||
/**
|
||||
* 排序方式:asc或desc
|
||||
*/
|
||||
@Schema(description = "排序方式")
|
||||
private String sortOrder;
|
||||
|
||||
}
|
80
src/main/java/com/example/demo/common/domain/BaseVO.java
Normal file
80
src/main/java/com/example/demo/common/domain/BaseVO.java
Normal file
@ -0,0 +1,80 @@
|
||||
package com.example.demo.common.domain;
|
||||
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 基础视图对象
|
||||
* 所有VO类的基类,用于向前端返回数据
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Schema(description = "基础视图对象")
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BaseVO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Schema(description = "ID")
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 键
|
||||
*/
|
||||
@Schema(description = "key")
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* 名称
|
||||
*/
|
||||
@Schema(description = "name")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description = "创建时间")
|
||||
private Date createdTime;
|
||||
|
||||
/**
|
||||
* 创建人ID
|
||||
*/
|
||||
@Schema(description = "创建人ID")
|
||||
private String createdId;
|
||||
|
||||
/**
|
||||
* 更新时间
|
||||
*/
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description = "更新时间")
|
||||
private Date updatedTime;
|
||||
|
||||
/**
|
||||
* 更新人ID
|
||||
*/
|
||||
@Schema(description = "更新人ID")
|
||||
private String updatedId;
|
||||
|
||||
/**
|
||||
* 是否删除(0:未删除,1:已删除)
|
||||
*/
|
||||
@Schema(description = "是否删除")
|
||||
private String isDelete;
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package com.example.demo.common.exception;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 业务异常类
|
||||
* 用于表示业务逻辑中的异常情况
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Getter
|
||||
@Setter(value = AccessLevel.PRIVATE)
|
||||
public class BusinessException extends RuntimeException {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 错误码
|
||||
*/
|
||||
private int code;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*
|
||||
* @param code 错误码
|
||||
* @param message 错误信息
|
||||
*/
|
||||
public BusinessException(int code, String message) {
|
||||
super(message);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数,使用默认错误码
|
||||
*
|
||||
* @param message 错误信息
|
||||
*/
|
||||
public BusinessException(String message) {
|
||||
super(message);
|
||||
this.code = 500;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数,包含异常原因
|
||||
*
|
||||
* @param code 错误码
|
||||
* @param message 错误信息
|
||||
* @param cause 异常原因
|
||||
*/
|
||||
public BusinessException(int code, String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造函数,包含异常原因,使用默认错误码
|
||||
*
|
||||
* @param message 错误信息
|
||||
* @param cause 异常原因
|
||||
*/
|
||||
public BusinessException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.code = 500;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BusinessException{code=" + code + ", message='" + getMessage() + "'}";
|
||||
}
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
package com.example.demo.common.exception.global;
|
||||
|
||||
import com.example.demo.common.wrapper.WrapMapper;
|
||||
import com.example.demo.common.wrapper.Wrapper;
|
||||
import com.example.demo.common.exception.BusinessException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.validation.BindException;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.multipart.MaxUploadSizeExceededException;
|
||||
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 全局异常处理器
|
||||
* 统一处理系统异常,返回规范的错误响应
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Slf4j
|
||||
@RestControllerAdvice
|
||||
public class GlobalExceptionHandler {
|
||||
|
||||
/**
|
||||
* 处理业务异常
|
||||
*
|
||||
* @param e 业务异常
|
||||
* @return 错误响应
|
||||
*/
|
||||
@ExceptionHandler(BusinessException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Wrapper<String> handleBusinessException(BusinessException e) {
|
||||
log.warn("业务异常: {}", e.getMessage(), e);
|
||||
return WrapMapper.fail(String.valueOf(e.getCode()), e.getMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理参数校验异常(MethodArgumentNotValidException)
|
||||
*
|
||||
* @param e 参数校验异常
|
||||
* @return 错误响应
|
||||
*/
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Wrapper<String> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
|
||||
List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
|
||||
String errorMessage = fieldErrors.stream()
|
||||
.map(error -> error.getField() + ": " + error.getDefaultMessage())
|
||||
.collect(Collectors.joining("; "));
|
||||
|
||||
log.warn("参数校验异常: {}", errorMessage);
|
||||
return WrapMapper.fail("PARAM_VALIDATION_ERROR", errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理参数绑定异常(BindException)
|
||||
*
|
||||
* @param e 参数绑定异常
|
||||
* @return 错误响应
|
||||
*/
|
||||
@ExceptionHandler(BindException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Wrapper<String> handleBindException(BindException e) {
|
||||
List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
|
||||
String errorMessage = fieldErrors.stream()
|
||||
.map(error -> error.getField() + ": " + error.getDefaultMessage())
|
||||
.collect(Collectors.joining("; "));
|
||||
|
||||
log.warn("参数绑定异常: {}", errorMessage);
|
||||
return WrapMapper.fail("PARAM_BINDING_ERROR", errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理约束违反异常(ConstraintViolationException)
|
||||
*
|
||||
* @param e 约束违反异常
|
||||
* @return 错误响应
|
||||
*/
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Wrapper<String> handleConstraintViolationException(ConstraintViolationException e) {
|
||||
Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
|
||||
String errorMessage = violations.stream()
|
||||
.map(violation -> violation.getPropertyPath() + ": " + violation.getMessage())
|
||||
.collect(Collectors.joining("; "));
|
||||
|
||||
log.warn("约束违反异常: {}", errorMessage);
|
||||
return WrapMapper.fail("CONSTRAINT_VIOLATION_ERROR", errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理文件上传大小限制异常
|
||||
*
|
||||
* @param e 文件上传大小限制异常
|
||||
* @return 错误响应
|
||||
*/
|
||||
@ExceptionHandler(MaxUploadSizeExceededException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
public Wrapper<String> handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e) {
|
||||
log.warn("文件上传大小限制异常: {}", e.getMessage(), e);
|
||||
return WrapMapper.fail("FILE_UPLOAD_SIZE_LIMIT", "上传文件大小超过限制");
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理系统异常
|
||||
*
|
||||
* @param e 系统异常
|
||||
* @return 错误响应
|
||||
*/
|
||||
@ExceptionHandler(Exception.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public Wrapper<String> handleException(Exception e) {
|
||||
log.error("系统异常: {}", e.getMessage(), e);
|
||||
return WrapMapper.fail("SYSTEM_ERROR", "系统内部错误,请联系管理员");
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理运行时异常
|
||||
*
|
||||
* @param e 运行时异常
|
||||
* @return 错误响应
|
||||
*/
|
||||
@ExceptionHandler(RuntimeException.class)
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public Wrapper<String> handleRuntimeException(RuntimeException e) {
|
||||
log.error("运行时异常: {}", e.getMessage(), e);
|
||||
return WrapMapper.fail("RUNTIME_ERROR", "系统运行时错误,请联系管理员");
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package com.example.demo.common.typography;
|
||||
|
||||
/**
|
||||
* 统一 Controller 接口
|
||||
* 统一定义 Controller 基础接口
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
public abstract class BaseController {
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.example.demo.common.typography;
|
||||
|
||||
import cn.zhxu.bs.SearchResult;
|
||||
import com.example.demo.common.domain.BaseDTO;
|
||||
import com.example.demo.common.domain.BaseEntity;
|
||||
import com.example.demo.common.domain.BaseQueryDTO;
|
||||
import com.example.demo.common.domain.BaseVO;
|
||||
import com.mybatisflex.core.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 统一 Service 接口
|
||||
* 统一定义Service基础接口
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
public interface BaseService<Entity extends BaseEntity, VO extends BaseVO, DTO extends BaseDTO, QueryDTO extends BaseQueryDTO>
|
||||
extends IService<Entity> {
|
||||
|
||||
/**
|
||||
* 创建
|
||||
* @param dto DTO
|
||||
* @return 创建结果
|
||||
*/
|
||||
VO create(DTO dto);
|
||||
|
||||
/**
|
||||
* 删除
|
||||
* @param id ID
|
||||
*/
|
||||
void delete(String id);
|
||||
|
||||
/**
|
||||
* 更新
|
||||
* @param dto DTO
|
||||
* @return 是否更新成功
|
||||
*/
|
||||
Boolean update(DTO dto);
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
* @param dto 查询条件
|
||||
* @return 分页结果
|
||||
*/
|
||||
SearchResult<VO> pageList(QueryDTO dto);
|
||||
|
||||
/**
|
||||
* 获取下拉框数据
|
||||
* @param dto 查询条件
|
||||
* @return 下拉框数据列表
|
||||
*/
|
||||
List<VO> option(QueryDTO dto);
|
||||
|
||||
/**
|
||||
* 获取详情
|
||||
* @param id ID
|
||||
* @return 详情
|
||||
*/
|
||||
VO detail(String id);
|
||||
|
||||
/**
|
||||
* 刷新缓存
|
||||
*/
|
||||
void refreshCache();
|
||||
|
||||
}
|
@ -0,0 +1,208 @@
|
||||
package com.example.demo.common.typography;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.zhxu.bs.BeanSearcher;
|
||||
import cn.zhxu.bs.SearchResult;
|
||||
import cn.zhxu.bs.operator.Contain;
|
||||
import cn.zhxu.bs.util.MapUtils;
|
||||
import com.example.demo.common.constant.GlobalConstants;
|
||||
import com.example.demo.common.domain.BaseDTO;
|
||||
import com.example.demo.common.domain.BaseEntity;
|
||||
import com.example.demo.common.domain.BaseQueryDTO;
|
||||
import com.example.demo.common.domain.BaseVO;
|
||||
import com.fhs.trans.service.impl.TransService;
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public abstract class BaseServiceImpl<
|
||||
Entity extends BaseEntity,
|
||||
VO extends BaseVO,
|
||||
DTO extends BaseDTO,
|
||||
QueryDTO extends BaseQueryDTO,
|
||||
Mapper extends BaseMapper<Entity>
|
||||
>
|
||||
extends
|
||||
ServiceImpl<Mapper, Entity>
|
||||
implements
|
||||
BaseService<Entity, VO, DTO, QueryDTO>, InitializingBean, DisposableBean {
|
||||
|
||||
/** 实际Log出例服务 */
|
||||
private final Logger log;
|
||||
|
||||
/** 实际业务实现类 */
|
||||
private final String CLASS_NAME;
|
||||
|
||||
/** 实际业务实现VO类 */
|
||||
private final Class<VO> clazzVO;
|
||||
|
||||
/** 提供Select服务 */
|
||||
private final BeanSearcher beanSearcher;
|
||||
|
||||
/** 提供数据翻译服务 */
|
||||
private final TransService transService;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public VO create(DTO dto) {
|
||||
Entity entity = createEntity();
|
||||
BeanUtil.copyProperties(dto, entity);
|
||||
// 新增数据
|
||||
save(entity);
|
||||
// 仅返回数据ID
|
||||
@SuppressWarnings("all")
|
||||
VO resultVO = (VO) VO.builder().id(entity.getId()).build();
|
||||
// 其他处理...
|
||||
return resultVO;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void delete(String id) {
|
||||
// 使用逻辑删除
|
||||
removeById(id);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public Boolean update(DTO dto) {
|
||||
Entity entity = createEntity();
|
||||
BeanUtil.copyProperties(dto, entity);
|
||||
// 更新数据
|
||||
return updateById(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SearchResult<VO> pageList(QueryDTO dto) {
|
||||
// 组装分页查询参数
|
||||
Map<String, Object> paramMap = MapUtils.builder()
|
||||
// 分页查询
|
||||
.page(dto.getPageNum(), dto.getPageSize())
|
||||
.limit(dto.getPageNum(), dto.getPageSize())
|
||||
// 模糊查询
|
||||
.field(VO::getName, dto.getFuzzy()).op(Contain.class)
|
||||
// 未删除数据
|
||||
.field(VO::getIsDelete, GlobalConstants.N)
|
||||
// 分页排序,默认强制按照更新时间倒序,单词正序
|
||||
.orderBy(VO::getUpdatedTime).desc()
|
||||
.orderBy(VO::getName).asc()
|
||||
.build();
|
||||
@SuppressWarnings("all")
|
||||
SearchResult<VO> vos = beanSearcher.search(this.clazzVO, paramMap);
|
||||
|
||||
if(CollUtil.isEmpty(vos.getDataList())) {
|
||||
return vos;
|
||||
}
|
||||
|
||||
// 批量数据翻译
|
||||
// transService.transBatch(vos.getDataList());
|
||||
return vos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List option(QueryDTO dto) {
|
||||
Map<String, Object> paramMap = MapUtils.builder()
|
||||
.onlySelect(
|
||||
VO::getId,
|
||||
VO::getName,
|
||||
VO::getKey
|
||||
)
|
||||
// 下拉框,允许模糊筛选
|
||||
.field(VO::getName, dto.getFuzzy()).op(Contain.class)
|
||||
// 下拉框,只能查询未删除的数据
|
||||
.field(VO::getIsDelete, GlobalConstants.N)
|
||||
// 下拉框,强制使用单词正序,时间倒序
|
||||
.orderBy(VO::getName).asc()
|
||||
.orderBy(VO::getCreatedTime).desc()
|
||||
.build();
|
||||
List<VO> vos = beanSearcher.searchAll(this.clazzVO, paramMap);
|
||||
|
||||
if (CollUtil.isEmpty(vos)) {
|
||||
return List.of();
|
||||
}
|
||||
return vos;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public VO detail(String id) {
|
||||
Map<String, Object> paramMap = MapUtils.builder()
|
||||
.field(VO::getId, id)
|
||||
.field(VO::getIsDelete, GlobalConstants.N)
|
||||
.build();
|
||||
VO wordVO = beanSearcher.searchFirst(this.clazzVO, paramMap);
|
||||
|
||||
// 数据翻译
|
||||
if (ObjectUtil.isNotEmpty(wordVO)) {
|
||||
// transService.transOne(wordVO);
|
||||
}
|
||||
return wordVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshCache() {
|
||||
// ignore
|
||||
log.warn("刷新缓存(暂无实现)");
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void preDestroy() {
|
||||
// ignore
|
||||
}
|
||||
|
||||
/**
|
||||
* 实例化 entity
|
||||
* @return 获取新实例化 entity 类
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
protected Entity createEntity() {
|
||||
return (Entity) Entity.builder().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 实例化 entity
|
||||
* @return 获取新实例化 entity 类
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
protected VO createVO() {
|
||||
return (VO) VO.builder().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 实例化 entity
|
||||
* @return 获取新实例化 entity 类
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
protected DTO createDTO() {
|
||||
return (DTO) DTO.builder().build();
|
||||
}
|
||||
}
|
315
src/main/java/com/example/demo/common/utils/FileUtil.java
Normal file
315
src/main/java/com/example/demo/common/utils/FileUtil.java
Normal file
@ -0,0 +1,315 @@
|
||||
package com.example.demo.common.utils;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 文件操作工具类
|
||||
* 提供文件读写、复制、删除等通用功能
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
public class FileUtil {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(FileUtil.class);
|
||||
|
||||
/**
|
||||
* 读取文件内容
|
||||
*
|
||||
* @param filePath 文件路径
|
||||
* @return 文件内容
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static String readFileContent(String filePath) throws IOException {
|
||||
return new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入内容到文件
|
||||
*
|
||||
* @param filePath 文件路径
|
||||
* @param content 文件内容
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static void writeFileContent(String filePath, String content) throws IOException {
|
||||
// 确保父目录存在
|
||||
Path path = Paths.get(filePath);
|
||||
Path parentDir = path.getParent();
|
||||
if (parentDir != null) {
|
||||
Files.createDirectories(parentDir);
|
||||
}
|
||||
// 写入文件
|
||||
Files.write(path, content.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
|
||||
}
|
||||
|
||||
/**
|
||||
* 追加内容到文件
|
||||
*
|
||||
* @param filePath 文件路径
|
||||
* @param content 文件内容
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static void appendFileContent(String filePath, String content) throws IOException {
|
||||
// 确保父目录存在
|
||||
Path path = Paths.get(filePath);
|
||||
Path parentDir = path.getParent();
|
||||
if (parentDir != null) {
|
||||
Files.createDirectories(parentDir);
|
||||
}
|
||||
// 追加文件
|
||||
Files.write(path, content.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* 复制文件
|
||||
*
|
||||
* @param sourceFilePath 源文件路径
|
||||
* @param targetFilePath 目标文件路径
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static void copyFile(String sourceFilePath, String targetFilePath) throws IOException {
|
||||
Path sourcePath = Paths.get(sourceFilePath);
|
||||
Path targetPath = Paths.get(targetFilePath);
|
||||
|
||||
// 确保目标目录存在
|
||||
Path targetDir = targetPath.getParent();
|
||||
if (targetDir != null) {
|
||||
Files.createDirectories(targetDir);
|
||||
}
|
||||
|
||||
// 复制文件
|
||||
Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移动文件
|
||||
*
|
||||
* @param sourceFilePath 源文件路径
|
||||
* @param targetFilePath 目标文件路径
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static void moveFile(String sourceFilePath, String targetFilePath) throws IOException {
|
||||
Path sourcePath = Paths.get(sourceFilePath);
|
||||
Path targetPath = Paths.get(targetFilePath);
|
||||
|
||||
// 确保目标目录存在
|
||||
Path targetDir = targetPath.getParent();
|
||||
if (targetDir != null) {
|
||||
Files.createDirectories(targetDir);
|
||||
}
|
||||
|
||||
// 移动文件
|
||||
Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除文件
|
||||
*
|
||||
* @param filePath 文件路径
|
||||
* @return 是否删除成功
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static boolean deleteFile(String filePath) throws IOException {
|
||||
return Files.deleteIfExists(Paths.get(filePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建目录
|
||||
*
|
||||
* @param dirPath 目录路径
|
||||
* @return 是否创建成功
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static boolean createDirectory(String dirPath) throws IOException {
|
||||
Path path = Paths.get(dirPath);
|
||||
if (Files.exists(path)) {
|
||||
return Files.isDirectory(path);
|
||||
}
|
||||
Files.createDirectories(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除目录(包括目录下的所有文件)
|
||||
*
|
||||
* @param dirPath 目录路径
|
||||
* @return 是否删除成功
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static boolean deleteDirectory(String dirPath) throws IOException {
|
||||
Path path = Paths.get(dirPath);
|
||||
if (!Files.exists(path)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 递归删除目录内容
|
||||
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
Files.delete(file);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
|
||||
Files.delete(dir);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件大小
|
||||
*
|
||||
* @param filePath 文件路径
|
||||
* @return 文件大小(字节)
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static long getFileSize(String filePath) throws IOException {
|
||||
return Files.size(Paths.get(filePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件扩展名
|
||||
*
|
||||
* @param fileName 文件名
|
||||
* @return 文件扩展名(小写)
|
||||
*/
|
||||
public static String getFileExtension(String fileName) {
|
||||
if (fileName == null || fileName.lastIndexOf('.') == -1) {
|
||||
return "";
|
||||
}
|
||||
return fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一文件名
|
||||
*
|
||||
* @param originalFileName 原始文件名
|
||||
* @return 唯一文件名
|
||||
*/
|
||||
public static String generateUniqueFileName(String originalFileName) {
|
||||
String extension = getFileExtension(originalFileName);
|
||||
String timestamp = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(new Date());
|
||||
String uuid = UUID.randomUUID().toString().replaceAll("-|", "");
|
||||
|
||||
if (extension.isEmpty()) {
|
||||
return timestamp + "_" + uuid;
|
||||
} else {
|
||||
return timestamp + "_" + uuid + "." + extension;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出目录下的所有文件
|
||||
*
|
||||
* @param dirPath 目录路径
|
||||
* @return 文件路径列表
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static List<String> listFiles(String dirPath) throws IOException {
|
||||
List<String> filePaths = new ArrayList<>();
|
||||
Path path = Paths.get(dirPath);
|
||||
|
||||
if (Files.exists(path) && Files.isDirectory(path)) {
|
||||
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
filePaths.add(file.toString());
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return filePaths;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件的MIME类型
|
||||
*
|
||||
* @param filePath 文件路径
|
||||
* @return MIME类型
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static String getMimeType(String filePath) throws IOException {
|
||||
return Files.probeContentType(Paths.get(filePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查文件是否存在
|
||||
*
|
||||
* @param filePath 文件路径
|
||||
* @return 是否存在
|
||||
*/
|
||||
public static boolean fileExists(String filePath) {
|
||||
return Files.exists(Paths.get(filePath));
|
||||
}
|
||||
|
||||
/**
|
||||
* 清理临时文件
|
||||
*
|
||||
* @param dirPath 临时目录路径
|
||||
* @param daysAgo 清理多少天前的文件
|
||||
* @return 清理的文件数量
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static int cleanTempFiles(String dirPath, int daysAgo) throws IOException {
|
||||
final int[] deletedCount = {0};
|
||||
Path path = Paths.get(dirPath);
|
||||
|
||||
if (!Files.exists(path) || !Files.isDirectory(path)) {
|
||||
return deletedCount[0];
|
||||
}
|
||||
|
||||
long cutoffTime = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(daysAgo);
|
||||
|
||||
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
try {
|
||||
// 检查文件的最后修改时间
|
||||
if (Files.getLastModifiedTime(file).toMillis() < cutoffTime) {
|
||||
Files.delete(file);
|
||||
deletedCount[0]++;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("删除临时文件失败: {}", file, e);
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
});
|
||||
|
||||
return deletedCount[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建临时文件
|
||||
*
|
||||
* @param prefix 文件前缀
|
||||
* @param suffix 文件后缀
|
||||
* @param tempDir 临时目录
|
||||
* @return 临时文件路径
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static String createTempFile(String prefix, String suffix, String tempDir) throws IOException {
|
||||
// 确保临时目录存在
|
||||
createDirectory(tempDir);
|
||||
|
||||
// 创建临时文件
|
||||
File tempFile = File.createTempFile(prefix, suffix, new File(tempDir));
|
||||
return tempFile.getAbsolutePath();
|
||||
}
|
||||
}
|
382
src/main/java/com/example/demo/common/utils/XmlParserUtil.java
Normal file
382
src/main/java/com/example/demo/common/utils/XmlParserUtil.java
Normal file
@ -0,0 +1,382 @@
|
||||
package com.example.demo.common.utils;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import org.w3c.dom.*;
|
||||
import org.xml.sax.InputSource;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* XML解析工具类
|
||||
* 提供XML文件解析和转换为TXT文件的核心功能
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
public class XmlParserUtil {
|
||||
|
||||
/**
|
||||
* 解析XML文件并转换为TXT文件
|
||||
*
|
||||
* @param xmlFilePath XML文件路径
|
||||
* @param txtFilePath TXT文件路径
|
||||
* @throws Exception 解析过程中的异常
|
||||
*/
|
||||
public static void parseXmlToTxt(String xmlFilePath, String txtFilePath) throws Exception {
|
||||
// 读取XML文件并解析
|
||||
Document document = parseXmlFile(xmlFilePath);
|
||||
|
||||
// 创建TXT文件
|
||||
createTxtFile(document, txtFilePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析XML文件为Document对象
|
||||
*
|
||||
* @param xmlFilePath XML文件路径
|
||||
* @return Document对象
|
||||
* @throws Exception 解析异常
|
||||
*/
|
||||
public static Document parseXmlFile(String xmlFilePath) throws Exception {
|
||||
// 确保文件存在
|
||||
File file = new File(xmlFilePath);
|
||||
if (!file.exists()) {
|
||||
throw new FileNotFoundException("XML文件不存在: " + xmlFilePath);
|
||||
}
|
||||
|
||||
// 创建DocumentBuilder并解析文件
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
factory.setIgnoringElementContentWhitespace(true);
|
||||
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
InputSource is = new InputSource(new InputStreamReader(fis, StandardCharsets.UTF_8));
|
||||
return factory.newDocumentBuilder().parse(is);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Document对象转换为TXT文件
|
||||
*
|
||||
* @param document XML文档对象
|
||||
* @param txtFilePath TXT文件路径
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public static void createTxtFile(Document document, String txtFilePath) throws IOException {
|
||||
// 确保输出目录存在
|
||||
Path outputPath = Paths.get(txtFilePath).getParent();
|
||||
if (outputPath != null && !Files.exists(outputPath)) {
|
||||
Files.createDirectories(outputPath);
|
||||
}
|
||||
|
||||
// 写入TXT文件
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(txtFilePath), StandardCharsets.UTF_8)) {
|
||||
// 处理根元素
|
||||
Element rootElement = document.getDocumentElement();
|
||||
processElement(rootElement, writer, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 递归处理XML元素并写入TXT文件
|
||||
* 将中文XML标签转换为特定的TXT格式
|
||||
*
|
||||
* @param element 当前XML元素
|
||||
* @param writer 输出写入器
|
||||
* @param indentLevel 缩进级别
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
private static void processElement(Element element, BufferedWriter writer, int indentLevel) throws IOException {
|
||||
String tagName = element.getTagName();
|
||||
String indent = " ".repeat(Math.max(0, indentLevel));
|
||||
|
||||
// 根据中文标签名映射到对应的TXT格式
|
||||
switch (tagName) {
|
||||
case "任务":
|
||||
processTaskElement(element, writer, indentLevel);
|
||||
break;
|
||||
case "任务信息":
|
||||
processTaskInfoElement(element, writer, indentLevel);
|
||||
break;
|
||||
case "平台":
|
||||
processPlatformElement(element, writer, indentLevel);
|
||||
break;
|
||||
case "行动":
|
||||
processActionElement(element, writer, indentLevel);
|
||||
break;
|
||||
default:
|
||||
processGenericElement(element, writer, indentLevel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理任务元素
|
||||
*/
|
||||
private static void processTaskElement(Element element, BufferedWriter writer, int indentLevel) throws IOException {
|
||||
String indent = " ".repeat(Math.max(0, indentLevel));
|
||||
|
||||
// 获取任务行动信息
|
||||
String taskAction = getElementTextByTagName(element, "任务行动信息");
|
||||
if (StrUtil.isNotBlank(taskAction)) {
|
||||
writer.write(indent + "task " + taskAction + " # 任务信息");
|
||||
writer.newLine();
|
||||
}
|
||||
|
||||
// 处理子元素
|
||||
processChildElements(element, writer, indentLevel + 1);
|
||||
|
||||
writer.write(indent + "end_task");
|
||||
writer.newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理任务信息元素
|
||||
*/
|
||||
private static void processTaskInfoElement(Element element, BufferedWriter writer, int indentLevel) throws IOException {
|
||||
String indent = " ".repeat(Math.max(0, indentLevel));
|
||||
|
||||
// 处理指令有效期(拆分为开始和结束时间)
|
||||
String instructionPeriod = getElementTextByTagName(element, "指令有效期");
|
||||
if (StrUtil.isNotBlank(instructionPeriod)) {
|
||||
String[] timeRange = instructionPeriod.split("~");
|
||||
if (timeRange.length == 2) {
|
||||
writer.write(indent + "start_time " + timeRange[0].trim());
|
||||
writer.newLine();
|
||||
writer.write(indent + "end_time " + timeRange[1].trim());
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
|
||||
// 处理其他子元素
|
||||
processChildElements(element, writer, indentLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理平台元素
|
||||
*/
|
||||
private static void processPlatformElement(Element element, BufferedWriter writer, int indentLevel) throws IOException {
|
||||
String indent = " ".repeat(Math.max(0, indentLevel));
|
||||
|
||||
writer.write(indent + "platform # 平台信息");
|
||||
writer.newLine();
|
||||
|
||||
// 处理平台子元素
|
||||
String platformName = getElementTextByTagName(element, "平台名称");
|
||||
String machineType = getElementTextByTagName(element, "机型");
|
||||
String numOfCpus = getElementTextByTagName(element, "架数");
|
||||
String platformId = getElementTextByTagName(element, "平台识别码");
|
||||
String country = getElementTextByTagName(element, "国家");
|
||||
|
||||
if (StrUtil.isNotBlank(platformName)) {
|
||||
writer.write(indent + " platform_name " + platformName);
|
||||
writer.newLine();
|
||||
}
|
||||
if (StrUtil.isNotBlank(machineType)) {
|
||||
writer.write(indent + " machine_type " + machineType);
|
||||
writer.newLine();
|
||||
}
|
||||
if (StrUtil.isNotBlank(numOfCpus)) {
|
||||
writer.write(indent + " num_of_cpus " + numOfCpus);
|
||||
writer.newLine();
|
||||
}
|
||||
if (StrUtil.isNotBlank(platformId)) {
|
||||
writer.write(indent + " platform_id " + platformId);
|
||||
writer.newLine();
|
||||
}
|
||||
if (StrUtil.isNotBlank(country)) {
|
||||
writer.write(indent + " country " + country);
|
||||
writer.newLine();
|
||||
}
|
||||
|
||||
// 处理行动子元素
|
||||
processChildElements(element, writer, indentLevel + 1);
|
||||
|
||||
writer.write(indent + "end_platform");
|
||||
writer.newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理行动元素
|
||||
*/
|
||||
private static void processActionElement(Element element, BufferedWriter writer, int indentLevel) throws IOException {
|
||||
String indent = " ".repeat(Math.max(0, indentLevel));
|
||||
|
||||
writer.write(indent + "action");
|
||||
writer.newLine();
|
||||
|
||||
// 处理行动属性
|
||||
if (element.hasAttributes()) {
|
||||
NamedNodeMap attributes = element.getAttributes();
|
||||
for (int i = 0; i < attributes.getLength(); i++) {
|
||||
Attr attr = (Attr) attributes.item(i);
|
||||
if ("label".equals(attr.getName())) {
|
||||
writer.write(indent + " action_name " + attr.getValue());
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 处理航线名称
|
||||
String routeName = getElementTextByTagName(element, "航线名称");
|
||||
if (StrUtil.isNotBlank(routeName)) {
|
||||
writer.write(indent + " route_name " + routeName);
|
||||
writer.newLine();
|
||||
}
|
||||
|
||||
writer.write(indent + "end_action");
|
||||
writer.newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理通用元素
|
||||
*/
|
||||
private static void processGenericElement(Element element, BufferedWriter writer, int indentLevel) throws IOException {
|
||||
String tagName = element.getTagName();
|
||||
String indent = " ".repeat(Math.max(0, indentLevel));
|
||||
|
||||
// 将中文标签名转换为英文(简单映射)
|
||||
String englishTag = convertChineseTagToEnglish(tagName);
|
||||
|
||||
if (StrUtil.isNotBlank(englishTag)) {
|
||||
String textContent = getElementText(element);
|
||||
if (StrUtil.isNotBlank(textContent)) {
|
||||
writer.write(indent + englishTag + " " + textContent);
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理子元素
|
||||
*/
|
||||
private static void processChildElements(Element parent, BufferedWriter writer, int indentLevel) throws IOException {
|
||||
NodeList children = parent.getChildNodes();
|
||||
for (int i = 0; i < children.getLength(); i++) {
|
||||
if (children.item(i) instanceof Element) {
|
||||
processElement((Element) children.item(i), writer, indentLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据标签名获取元素文本内容
|
||||
*/
|
||||
private static String getElementTextByTagName(Element parent, String tagName) {
|
||||
NodeList elements = parent.getElementsByTagName(tagName);
|
||||
if (elements.getLength() > 0) {
|
||||
Element element = (Element) elements.item(0);
|
||||
return getElementText(element);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 将中文标签转换为英文标签
|
||||
*/
|
||||
private static String convertChineseTagToEnglish(String chineseTag) {
|
||||
// 简单的中文到英文映射
|
||||
switch (chineseTag) {
|
||||
case "指令确认信息": return "confirm_info";
|
||||
case "覆盖的指令文档": return "document_version";
|
||||
default: return chineseTag;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从XML字符串解析为Document对象
|
||||
*
|
||||
* @param xmlContent XML字符串内容
|
||||
* @return Document对象
|
||||
* @throws Exception 解析异常
|
||||
*/
|
||||
public static Document parseXmlString(String xmlContent) throws Exception {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
|
||||
try (InputStream inputStream = new ByteArrayInputStream(xmlContent.getBytes(StandardCharsets.UTF_8))) {
|
||||
InputSource is = new InputSource(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
|
||||
return factory.newDocumentBuilder().parse(is);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取XML元素的文本内容
|
||||
*
|
||||
* @param element XML元素
|
||||
* @return 文本内容
|
||||
*/
|
||||
public static String getElementText(Element element) {
|
||||
if (element == null) {
|
||||
return "";
|
||||
}
|
||||
NodeList childNodes = element.getChildNodes();
|
||||
StringBuilder textContent = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node node = childNodes.item(i);
|
||||
if (node.getNodeType() == Node.TEXT_NODE) {
|
||||
textContent.append(node.getNodeValue());
|
||||
}
|
||||
}
|
||||
|
||||
return textContent.toString().trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定路径的XML元素
|
||||
*
|
||||
* @param document XML文档对象
|
||||
* @param xpath 元素路径
|
||||
* @return 元素列表
|
||||
*/
|
||||
public static List<Element> getElementsByPath(Document document, String xpath) {
|
||||
List<Element> elements = new ArrayList<>();
|
||||
|
||||
// 简单实现XPath功能,实际项目中可使用JAXB或XPath API
|
||||
String[] pathParts = xpath.split("/");
|
||||
if (pathParts.length == 0) {
|
||||
return elements;
|
||||
}
|
||||
|
||||
// 查找根元素
|
||||
Element currentElement = document.getDocumentElement();
|
||||
if (!currentElement.getTagName().equals(pathParts[0])) {
|
||||
return elements;
|
||||
}
|
||||
|
||||
// 递归查找子元素
|
||||
for (int i = 1; i < pathParts.length; i++) {
|
||||
currentElement = findChildElement(currentElement, pathParts[i]);
|
||||
if (currentElement == null) {
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
|
||||
elements.add(currentElement);
|
||||
return elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在父元素中查找指定名称的子元素
|
||||
*
|
||||
* @param parent 父元素
|
||||
* @param tagName 子元素标签名
|
||||
* @return 子元素
|
||||
*/
|
||||
private static Element findChildElement(Element parent, String tagName) {
|
||||
NodeList childNodes = parent.getChildNodes();
|
||||
for (int i = 0; i < childNodes.getLength(); i++) {
|
||||
Node node = childNodes.item(i);
|
||||
if (node.getNodeType() == Node.ELEMENT_NODE && node.getNodeName().equals(tagName)) {
|
||||
return (Element) node;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package com.example.demo.common.wrapper;
|
||||
|
||||
/**
|
||||
* 统一响应包装工具类
|
||||
* 提供静态方法创建Wrapper实例
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
public class WrapMapper {
|
||||
|
||||
/**
|
||||
* 成功响应(无数据)
|
||||
*
|
||||
* @return 响应结果
|
||||
*/
|
||||
public static Wrapper<Object> ok() {
|
||||
return ok(null, "操作成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功响应(带消息)
|
||||
*
|
||||
* @param message 响应消息
|
||||
* @return 响应结果
|
||||
*/
|
||||
public static Wrapper<Object> ok(String message) {
|
||||
return ok(null, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功响应(带数据)
|
||||
*
|
||||
* @param data 响应数据
|
||||
* @return 响应结果
|
||||
*/
|
||||
public static <T> Wrapper<T> ok(T data) {
|
||||
return ok(data, "操作成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功响应(带数据和消息)
|
||||
*
|
||||
* @param data 响应数据
|
||||
* @param message 响应消息
|
||||
* @return 响应结果
|
||||
*/
|
||||
public static <T> Wrapper<T> ok(T data, String message) {
|
||||
Wrapper<T> result = new Wrapper<>();
|
||||
result.setCode("SUCCESS");
|
||||
result.setMessage(message);
|
||||
result.setData(data);
|
||||
result.setTimestamp(System.currentTimeMillis());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败响应(默认消息)
|
||||
*
|
||||
* @return 响应结果
|
||||
*/
|
||||
public static <T> Wrapper<T> fail() {
|
||||
return fail("FAIL", "操作失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败响应(带消息)
|
||||
*
|
||||
* @param message 响应消息
|
||||
* @return 响应结果
|
||||
*/
|
||||
public static <T> Wrapper<T> fail(String message) {
|
||||
return fail("FAIL", message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 失败响应(带状态码和消息)
|
||||
*
|
||||
* @param code 状态码
|
||||
* @param message 响应消息
|
||||
* @return 响应结果
|
||||
*/
|
||||
public static <T> Wrapper<T> fail(String code, String message) {
|
||||
Wrapper<T> result = new Wrapper<>();
|
||||
result.setCode(code);
|
||||
result.setMessage(message);
|
||||
result.setTimestamp(System.currentTimeMillis());
|
||||
return result;
|
||||
}
|
||||
}
|
61
src/main/java/com/example/demo/common/wrapper/Wrapper.java
Normal file
61
src/main/java/com/example/demo/common/wrapper/Wrapper.java
Normal file
@ -0,0 +1,61 @@
|
||||
package com.example.demo.common.wrapper;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 统一响应包装类
|
||||
* 用于封装所有RESTful API的响应数据
|
||||
*
|
||||
* @param <T> 响应数据类型
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
public class Wrapper<T> implements Serializable {
|
||||
|
||||
/**
|
||||
* 响应状态码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 响应消息
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 响应数据
|
||||
*/
|
||||
private T data;
|
||||
|
||||
/**
|
||||
* 时间戳
|
||||
*/
|
||||
private Long timestamp;
|
||||
|
||||
/**
|
||||
* 判断响应是否成功
|
||||
*
|
||||
* @return 是否成功
|
||||
*/
|
||||
public boolean isSuccess() {
|
||||
return "SUCCESS".equals(code);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断响应是否失败
|
||||
*
|
||||
* @return 是否失败
|
||||
*/
|
||||
public boolean isFail() {
|
||||
return !isSuccess();
|
||||
}
|
||||
}
|
20
src/main/java/com/example/demo/draft/demo043/0.java
Normal file
20
src/main/java/com/example/demo/draft/demo043/0.java
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
// TODO XML 转成 JSON 注意事项
|
||||
// 1、 XML标签 需要映射到 特定的JSON路径上
|
||||
// 2、 XML标签 映射时允许模糊映射
|
||||
// 3、 XML标签 映射时允许批量映射
|
||||
// 4、 XML标签 映射时允许块映射
|
||||
|
||||
// TODO XML 转成 JSON 一定需要解决或者对接统一的问题
|
||||
// 5、 XML标签值 部分内容需要格式化,例如: 时间
|
||||
// 6、 XML标签值 部分内容需要函数计算,例如: 经纬度统一转化
|
||||
// 7、 XML标签值 部分内容需要确定统一单位,例如: 速度单位 m/s
|
||||
|
||||
// TODO XML 转成 JSON 可能存在的问题
|
||||
// 8、 XML标签,一定存在部分数据是固定数据,例如: 各种类型、枚举
|
||||
// 9、 XML标签、值、属性 内容需要合并
|
||||
// 10、 XML标签 自定义函数问题
|
||||
// 11、 XML标签值,存在一部分值需要拆分成多个数据
|
||||
// 97、 增量更新问题,例如: 推演过程中,数据是动态不断更新的,这种是需要追加旧数据,还是读到什么数据就是什么数据?
|
||||
// 98、 允许组合规则、条件生效
|
||||
// 99、 对接时,需要一个字段一个字段对应
|
@ -0,0 +1,67 @@
|
||||
package com.example.demo.draft.demo043;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.example.demo.draft.demo043.domain.ConfigDocument;
|
||||
import com.example.demo.draft.demo043.core.EnhancedTemplateGenerator;
|
||||
import com.example.demo.draft.demo043.core.Xml2AFSIMTransformation;
|
||||
import com.example.demo.draft.demo043.util.FormatUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
public class ApplicationTest__01 {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
List<String> dataList = new ArrayList<>() {{
|
||||
add("20250923_6b399e.xml");
|
||||
add("20250923_6ba0d8.xml");
|
||||
add("20250923_9efa34.xml");
|
||||
add("20250923_b345dd.xml");
|
||||
add("20250923_e9dd05.xml");
|
||||
}};
|
||||
|
||||
String prefix = "src/main/resources/data/01-作战部队武器装备/";
|
||||
String inputTemplateData = prefix + "default.json";
|
||||
String inputData = prefix + dataList.get(new Random().nextInt(dataList.size()));
|
||||
String processJSONFile = "output-transformed-cg-003__01.json";
|
||||
|
||||
// Step.1
|
||||
try {
|
||||
Map<String, String> rules = new HashMap<>();
|
||||
rules.put("根\\.(.*)", "$1");
|
||||
Xml2AFSIMTransformation converter = new Xml2AFSIMTransformation(rules);
|
||||
File xmlFile = new File(inputData);
|
||||
File jsonFile = new File(processJSONFile);
|
||||
converter.convertXmlToJson(xmlFile, jsonFile, "作战部队武器装备");
|
||||
System.out.println("XML转JSON并转换完成");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Step.2
|
||||
String targetContent = Files.readString(Path.of(processJSONFile), StandardCharsets.UTF_8);
|
||||
List<Object> list = JSON.parseArray(targetContent);
|
||||
|
||||
String templateContent = Files.readString(Path.of(inputTemplateData), StandardCharsets.UTF_8);
|
||||
ConfigDocument document = JSON.parseObject(templateContent, ConfigDocument.class);
|
||||
|
||||
String result = JSON.toJSONString(document);
|
||||
System.out.println(result);
|
||||
for(Object obj: list) {
|
||||
Map<String, String> map = JSON.parseObject(JSON.toJSONString(obj), Map.class);
|
||||
result = FormatUtil.stealBeamsAndReplacePillars(result, map);
|
||||
}
|
||||
|
||||
// Step.3
|
||||
Map demoData = JSON.parseObject(result, Map.class);
|
||||
System.out.println("=== 测试动态模板 ===");
|
||||
String result1 = EnhancedTemplateGenerator.generateCodeWithFormat(demoData, "generator/jinjia2/dynamic-template.j2");
|
||||
System.out.println(result1);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package com.example.demo.draft.demo043;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.example.demo.draft.demo043.domain.ConfigDocument;
|
||||
import com.example.demo.draft.demo043.core.EnhancedTemplateGenerator;
|
||||
import com.example.demo.draft.demo043.core.Xml2AFSIMTransformation;
|
||||
import com.example.demo.draft.demo043.util.FormatUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
public class ApplicationTest__02 {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
List<String> dataList = new ArrayList<>() {{
|
||||
add("20250923_5e813d.xml");
|
||||
add("20250923_7bbb1d.xml");
|
||||
add("20250923_7f3eb1.xml");
|
||||
add("20250923_199d51.xml");
|
||||
}};
|
||||
|
||||
String prefix = "src/main/resources/data/02-单个空中平台任务数据/";
|
||||
String inputTemplateData = prefix + "default.json";
|
||||
String inputData = prefix + dataList.get(new Random().nextInt(dataList.size()));
|
||||
String processJSONFile = "output-transformed-cg-003__02.json";
|
||||
|
||||
// Step.1
|
||||
try {
|
||||
Map<String, String> rules = new HashMap<>();
|
||||
rules.put("根\\.(.*)", "$1");
|
||||
rules.put("单个空中平台任务数据.机型名称", "单个空中平台任务数据.平台名称");
|
||||
Xml2AFSIMTransformation converter = new Xml2AFSIMTransformation(rules);
|
||||
File xmlFile = new File(inputData);
|
||||
File jsonFile = new File(processJSONFile);
|
||||
converter.convertXmlToJson(xmlFile, jsonFile, "单个空中平台任务数据");
|
||||
System.out.println("XML转JSON并转换完成");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Step.2
|
||||
String targetContent = Files.readString(Path.of(processJSONFile), StandardCharsets.UTF_8);
|
||||
List<Object> list = JSON.parseArray(targetContent);
|
||||
|
||||
String templateContent = Files.readString(Path.of(inputTemplateData), StandardCharsets.UTF_8);
|
||||
ConfigDocument document = JSON.parseObject(templateContent, ConfigDocument.class);
|
||||
|
||||
String result = JSON.toJSONString(document);
|
||||
System.out.println(result);
|
||||
for(Object obj: list) {
|
||||
Map<String, String> map = JSON.parseObject(JSON.toJSONString(obj), Map.class);
|
||||
result = FormatUtil.stealBeamsAndReplacePillars(result, map);
|
||||
}
|
||||
|
||||
// Step.3
|
||||
Map demoData = JSON.parseObject(result, Map.class);
|
||||
System.out.println("=== 测试动态模板 ===");
|
||||
String result1 = EnhancedTemplateGenerator.generateCodeWithFormat(demoData, "generator/jinjia2/dynamic-template.j2");
|
||||
System.out.println(result1);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
package com.example.demo.draft.demo043;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.example.demo.draft.demo043.domain.ConfigDocument;
|
||||
import com.example.demo.draft.demo043.core.EnhancedTemplateGenerator;
|
||||
import com.example.demo.draft.demo043.core.Xml2AFSIMTransformation;
|
||||
import com.example.demo.draft.demo043.util.FormatUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
public class ApplicationTest__03 {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
List<String> dataList = new ArrayList<>() {{
|
||||
add("20250923_4c32c8.xml");
|
||||
add("20250923_82c579.xml");
|
||||
add("20250923_422dc2.xml");
|
||||
add("20250923_b43a26.xml");
|
||||
add("20250923_c87aa1.xml");
|
||||
}};
|
||||
|
||||
String prefix = "src/main/resources/data/03-任务航线/";
|
||||
String inputTemplateData = prefix + "default.json";
|
||||
String inputData = prefix + dataList.get(new Random().nextInt(dataList.size()));
|
||||
String processJSONFile = "output-transformed-cg-003__03.json";
|
||||
|
||||
// Step.1
|
||||
try {
|
||||
Map<String, String> rules = new HashMap<>();
|
||||
rules.put("根\\.(.*)", "$1");
|
||||
Xml2AFSIMTransformation converter = new Xml2AFSIMTransformation(rules);
|
||||
File xmlFile = new File(inputData);
|
||||
File jsonFile = new File(processJSONFile);
|
||||
converter.convertXmlToJson(xmlFile, jsonFile, "任务航线");
|
||||
System.out.println("XML转JSON并转换完成");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Step.2
|
||||
String targetContent = Files.readString(Path.of(processJSONFile), StandardCharsets.UTF_8);
|
||||
List<Object> list = JSON.parseArray(targetContent);
|
||||
|
||||
String templateContent = Files.readString(Path.of(inputTemplateData), StandardCharsets.UTF_8);
|
||||
ConfigDocument document = JSON.parseObject(templateContent, ConfigDocument.class);
|
||||
|
||||
String result = JSON.toJSONString(document);
|
||||
System.out.println(result);
|
||||
for(Object obj: list) {
|
||||
Map<String, String> map = JSON.parseObject(JSON.toJSONString(obj), Map.class);
|
||||
result = FormatUtil.stealBeamsAndReplacePillars(result, map);
|
||||
}
|
||||
|
||||
// Step.3
|
||||
Map demoData = JSON.parseObject(result, Map.class);
|
||||
System.out.println("=== 测试动态模板 ===");
|
||||
String result1 = EnhancedTemplateGenerator.generateCodeWithFormat(demoData, "generator/jinjia2/dynamic-template.j2");
|
||||
System.out.println(result1);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package com.example.demo.draft.demo043;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.example.demo.draft.demo043.domain.ConfigDocument;
|
||||
import com.example.demo.draft.demo043.core.EnhancedTemplateGenerator;
|
||||
import com.example.demo.draft.demo043.core.Xml2AFSIMTransformation;
|
||||
import com.example.demo.draft.demo043.util.FormatUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
public class ApplicationTest__04 {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
List<String> dataList = new ArrayList<>() {{
|
||||
add("20250923_02d1d0.xml");
|
||||
add("20250923_5da5e9.xml");
|
||||
add("20250923_3929b4.xml");
|
||||
}};
|
||||
|
||||
String prefix = "src/main/resources/data/04-空域数据/";
|
||||
String inputTemplateData = prefix + "default.json";
|
||||
String inputData = prefix + dataList.get(new Random().nextInt(dataList.size()));
|
||||
String processJSONFile = "output-transformed-cg-003__04.json";
|
||||
|
||||
// Step.1
|
||||
try {
|
||||
Map<String, String> rules = new HashMap<>();
|
||||
rules.put("根\\.(.*)", "$1");
|
||||
Xml2AFSIMTransformation converter = new Xml2AFSIMTransformation(rules);
|
||||
File xmlFile = new File(inputData);
|
||||
File jsonFile = new File(processJSONFile);
|
||||
converter.convertXmlToJson(xmlFile, jsonFile, "空域数据");
|
||||
System.out.println("XML转JSON并转换完成");
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// Step.2
|
||||
String targetContent = Files.readString(Path.of(processJSONFile), StandardCharsets.UTF_8);
|
||||
List<Object> list = JSON.parseArray(targetContent);
|
||||
|
||||
String templateContent = Files.readString(Path.of(inputTemplateData), StandardCharsets.UTF_8);
|
||||
ConfigDocument document = JSON.parseObject(templateContent, ConfigDocument.class);
|
||||
|
||||
String result = JSON.toJSONString(document);
|
||||
System.out.println(result);
|
||||
for(Object obj: list) {
|
||||
Map<String, String> map = JSON.parseObject(JSON.toJSONString(obj), Map.class);
|
||||
result = FormatUtil.stealBeamsAndReplacePillars(result, map);
|
||||
}
|
||||
|
||||
// Step.3
|
||||
Map demoData = JSON.parseObject(result, Map.class);
|
||||
System.out.println("=== 测试动态模板 ===");
|
||||
String result1 = EnhancedTemplateGenerator.generateCodeWithFormat(demoData, "generator/jinjia2/dynamic-template.j2");
|
||||
System.out.println(result1);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
package com.example.demo.draft.demo043;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.example.demo.draft.demo043.core.EnhancedTemplateGenerator;
|
||||
import com.example.demo.draft.demo043.domain.ConfigDocument;
|
||||
import com.example.demo.draft.demo043.domain.ConfigValue;
|
||||
import com.example.demo.draft.demo043.domain.LevelConfig;
|
||||
import com.example.demo.draft.demo043.domain.ValueConfig;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ConfigDataCreator__02 {
|
||||
|
||||
@SneakyThrows
|
||||
public static void main(String[] args) {
|
||||
System.out.println(JSON.toJSONString(createConfigDocument()));
|
||||
String result1 = EnhancedTemplateGenerator.generateCodeWithFormat(
|
||||
JSON.parseObject(JSON.toJSONString(createConfigDocument()), Map.class),
|
||||
"generator/jinjia2/dynamic-template.j2");
|
||||
System.out.println(result1);
|
||||
}
|
||||
|
||||
private static final String customTemplateCode = "string %s = \"%s\" # %s";
|
||||
|
||||
public static ConfigDocument createConfigDocument() {
|
||||
// 创建最内层的ConfigValue对象
|
||||
ConfigValue tacanWorkChannelValue = ConfigValue.builder()
|
||||
.value(String.format(
|
||||
customTemplateCode,
|
||||
"tacanWorkChannel",
|
||||
"单个空中平台任务数据.塔康工作频道",
|
||||
"塔康工作频道"
|
||||
))
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue platformIdCardCodeValue = ConfigValue.builder()
|
||||
.value(String.format(
|
||||
customTemplateCode,
|
||||
"platformIdCardCode",
|
||||
"单个空中平台任务数据.平台识别码",
|
||||
"平台识别码"
|
||||
))
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue platformIdCardNumberValue = ConfigValue.builder()
|
||||
.value(String.format(
|
||||
customTemplateCode,
|
||||
"platformIdCardNumber",
|
||||
"单个空中平台任务数据.平台识别号",
|
||||
"平台识别号"
|
||||
))
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue quantity1Value = ConfigValue.builder()
|
||||
.value("数量1")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue quantity2Value = ConfigValue.builder()
|
||||
.value("数量2")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
// 创建ValueConfig对象
|
||||
ValueConfig tacanWorkChannelConfig = ValueConfig.builder()
|
||||
.valueName(null)
|
||||
.values(Collections.singletonList(tacanWorkChannelValue))
|
||||
.build();
|
||||
|
||||
ValueConfig platformIdCardCodeConfig = ValueConfig.builder()
|
||||
.valueName(null)
|
||||
.values(Collections.singletonList(platformIdCardCodeValue))
|
||||
.build();
|
||||
|
||||
ValueConfig platformIdCardNumberConfig = ValueConfig.builder()
|
||||
.valueName(null)
|
||||
.values(Collections.singletonList(platformIdCardNumberValue))
|
||||
.build();
|
||||
|
||||
ValueConfig quantity1Config = ValueConfig.builder()
|
||||
.valueName("quantity")
|
||||
.values(Collections.singletonList(quantity1Value))
|
||||
.comment(null)
|
||||
.build();
|
||||
|
||||
ValueConfig quantity2Config = ValueConfig.builder()
|
||||
.valueName("quantity")
|
||||
.values(Collections.singletonList(quantity2Value))
|
||||
.comment(null)
|
||||
.build();
|
||||
|
||||
// 创建子LevelConfig对象
|
||||
LevelConfig commLevel = LevelConfig.builder()
|
||||
.levelName("comm")
|
||||
.values(Arrays.asList("xxx", "默认通信链"))
|
||||
.comment(null)
|
||||
.conditionType(null)
|
||||
.valueConfigs(Collections.singletonList(tacanWorkChannelConfig))
|
||||
.subLevels(List.of())
|
||||
.build();
|
||||
|
||||
LevelConfig auxDataLevel = LevelConfig.builder()
|
||||
.levelName("aux_data")
|
||||
.values(Arrays.asList())
|
||||
.comment(null)
|
||||
.conditionType(null)
|
||||
.valueConfigs(Arrays.asList(platformIdCardCodeConfig, platformIdCardNumberConfig))
|
||||
.subLevels(List.of())
|
||||
.build();
|
||||
|
||||
LevelConfig weapon1Level = LevelConfig.builder()
|
||||
.levelName("weapon")
|
||||
.values(Arrays.asList("单个空中平台任务数据.主挂载武器", "类型"))
|
||||
.comment(null)
|
||||
.conditionType(null)
|
||||
.valueConfigs(Collections.singletonList(quantity1Config))
|
||||
.subLevels(List.of())
|
||||
.build();
|
||||
|
||||
LevelConfig weapon2Level = LevelConfig.builder()
|
||||
.levelName("weapon")
|
||||
.values(Arrays.asList("单个空中平台任务数据.次挂载武器", "类型"))
|
||||
.comment(null)
|
||||
.conditionType(null)
|
||||
.valueConfigs(Collections.singletonList(quantity2Config))
|
||||
.subLevels(List.of())
|
||||
.build();
|
||||
|
||||
// 创建主LevelConfig对象
|
||||
LevelConfig platformLevel = LevelConfig.builder()
|
||||
.levelName("platform")
|
||||
.values(Arrays.asList("单个空中平台任务数据.机型名称", "单个空中平台任务数据.机型"))
|
||||
.comment(null)
|
||||
.conditionType(null)
|
||||
.valueConfigs(Arrays.asList(
|
||||
ValueConfig.builder().valueName("side").values(Arrays.asList(
|
||||
ConfigValue.builder().value("red").unit(null).combined(false).build()
|
||||
)).comment(null).build(),
|
||||
ValueConfig.builder().valueName("icon").values(Arrays.asList(
|
||||
ConfigValue.builder().value("weasel").unit(null).combined(false).build()
|
||||
)).comment(null).build()
|
||||
))
|
||||
.subLevels(Arrays.asList(commLevel, auxDataLevel, weapon1Level, weapon2Level))
|
||||
.build();
|
||||
|
||||
// 创建ConfigDocument对象
|
||||
return ConfigDocument.builder()
|
||||
.globalComment(null)
|
||||
.initialIndent(null)
|
||||
.conditionMap(new HashMap<>())
|
||||
.levelConfigs(Arrays.asList(platformLevel))
|
||||
.build();
|
||||
}
|
||||
}
|
@ -0,0 +1,197 @@
|
||||
package com.example.demo.draft.demo043;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.example.demo.draft.demo043.core.EnhancedTemplateGenerator;
|
||||
import com.example.demo.draft.demo043.domain.ConfigDocument;
|
||||
import com.example.demo.draft.demo043.domain.ConfigValue;
|
||||
import com.example.demo.draft.demo043.domain.LevelConfig;
|
||||
import com.example.demo.draft.demo043.domain.ValueConfig;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class ConfigDataCreator__03 {
|
||||
|
||||
@SneakyThrows
|
||||
public static void main(String[] args) {
|
||||
System.out.println(JSON.toJSONString(createConfigDocument()));
|
||||
String result1 = EnhancedTemplateGenerator.generateCodeWithFormat(
|
||||
JSON.parseObject(JSON.toJSONString(createConfigDocument()), Map.class),
|
||||
"generator/jinjia2/dynamic-template.j2");
|
||||
System.out.println(result1);
|
||||
}
|
||||
|
||||
private static final String customTemplateCode = "string %s = \"%s\" # %s";
|
||||
|
||||
public static ConfigDocument createConfigDocument() {
|
||||
// 创建最内层的ConfigValue对象 - waypoint层级的值配置
|
||||
|
||||
ConfigValue positionValue = ConfigValue.builder()
|
||||
// .value("39.9242N 116.5074E")
|
||||
.value("任务航线.航线点坐标")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue waypointTypeValue = ConfigValue.builder()
|
||||
.value("任务航线.航线点类型")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue etaValue = ConfigValue.builder()
|
||||
.value("任务航线.准时到达时间")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue turnMethodValue = ConfigValue.builder()
|
||||
.value("任务航线.转弯方式")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue turnDirectionValue = ConfigValue.builder()
|
||||
.value("任务航线.转向方式")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue bankAngleValue = ConfigValue.builder()
|
||||
.value("任务航线.坡度")
|
||||
.unit("deg")
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue speedValue = ConfigValue.builder()
|
||||
.value("任务航线.速度")
|
||||
.unit("km/h")
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue altitudeValue = ConfigValue.builder()
|
||||
.value("任务航线.高度")
|
||||
.unit("m")
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue altitudeTypeValue = ConfigValue.builder()
|
||||
.value("任务航线.高度属性")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue climbRateValue = ConfigValue.builder()
|
||||
.value("任务航线.升降率")
|
||||
.unit("m/s")
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
// 创建ValueConfig对象 - waypoint层级的值配置
|
||||
ValueConfig positionConfig = ValueConfig.builder()
|
||||
.valueName("position")
|
||||
.values(Arrays.asList(positionValue))
|
||||
.comment("航线点坐标")
|
||||
.build();
|
||||
|
||||
ValueConfig waypointTypeConfig = ValueConfig.builder()
|
||||
.valueName("waypoint_type")
|
||||
.values(Arrays.asList(waypointTypeValue))
|
||||
.comment("航线点类型")
|
||||
.build();
|
||||
|
||||
ValueConfig etaConfig = ValueConfig.builder()
|
||||
.valueName("eta")
|
||||
.values(Arrays.asList(etaValue))
|
||||
.comment("准时到达时间")
|
||||
.build();
|
||||
|
||||
ValueConfig turnMethodConfig = ValueConfig.builder()
|
||||
.valueName("turn_method")
|
||||
.values(Arrays.asList(turnMethodValue))
|
||||
.comment("转弯方式")
|
||||
.build();
|
||||
|
||||
ValueConfig turnDirectionConfig = ValueConfig.builder()
|
||||
.valueName("turn_direction")
|
||||
.values(Arrays.asList(turnDirectionValue))
|
||||
.comment("转向方式")
|
||||
.build();
|
||||
|
||||
ValueConfig bankAngleConfig = ValueConfig.builder()
|
||||
.valueName("bank_angle")
|
||||
.values(Arrays.asList(bankAngleValue))
|
||||
.comment("坡度")
|
||||
.build();
|
||||
|
||||
ValueConfig speedConfig = ValueConfig.builder()
|
||||
.valueName("speed")
|
||||
.values(Arrays.asList(speedValue))
|
||||
.comment("速度")
|
||||
.build();
|
||||
|
||||
ValueConfig altitudeConfig = ValueConfig.builder()
|
||||
.valueName("altitude")
|
||||
.values(Arrays.asList(altitudeValue))
|
||||
.comment("高度")
|
||||
.build();
|
||||
|
||||
ValueConfig altitudeTypeConfig = ValueConfig.builder()
|
||||
.valueName("altitude_type")
|
||||
.values(Arrays.asList(altitudeTypeValue))
|
||||
.comment("高度属性")
|
||||
.build();
|
||||
|
||||
ValueConfig climbRateConfig = ValueConfig.builder()
|
||||
.valueName("climb_rate")
|
||||
.values(Arrays.asList(climbRateValue))
|
||||
.comment("升降率")
|
||||
.build();
|
||||
|
||||
// 创建waypoint LevelConfig对象
|
||||
LevelConfig waypointLevel = LevelConfig.builder()
|
||||
.levelName("waypoint")
|
||||
.values(Arrays.asList("任务航线.航线点型号", "任务航线.航线点名称"))
|
||||
.comment("航线点型号为 任务航线.航线点型号 ,名称为 任务航线.航线点名称")
|
||||
.conditionType(null)
|
||||
.valueConfigs(Arrays.asList(
|
||||
positionConfig, waypointTypeConfig, etaConfig, turnMethodConfig,
|
||||
turnDirectionConfig, bankAngleConfig, speedConfig, altitudeConfig,
|
||||
altitudeTypeConfig, climbRateConfig
|
||||
))
|
||||
.subLevels(Arrays.asList())
|
||||
.build();
|
||||
|
||||
// 创建route LevelConfig对象
|
||||
LevelConfig routeLevel = LevelConfig.builder()
|
||||
.levelName("route")
|
||||
.values(Arrays.asList())
|
||||
.comment(null)
|
||||
.conditionType(null)
|
||||
.valueConfigs(Arrays.asList())
|
||||
.subLevels(Arrays.asList(waypointLevel))
|
||||
.build();
|
||||
|
||||
// 创建主LevelConfig对象 - platform
|
||||
LevelConfig platformLevel = LevelConfig.builder()
|
||||
.levelName("platform")
|
||||
.values(Arrays.asList("mission_plane", "AIRCRAFT"))
|
||||
.comment(null)
|
||||
.conditionType(null)
|
||||
.valueConfigs(Arrays.asList(
|
||||
ValueConfig.builder().valueName("heading").values(Arrays.asList(
|
||||
ConfigValue.builder().value(0).unit("deg").combined(false).build()
|
||||
)).comment("初始航向为0度").build()
|
||||
))
|
||||
.subLevels(Arrays.asList(routeLevel))
|
||||
.build();
|
||||
|
||||
// 创建ConfigDocument对象
|
||||
return ConfigDocument.builder()
|
||||
.globalComment(null)
|
||||
.initialIndent(null)
|
||||
.conditionMap(new HashMap<>())
|
||||
.levelConfigs(Arrays.asList(platformLevel))
|
||||
.build();
|
||||
}
|
||||
}
|
@ -0,0 +1,318 @@
|
||||
package com.example.demo.draft.demo043;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.example.demo.draft.demo043.core.EnhancedTemplateGenerator;
|
||||
import com.example.demo.draft.demo043.domain.ConfigDocument;
|
||||
import com.example.demo.draft.demo043.domain.ConfigValue;
|
||||
import com.example.demo.draft.demo043.domain.LevelConfig;
|
||||
import com.example.demo.draft.demo043.domain.ValueConfig;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ConfigDataCreator__04 {
|
||||
|
||||
@SneakyThrows
|
||||
public static void main(String[] args) {
|
||||
System.out.println(JSON.toJSONString(createConfigDocument()));
|
||||
String result1 = EnhancedTemplateGenerator.generateCodeWithFormat(
|
||||
JSON.parseObject(JSON.toJSONString(createConfigDocument()), Map.class),
|
||||
"generator/jinjia2/dynamic-template.j2");
|
||||
System.out.println(result1);
|
||||
}
|
||||
|
||||
private static final String customTemplateCode = "string %s = \"%s\" # %s";
|
||||
|
||||
public static ConfigDocument createConfigDocument() {
|
||||
// 创建最内层的ConfigValue对象 - time_window层级
|
||||
ConfigValue modeValue = ConfigValue.builder()
|
||||
.value("空域数据.空域生效时间段.日期时间使用模式")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue startValue = ConfigValue.builder()
|
||||
.value("空域数据.空域生效时间段.开始时间")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue endValue = ConfigValue.builder()
|
||||
.value("空域数据.空域生效时间段.结束时间")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue endTypeValue = ConfigValue.builder()
|
||||
.value("空域数据.空域生效时间段.结束时间标识符")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue intervalValue = ConfigValue.builder()
|
||||
.value("空域数据.空域生效时间段.间隔频率")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue intervalEndValue = ConfigValue.builder()
|
||||
.value("空域数据.空域生效时间段.间隔结束时间")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue relativeStartValue = ConfigValue.builder()
|
||||
.value("空域数据.空域生效时间段.相对时开始时间")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue relativeEndValue = ConfigValue.builder()
|
||||
.value("空域数据.空域生效时间段.相对时结束数据")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue timeFormatValue = ConfigValue.builder()
|
||||
.value("空域数据.空域生效时间段.时间类型")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
// 创建最内层的ConfigValue对象 - control_point层级
|
||||
ConfigValue typeValue = ConfigValue.builder()
|
||||
.value("空域数据.代表空域相关的控制点.控制点类型")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue positionValue = ConfigValue.builder()
|
||||
.value("空域数据.空域几何数据.几何数据信息.纬度N 空域数据.空域几何数据.几何数据信息.经度E")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue topAltitudeValue = ConfigValue.builder()
|
||||
.value("空域数据.代表空域相关的控制点.控制点的顶高")
|
||||
.unit("m")
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue bottomAltitudeValue = ConfigValue.builder()
|
||||
.value("空域数据.代表空域相关的控制点.控制点的底高")
|
||||
.unit("m")
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue visibleValue = ConfigValue.builder()
|
||||
.value("空域数据.代表空域相关的控制点.是否隐藏控制点")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
// 创建最内层的ConfigValue对象 - geometry层级
|
||||
ConfigValue shapeValue = ConfigValue.builder()
|
||||
.value("空域数据.空域几何数据.形状类型")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue centerValue = ConfigValue.builder()
|
||||
.value("空域数据.代表空域相关的控制点.控制点的坐标位置纬度N 空域数据.代表空域相关的控制点.控制点的坐标位置经度E")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
ConfigValue pointCountValue = ConfigValue.builder()
|
||||
.value("空域数据.空域几何数据.数据点数目")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
// 创建ValueConfig对象 - time_window层级
|
||||
ValueConfig modeConfig = ValueConfig.builder()
|
||||
.valueName("mode")
|
||||
.values(Arrays.asList(modeValue))
|
||||
.comment("日期时间使用模式")
|
||||
.build();
|
||||
|
||||
ValueConfig startConfig = ValueConfig.builder()
|
||||
.valueName("start")
|
||||
.values(Arrays.asList(startValue))
|
||||
.comment("开始时间")
|
||||
.build();
|
||||
|
||||
ValueConfig endConfig = ValueConfig.builder()
|
||||
.valueName("end")
|
||||
.values(Arrays.asList(endValue))
|
||||
.comment("结束时间")
|
||||
.build();
|
||||
|
||||
ValueConfig endTypeConfig = ValueConfig.builder()
|
||||
.valueName("end_type")
|
||||
.values(Arrays.asList(endTypeValue))
|
||||
.comment("结束时间标识符")
|
||||
.build();
|
||||
|
||||
ValueConfig intervalConfig = ValueConfig.builder()
|
||||
.valueName("interval")
|
||||
.values(Arrays.asList(intervalValue))
|
||||
.comment("间隔频率")
|
||||
.build();
|
||||
|
||||
ValueConfig intervalEndConfig = ValueConfig.builder()
|
||||
.valueName("interval_end")
|
||||
.values(Arrays.asList(intervalEndValue))
|
||||
.comment("间隔结束时间")
|
||||
.build();
|
||||
|
||||
ValueConfig relativeStartConfig = ValueConfig.builder()
|
||||
.valueName("relative_start")
|
||||
.values(Arrays.asList(relativeStartValue))
|
||||
.comment("相对时开始时间")
|
||||
.build();
|
||||
|
||||
ValueConfig relativeEndConfig = ValueConfig.builder()
|
||||
.valueName("relative_end")
|
||||
.values(Arrays.asList(relativeEndValue))
|
||||
.comment("相对时结束数据")
|
||||
.build();
|
||||
|
||||
ValueConfig timeFormatConfig = ValueConfig.builder()
|
||||
.valueName("time_format")
|
||||
.values(Arrays.asList(timeFormatValue))
|
||||
.comment("时间类型")
|
||||
.build();
|
||||
|
||||
// 创建ValueConfig对象 - control_point层级
|
||||
ValueConfig typeConfig = ValueConfig.builder()
|
||||
.valueName("type")
|
||||
.values(Arrays.asList(typeValue))
|
||||
.comment("控制点类型")
|
||||
.build();
|
||||
|
||||
ValueConfig positionConfig = ValueConfig.builder()
|
||||
.valueName("position")
|
||||
.values(Arrays.asList(positionValue))
|
||||
.comment("控制点坐标(纬度,经度)")
|
||||
.build();
|
||||
|
||||
ValueConfig topAltitudeConfig = ValueConfig.builder()
|
||||
.valueName("top_altitude")
|
||||
.values(Arrays.asList(topAltitudeValue))
|
||||
.comment("控制点顶高")
|
||||
.build();
|
||||
|
||||
ValueConfig bottomAltitudeConfig = ValueConfig.builder()
|
||||
.valueName("bottom_altitude")
|
||||
.values(Arrays.asList(bottomAltitudeValue))
|
||||
.comment("控制点底高")
|
||||
.build();
|
||||
|
||||
ValueConfig visibleConfig = ValueConfig.builder()
|
||||
.valueName("visible")
|
||||
.values(Arrays.asList(visibleValue))
|
||||
.comment("是否隐藏控制点(false表示显示)")
|
||||
.build();
|
||||
|
||||
// 创建ValueConfig对象 - geometry层级
|
||||
ValueConfig shapeConfig = ValueConfig.builder()
|
||||
.valueName("shape")
|
||||
.values(Arrays.asList(shapeValue))
|
||||
.comment("形状类型")
|
||||
.build();
|
||||
|
||||
ValueConfig centerConfig = ValueConfig.builder()
|
||||
.valueName("center")
|
||||
.values(Arrays.asList(centerValue))
|
||||
.comment("圆心坐标")
|
||||
.build();
|
||||
|
||||
ValueConfig pointCountConfig = ValueConfig.builder()
|
||||
.valueName("point_count")
|
||||
.values(Arrays.asList(pointCountValue))
|
||||
.comment("数据点数目")
|
||||
.build();
|
||||
|
||||
// 创建子LevelConfig对象 - time_window
|
||||
LevelConfig timeWindowLevel = LevelConfig.builder()
|
||||
.levelName("time_window")
|
||||
.values(Arrays.asList())
|
||||
.comment("空域生效时间配置")
|
||||
.conditionType(null)
|
||||
.valueConfigs(Arrays.asList(
|
||||
modeConfig, startConfig, endConfig, endTypeConfig, intervalConfig,
|
||||
intervalEndConfig, relativeStartConfig, relativeEndConfig, timeFormatConfig
|
||||
))
|
||||
.subLevels(Arrays.asList())
|
||||
.build();
|
||||
|
||||
// 创建子LevelConfig对象 - control_point
|
||||
LevelConfig controlPointLevel = LevelConfig.builder()
|
||||
.levelName("control_point")
|
||||
.values(Arrays.asList("空域数据.代表空域相关的控制点.控制点ID", "空域数据.代表空域相关的控制点.控制点名称"))
|
||||
.comment("控制点ID和名称")
|
||||
.conditionType(null)
|
||||
.valueConfigs(Arrays.asList(
|
||||
typeConfig, positionConfig, topAltitudeConfig, bottomAltitudeConfig, visibleConfig
|
||||
))
|
||||
.subLevels(Arrays.asList())
|
||||
.build();
|
||||
|
||||
// 创建子LevelConfig对象 - geometry
|
||||
LevelConfig geometryLevel = LevelConfig.builder()
|
||||
.levelName("geometry")
|
||||
.values(Arrays.asList())
|
||||
.comment("空域几何形状配置")
|
||||
.conditionType(null)
|
||||
.valueConfigs(Arrays.asList(
|
||||
shapeConfig, centerConfig, pointCountConfig
|
||||
))
|
||||
.subLevels(Arrays.asList())
|
||||
.build();
|
||||
|
||||
// 创建主LevelConfig对象 - platform
|
||||
LevelConfig platformLevel = LevelConfig.builder()
|
||||
.levelName("platform")
|
||||
.values(Arrays.asList("airspace", "AERIAL_REGION"))
|
||||
.comment(null)
|
||||
.conditionType(null)
|
||||
.valueConfigs(Arrays.asList(
|
||||
ValueConfig.builder().valueName("id").values(Arrays.asList(
|
||||
ConfigValue.builder().value("空域数据.空域ID").unit(null).combined(false).build()
|
||||
)).comment("空域ID").build(),
|
||||
|
||||
ValueConfig.builder().valueName("name").values(Arrays.asList(
|
||||
ConfigValue.builder().value("空域数据.空域名称").unit(null).combined(false).build()
|
||||
)).comment("空域名称").build(),
|
||||
|
||||
ValueConfig.builder().valueName("category").values(Arrays.asList(
|
||||
ConfigValue.builder().value("空域数据.协调措施所属的大类型").unit(null).combined(false).build()
|
||||
)).comment("协调措施所属的大类型").build(),
|
||||
|
||||
ValueConfig.builder().valueName("subcategory").values(Arrays.asList(
|
||||
ConfigValue.builder().value("空域数据.空域的具体协调措施类型").unit(null).combined(false).build()
|
||||
)).comment("空域的具体协调措施类型").build(),
|
||||
|
||||
ValueConfig.builder().valueName("status").values(Arrays.asList(
|
||||
ConfigValue.builder().value("空域数据.空域管控状态").unit(null).combined(false).build()
|
||||
)).comment("空域管控状态").build(),
|
||||
|
||||
ValueConfig.builder().valueName("control_status").values(Arrays.asList(
|
||||
ConfigValue.builder().value("limit").unit(null).combined(false).build()
|
||||
)).comment("空域管控状态").build()
|
||||
))
|
||||
.subLevels(Arrays.asList(timeWindowLevel, controlPointLevel, geometryLevel))
|
||||
.build();
|
||||
|
||||
// 创建ConfigDocument对象
|
||||
return ConfigDocument.builder()
|
||||
.globalComment(null)
|
||||
.initialIndent(null)
|
||||
.conditionMap(new HashMap<>())
|
||||
.levelConfigs(Arrays.asList(platformLevel))
|
||||
.build();
|
||||
}
|
||||
}
|
147
src/main/java/com/example/demo/draft/demo043/QA-AI.txt
Normal file
147
src/main/java/com/example/demo/draft/demo043/QA-AI.txt
Normal file
@ -0,0 +1,147 @@
|
||||
## AI提示词(用于离线本地AI生成)
|
||||
|
||||
### 系统角色设定
|
||||
```
|
||||
你是一个专业的Java代码生成专家,专门负责根据文本配置格式生成对应的Java实体对象构建代码。请严格按照以下规范生成代码。
|
||||
```
|
||||
|
||||
### 任务描述
|
||||
```
|
||||
请根据提供的文本配置格式,生成对应的Java实体对象构建代码。文本格式遵循 `xxx ... end_xxx` 的层级结构,需要转换为ConfigDocument对象。
|
||||
```
|
||||
|
||||
### 输入数据结构说明
|
||||
```
|
||||
输入数据采用以下Java实体结构:
|
||||
|
||||
1. **ConfigDocument** - 配置文档根对象
|
||||
- globalComment: 全局注释
|
||||
- initialIndent: 初始缩进
|
||||
- conditionMap: 条件映射表
|
||||
- levelConfigs: 层级配置列表
|
||||
|
||||
2. **LevelConfig** - 层级配置
|
||||
- levelName: 层级名称(如 "platform", "aux_data")
|
||||
- levelLoopIndex: 层级循环索引(用于生成带索引的层级名)
|
||||
- enableLevel: 是否启用该层级
|
||||
- values: 层级值列表(如 ["north_cap_1", "STRIKER"])
|
||||
- comment: 层级注释
|
||||
- conditionType: 条件类型
|
||||
- valueConfigs: 值配置列表
|
||||
- subLevels: 子层级列表
|
||||
- enableLoop: 是否启用循环
|
||||
- loopCount: 循环次数
|
||||
- enumMapping: 枚举映射
|
||||
- utilFunction: 工具函数配置
|
||||
|
||||
3. **ValueConfig** - 值配置
|
||||
- valueName: 值名称(如 "side", "icon")
|
||||
- values: 配置值列表
|
||||
- comment: 值注释
|
||||
|
||||
4. **ConfigValue** - 配置值
|
||||
- value: 实际值
|
||||
- unit: 单位
|
||||
- combined: 是否组合值
|
||||
- regexPattern: 正则表达式模式
|
||||
- regexReplacement: 正则替换
|
||||
- enumMapping: 枚举映射
|
||||
- utilFunction: 工具函数
|
||||
```
|
||||
|
||||
### 输出要求:
|
||||
|
||||
#### 代码结构:
|
||||
|
||||
```java
|
||||
public static ConfigDocument createConfigDocument() {
|
||||
// 按从外到内的顺序创建对象
|
||||
// 1. 先创建最内层的ConfigValue
|
||||
// 2. 然后创建ValueConfig包含ConfigValue列表
|
||||
// 3. 创建LevelConfig包含ValueConfig列表和子层级
|
||||
// 4. 最后创建ConfigDocument包含LevelConfig列表
|
||||
|
||||
ConfigValue batchnumberValue = ConfigValue.builder()
|
||||
.value("333333665")
|
||||
.unit(null)
|
||||
.combined(false)
|
||||
.build();
|
||||
|
||||
// 创建ValueConfig对象
|
||||
ValueConfig batchnumberConfig = ValueConfig.builder()
|
||||
.valueName("batchnumber")
|
||||
.values(Arrays.asList(batchnumberValue))
|
||||
.comment("批次号")
|
||||
.build();
|
||||
|
||||
ValueConfig sideConfig = ValueConfig.builder()
|
||||
.valueName("side")
|
||||
.values(Arrays.asList(ConfigValue.builder().value("red").build()))
|
||||
.comment("阵营")
|
||||
.build();
|
||||
|
||||
ValueConfig iconConfig = ValueConfig.builder()
|
||||
.valueName("icon")
|
||||
.values(Arrays.asList(ConfigValue.builder().value("weasel").build()))
|
||||
.comment("图标")
|
||||
.build();
|
||||
|
||||
// 创建子LevelConfig对象
|
||||
LevelConfig auxDataLevel = LevelConfig.builder()
|
||||
.levelName("aux_data")
|
||||
.values(Arrays.asList())
|
||||
.comment("辅助数据")
|
||||
.valueConfigs(Arrays.asList(batchnumberConfig))
|
||||
.subLevels(Arrays.asList())
|
||||
.build();
|
||||
|
||||
// 创建主LevelConfig对象
|
||||
LevelConfig platformLevel = LevelConfig.builder()
|
||||
.levelName("platform")
|
||||
.values(Arrays.asList("north_cap_1", "STRIKER"))
|
||||
.comment("平台配置")
|
||||
.valueConfigs(Arrays.asList(sideConfig, iconConfig))
|
||||
.subLevels(Arrays.asList(auxDataLevel))
|
||||
.build();
|
||||
|
||||
// 创建ConfigDocument对象
|
||||
return ConfigDocument.builder()
|
||||
// ... 构建逻辑
|
||||
.build();
|
||||
}
|
||||
```
|
||||
## 转换规则
|
||||
|
||||
### 文本格式解析规则:
|
||||
1. **层级定义**:`levelName value1 value2 ... # 注释`
|
||||
2. **值配置**:`valueName value [unit] # 注释`
|
||||
3. **条件类型**:单独一行,无前缀
|
||||
4. **子层级**:缩进表示嵌套关系
|
||||
5. **结束标记**:`end_levelName`
|
||||
|
||||
### 映射规则:
|
||||
- 每行开头单词为`levelName` → 创建LevelConfig
|
||||
- 缩进2空格后的单词为`valueName` → 创建ValueConfig
|
||||
- `#`后面的内容 → 对应comment字段
|
||||
- 行中的数值/字符串 → 创建ConfigValue
|
||||
- 存在=等于符号的,整行内容默认全部为 value → ConfigValue.value字段
|
||||
- 数值后的单位 → ConfigValue.unit字段
|
||||
- 条件类型单独一行 → LevelConfig.conditionType
|
||||
|
||||
### 处理流程:
|
||||
1. 解析文本配置,识别层级结构
|
||||
2. 按从内到外的顺序创建对象:
|
||||
- 先创建最内层的ConfigValue
|
||||
- 然后创建包含ConfigValue的ValueConfig
|
||||
- 再创建包含ValueConfig和子层级的LevelConfig
|
||||
- 最后创建包含LevelConfig列表的ConfigDocument
|
||||
3. 保持正确的缩进和嵌套关系
|
||||
4. 处理注释信息
|
||||
5. 生成完整的Java构建代码
|
||||
|
||||
### 质量要求:
|
||||
- 生成的代码必须语法正确
|
||||
- 使用正确的Builder模式
|
||||
- 保持代码格式整洁
|
||||
- 正确处理空值和默认值
|
||||
- 支持中英文混合内容
|
@ -0,0 +1,55 @@
|
||||
package com.example.demo.draft.demo043;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.example.demo.draft.demo043.domain.ConfigDocument;
|
||||
import com.example.demo.draft.demo043.domain.LevelConfig;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* 测试LevelConfig的loopCount字段修复
|
||||
*/
|
||||
public class TestLoopCountFix {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// 读取default.json文件
|
||||
String templateContent = Files.readString(
|
||||
Path.of("src/main/resources/data/02-单个空中平台任务数据/default.json"),
|
||||
StandardCharsets.UTF_8
|
||||
);
|
||||
|
||||
System.out.println("=== 原始JSON内容 ===");
|
||||
System.out.println(templateContent);
|
||||
|
||||
// 解析JSON到ConfigDocument对象
|
||||
ConfigDocument document = JSON.parseObject(templateContent, ConfigDocument.class);
|
||||
|
||||
System.out.println("\n=== 解析后的ConfigDocument ===");
|
||||
System.out.println("levelConfigs数量: " + document.getLevelConfigs().size());
|
||||
|
||||
if (!document.getLevelConfigs().isEmpty()) {
|
||||
LevelConfig platformLevel = document.getLevelConfigs().get(0);
|
||||
|
||||
System.out.println("\n=== platform层级配置 ===");
|
||||
System.out.println("levelName: " + platformLevel.getLevelName());
|
||||
System.out.println("enableLoop: " + platformLevel.getEnableLoop());
|
||||
System.out.println("loopCount: " + platformLevel.getLoopCount());
|
||||
System.out.println("values: " + platformLevel.getValues());
|
||||
|
||||
// 验证loopCount是否正确获取
|
||||
if (platformLevel.getLoopCount() != null) {
|
||||
System.out.println("✅ SUCCESS: loopCount字段已正确获取值: " + platformLevel.getLoopCount());
|
||||
} else {
|
||||
System.out.println("❌ FAILED: loopCount字段仍然为null");
|
||||
}
|
||||
|
||||
if (platformLevel.getEnableLoop() != null && platformLevel.getEnableLoop()) {
|
||||
System.out.println("✅ SUCCESS: enableLoop字段已正确获取值: " + platformLevel.getEnableLoop());
|
||||
} else {
|
||||
System.out.println("❌ FAILED: enableLoop字段获取异常");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,338 @@
|
||||
package com.example.demo.draft.demo043.core;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.example.demo.draft.demo043.domain.ConfigValue;
|
||||
import com.example.demo.draft.demo043.domain.LevelConfig;
|
||||
import com.example.demo.draft.demo043.domain.ValueConfig;
|
||||
import com.example.demo.draft.demo043.util.FormatUtil;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 增强的配置处理器
|
||||
*
|
||||
* <p>处理配置中的循环、正则表达式、枚举映射和工具函数调用功能。</p>
|
||||
*
|
||||
* <p><b>功能说明:</b></p>
|
||||
* <ul>
|
||||
* <li>层级循环处理</li>
|
||||
* <li>值正则表达式处理</li>
|
||||
* <li>枚举映射转换</li>
|
||||
* <li>工具函数调用</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class EnhancedConfigProcessor {
|
||||
|
||||
/**
|
||||
* 处理层级配置
|
||||
*
|
||||
* @param levelConfig 层级配置
|
||||
* @param context 处理上下文
|
||||
* @return 处理后的层级配置列表(可能包含循环生成的多个配置)
|
||||
*/
|
||||
public static List<LevelConfig> processLevelConfig(LevelConfig levelConfig, Map<String, Object> context) {
|
||||
List<LevelConfig> result = new ArrayList<>();
|
||||
|
||||
// 检查是否启用循环
|
||||
if (levelConfig.getEnableLoop() != null && levelConfig.getEnableLoop()) {
|
||||
int loopCount = 0;
|
||||
if(StrUtil.isBlank(levelConfig.getLoopCount())) {
|
||||
levelConfig.setLoopCount("1");
|
||||
}
|
||||
try {
|
||||
loopCount = Integer.parseInt(levelConfig.getLoopCount());
|
||||
} catch (NumberFormatException e) {
|
||||
loopCount = 1;
|
||||
}
|
||||
|
||||
// 根据loopCount的最大值确定数字格式化的位数
|
||||
int maxDigits = String.valueOf(loopCount).length();
|
||||
|
||||
// 遍历每个配置项,从1开始到loopCount结束(包含两端)
|
||||
for (int i = 1; i <= loopCount; i++) {
|
||||
// 处理单个层级的配置,传入当前索引(i-1因为processSingleLevelConfig期望从0开始)
|
||||
LevelConfig processedConfig = processSingleLevelConfig(levelConfig, context, i - 1);
|
||||
|
||||
String newValue;
|
||||
if (loopCount >= 2) {
|
||||
// 当loopCount大于等于2时,添加带序号的后缀(根据最大位数自动补零)
|
||||
newValue = String.format("%s_%0" + maxDigits + "d", processedConfig.getValues().getFirst(), i);
|
||||
} else {
|
||||
// 当loopCount等于1时,不添加后缀编号,直接使用原始值
|
||||
newValue = processedConfig.getValues().getFirst();
|
||||
}
|
||||
|
||||
// 获取原始值列表
|
||||
List<String> values = processedConfig.getValues();
|
||||
|
||||
// 检查值列表是否非空
|
||||
if(CollUtil.isNotEmpty(values)) {
|
||||
// 移除第一个值(通常是要被替换的基础值)
|
||||
values.removeFirst();
|
||||
|
||||
// 创建新的值列表:包含格式化后的新值,然后添加剩余的值
|
||||
List<String> newValues = new ArrayList<>() {{
|
||||
add(newValue); // 添加格式化后的新值作为第一个元素
|
||||
addAll(values); // 添加原始列表中剩余的所有值
|
||||
}};
|
||||
|
||||
// 将新值列表设置回处理后的配置对象
|
||||
processedConfig.setValues(newValues);
|
||||
}
|
||||
|
||||
// 将处理后的配置添加到结果列表中
|
||||
result.add(processedConfig);
|
||||
}
|
||||
} else {
|
||||
LevelConfig processedConfig = processSingleLevelConfig(levelConfig, context, 0);
|
||||
result.add(processedConfig);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理单个层级配置
|
||||
*/
|
||||
private static LevelConfig processSingleLevelConfig(LevelConfig levelConfig, Map<String, Object> context, int loopIndex) {
|
||||
LevelConfig result = new LevelConfig();
|
||||
result.setLevelName(levelConfig.getLevelName());
|
||||
result.setComment(levelConfig.getComment());
|
||||
result.setConditionType(levelConfig.getConditionType());
|
||||
|
||||
// 处理层级值
|
||||
if (levelConfig.getValues() != null) {
|
||||
List<String> processedValues = new ArrayList<>();
|
||||
for (String value : levelConfig.getValues()) {
|
||||
String processedValue = processValue(value, levelConfig.getEnumMapping(),
|
||||
levelConfig.getUtilFunction(), context, loopIndex);
|
||||
processedValues.add(processedValue);
|
||||
}
|
||||
result.setValues(processedValues);
|
||||
}
|
||||
|
||||
// 处理值配置
|
||||
if (levelConfig.getValueConfigs() != null) {
|
||||
List<ValueConfig> processedValueConfigs = new ArrayList<>();
|
||||
for (ValueConfig valueConfig : levelConfig.getValueConfigs()) {
|
||||
ValueConfig processedValueConfig = processValueConfig(valueConfig, context, loopIndex);
|
||||
processedValueConfigs.add(processedValueConfig);
|
||||
}
|
||||
result.setValueConfigs(processedValueConfigs);
|
||||
}
|
||||
|
||||
// 处理子层级
|
||||
if (levelConfig.getSubLevels() != null) {
|
||||
List<LevelConfig> processedSubLevels = new ArrayList<>();
|
||||
for (LevelConfig subLevel : levelConfig.getSubLevels()) {
|
||||
List<LevelConfig> processedSubs = processLevelConfig(subLevel, context);
|
||||
processedSubLevels.addAll(processedSubs);
|
||||
}
|
||||
result.setSubLevels(processedSubLevels);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理配置值
|
||||
*
|
||||
* @param value 原始值
|
||||
* @param enumMapping 枚举映射配置
|
||||
* @param utilFunction 工具函数配置
|
||||
* @param context 处理上下文
|
||||
* @param loopIndex 循环索引
|
||||
* @return 处理后的值
|
||||
*/
|
||||
public static String processValue(String value, Map<String, String> enumMapping,
|
||||
Map<String, Object> utilFunction, Map<String, Object> context, int loopIndex) {
|
||||
if (value == null) return null;
|
||||
|
||||
String result = value;
|
||||
|
||||
// 1. 应用枚举映射
|
||||
if (enumMapping != null && enumMapping.containsKey(result)) {
|
||||
result = enumMapping.get(result);
|
||||
}
|
||||
|
||||
// 2. 应用工具函数
|
||||
if (utilFunction != null && !utilFunction.isEmpty()) {
|
||||
result = applyUtilFunction(result, utilFunction, context, loopIndex);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理值配置对象
|
||||
*
|
||||
* @param valueConfig 值配置对象
|
||||
* @param context 处理上下文
|
||||
* @param loopIndex 循环索引
|
||||
* @return 处理后的值配置对象
|
||||
*/
|
||||
public static ValueConfig processValueConfig(ValueConfig valueConfig, Map<String, Object> context, int loopIndex) {
|
||||
if (valueConfig == null) return null;
|
||||
|
||||
ValueConfig result = new ValueConfig();
|
||||
result.setValueName(valueConfig.getValueName());
|
||||
result.setComment(valueConfig.getComment());
|
||||
|
||||
// 处理配置值列表
|
||||
if (valueConfig.getValues() != null) {
|
||||
List<ConfigValue> processedValues = new ArrayList<>();
|
||||
for (ConfigValue configValue : valueConfig.getValues()) {
|
||||
ConfigValue processedConfigValue = processConfigValue(configValue, context, loopIndex);
|
||||
processedValues.add(processedConfigValue);
|
||||
}
|
||||
result.setValues(processedValues);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理配置值对象
|
||||
*
|
||||
* @param configValue 配置值对象
|
||||
* @param context 处理上下文
|
||||
* @param loopIndex 循环索引
|
||||
* @return 处理后的配置值对象
|
||||
*/
|
||||
public static ConfigValue processConfigValue(ConfigValue configValue, Map<String, Object> context, int loopIndex) {
|
||||
if (configValue == null) return null;
|
||||
|
||||
ConfigValue result = new ConfigValue();
|
||||
result.setUnit(configValue.getUnit());
|
||||
result.setCombined(configValue.isCombined());
|
||||
|
||||
Object originalValue = configValue.getValue();
|
||||
Object processedValue = originalValue;
|
||||
|
||||
// 处理字符串值
|
||||
if (originalValue instanceof String) {
|
||||
@SuppressWarnings("all")
|
||||
String strValue = (String) originalValue;
|
||||
|
||||
// 1. 应用正则表达式
|
||||
if (configValue.getRegexPattern() != null && configValue.getRegexReplacement() != null) {
|
||||
try {
|
||||
Pattern pattern = Pattern.compile(configValue.getRegexPattern());
|
||||
Matcher matcher = pattern.matcher(strValue);
|
||||
strValue = matcher.replaceAll(configValue.getRegexReplacement());
|
||||
} catch (Exception e) {
|
||||
// 正则表达式错误,保持原值
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 应用枚举映射
|
||||
if (configValue.getEnumMapping() != null && configValue.getEnumMapping().containsKey(strValue)) {
|
||||
strValue = configValue.getEnumMapping().get(strValue);
|
||||
}
|
||||
|
||||
// 3. 应用工具函数
|
||||
if (configValue.getUtilFunction() != null && !configValue.getUtilFunction().isEmpty()) {
|
||||
strValue = applyUtilFunction(strValue, configValue.getUtilFunction(), context, loopIndex);
|
||||
}
|
||||
|
||||
processedValue = strValue;
|
||||
}
|
||||
|
||||
result.setValue(processedValue);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用工具函数
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
private static String applyUtilFunction(String value, Map<String, Object> utilFunction,
|
||||
Map<String, Object> context, int loopIndex) {
|
||||
if (utilFunction == null || utilFunction.isEmpty()) return value;
|
||||
|
||||
String result = value;
|
||||
|
||||
try {
|
||||
// 获取函数名称
|
||||
String functionName = utilFunction.keySet().iterator().next();
|
||||
Object functionParams = utilFunction.get(functionName);
|
||||
|
||||
// 构建参数映射
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
if (functionParams instanceof Map) {
|
||||
params.putAll((Map<String, Object>) functionParams);
|
||||
}
|
||||
|
||||
// 添加上下文和循环索引
|
||||
params.put("context", context);
|
||||
params.put("loopIndex", loopIndex);
|
||||
|
||||
// 调用工具函数
|
||||
result = callFormatUtilFunction(functionName, value, params);
|
||||
|
||||
} catch (Exception e) {
|
||||
// 工具函数调用失败,保持原值
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用 FormatUtil 工具函数
|
||||
*/
|
||||
private static String callFormatUtilFunction(String functionName, String value, Map<String, Object> params) {
|
||||
try {
|
||||
Method method = FormatUtil.class.getMethod(functionName, String.class, Map.class);
|
||||
Object result = method.invoke(null, value, params);
|
||||
return result != null ? result.toString() : value;
|
||||
} catch (Exception e) {
|
||||
// 方法调用失败,尝试其他方式
|
||||
return callCustomUtilFunction(functionName, value, params);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用自定义工具函数
|
||||
*/
|
||||
private static String callCustomUtilFunction(String functionName, String value, Map<String, Object> params) {
|
||||
// 这里可以扩展支持其他工具类
|
||||
// 目前只支持 FormatUtil
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量处理层级配置列表
|
||||
*/
|
||||
public static List<LevelConfig> processLevelConfigs(List<LevelConfig> levelConfigs, Map<String, Object> context) {
|
||||
List<LevelConfig> result = new ArrayList<>();
|
||||
|
||||
if (levelConfigs != null) {
|
||||
for (LevelConfig levelConfig : levelConfigs) {
|
||||
List<LevelConfig> processedConfigs = processLevelConfig(levelConfig, context);
|
||||
result.addAll(processedConfigs);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量处理配置值列表
|
||||
*/
|
||||
public static List<ConfigValue> processConfigValues(List<ConfigValue> configValues, Map<String, Object> context, int loopIndex) {
|
||||
List<ConfigValue> result = new ArrayList<>();
|
||||
|
||||
if (configValues != null) {
|
||||
for (ConfigValue configValue : configValues) {
|
||||
ConfigValue processedValue = processConfigValue(configValue, context, loopIndex);
|
||||
result.add(processedValue);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
@ -0,0 +1,628 @@
|
||||
package com.example.demo.draft.demo043.core;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.example.demo.draft.demo043.domain.ConfigValue;
|
||||
import com.example.demo.draft.demo043.domain.LevelConfig;
|
||||
import com.example.demo.draft.demo043.domain.ValueConfig;
|
||||
import com.example.demo.draft.demo043.util.FormatUtil;
|
||||
import com.hubspot.jinjava.Jinjava;
|
||||
import com.hubspot.jinjava.JinjavaConfig;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 增强的 Jinja2 模板生成器
|
||||
*
|
||||
* <p>该类提供了基于 Jinja2 模板引擎的动态代码生成功能,支持从文件系统或类路径加载模板文件,
|
||||
* 实现了灵活的模板管理和渲染机制。</p>
|
||||
*
|
||||
* <h3>主要特性:</h3>
|
||||
* <ul>
|
||||
* <li>支持从类路径和文件系统加载模板文件</li>
|
||||
* <li>内置模板缓存机制,提高渲染性能</li>
|
||||
* <li>支持多种数据格式和复杂的嵌套结构</li>
|
||||
* <li>提供条件判断、循环控制等高级模板功能</li>
|
||||
* <li>灵活的缩进控制和格式化管理</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>使用示例:</h3>
|
||||
* <pre>{@code
|
||||
* // 构建模板数据
|
||||
* TemplateData data = EnhancedTemplateGenerator.TemplateData.builder()
|
||||
* .globalComment("示例配置")
|
||||
* .levelConfigs(Arrays.asList(...))
|
||||
* .build();
|
||||
*
|
||||
* // 使用默认模板生成代码
|
||||
* String result = EnhancedTemplateGenerator.generateCode(data);
|
||||
*
|
||||
* // 使用指定模板文件生成代码
|
||||
* String result2 = EnhancedTemplateGenerator.generateCode(data, "templates/custom-template.j2");
|
||||
* }</pre>
|
||||
*
|
||||
* @author Template Generator Team
|
||||
* @version 1.0.0
|
||||
* @since 2024-01-01
|
||||
* @see TemplateFileLoader
|
||||
*/
|
||||
public class EnhancedTemplateGenerator {
|
||||
|
||||
/**
|
||||
* Jinja2 模板引擎实例
|
||||
* <p>使用单例模式确保整个应用中只有一个引擎实例,提高性能并避免资源浪费。</p>
|
||||
*/
|
||||
private static final Jinjava JINJAVA;
|
||||
|
||||
/**
|
||||
* 默认模板文件路径
|
||||
* <p>当不指定模板路径时,将使用此路径对应的模板文件。</p>
|
||||
*/
|
||||
private static final String DEFAULT_TEMPLATE = "generator/jinjia2/dynamic-template.j2";
|
||||
|
||||
// 静态初始化块 - 配置 Jinja2 引擎
|
||||
static {
|
||||
// 初始化 Jinja2 引擎配置
|
||||
JinjavaConfig config = JinjavaConfig.newBuilder()
|
||||
.withTrimBlocks(true) // 启用块修剪,去除标签后的换行符
|
||||
.withLstripBlocks(true) // 启用行修剪,去除标签前的空格
|
||||
.build();
|
||||
JINJAVA = new Jinjava(config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用指定模板文件生成代码
|
||||
*
|
||||
* <p>该方法允许使用自定义的模板文件进行代码生成,提供更大的灵活性。</p>
|
||||
*
|
||||
* <h3>模板路径支持格式:</h3>
|
||||
* <ul>
|
||||
* <li>类路径资源:"templates/my-template.j2"</li>
|
||||
* <li>类路径前缀:"classpath:templates/my-template.j2"</li>
|
||||
* <li>文件系统路径:"file:/path/to/template.j2"</li>
|
||||
* <li>相对路径:"file:./templates/my-template.j2"</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param data 模板数据对象
|
||||
* @param templatePath 模板文件路径,支持类路径和文件系统路径
|
||||
* @return 渲染后的代码字符串
|
||||
* @throws IOException 当模板文件不存在或读取失败时抛出
|
||||
* @throws IllegalArgumentException 当模板路径格式不正确时抛出
|
||||
*
|
||||
* @see TemplateFileLoader#loadTemplate(String)
|
||||
*
|
||||
* @example
|
||||
* <pre>{@code
|
||||
* // 使用类路径模板
|
||||
* String code1 = generateCode(data, "templates/custom.j2");
|
||||
*
|
||||
* // 使用文件系统模板
|
||||
* String code2 = generateCode(data, "file:/home/user/templates/custom.j2");
|
||||
* }</pre>
|
||||
*/
|
||||
public static String generateCode(Map<String, Object> data, String templatePath) throws IOException {
|
||||
// 参数校验
|
||||
if (templatePath == null || templatePath.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("模板路径不能为空");
|
||||
}
|
||||
|
||||
if (data == null) {
|
||||
throw new IllegalArgumentException("模板数据不能为空");
|
||||
}
|
||||
|
||||
// 应用增强配置处理
|
||||
// FIXME 2025-9-25 13:44:26 增强解析能力异常
|
||||
@SuppressWarnings("all")
|
||||
Map<String, Object> processedMap = data;
|
||||
processedMap = applyEnhancedProcessing(processedMap);
|
||||
|
||||
String groupLog = String.format("%s %s %s", "=".repeat(40), "%s","=".repeat(40));
|
||||
System.out.printf((groupLog) + "%n", "最终Map ↓↓↓");
|
||||
System.out.println(JSON.toJSONString(processedMap));
|
||||
System.out.printf((groupLog) + "%n", "最终Map ↑↑↑");
|
||||
|
||||
// 加载模板内容
|
||||
String templateContent = TemplateFileLoader.loadTemplate(templatePath);
|
||||
|
||||
// 渲染模板
|
||||
return renderTemplate(processedMap, templateContent);
|
||||
}
|
||||
/**
|
||||
* 使用增强功能处理模板数据并生成格式化代码
|
||||
*
|
||||
* <p>该方法在生成代码前会应用增强的配置处理功能,包括:</p>
|
||||
* <ul>
|
||||
* <li>层级循环处理</li>
|
||||
* <li>值正则表达式处理</li>
|
||||
* <li>枚举映射转换</li>
|
||||
* <li>工具函数调用</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param map 模板数据映射
|
||||
* @param templatePath 模板文件路径
|
||||
* @return 处理后的格式化代码
|
||||
* @throws IOException 当模板文件不存在或读取失败时抛出
|
||||
*/
|
||||
public static String generateCodeWithFormat(Map<String, Object> map, String templatePath) throws IOException {
|
||||
// 生成基础代码
|
||||
String data = generateCode(map, templatePath);
|
||||
|
||||
// 格式化输出
|
||||
String result = FormatUtil.replaceRepeatedPatterns(data, "\r\n", "", 1, 1);
|
||||
result = result.replaceAll("( {4,})( {4})end_(\\w+)", "$1end_$3");
|
||||
// result = result.replaceAll("\r\n( {4})", "\r\n");
|
||||
// result = result.replaceAll("\r\n( {8})", "\r\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用增强配置处理
|
||||
*
|
||||
* <p>对模板数据中的层级配置进行增强处理,包括循环、正则、枚举映射和函数调用。</p>
|
||||
*
|
||||
* @param originalMap 原始模板数据
|
||||
* @return 处理后的模板数据
|
||||
*/
|
||||
public static Map<String, Object> applyEnhancedProcessing(Map<String, Object> originalMap) {
|
||||
Map<String, Object> processedMap = new HashMap<>(originalMap);
|
||||
|
||||
// 检查是否包含层级配置
|
||||
if (processedMap.containsKey("levelConfigs")) {
|
||||
Object levelConfigsObj = processedMap.get("levelConfigs");
|
||||
if (levelConfigsObj instanceof List) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> levelConfigsList = (List<Object>) levelConfigsObj;
|
||||
|
||||
// 处理每个层级配置
|
||||
List<Object> processedLevelConfigs = new ArrayList<>();
|
||||
Map<String, Object> context = new HashMap<>();
|
||||
|
||||
for (Object levelConfigObj : levelConfigsList) {
|
||||
if (levelConfigObj instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> levelConfigMap = (Map<String, Object>) levelConfigObj;
|
||||
|
||||
// 转换为LevelConfig对象进行处理
|
||||
LevelConfig levelConfig = convertMapToLevelConfig(levelConfigMap);
|
||||
|
||||
// 应用增强处理
|
||||
List<LevelConfig> processedConfigs = EnhancedConfigProcessor.processLevelConfig(levelConfig, context);
|
||||
|
||||
// 转换回Map格式
|
||||
for (LevelConfig processedConfig : processedConfigs) {
|
||||
Map<String, Object> processedConfigMap = convertLevelConfigToMap(processedConfig);
|
||||
processedLevelConfigs.add(processedConfigMap);
|
||||
}
|
||||
} else {
|
||||
// 保持原样
|
||||
processedLevelConfigs.add(levelConfigObj);
|
||||
}
|
||||
}
|
||||
|
||||
processedMap.put("levelConfigs", processedLevelConfigs);
|
||||
}
|
||||
}
|
||||
|
||||
return processedMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将Map转换为LevelConfig对象
|
||||
*/
|
||||
private static LevelConfig convertMapToLevelConfig(Map<String, Object> map) {
|
||||
LevelConfig.LevelConfigBuilder builder = LevelConfig.builder();
|
||||
|
||||
if (map.containsKey("levelName")) {
|
||||
builder.levelName((String) map.get("levelName"));
|
||||
}
|
||||
|
||||
if (map.containsKey("values")) {
|
||||
Object valuesObj = map.get("values");
|
||||
if (valuesObj instanceof List) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> values = (List<String>) valuesObj;
|
||||
builder.values(values);
|
||||
}
|
||||
}
|
||||
|
||||
if (map.containsKey("comment")) {
|
||||
builder.comment((String) map.get("comment"));
|
||||
}
|
||||
|
||||
if (map.containsKey("conditionType")) {
|
||||
builder.conditionType((String) map.get("conditionType"));
|
||||
}
|
||||
|
||||
if (map.containsKey("enableLoop")) {
|
||||
builder.enableLoop((Boolean) map.get("enableLoop"));
|
||||
}
|
||||
|
||||
if (map.containsKey("loopCount")) {
|
||||
Object loopCountObj = map.get("loopCount");
|
||||
if (loopCountObj instanceof String) {
|
||||
try {
|
||||
int loopCountInteger = Integer.parseInt(loopCountObj.toString());
|
||||
builder.loopCount(String.valueOf(loopCountInteger));
|
||||
} catch (NumberFormatException e) {
|
||||
builder.loopCount("1");
|
||||
}
|
||||
} else if (loopCountObj instanceof Integer) {
|
||||
builder.loopCount(String.valueOf(loopCountObj));
|
||||
}
|
||||
}
|
||||
|
||||
if (map.containsKey("enumMapping")) {
|
||||
Object enumMappingObj = map.get("enumMapping");
|
||||
if (enumMappingObj instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> enumMapping = (Map<String, String>) enumMappingObj;
|
||||
builder.enumMapping(enumMapping);
|
||||
}
|
||||
}
|
||||
|
||||
if (map.containsKey("utilFunction")) {
|
||||
Object utilFunctionObj = map.get("utilFunction");
|
||||
if (utilFunctionObj instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> utilFunction = (Map<String, Object>) utilFunctionObj;
|
||||
builder.utilFunction(utilFunction);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理valueConfigs
|
||||
if (map.containsKey("valueConfigs")) {
|
||||
Object valueConfigsObj = map.get("valueConfigs");
|
||||
if (valueConfigsObj instanceof List) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> valueConfigsList = (List<Object>) valueConfigsObj;
|
||||
List<ValueConfig> valueConfigs = new ArrayList<>();
|
||||
|
||||
for (Object valueConfigObj : valueConfigsList) {
|
||||
if (valueConfigObj instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> valueConfigMap = (Map<String, Object>) valueConfigObj;
|
||||
ValueConfig valueConfig = convertMapToValueConfig(valueConfigMap);
|
||||
valueConfigs.add(valueConfig);
|
||||
}
|
||||
}
|
||||
|
||||
builder.valueConfigs(valueConfigs);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理subLevels
|
||||
if (map.containsKey("subLevels")) {
|
||||
Object subLevelsObj = map.get("subLevels");
|
||||
if (subLevelsObj instanceof List) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> subLevelsList = (List<Object>) subLevelsObj;
|
||||
List<LevelConfig> subLevels = new ArrayList<>();
|
||||
|
||||
for (Object subLevelObj : subLevelsList) {
|
||||
if (subLevelObj instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> subLevelMap = (Map<String, Object>) subLevelObj;
|
||||
LevelConfig subLevel = convertMapToLevelConfig(subLevelMap);
|
||||
subLevels.add(subLevel);
|
||||
}
|
||||
}
|
||||
|
||||
builder.subLevels(subLevels);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Map转换为ValueConfig对象
|
||||
*/
|
||||
private static ValueConfig convertMapToValueConfig(Map<String, Object> map) {
|
||||
ValueConfig.ValueConfigBuilder builder = ValueConfig.builder();
|
||||
|
||||
if (map.containsKey("valueName")) {
|
||||
builder.valueName((String) map.get("valueName"));
|
||||
}
|
||||
|
||||
if (map.containsKey("comment")) {
|
||||
builder.comment((String) map.get("comment"));
|
||||
}
|
||||
|
||||
// 处理values
|
||||
if (map.containsKey("values")) {
|
||||
Object valuesObj = map.get("values");
|
||||
if (valuesObj instanceof List) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<Object> valuesList = (List<Object>) valuesObj;
|
||||
List<ConfigValue> configValues = new ArrayList<>();
|
||||
|
||||
for (Object valueUnitObj : valuesList) {
|
||||
if (valueUnitObj instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> valueUnitMap = (Map<String, Object>) valueUnitObj;
|
||||
ConfigValue configValue = convertMapToConfigValue(valueUnitMap);
|
||||
configValues.add(configValue);
|
||||
}
|
||||
}
|
||||
|
||||
builder.values(configValues);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将Map转换为ConfigValue对象
|
||||
*/
|
||||
private static ConfigValue convertMapToConfigValue(Map<String, Object> map) {
|
||||
ConfigValue.ConfigValueBuilder builder = ConfigValue.builder();
|
||||
|
||||
if (map.containsKey("value")) {
|
||||
builder.value(map.get("value"));
|
||||
}
|
||||
|
||||
if (map.containsKey("unit")) {
|
||||
builder.unit((String) map.get("unit"));
|
||||
}
|
||||
|
||||
if (map.containsKey("combined")) {
|
||||
builder.combined((Boolean) map.get("combined"));
|
||||
}
|
||||
|
||||
if (map.containsKey("regexPattern")) {
|
||||
builder.regexPattern((String) map.get("regexPattern"));
|
||||
}
|
||||
if (map.containsKey("regexReplacement")) {
|
||||
builder.regexReplacement((String) map.get("regexReplacement"));
|
||||
}
|
||||
|
||||
if (map.containsKey("enumMapping")) {
|
||||
Object enumMappingObj = map.get("enumMapping");
|
||||
if (enumMappingObj instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, String> enumMapping = (Map<String, String>) enumMappingObj;
|
||||
builder.enumMapping(enumMapping);
|
||||
}
|
||||
}
|
||||
|
||||
if (map.containsKey("utilFunction")) {
|
||||
Object utilFunctionObj = map.get("utilFunction");
|
||||
if (utilFunctionObj instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> utilFunction = (Map<String, Object>) utilFunctionObj;
|
||||
builder.utilFunction(utilFunction);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将LevelConfig对象转换为Map
|
||||
*/
|
||||
private static Map<String, Object> convertLevelConfigToMap(LevelConfig levelConfig) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
|
||||
if (levelConfig.getLevelName() != null) {
|
||||
map.put("levelName", levelConfig.getLevelName());
|
||||
}
|
||||
|
||||
if (levelConfig.getValues() != null) {
|
||||
map.put("values", levelConfig.getValues());
|
||||
}
|
||||
|
||||
if (levelConfig.getComment() != null) {
|
||||
map.put("comment", levelConfig.getComment());
|
||||
}
|
||||
|
||||
if (levelConfig.getConditionType() != null) {
|
||||
map.put("conditionType", levelConfig.getConditionType());
|
||||
}
|
||||
|
||||
if (levelConfig.getValueConfigs() != null) {
|
||||
List<Map<String, Object>> valueConfigsList = new ArrayList<>();
|
||||
for (ValueConfig valueConfig : levelConfig.getValueConfigs()) {
|
||||
Map<String, Object> valueConfigMap = convertValueConfigToMap(valueConfig);
|
||||
valueConfigsList.add(valueConfigMap);
|
||||
}
|
||||
map.put("valueConfigs", valueConfigsList);
|
||||
}
|
||||
|
||||
if (levelConfig.getSubLevels() != null) {
|
||||
List<Map<String, Object>> subLevelsList = new ArrayList<>();
|
||||
for (LevelConfig subLevel : levelConfig.getSubLevels()) {
|
||||
Map<String, Object> subLevelMap = convertLevelConfigToMap(subLevel);
|
||||
subLevelsList.add(subLevelMap);
|
||||
}
|
||||
map.put("subLevels", subLevelsList);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将ValueConfig对象转换为Map
|
||||
*/
|
||||
private static Map<String, Object> convertValueConfigToMap(ValueConfig valueConfig) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
|
||||
if (valueConfig.getValueName() != null) {
|
||||
map.put("valueName", valueConfig.getValueName());
|
||||
}
|
||||
|
||||
if (valueConfig.getComment() != null) {
|
||||
map.put("comment", valueConfig.getComment());
|
||||
}
|
||||
|
||||
if (valueConfig.getValues() != null) {
|
||||
List<Map<String, Object>> valuesList = new ArrayList<>();
|
||||
for (ConfigValue configValue : valueConfig.getValues()) {
|
||||
Map<String, Object> configValueMap = convertConfigValueToMap(configValue);
|
||||
valuesList.add(configValueMap);
|
||||
}
|
||||
map.put("values", valuesList);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将ConfigValue对象转换为Map
|
||||
*/
|
||||
private static Map<String, Object> convertConfigValueToMap(ConfigValue configValue) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
|
||||
if (ObjectUtil.isNotNull(configValue.getValue())) {
|
||||
map.put("value", configValue.getValue());
|
||||
}
|
||||
|
||||
if (ObjectUtil.isNotNull(configValue.getUnit())) {
|
||||
map.put("unit", configValue.getUnit());
|
||||
}
|
||||
|
||||
if (configValue.isCombined()) {
|
||||
map.put("combined", true);
|
||||
}
|
||||
|
||||
if (ObjectUtil.isNotNull(configValue.getRegexPattern())) {
|
||||
map.put("regexPattern", configValue.getRegexPattern());
|
||||
}
|
||||
|
||||
if (ObjectUtil.isNotNull(configValue.getRegexReplacement())) {
|
||||
map.put("regexReplacement", configValue.getRegexReplacement());
|
||||
}
|
||||
|
||||
if (CollUtil.isNotEmpty(configValue.getEnumMapping())) {
|
||||
map.put("enumMapping", configValue.getEnumMapping());
|
||||
}
|
||||
|
||||
if (CollUtil.isNotEmpty(configValue.getUtilFunction())) {
|
||||
map.put("utilFunction", configValue.getUtilFunction());
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行模板渲染
|
||||
*
|
||||
* <p>内部方法,负责准备上下文数据并调用 Jinja2 引擎进行渲染。</p>
|
||||
*
|
||||
* <h3>上下文变量:</h3>
|
||||
* <ul>
|
||||
* <li>{@code data}: 主要的模板数据对象</li>
|
||||
* <li>{@code indent}: 缩进字符串,根据 indentSpaces 生成</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param data 模板数据
|
||||
* @param templateContent 模板内容
|
||||
* @return 渲染结果
|
||||
* @throws RuntimeException 当模板渲染过程中出现错误时抛出
|
||||
*/
|
||||
private static String renderTemplate(Map<String, Object> data, String templateContent) {
|
||||
// 准备模板上下文
|
||||
Map<String, Object> context = new HashMap<>();
|
||||
context.put("data", data);
|
||||
context.put("indent", " ".repeat((Integer) data.getOrDefault("indent", 4)));
|
||||
|
||||
try {
|
||||
// 执行模板渲染
|
||||
return JINJAVA.render(templateContent, context);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("模板渲染失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 列出可用的模板文件
|
||||
*
|
||||
* <p>该方法会检查预定义的模板文件是否存在,并显示每个模板的基本信息。</p>
|
||||
*
|
||||
* <h3>输出信息:</h3>
|
||||
* <ul>
|
||||
* <li>模板文件路径</li>
|
||||
* <li>加载状态(✓ 表示成功,✗ 表示失败)</li>
|
||||
* <li>模板内容长度(字符数)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @example
|
||||
* <pre>{@code
|
||||
* 可用的模板文件:
|
||||
* ✓ templates/dynamic-template.j2 (856 字符)
|
||||
* ✓ templates/simple-template.j2 (512 字符)
|
||||
* ✗ templates/custom-template.j2 (未找到)
|
||||
* }</pre>
|
||||
*/
|
||||
public static void listAvailableTemplates() {
|
||||
// 预定义的模板文件列表
|
||||
String[] templates = {
|
||||
"generator/jinjia2/dynamic-template.j2"
|
||||
};
|
||||
|
||||
System.out.println("可用的模板文件:");
|
||||
for (String template : templates) {
|
||||
try {
|
||||
// 尝试加载模板文件
|
||||
String content = TemplateFileLoader.loadTemplate(template);
|
||||
System.out.println("✓ " + template + " (" + content.length() + " 字符)");
|
||||
} catch (IOException e) {
|
||||
System.out.println("✗ " + template + " (未找到)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 Jinja2 引擎实例
|
||||
*
|
||||
* <p>提供对内部 Jinja2 引擎的访问,用于高级定制或扩展功能。</p>
|
||||
*
|
||||
* <h3>使用注意事项:</h3>
|
||||
* <ul>
|
||||
* <li>不建议直接修改引擎配置</li>
|
||||
* <li>主要用于添加自定义过滤器或函数</li>
|
||||
* <li>修改配置可能会影响其他模板渲染</li>
|
||||
* </ul>
|
||||
*
|
||||
* @return Jinja2 引擎实例
|
||||
*/
|
||||
public static Jinjava getJinjavaEngine() {
|
||||
return JINJAVA;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认模板路径
|
||||
*
|
||||
* @return 默认模板文件路径
|
||||
*/
|
||||
public static String getDefaultTemplatePath() {
|
||||
return DEFAULT_TEMPLATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空模板缓存
|
||||
*
|
||||
* <p>清除所有已缓存的模板内容,强制下次加载时重新读取文件。</p>
|
||||
*
|
||||
* <h3>适用场景:</h3>
|
||||
* <ul>
|
||||
* <li>模板文件内容已更新</li>
|
||||
* <li>需要释放内存</li>
|
||||
* <li>测试缓存机制</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static void clearTemplateCache() {
|
||||
TemplateFileLoader.clearCache();
|
||||
}
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
package com.example.demo.draft.demo043.core;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 模板文件工具类
|
||||
* 负责从文件系统或类路径加载模板文件
|
||||
*/
|
||||
@Slf4j
|
||||
public class TemplateFileLoader {
|
||||
|
||||
private static final String DEFAULT_TEMPLATE_DIR = "templates/";
|
||||
private static final String CLASS_PATH_PREFIX = "classpath:";
|
||||
private static final String FILE_PATH_PREFIX = "file:";
|
||||
|
||||
// 模板缓存
|
||||
private static final Map<String, String> TEMPLATE_CACHE = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 从类路径加载模板文件
|
||||
*/
|
||||
public static String loadTemplateFromClasspath(String templatePath) throws IOException {
|
||||
String cacheKey = CLASS_PATH_PREFIX + templatePath;
|
||||
if (TEMPLATE_CACHE.containsKey(cacheKey)) {
|
||||
return TEMPLATE_CACHE.get(cacheKey);
|
||||
}
|
||||
|
||||
try {
|
||||
// 从类路径加载
|
||||
String fullPath = templatePath.startsWith("/") ? templatePath : "/" + templatePath;
|
||||
java.io.InputStream inputStream = TemplateFileLoader.class.getResourceAsStream(fullPath);
|
||||
|
||||
if (inputStream == null) {
|
||||
throw new IOException("模板文件未找到: " + templatePath);
|
||||
}
|
||||
|
||||
String content = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
|
||||
TEMPLATE_CACHE.put(cacheKey, content);
|
||||
log.info("从类路径加载模板: {}", templatePath);
|
||||
return content;
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("从类路径加载模板失败: {}", templatePath, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从文件系统加载模板文件
|
||||
*/
|
||||
public static String loadTemplateFromFileSystem(String filePath) throws IOException {
|
||||
String cacheKey = FILE_PATH_PREFIX + filePath;
|
||||
if (TEMPLATE_CACHE.containsKey(cacheKey)) {
|
||||
return TEMPLATE_CACHE.get(cacheKey);
|
||||
}
|
||||
|
||||
try {
|
||||
Path path = Paths.get(filePath);
|
||||
if (!Files.exists(path)) {
|
||||
throw new IOException("模板文件不存在: " + filePath);
|
||||
}
|
||||
|
||||
String content = Files.readString(path, StandardCharsets.UTF_8);
|
||||
TEMPLATE_CACHE.put(cacheKey, content);
|
||||
log.info("从文件系统加载模板: {}", filePath);
|
||||
return content;
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("从文件系统加载模板失败: {}", filePath, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 智能加载模板(自动判断路径类型)
|
||||
*/
|
||||
public static String loadTemplate(String templatePath) throws IOException {
|
||||
if (templatePath.startsWith(CLASS_PATH_PREFIX)) {
|
||||
return loadTemplateFromClasspath(templatePath.substring(CLASS_PATH_PREFIX.length()));
|
||||
} else if (templatePath.startsWith(FILE_PATH_PREFIX)) {
|
||||
return loadTemplateFromFileSystem(templatePath.substring(FILE_PATH_PREFIX.length()));
|
||||
} else {
|
||||
// 默认从类路径加载
|
||||
return loadTemplateFromClasspath(templatePath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除模板缓存
|
||||
*/
|
||||
public static void clearCache() {
|
||||
TEMPLATE_CACHE.clear();
|
||||
log.info("模板缓存已清除");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存中的模板数量
|
||||
*/
|
||||
public static int getCacheSize() {
|
||||
return TEMPLATE_CACHE.size();
|
||||
}
|
||||
}
|
@ -0,0 +1,294 @@
|
||||
package com.example.demo.draft.demo043.core;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@Slf4j
|
||||
public class Xml2AFSIMTransformation {
|
||||
|
||||
private final Map<Pattern, String> regexRules;
|
||||
|
||||
public Xml2AFSIMTransformation(Map<String, String> rules) {
|
||||
log.info("初始化转换器,规则数量: {}", rules != null ? rules.size() : 0);
|
||||
// 编译正则表达式规则
|
||||
regexRules = new HashMap<>();
|
||||
if (rules != null) {
|
||||
for (Map.Entry<String, String> entry : rules.entrySet()) {
|
||||
regexRules.put(Pattern.compile(entry.getKey()), entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 流式XML转JSON并应用转换规则
|
||||
*/
|
||||
public void convertXmlToJson(File xmlFile, File jsonFile, String rootElement) throws Exception {
|
||||
log.info("开始XML转JSON转换并应用规则");
|
||||
|
||||
try (FileInputStream xmlInputStream = new FileInputStream(xmlFile);
|
||||
FileWriter jsonWriter = new FileWriter(jsonFile)) {
|
||||
|
||||
XMLInputFactory factory = XMLInputFactory.newInstance();
|
||||
XMLStreamReader reader = factory.createXMLStreamReader(xmlInputStream);
|
||||
|
||||
jsonWriter.write("[\n");
|
||||
|
||||
boolean firstObject = true;
|
||||
int objectCount = 0;
|
||||
|
||||
// 用于跟踪当前解析状态
|
||||
Stack<String> elementStack = new Stack<>();
|
||||
Map<String, Object> currentObject = new HashMap<>();
|
||||
StringBuilder currentText = new StringBuilder();
|
||||
String currentElement = null;
|
||||
|
||||
while (reader.hasNext()) {
|
||||
int event = reader.next();
|
||||
|
||||
switch (event) {
|
||||
case XMLStreamReader.START_ELEMENT:
|
||||
String elementName = reader.getLocalName();
|
||||
elementStack.push(elementName);
|
||||
currentElement = elementName;
|
||||
currentText.setLength(0); // 重置文本内容
|
||||
|
||||
log.debug("开始元素: {}, 栈深度: {}", elementName, elementStack.size());
|
||||
|
||||
// 如果是根元素,开始新对象
|
||||
if (elementName.equals(rootElement)) {
|
||||
currentObject.clear();
|
||||
// 处理根元素的属性
|
||||
processAttributesForElement(reader, elementStack, currentObject);
|
||||
} else {
|
||||
// 处理子元素的属性
|
||||
processAttributesForElement(reader, elementStack, currentObject);
|
||||
}
|
||||
break;
|
||||
|
||||
case XMLStreamReader.CHARACTERS:
|
||||
if (!reader.isWhiteSpace()) {
|
||||
String text = reader.getText().trim();
|
||||
if (!text.isEmpty()) {
|
||||
currentText.append(text);
|
||||
log.debug("文本内容: {}", text);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case XMLStreamReader.END_ELEMENT:
|
||||
String endedElement = elementStack.pop();
|
||||
String elementContent = currentText.toString().trim();
|
||||
|
||||
log.debug("结束元素: {}, 内容: {}, 栈深度: {}",
|
||||
endedElement, elementContent, elementStack.size());
|
||||
|
||||
// 处理元素内容
|
||||
if (!elementContent.isEmpty()) {
|
||||
processElementContent(endedElement, elementContent, elementStack, currentObject);
|
||||
}
|
||||
|
||||
// 如果是根元素结束,输出当前对象
|
||||
if (endedElement.equals(rootElement)) {
|
||||
// 应用转换规则
|
||||
Map<String, Object> transformedObject = applyRules(currentObject);
|
||||
|
||||
String json = convertObjectToJson(transformedObject);
|
||||
if (json != null && !json.trim().isEmpty()) {
|
||||
if (!firstObject) {
|
||||
jsonWriter.write(",\n");
|
||||
} else {
|
||||
firstObject = false;
|
||||
}
|
||||
jsonWriter.write(json);
|
||||
objectCount++;
|
||||
|
||||
if (objectCount % 100 == 0) {
|
||||
log.info("已处理 {} 个对象", objectCount);
|
||||
jsonWriter.flush();
|
||||
}
|
||||
}
|
||||
currentObject.clear();
|
||||
}
|
||||
|
||||
currentText.setLength(0); // 重置文本内容
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
jsonWriter.write("\n]");
|
||||
log.info("转换完成,共处理 {} 个对象", objectCount);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("转换失败", e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理元素的属性
|
||||
*/
|
||||
private void processAttributesForElement(XMLStreamReader reader, Stack<String> elementStack,
|
||||
Map<String, Object> currentObject) {
|
||||
if (reader.getAttributeCount() > 0) {
|
||||
for (int i = 0; i < reader.getAttributeCount(); i++) {
|
||||
String attrName = reader.getAttributeLocalName(i);
|
||||
String attrValue = reader.getAttributeValue(i);
|
||||
// 默认处理:将属性添加到对象中
|
||||
String attrKey = elementStack.peek() + "@" + attrName;
|
||||
currentObject.put(attrKey, attrValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理元素文本内容
|
||||
*/
|
||||
private void processElementContent(String elementName, String content,
|
||||
Stack<String> elementStack, Map<String, Object> currentObject) {
|
||||
// 默认处理:将元素内容添加到对象中
|
||||
// 构建完整的元素路径作为key
|
||||
String elementKey = String.join(".", elementStack) + "." + elementName;
|
||||
currentObject.put(elementKey, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将对象转换为JSON字符串
|
||||
*/
|
||||
private String convertObjectToJson(Map<String, Object> object) {
|
||||
if (object.isEmpty()) {
|
||||
log.warn("空对象,跳过输出");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return mapToJson(object);
|
||||
} catch (Exception e) {
|
||||
log.error("对象转JSON失败", e);
|
||||
return "{}";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map转JSON字符串
|
||||
*/
|
||||
private String mapToJson(Map<String, Object> map) {
|
||||
if (map.isEmpty()) {
|
||||
return "{}";
|
||||
}
|
||||
|
||||
StringBuilder json = new StringBuilder("{");
|
||||
boolean first = true;
|
||||
|
||||
for (Map.Entry<String, Object> entry : map.entrySet()) {
|
||||
if (!first) {
|
||||
json.append(",");
|
||||
}
|
||||
first = false;
|
||||
|
||||
json.append("\"").append(escapeJson(entry.getKey())).append("\":");
|
||||
json.append(valueToJson(entry.getValue()));
|
||||
}
|
||||
|
||||
json.append("}");
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 值转JSON
|
||||
*/
|
||||
private String valueToJson(Object value) {
|
||||
if (value == null) {
|
||||
return "null";
|
||||
}
|
||||
|
||||
if (value instanceof String) {
|
||||
return "\"" + escapeJson((String) value) + "\"";
|
||||
}
|
||||
|
||||
if (value instanceof Number || value instanceof Boolean) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
if (value instanceof Map) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = (Map<String, Object>) value;
|
||||
return mapToJson(map);
|
||||
}
|
||||
|
||||
if (value instanceof List<?> list) {
|
||||
StringBuilder json = new StringBuilder("[");
|
||||
boolean first = true;
|
||||
for (Object item : list) {
|
||||
if (!first) {
|
||||
json.append(",");
|
||||
}
|
||||
first = false;
|
||||
json.append(valueToJson(item));
|
||||
}
|
||||
json.append("]");
|
||||
return json.toString();
|
||||
}
|
||||
|
||||
return "\"" + escapeJson(value.toString()) + "\"";
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON特殊字符转义
|
||||
*/
|
||||
private String escapeJson(String text) {
|
||||
if (text == null) return "";
|
||||
return text.replace("\\", "\\\\")
|
||||
.replace("\"", "\\\"")
|
||||
.replace("\b", "\\b")
|
||||
.replace("\f", "\\f")
|
||||
.replace("\n", "\\n")
|
||||
.replace("\r", "\\r")
|
||||
.replace("\t", "\\t");
|
||||
}
|
||||
|
||||
/**
|
||||
* 应用正则表达式转换规则到单个对象
|
||||
*/
|
||||
private Map<String, Object> applyRules(Map<String, Object> originalMap) {
|
||||
Map<String, Object> transformedMap = new HashMap<>();
|
||||
|
||||
for (Map.Entry<String, Object> entry : originalMap.entrySet()) {
|
||||
String originalKey = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
String newKey = findAndReplace(originalKey);
|
||||
|
||||
// 如果找到匹配的规则则使用新key,否则保留原key
|
||||
if (newKey != null) {
|
||||
transformedMap.put(newKey, value);
|
||||
log.debug("转换键: {} -> {}", originalKey, newKey);
|
||||
} else {
|
||||
transformedMap.put(originalKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
return transformedMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找并替换匹配的正则规则
|
||||
*/
|
||||
private String findAndReplace(String originalKey) {
|
||||
for (Map.Entry<Pattern, String> rule : regexRules.entrySet()) {
|
||||
if (rule.getKey().matcher(originalKey).matches()) {
|
||||
return rule.getKey().matcher(originalKey).replaceAll(rule.getValue());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
package com.example.demo.draft.demo043.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 配置文档根实体
|
||||
*
|
||||
* <p>该实体表示完整的配置文档结构,包含全局注释、条件类型映射和多个层级配置。</p>
|
||||
*
|
||||
* <h3>数据结构说明:</h3>
|
||||
* <ul>
|
||||
* <li>{@link #globalComment} - 全局配置说明</li>
|
||||
* <li>{@link #levelConfigs} - 层级配置列表</li>
|
||||
* <li>{@link #conditionMap} - 条件判断映射表</li>
|
||||
* <li>{@link #indentSpaces} - 缩进空格数控制</li>
|
||||
* <li>{@link #initialIndent} - 初始缩进配置</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p><b>使用建造者模式简化对象创建过程,使用示例:</b></p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* ConfigDocument config = ConfigDocument.builder()
|
||||
* .globalComment("系统主配置文件")
|
||||
* .conditionMap(Map.of("required", "必须配置"))
|
||||
* .levelConfigs(List.of(systemLevelConfig))
|
||||
* .build();
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @author Generated
|
||||
* @version 1.0
|
||||
* @since 2024
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ConfigDocument {
|
||||
|
||||
/**
|
||||
* 全局备注信息
|
||||
* <p>用于描述整个配置文件的用途、版本信息或其他全局性说明。</p>
|
||||
*
|
||||
* <p>示例:</p>
|
||||
* <pre>{@code
|
||||
* # 这是全局备注信息
|
||||
* }</pre>
|
||||
*/
|
||||
private String globalComment;
|
||||
|
||||
/**
|
||||
* 初始缩进配置(保留字段)
|
||||
* <p>用于格式化输出时的初始缩进空格,当前版本通常为空字符串。</p>
|
||||
*
|
||||
* @default ""
|
||||
*/
|
||||
@Builder.Default
|
||||
private String initialIndent = "";
|
||||
|
||||
/**
|
||||
* 缩进空格数
|
||||
* <p>控制输出内容的缩进格式,默认使用 4 个空格。</p>
|
||||
*
|
||||
* <p>取值范围:正整数,建议使用 2、4、8 等常用值。</p>
|
||||
*
|
||||
* @default 4
|
||||
*/
|
||||
@Builder.Default
|
||||
private Integer indentSpaces = 4;
|
||||
|
||||
/**
|
||||
* 条件类型映射表
|
||||
* <p>定义不同条件类型的描述信息,用于说明配置项的必要性级别。</p>
|
||||
*
|
||||
* <p><b>常见键值:</b></p>
|
||||
* <ul>
|
||||
* <li>required - 必须配置</li>
|
||||
* <li>optional - 可选配置</li>
|
||||
* <li>advanced - 高级选项(需要权限)</li>
|
||||
* <li>deprecated - 已弃用(不推荐使用)</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>示例:</p>
|
||||
* <pre>{@code
|
||||
* conditionMap.put("type1", "显示内容1");
|
||||
* conditionMap.put("type2", "显示内容2");
|
||||
* }</pre>
|
||||
*/
|
||||
private Map<String, String> conditionMap;
|
||||
|
||||
/**
|
||||
* 层级配置列表
|
||||
* <p>包含系统各个模块的配置信息,支持多层级的嵌套结构。</p>
|
||||
*/
|
||||
private List<LevelConfig> levelConfigs;
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
package com.example.demo.draft.demo043.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 配置值实体
|
||||
*
|
||||
* <p>表示单个配置值的详细信息,支持带单位的数值配置和标志位配置。</p>
|
||||
*
|
||||
* <p><b>值类型说明:</b></p>
|
||||
* <ul>
|
||||
* <li>数值类型:如超时时间、重试次数等</li>
|
||||
* <li>字符串类型:如文件路径、模式名称等</li>
|
||||
* <li>布尔类型:如启用/禁用标志</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ConfigValue {
|
||||
|
||||
/**
|
||||
* 配置值
|
||||
* <p>实际的配置数值,类型为Object以支持多种数据类型。</p>
|
||||
*
|
||||
* <p><b>支持的数据类型:</b></p>
|
||||
* <ul>
|
||||
* <li>Integer - 整数值,如30、5、10</li>
|
||||
* <li>String - 字符串值,如"min"、"max"、"admin"</li>
|
||||
* <li>Boolean - 布尔值,如"true"</li>
|
||||
* </ul>
|
||||
*/
|
||||
private Object value;
|
||||
|
||||
/**
|
||||
* 值单位
|
||||
* <p>配置值的单位说明,如"seconds"、"GB"、"retries"等。</p>
|
||||
*
|
||||
* <p><b>注意:</b>对于无单位的配置值,此字段可为空。</p>
|
||||
*/
|
||||
private String unit;
|
||||
|
||||
/**
|
||||
* 组合标志
|
||||
* <p>指示该值是否与其他值组合使用。</p>
|
||||
*
|
||||
* <p><b>取值说明:</b></p>
|
||||
* <ul>
|
||||
* <li>true - 组合值,需要与其他值一起解析</li>
|
||||
* <li>false - 独立值,可单独使用</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Builder.Default
|
||||
private boolean combined = false;
|
||||
|
||||
/**
|
||||
* 正则表达式模式
|
||||
* <p>用于对值内容进行正则匹配和替换。</p>
|
||||
*
|
||||
* <p><b>注意:</b>如果设置了此字段,将在值处理时应用正则替换</p>
|
||||
*/
|
||||
private String regexPattern;
|
||||
|
||||
/**
|
||||
* 正则替换字符串
|
||||
* <p>用于正则替换的目标字符串。</p>
|
||||
*
|
||||
* <p><b>格式说明:</b>支持正则表达式中的替换组引用,如$1、$2等</p>
|
||||
*/
|
||||
private String regexReplacement;
|
||||
|
||||
/**
|
||||
* 枚举映射配置
|
||||
* <p>用于将值映射到预定义的枚举值。</p>
|
||||
*
|
||||
* <p><b>格式说明:</b>key为原始值,value为映射后的值</p>
|
||||
*/
|
||||
private Map<String, String> enumMapping;
|
||||
|
||||
/**
|
||||
* 工具函数调用配置
|
||||
* <p>指定要调用的工具函数及其参数。</p>
|
||||
*
|
||||
* <p><b>格式说明:</b></p>
|
||||
* <ul>
|
||||
* <li>functionName - 函数名称</li>
|
||||
* <li>parameters - 函数参数列表</li>
|
||||
* </ul>
|
||||
*/
|
||||
private Map<String, Object> utilFunction;
|
||||
}
|
@ -0,0 +1,192 @@
|
||||
package com.example.demo.draft.demo043.domain;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 层级配置实体
|
||||
*
|
||||
* <p>表示配置中的一个层级节点,可以包含值配置和子层级,形成树状结构。</p>
|
||||
*
|
||||
* <p><b>典型应用场景:</b></p>
|
||||
* <ul>
|
||||
* <li>系统级配置(system)</li>
|
||||
* <li>数据库配置(database)</li>
|
||||
* <li>日志配置(logging)</li>
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* <h3>模板中的表现形式:</h3>
|
||||
* <pre>{@code
|
||||
* section param1 param2 # 层级备注
|
||||
* condition_value
|
||||
* values 100 ms 200 kb
|
||||
* end_section
|
||||
* }</pre>
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
public class LevelConfig {
|
||||
|
||||
/**
|
||||
* 层级名称
|
||||
* <p>标识当前配置层级的唯一名称,如"system"、"database"等。</p>
|
||||
*
|
||||
* <p>在模板中作为开始标签和结束标签的标识:</p>
|
||||
* <pre>{@code
|
||||
* {{ levelName }} ... end_{{ levelName }}
|
||||
* }</pre>
|
||||
*/
|
||||
private String levelName;
|
||||
|
||||
/**
|
||||
* 层级值循环索引号
|
||||
* <p>标识当前配置层级的索引,如"1"、"2"等。</p>
|
||||
*
|
||||
* <p>为空时,示例模板:</p>
|
||||
* <pre>{@code
|
||||
* {{ levelName }} param1 ... end_{{ levelName }}
|
||||
* }</pre>
|
||||
*
|
||||
* <p>不为空时,示例模板:</p>
|
||||
* <pre>{@code
|
||||
* {{ levelName }} param1_01 ... end_{{ levelName }}
|
||||
* }</pre>
|
||||
*/
|
||||
private String levelLoopIndex;
|
||||
|
||||
/**
|
||||
* 是否启用循环
|
||||
* <p>控制是否对当前层级进行循环处理。</p>
|
||||
*
|
||||
* <p><b>取值说明:</b></p>
|
||||
* <ul>
|
||||
* <li>true - 启用循环处理</li>
|
||||
* <li>false - 不启用循环处理(默认)</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Builder.Default
|
||||
private Boolean enableLevel = true;
|
||||
|
||||
/**
|
||||
* 层级值列表
|
||||
* <p>当前层级的主要配置值,如版本号、启用状态等。</p>
|
||||
*
|
||||
* <p>示例:</p>
|
||||
* <pre>{@code
|
||||
* Arrays.asList("param1", "param2", "param3")
|
||||
* }</pre>
|
||||
*/
|
||||
private List<String> values;
|
||||
|
||||
/**
|
||||
* 层级注释说明
|
||||
* <p>描述当前层级的用途、功能或注意事项。</p>
|
||||
*/
|
||||
private String comment;
|
||||
|
||||
/**
|
||||
* 条件类型
|
||||
* <p>引用conditionMap中的键,表示该层级的配置必要性。</p>
|
||||
*
|
||||
* @see ConfigDocument#getConditionMap()
|
||||
*
|
||||
* <p>示例模板:</p>
|
||||
* <pre>{@code
|
||||
* <p>xxx param1 # description</p>
|
||||
* <p> conditionType</p>
|
||||
* <p> key1 value1</p>
|
||||
* <p> key2 value2</p>
|
||||
* <p> key3 value3</p>
|
||||
* <p>end_xxx</p>
|
||||
* }</pre>
|
||||
*/
|
||||
private String conditionType;
|
||||
|
||||
/**
|
||||
* 值配置列表
|
||||
* <p>当前层级下的具体配置项集合。</p>
|
||||
*/
|
||||
private List<ValueConfig> valueConfigs;
|
||||
|
||||
/**
|
||||
* 子层级列表
|
||||
* <p>嵌套的子级配置,支持无限层级嵌套。</p>
|
||||
*/
|
||||
private List<LevelConfig> subLevels;
|
||||
|
||||
/**
|
||||
* 是否启用循环
|
||||
* <p>控制是否对当前层级进行循环处理。</p>
|
||||
*
|
||||
* <p><b>取值说明:</b></p>
|
||||
* <ul>
|
||||
* <li>true - 启用循环处理</li>
|
||||
* <li>false - 不启用循环处理(默认)</li>
|
||||
* </ul>
|
||||
*/
|
||||
private Boolean enableLoop = false;
|
||||
|
||||
/**
|
||||
* 循环次数
|
||||
* <p>指定循环处理的次数,当启用循环时有效。</p>
|
||||
*
|
||||
* <p><b>注意:</b>如果为null或小于等于0,则使用默认循环次数1</p>
|
||||
*/
|
||||
private String loopCount;
|
||||
|
||||
/**
|
||||
* 枚举映射配置
|
||||
* <p>用于将值映射到预定义的枚举值。</p>
|
||||
*
|
||||
* <p><b>格式说明:</b>key为原始值,value为映射后的值</p>
|
||||
*/
|
||||
private Map<String, String> enumMapping;
|
||||
|
||||
/**
|
||||
* 工具函数调用配置
|
||||
* <p>指定要调用的工具函数及其参数。</p>
|
||||
*
|
||||
* <p><b>格式说明:</b></p>
|
||||
* <ul>
|
||||
* <li>functionName - 函数名称</li>
|
||||
* <li>parameters - 函数参数列表</li>
|
||||
* </ul>
|
||||
*/
|
||||
private Map<String, Object> utilFunction;
|
||||
|
||||
public LevelConfig(
|
||||
String levelName,
|
||||
String levelLoopIndex,
|
||||
Boolean enableLevel,
|
||||
List<String> values,
|
||||
String comment,
|
||||
String conditionType,
|
||||
List<ValueConfig> valueConfigs,
|
||||
List<LevelConfig> subLevels,
|
||||
Boolean enableLoop,
|
||||
String loopCount,
|
||||
Map<String, String> enumMapping,
|
||||
Map<String, Object> utilFunction
|
||||
) {
|
||||
this.levelName = levelName;
|
||||
this.levelLoopIndex = levelLoopIndex;
|
||||
this.enableLevel = enableLevel;
|
||||
this.values = values;
|
||||
this.comment = comment;
|
||||
this.conditionType = conditionType;
|
||||
this.valueConfigs = valueConfigs;
|
||||
this.subLevels = subLevels;
|
||||
this.enableLoop = enableLoop;
|
||||
this.loopCount = loopCount;
|
||||
this.enumMapping = enumMapping;
|
||||
this.utilFunction = utilFunction;
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package com.example.demo.draft.demo043.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 值配置实体
|
||||
*
|
||||
* <p>表示具体的配置项,包含配置名称、值列表和注释信息。</p>
|
||||
*
|
||||
* <p><b>注意:</b>values字段可以包含不同类型的配置值,支持复杂配置场景。</p>
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ValueConfig {
|
||||
|
||||
/**
|
||||
* 值配置名称
|
||||
* <p>配置项的唯一标识,如"timeout"、"memory"等。</p>
|
||||
*/
|
||||
private String valueName;
|
||||
|
||||
/**
|
||||
* 配置值列表
|
||||
* <p>包含一个或多个配置值对象,支持多值配置。</p>
|
||||
*/
|
||||
private List<ConfigValue> values;
|
||||
|
||||
/**
|
||||
* 值配置注释
|
||||
* <p>描述该配置项的作用、取值范围或特殊说明。</p>
|
||||
*/
|
||||
private String comment;
|
||||
}
|
1432
src/main/java/com/example/demo/draft/demo043/util/FormatUtil.java
Normal file
1432
src/main/java/com/example/demo/draft/demo043/util/FormatUtil.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,245 @@
|
||||
//package com.example.demo.parser.controller;
|
||||
//
|
||||
//import com.example.demo.common.wrapper.WrapMapper;
|
||||
//import com.example.demo.common.wrapper.Wrapper;
|
||||
//import com.example.demo.common.exception.BusinessException;
|
||||
//import com.example.demo.common.utils.FileUtil;
|
||||
//import com.example.demo.common.utils.XmlParserUtil;
|
||||
//import com.example.demo.parser.entity.FileRecordEntity;
|
||||
//import com.example.demo.parser.model.dto.FileRecordDTO;
|
||||
//import com.example.demo.parser.model.vo.FileRecordVO;
|
||||
//import com.example.demo.parser.service.FileRecordService;
|
||||
//import com.mybatisflex.core.paginate.Page;
|
||||
//import io.swagger.v3.oas.annotations.Operation;
|
||||
//import io.swagger.v3.oas.annotations.Parameter;
|
||||
//import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
//import lombok.RequiredArgsConstructor;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.beans.factory.annotation.Value;
|
||||
//import org.springframework.web.bind.annotation.*;
|
||||
//import org.springframework.web.multipart.MultipartFile;
|
||||
//
|
||||
//import java.io.File;
|
||||
//import java.nio.file.Files;
|
||||
//import java.nio.file.Path;
|
||||
//import java.nio.file.Paths;
|
||||
//import java.time.LocalDateTime;
|
||||
//import java.util.List;
|
||||
//import java.util.UUID;
|
||||
//
|
||||
///**
|
||||
// * 文件解析控制器
|
||||
// * 提供文件上传、解析和转换的RESTful API接口
|
||||
// *
|
||||
// * @author system
|
||||
// * @version 1.0
|
||||
// */
|
||||
//@Slf4j
|
||||
//@RestController
|
||||
//@RequestMapping("/parser/files")
|
||||
//@RequiredArgsConstructor
|
||||
//@Tag(name = "文件解析管理", description = "提供XML文件上传、解析和转换的接口")
|
||||
//public class FileParserController {
|
||||
//
|
||||
// private final FileRecordService fileRecordService;
|
||||
//
|
||||
// @Value("${xml-parser.file.upload-dir:./upload}")
|
||||
// private String uploadDir;
|
||||
//
|
||||
// @Value("${xml-parser.file.temp-dir:./temp}")
|
||||
// private String tempDir;
|
||||
//
|
||||
// /**
|
||||
// * 上传XML文件
|
||||
// *
|
||||
// * @param file 上传的XML文件
|
||||
// * @return 操作结果
|
||||
// */
|
||||
// @PostMapping("/upload")
|
||||
// @Operation(summary = "上传XML文件", description = "上传XML文件并进行解析准备")
|
||||
// public Wrapper<FileRecordVO> uploadFile(
|
||||
// @Parameter(description = "XML文件", required = true)
|
||||
// @RequestParam("file") MultipartFile file) {
|
||||
// try {
|
||||
// // 验证文件类型
|
||||
// if (!isValidXmlFile(file)) {
|
||||
// return WrapMapper.fail("请上传有效的XML文件");
|
||||
// }
|
||||
//
|
||||
// // 创建上传目录
|
||||
// FileUtil.createDirectory(uploadDir);
|
||||
//
|
||||
// // 生成唯一文件名
|
||||
// String originalFilename = file.getOriginalFilename();
|
||||
// String uniqueFilename = FileUtil.generateUniqueFileName(originalFilename);
|
||||
// String filePath = Paths.get(uploadDir, uniqueFilename).toString();
|
||||
//
|
||||
// // 保存文件
|
||||
// file.transferTo(new File(filePath));
|
||||
//
|
||||
// // 创建文件记录
|
||||
// FileRecordDTO record = new FileRecordDTO();
|
||||
// record.setFileName(originalFilename);
|
||||
// record.setFilePath(filePath);
|
||||
// record.setFileSize(file.getSize());
|
||||
// record.setStatus("UPLOADED");
|
||||
// record.setProcessLog("文件上传成功");
|
||||
//
|
||||
// String recordId = fileRecordService.create(record);
|
||||
// FileRecordVO result = fileRecordService.getById(recordId);
|
||||
//
|
||||
// return WrapMapper.ok(result, "文件上传成功");
|
||||
// } catch (BusinessException e) {
|
||||
// log.error("文件上传失败: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail(e.getMessage());
|
||||
// } catch (Exception e) {
|
||||
// log.error("文件上传异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("文件上传失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 解析XML文件
|
||||
// *
|
||||
// * @param recordId 文件记录ID
|
||||
// * @return 操作结果
|
||||
// */
|
||||
// @PostMapping("/parse/{recordId}")
|
||||
// @Operation(summary = "解析XML文件", description = "解析已上传的XML文件")
|
||||
// public Wrapper<FileRecordVO> parseFile(
|
||||
// @Parameter(description = "文件记录ID", required = true)
|
||||
// @PathVariable String recordId) {
|
||||
// try {
|
||||
// FileRecordVO record = fileRecordService.getById(recordId);
|
||||
// if (record == null) {
|
||||
// return WrapMapper.fail("文件记录不存在");
|
||||
// }
|
||||
//
|
||||
// // 更新状态为解析中
|
||||
// fileRecordService.updateStatus(recordId, "PARSING", "开始解析XML文件");
|
||||
//
|
||||
// // 解析XML文件
|
||||
// String xmlFilePath = record.getFilePath();
|
||||
// String txtFilePath = generateTxtFilePath(xmlFilePath);
|
||||
//
|
||||
// try {
|
||||
// XmlParserUtil.parseXmlToTxt(xmlFilePath, txtFilePath);
|
||||
//
|
||||
// // 更新状态为解析成功
|
||||
// fileRecordService.updateStatus(recordId, "PARSED", "XML文件解析成功");
|
||||
//
|
||||
// FileRecordVO result = fileRecordService.getById(recordId);
|
||||
// return WrapMapper.ok(result, "XML文件解析成功");
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// // 更新状态为解析失败
|
||||
// fileRecordService.updateStatus(recordId, "PARSE_FAILED", "XML文件解析失败: " + e.getMessage());
|
||||
// throw new BusinessException("XML文件解析失败: " + e.getMessage());
|
||||
// }
|
||||
//
|
||||
// } catch (BusinessException e) {
|
||||
// log.error("文件解析失败: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail(e.getMessage());
|
||||
// } catch (Exception e) {
|
||||
// log.error("文件解析异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("文件解析失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 获取文件记录详情
|
||||
// *
|
||||
// * @param recordId 文件记录ID
|
||||
// * @return 文件记录详情
|
||||
// */
|
||||
// @GetMapping("/{recordId}")
|
||||
// @Operation(summary = "获取文件记录详情", description = "根据ID获取文件记录的详细信息")
|
||||
// public Wrapper<FileRecordVO> getFileRecord(
|
||||
// @Parameter(description = "文件记录ID", required = true)
|
||||
// @PathVariable String recordId) {
|
||||
// try {
|
||||
// FileRecordVO result = fileRecordService.getById(recordId);
|
||||
// return WrapMapper.ok(result, "获取文件记录详情成功");
|
||||
// } catch (BusinessException e) {
|
||||
// log.error("获取文件记录详情失败: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail(e.getMessage());
|
||||
// } catch (Exception e) {
|
||||
// log.error("获取文件记录详情异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("获取文件记录详情失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 分页查询文件记录列表
|
||||
// *
|
||||
// * @param pageNumber 页码
|
||||
// * @param pageSize 每页大小
|
||||
// * @return 分页结果
|
||||
// */
|
||||
// @GetMapping("/page")
|
||||
// @Operation(summary = "分页查询文件记录", description = "分页查询文件记录列表")
|
||||
// public Wrapper<Page<FileRecordVO>> pageList(
|
||||
// @Parameter(description = "页码", example = "1")
|
||||
// @RequestParam(defaultValue = "1") Integer pageNumber,
|
||||
// @Parameter(description = "每页大小", example = "10")
|
||||
// @RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
// try {
|
||||
// Page<FileRecordVO> result = fileRecordService.pageList(pageNumber, pageSize);
|
||||
// return WrapMapper.ok(result, "查询文件记录列表成功");
|
||||
// } catch (Exception e) {
|
||||
// log.error("查询文件记录列表异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("查询文件记录列表失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 获取所有文件记录列表
|
||||
// *
|
||||
// * @return 文件记录列表
|
||||
// */
|
||||
// @GetMapping("/list")
|
||||
// @Operation(summary = "获取所有文件记录", description = "获取所有文件记录的列表")
|
||||
// public Wrapper<List<FileRecordVO>> listAll() {
|
||||
// try {
|
||||
// List<FileRecordVO> result = fileRecordService.listAll();
|
||||
// return WrapMapper.ok(result, "获取所有文件记录成功");
|
||||
// } catch (Exception e) {
|
||||
// log.error("获取所有文件记录异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("获取所有文件记录失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 验证是否为有效的XML文件
|
||||
// *
|
||||
// * @param file 上传的文件
|
||||
// * @return 是否有效
|
||||
// */
|
||||
// private boolean isValidXmlFile(MultipartFile file) {
|
||||
// if (file == null || file.isEmpty()) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// String originalFilename = file.getOriginalFilename();
|
||||
// if (originalFilename == null) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// // 检查文件扩展名
|
||||
// String extension = FileUtil.getFileExtension(originalFilename);
|
||||
// return "xml".equalsIgnoreCase(extension);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 生成TXT文件路径
|
||||
// *
|
||||
// * @param xmlFilePath XML文件路径
|
||||
// * @return TXT文件路径
|
||||
// */
|
||||
// private String generateTxtFilePath(String xmlFilePath) {
|
||||
// Path xmlPath = Paths.get(xmlFilePath);
|
||||
// String xmlFileName = xmlPath.getFileName().toString();
|
||||
// String txtFileName = xmlFileName.replace(".xml", ".txt");
|
||||
// return xmlPath.getParent().resolve(txtFileName).toString();
|
||||
// }
|
||||
//}
|
@ -0,0 +1,188 @@
|
||||
//package com.example.demo.parser.controller;
|
||||
//
|
||||
//import com.example.demo.common.exception.BusinessException;
|
||||
//import com.example.demo.common.wrapper.WrapMapper;
|
||||
//import com.example.demo.common.wrapper.Wrapper;
|
||||
//import com.example.demo.parser.model.dto.MapperRuleDTO;
|
||||
//import com.example.demo.parser.model.vo.MapperRuleVO;
|
||||
//import com.example.demo.parser.service.MapperRuleService;
|
||||
//import com.mybatisflex.core.paginate.Page;
|
||||
//import io.swagger.v3.oas.annotations.Operation;
|
||||
//import io.swagger.v3.oas.annotations.Parameter;
|
||||
//import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
//import jakarta.validation.Valid;
|
||||
//import lombok.RequiredArgsConstructor;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.validation.annotation.Validated;
|
||||
//import org.springframework.web.bind.annotation.*;
|
||||
//
|
||||
//import java.util.List;
|
||||
//
|
||||
///**
|
||||
// * 映射规则控制器
|
||||
// * 提供映射规则的RESTful API接口
|
||||
// *
|
||||
// * @author system
|
||||
// * @version 1.0
|
||||
// */
|
||||
//@Slf4j
|
||||
//@RestController
|
||||
//@RequestMapping("/parser/mapper-rules")
|
||||
//@RequiredArgsConstructor
|
||||
//@Validated
|
||||
//@Tag(name = "映射规则管理", description = "提供XML到TXT映射规则的增删改查接口")
|
||||
//public class MapperRuleController {
|
||||
//
|
||||
// private final MapperRuleService mapperRuleService;
|
||||
//
|
||||
// /**
|
||||
// * 创建映射规则
|
||||
// *
|
||||
// * @param dto 映射规则数据传输对象
|
||||
// * @return 操作结果
|
||||
// */
|
||||
// @PostMapping
|
||||
// @Operation(summary = "创建映射规则", description = "创建新的XML到TXT映射规则")
|
||||
// public Wrapper<String> create(@Valid @RequestBody MapperRuleDTO dto) {
|
||||
// try {
|
||||
// String id = mapperRuleService.create(dto);
|
||||
// return WrapMapper.ok(id, "创建映射规则成功");
|
||||
// } catch (BusinessException e) {
|
||||
// log.error("创建映射规则失败: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail(e.getMessage());
|
||||
// } catch (Exception e) {
|
||||
// log.error("创建映射规则异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("创建映射规则失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 删除映射规则
|
||||
// *
|
||||
// * @param id 映射规则ID
|
||||
// * @return 操作结果
|
||||
// */
|
||||
// @DeleteMapping("/{id}")
|
||||
// @Operation(summary = "删除映射规则", description = "根据ID删除映射规则")
|
||||
// public Wrapper<Boolean> delete(
|
||||
// @Parameter(description = "映射规则ID", required = true)
|
||||
// @PathVariable String id) {
|
||||
// try {
|
||||
// boolean result = mapperRuleService.delete(id);
|
||||
// return WrapMapper.ok(result, "删除映射规则成功");
|
||||
// } catch (BusinessException e) {
|
||||
// log.error("删除映射规则失败: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail(e.getMessage());
|
||||
// } catch (Exception e) {
|
||||
// log.error("删除映射规则异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("删除映射规则失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 更新映射规则
|
||||
// *
|
||||
// * @param dto 映射规则数据传输对象
|
||||
// * @return 操作结果
|
||||
// */
|
||||
// @PutMapping
|
||||
// @Operation(summary = "更新映射规则", description = "更新现有的映射规则")
|
||||
// public Wrapper<Boolean> update(@Valid @RequestBody MapperRuleDTO dto) {
|
||||
// try {
|
||||
// boolean result = mapperRuleService.update(dto);
|
||||
// return WrapMapper.ok(result, "更新映射规则成功");
|
||||
// } catch (BusinessException e) {
|
||||
// log.error("更新映射规则失败: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail(e.getMessage());
|
||||
// } catch (Exception e) {
|
||||
// log.error("更新映射规则异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("更新映射规则失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 根据ID获取映射规则详情
|
||||
// *
|
||||
// * @param id 映射规则ID
|
||||
// * @return 映射规则详情
|
||||
// */
|
||||
// @GetMapping("/{id}")
|
||||
// @Operation(summary = "获取映射规则详情", description = "根据ID获取映射规则的详细信息")
|
||||
// public Wrapper<MapperRuleVO> getById(
|
||||
// @Parameter(description = "映射规则ID", required = true)
|
||||
// @PathVariable String id) {
|
||||
// try {
|
||||
// MapperRuleVO result = mapperRuleService.getById(id);
|
||||
// return WrapMapper.ok(result, "获取映射规则详情成功");
|
||||
// } catch (BusinessException e) {
|
||||
// log.error("获取映射规则详情失败: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail(e.getMessage());
|
||||
// } catch (Exception e) {
|
||||
// log.error("获取映射规则详情异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("获取映射规则详情失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 分页查询映射规则列表
|
||||
// *
|
||||
// * @param pageNumber 页码
|
||||
// * @param pageSize 每页大小
|
||||
// * @return 分页结果
|
||||
// */
|
||||
// @GetMapping("/page")
|
||||
// @Operation(summary = "分页查询映射规则", description = "分页查询映射规则列表")
|
||||
// public Wrapper<Page<MapperRuleVO>> pageList(
|
||||
// @Parameter(description = "页码", example = "1")
|
||||
// @RequestParam(defaultValue = "1") Integer pageNumber,
|
||||
// @Parameter(description = "每页大小", example = "10")
|
||||
// @RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
// try {
|
||||
// Page<MapperRuleVO> result = mapperRuleService.pageList(pageNumber, pageSize);
|
||||
// return WrapMapper.ok(result, "查询映射规则列表成功");
|
||||
// } catch (Exception e) {
|
||||
// log.error("查询映射规则列表异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("查询映射规则列表失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 根据解析规则ID获取映射规则列表
|
||||
// *
|
||||
// * @param parseRuleId 解析规则ID
|
||||
// * @return 映射规则列表
|
||||
// */
|
||||
// @GetMapping("/by-parse-rule/{parseRuleId}")
|
||||
// @Operation(summary = "根据解析规则获取映射规则", description = "根据解析规则ID获取对应的映射规则列表")
|
||||
// public Wrapper<List<MapperRuleVO>> getByParseRuleId(
|
||||
// @Parameter(description = "解析规则ID", required = true)
|
||||
// @PathVariable String parseRuleId) {
|
||||
// try {
|
||||
// List<MapperRuleVO> result = mapperRuleService.getByParseRuleId(parseRuleId);
|
||||
// return WrapMapper.ok(result, "根据解析规则获取映射规则成功");
|
||||
// } catch (BusinessException e) {
|
||||
// log.error("根据解析规则获取映射规则失败: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail(e.getMessage());
|
||||
// } catch (Exception e) {
|
||||
// log.error("根据解析规则获取映射规则异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("根据解析规则获取映射规则失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 获取所有映射规则列表
|
||||
// *
|
||||
// * @return 映射规则列表
|
||||
// */
|
||||
// @GetMapping("/list")
|
||||
// @Operation(summary = "获取所有映射规则", description = "获取所有映射规则的列表")
|
||||
// public Wrapper<List<MapperRuleVO>> listAll() {
|
||||
// try {
|
||||
// List<MapperRuleVO> result = mapperRuleService.listAll();
|
||||
// return WrapMapper.ok(result, "获取所有映射规则成功");
|
||||
// } catch (Exception e) {
|
||||
// log.error("获取所有映射规则异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("获取所有映射规则失败");
|
||||
// }
|
||||
// }
|
||||
//}
|
@ -0,0 +1,188 @@
|
||||
//package com.example.demo.parser.controller;
|
||||
//
|
||||
//import cn.zhxu.bs.SearchResult;
|
||||
//import com.example.demo.common.exception.BusinessException;
|
||||
//import com.example.demo.common.wrapper.WrapMapper;
|
||||
//import com.example.demo.common.wrapper.Wrapper;
|
||||
//import com.example.demo.parser.entity.ParseRuleEntity;
|
||||
//import com.example.demo.parser.model.dto.ParseRuleDTO;
|
||||
//import com.example.demo.parser.model.vo.ParseRuleVO;
|
||||
//import com.example.demo.parser.service.ParseRuleService;
|
||||
//import com.mybatisflex.core.paginate.Page;
|
||||
//import io.swagger.v3.oas.annotations.Operation;
|
||||
//import io.swagger.v3.oas.annotations.Parameter;
|
||||
//import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
//import jakarta.validation.Valid;
|
||||
//import lombok.RequiredArgsConstructor;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.validation.annotation.Validated;
|
||||
//import org.springframework.web.bind.annotation.*;
|
||||
//
|
||||
//import java.util.List;
|
||||
//
|
||||
///**
|
||||
// * 解析规则控制器
|
||||
// * 提供解析规则的RESTful API接口
|
||||
// *
|
||||
// * @author system
|
||||
// * @version 1.0
|
||||
// */
|
||||
//@Slf4j
|
||||
//@RestController
|
||||
//@RequestMapping("/parser/parse-rules")
|
||||
//@RequiredArgsConstructor
|
||||
//@Validated
|
||||
//@Tag(name = "解析规则管理", description = "提供XML解析规则的增删改查接口")
|
||||
//public class ParseRuleController {
|
||||
//
|
||||
// private final ParseRuleService parseRuleService;
|
||||
//
|
||||
// /**
|
||||
// * 创建解析规则
|
||||
// *
|
||||
// * @param dto 解析规则数据传输对象
|
||||
// * @return 操作结果
|
||||
// */
|
||||
// @PostMapping
|
||||
// @Operation(summary = "创建解析规则", description = "创建新的XML解析规则")
|
||||
// public Wrapper<String> create(@Valid @RequestBody ParseRuleDTO dto) {
|
||||
// try {
|
||||
// String id = parseRuleService.create(dto);
|
||||
// return WrapMapper.ok(id, "创建解析规则成功");
|
||||
// } catch (BusinessException e) {
|
||||
// log.error("创建解析规则失败: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail(e.getMessage());
|
||||
// } catch (Exception e) {
|
||||
// log.error("创建解析规则异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("创建解析规则失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 删除解析规则
|
||||
// *
|
||||
// * @param id 解析规则ID
|
||||
// * @return 操作结果
|
||||
// */
|
||||
// @DeleteMapping("/{id}")
|
||||
// @Operation(summary = "删除解析规则", description = "根据ID删除解析规则")
|
||||
// public Wrapper<Boolean> delete(
|
||||
// @Parameter(description = "解析规则ID", required = true)
|
||||
// @PathVariable String id) {
|
||||
// try {
|
||||
// boolean result = parseRuleService.delete(id);
|
||||
// return WrapMapper.ok(result, "删除解析规则成功");
|
||||
// } catch (BusinessException e) {
|
||||
// log.error("删除解析规则失败: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail(e.getMessage());
|
||||
// } catch (Exception e) {
|
||||
// log.error("删除解析规则异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("删除解析规则失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 更新解析规则
|
||||
// *
|
||||
// * @param dto 解析规则数据传输对象
|
||||
// * @return 操作结果
|
||||
// */
|
||||
// @PutMapping
|
||||
// @Operation(summary = "更新解析规则", description = "更新现有的解析规则")
|
||||
// public Wrapper<Boolean> update(@Valid @RequestBody ParseRuleDTO dto) {
|
||||
// try {
|
||||
// boolean result = parseRuleService.update(dto);
|
||||
// return WrapMapper.ok(result, "更新解析规则成功");
|
||||
// } catch (BusinessException e) {
|
||||
// log.error("更新解析规则失败: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail(e.getMessage());
|
||||
// } catch (Exception e) {
|
||||
// log.error("更新解析规则异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("更新解析规则失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 根据ID获取解析规则详情
|
||||
// *
|
||||
// * @param id 解析规则ID
|
||||
// * @return 解析规则详情
|
||||
// */
|
||||
// @GetMapping("/{id}")
|
||||
// @Operation(summary = "获取解析规则详情", description = "根据ID获取解析规则的详细信息")
|
||||
// public Wrapper<ParseRuleVO> getById(
|
||||
// @Parameter(description = "解析规则ID", required = true)
|
||||
// @PathVariable String id) {
|
||||
// try {
|
||||
// ParseRuleVO result = parseRuleService.getById(id);
|
||||
// return WrapMapper.ok(result, "获取解析规则详情成功");
|
||||
// } catch (BusinessException e) {
|
||||
// log.error("获取解析规则详情失败: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail(e.getMessage());
|
||||
// } catch (Exception e) {
|
||||
// log.error("获取解析规则详情异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("获取解析规则详情失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 分页查询解析规则列表
|
||||
// *
|
||||
// * @param pageNumber 页码
|
||||
// * @param pageSize 每页大小
|
||||
// * @return 分页结果
|
||||
// */
|
||||
// @GetMapping("/page")
|
||||
// @Operation(summary = "分页查询解析规则", description = "分页查询解析规则列表")
|
||||
// public Wrapper<Page<ParseRuleVO>> pageList(
|
||||
// @Parameter(description = "页码", example = "1")
|
||||
// @RequestParam(defaultValue = "1") Integer pageNumber,
|
||||
// @Parameter(description = "每页大小", example = "10")
|
||||
// @RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
// try {
|
||||
// Page<ParseRuleVO> result = parseRuleService.pageList(pageNumber, pageSize);
|
||||
// return WrapMapper.ok(result, "查询解析规则列表成功");
|
||||
// } catch (Exception e) {
|
||||
// log.error("查询解析规则列表异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("查询解析规则列表失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 获取所有解析规则列表
|
||||
// *
|
||||
// * @return 解析规则列表
|
||||
// */
|
||||
// @GetMapping("/list")
|
||||
// @Operation(summary = "获取所有解析规则", description = "获取所有解析规则的列表")
|
||||
// public Wrapper<List<ParseRuleVO>> listAll() {
|
||||
// try {
|
||||
// List<ParseRuleVO> result = parseRuleService.listAll();
|
||||
// return WrapMapper.ok(result, "获取所有解析规则成功");
|
||||
// } catch (Exception e) {
|
||||
// log.error("获取所有解析规则异常: {}", e.getMessage(), e);
|
||||
// return WrapMapper.fail("获取所有解析规则失败");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 根据XML标签名获取解析规则详情
|
||||
// *
|
||||
// * @param xmlTag XML标签名
|
||||
// * @return 解析规则详情
|
||||
// */
|
||||
// @GetMapping("/by-xml-tag/{xmlTag}")
|
||||
// @Operation(summary = "根据XML标签名获取解析规则详情")
|
||||
// public Wrapper<ParseRuleVO> getByXmlTag(@PathVariable String xmlTag) {
|
||||
// log.info("根据XML标签名获取解析规则详情: {}", xmlTag);
|
||||
//
|
||||
// ParseRuleEntity entity = parseRuleService.getByXmlTag(xmlTag);
|
||||
// if (entity == null) {
|
||||
// return WrapMapper.fail("解析规则不存在: " + xmlTag);
|
||||
// }
|
||||
//
|
||||
// // 通过getById方法获取VO对象
|
||||
// ParseRuleVO result = parseRuleService.getById(entity.getId());
|
||||
// return WrapMapper.ok(result);
|
||||
// }
|
||||
//}
|
@ -0,0 +1,97 @@
|
||||
package com.example.demo.parser.entity;
|
||||
|
||||
import com.example.demo.common.domain.BaseEntity;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 文件记录实体类
|
||||
* 对应数据库中的file_record表,用于存储文件上传、解析、转换等操作记录
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Schema(description = "文件记录")
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("file_record")
|
||||
public class FileRecordEntity extends BaseEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
@Schema(description = "文件名")
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 文件路径
|
||||
*/
|
||||
@Schema(description = "文件路径")
|
||||
private String filePath;
|
||||
|
||||
/**
|
||||
* 文件大小
|
||||
*/
|
||||
@Schema(description = "文件大小")
|
||||
private Long fileSize;
|
||||
|
||||
/**
|
||||
* 文件类型:xml, txt
|
||||
*/
|
||||
@Schema(description = "文件类型")
|
||||
private String fileType;
|
||||
|
||||
/**
|
||||
* 文件状态:uploaded, parsed, converted
|
||||
*/
|
||||
@Schema(description = "文件状态")
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 上传时间
|
||||
*/
|
||||
@Schema(description = "上传时间")
|
||||
private Date uploadTime;
|
||||
|
||||
/**
|
||||
* 处理时间
|
||||
*/
|
||||
@Schema(description = "处理时间")
|
||||
private Date processTime;
|
||||
|
||||
/**
|
||||
* 处理日志
|
||||
*/
|
||||
@Schema(description = "处理日志")
|
||||
private String processLog;
|
||||
|
||||
/**
|
||||
* 处理结果文件ID
|
||||
*/
|
||||
@Schema(description = "处理结果文件ID")
|
||||
private Long resultFileId;
|
||||
|
||||
/**
|
||||
* 关联的解析规则ID
|
||||
*/
|
||||
@Schema(description = "关联的解析规则ID")
|
||||
private Long parseRuleId;
|
||||
|
||||
/**
|
||||
* 关联的映射规则ID
|
||||
*/
|
||||
@Schema(description = "关联的映射规则ID")
|
||||
private Long mapperRuleId;
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package com.example.demo.parser.entity;
|
||||
|
||||
import com.example.demo.common.domain.BaseEntity;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 映射规则实体类
|
||||
* 对应数据库中的mapper_rule表,用于存储XML到TXT的映射规则
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Schema(description = "映射规则")
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("mapper_rule")
|
||||
public class MapperRuleEntity extends BaseEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 关联的解析规则ID
|
||||
*/
|
||||
@Schema(description = "关联的解析规则ID")
|
||||
private String parseRuleId;
|
||||
|
||||
/**
|
||||
* TXT文件中的键名
|
||||
*/
|
||||
@Schema(description = "TXT文件中的键名")
|
||||
private String txtKey;
|
||||
|
||||
/**
|
||||
* 转换模板
|
||||
*/
|
||||
@Schema(description = "转换模板")
|
||||
private String template;
|
||||
|
||||
/**
|
||||
* 父级键名
|
||||
*/
|
||||
@Schema(description = "父级键名")
|
||||
private String parentKey;
|
||||
|
||||
/**
|
||||
* 排序顺序
|
||||
*/
|
||||
@Schema(description = "排序顺序")
|
||||
private Integer sortOrder;
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
package com.example.demo.parser.entity;
|
||||
|
||||
import com.example.demo.common.domain.BaseEntity;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 解析规则实体类
|
||||
* 对应数据库中的parse_rule表,用于存储XML解析规则
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Schema(description = "解析规则")
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("parse_rule")
|
||||
public class ParseRuleEntity extends BaseEntity {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* XML标签名
|
||||
*/
|
||||
@Schema(description = "XML标签名")
|
||||
private String xmlTag;
|
||||
|
||||
/**
|
||||
* 标签类型:root, node, leaf
|
||||
*/
|
||||
@Schema(description = "标签类型")
|
||||
private String tagType;
|
||||
|
||||
/**
|
||||
* 是否允许为空:0-不允许,1-允许
|
||||
*/
|
||||
@Schema(description = "是否允许为空")
|
||||
private String isNull;
|
||||
|
||||
/**
|
||||
* 节点路径
|
||||
*/
|
||||
@Schema(description = "节点路径")
|
||||
private String nodePath;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.example.demo.parser.mapper;
|
||||
|
||||
import com.example.demo.parser.entity.FileRecordEntity;
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 文件记录Mapper接口
|
||||
* 用于文件记录的数据库操作
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Mapper
|
||||
public interface FileRecordMapper extends BaseMapper<FileRecordEntity> {
|
||||
|
||||
// 可以添加自定义的SQL方法
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.example.demo.parser.mapper;
|
||||
|
||||
import com.example.demo.parser.entity.MapperRuleEntity;
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 映射规则Mapper接口
|
||||
* 用于映射规则的数据库操作
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Mapper
|
||||
public interface MapperRuleMapper extends BaseMapper<MapperRuleEntity> {
|
||||
|
||||
// 可以添加自定义的SQL方法
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.example.demo.parser.mapper;
|
||||
|
||||
import com.example.demo.parser.entity.ParseRuleEntity;
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 解析规则Mapper接口
|
||||
* 用于解析规则的数据库操作
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Mapper
|
||||
public interface ParseRuleMapper extends BaseMapper<ParseRuleEntity> {
|
||||
|
||||
// 可以添加自定义的SQL方法
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
package com.example.demo.parser.model.dto;
|
||||
|
||||
import cn.zhxu.bs.bean.DbField;
|
||||
import com.example.demo.common.domain.BaseDTO;
|
||||
import com.example.demo.common.domain.BaseQueryDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 文件记录查询数据传输对象
|
||||
* 用于映射规则的创建和更新操作
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class FileRecordDTO extends BaseDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 文件名,模糊查询
|
||||
*/
|
||||
@Schema(description = "文件名")
|
||||
@DbField(value = "file_name")
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 文件路径,模糊查询
|
||||
*/
|
||||
@Schema(description = "文件路径")
|
||||
@DbField(value = "file_path")
|
||||
private String filePath;
|
||||
|
||||
/**
|
||||
* 文件大小开始值
|
||||
*/
|
||||
@Schema(description = "文件大小开始值")
|
||||
@DbField(value = "file_size")
|
||||
private Long fileSizeStart;
|
||||
|
||||
/**
|
||||
* 文件大小结束值
|
||||
*/
|
||||
@Schema(description = "文件大小结束值")
|
||||
@DbField(value = "file_size")
|
||||
private Long fileSizeEnd;
|
||||
|
||||
/**
|
||||
* 文件类型
|
||||
*/
|
||||
@Schema(description = "文件类型")
|
||||
@DbField("file_type")
|
||||
private String fileType;
|
||||
|
||||
/**
|
||||
* 文件状态
|
||||
*/
|
||||
@Schema(description = "文件状态")
|
||||
@DbField("status")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 上传时间开始
|
||||
*/
|
||||
@Schema(description = "上传时间开始")
|
||||
@DbField(value = "upload_time")
|
||||
private Date uploadTimeStart;
|
||||
|
||||
/**
|
||||
* 上传时间结束
|
||||
*/
|
||||
@Schema(description = "上传时间结束")
|
||||
@DbField(value = "upload_time")
|
||||
private Date uploadTimeEnd;
|
||||
|
||||
/**
|
||||
* 处理时间开始
|
||||
*/
|
||||
@Schema(description = "处理时间开始")
|
||||
@DbField(value = "process_time")
|
||||
private Date processTimeStart;
|
||||
|
||||
/**
|
||||
* 处理时间结束
|
||||
*/
|
||||
@Schema(description = "处理时间结束")
|
||||
@DbField(value = "process_time")
|
||||
private Date processTimeEnd;
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package com.example.demo.parser.model.dto;
|
||||
|
||||
import cn.zhxu.bs.bean.DbField;
|
||||
import com.example.demo.common.domain.BaseQueryDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 文件记录查询数据传输对象
|
||||
* 用于封装文件记录的查询条件
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class FileRecordQueryDTO extends BaseQueryDTO {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 文件名,模糊查询
|
||||
*/
|
||||
@Schema(description = "文件名")
|
||||
@DbField(value = "file_name")
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 文件路径,模糊查询
|
||||
*/
|
||||
@Schema(description = "文件路径")
|
||||
@DbField(value = "file_path")
|
||||
private String filePath;
|
||||
|
||||
/**
|
||||
* 文件大小开始值
|
||||
*/
|
||||
@Schema(description = "文件大小开始值")
|
||||
@DbField(value = "file_size")
|
||||
private Long fileSizeStart;
|
||||
|
||||
/**
|
||||
* 文件大小结束值
|
||||
*/
|
||||
@Schema(description = "文件大小结束值")
|
||||
@DbField(value = "file_size")
|
||||
private Long fileSizeEnd;
|
||||
|
||||
/**
|
||||
* 文件类型
|
||||
*/
|
||||
@Schema(description = "文件类型")
|
||||
@DbField("file_type")
|
||||
private String fileType;
|
||||
|
||||
/**
|
||||
* 文件状态
|
||||
*/
|
||||
@Schema(description = "文件状态")
|
||||
@DbField("status")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 上传时间开始
|
||||
*/
|
||||
@Schema(description = "上传时间开始")
|
||||
@DbField(value = "upload_time")
|
||||
private Date uploadTimeStart;
|
||||
|
||||
/**
|
||||
* 上传时间结束
|
||||
*/
|
||||
@Schema(description = "上传时间结束")
|
||||
@DbField(value = "upload_time")
|
||||
private Date uploadTimeEnd;
|
||||
|
||||
/**
|
||||
* 处理时间开始
|
||||
*/
|
||||
@Schema(description = "处理时间开始")
|
||||
@DbField(value = "process_time")
|
||||
private Date processTimeStart;
|
||||
|
||||
/**
|
||||
* 处理时间结束
|
||||
*/
|
||||
@Schema(description = "处理时间结束")
|
||||
@DbField(value = "process_time")
|
||||
private Date processTimeEnd;
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
package com.example.demo.parser.model.dto;
|
||||
|
||||
import com.example.demo.common.domain.BaseDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 映射规则数据传输对象
|
||||
* 用于映射规则的创建和更新操作
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Schema(description = "映射规则数据传输对象")
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class MapperRuleDTO extends BaseDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 关联的解析规则ID
|
||||
*/
|
||||
@NotBlank(message = "关联的解析规则ID不能为空")
|
||||
@Schema(description = "关联的解析规则ID")
|
||||
private String parseRuleId;
|
||||
|
||||
/**
|
||||
* TXT文件中的键名
|
||||
*/
|
||||
@NotBlank(message = "TXT文件中的键名不能为空")
|
||||
@Size(max = 100, message = "TXT文件中的键名不能超过100个字符")
|
||||
@Schema(description = "TXT文件中的键名")
|
||||
private String txtKey;
|
||||
|
||||
/**
|
||||
* 转换模板
|
||||
*/
|
||||
@Size(max = 255, message = "转换模板不能超过255个字符")
|
||||
@Schema(description = "转换模板")
|
||||
private String template;
|
||||
|
||||
/**
|
||||
* 父级键名
|
||||
*/
|
||||
@Size(max = 100, message = "父级键名不能超过100个字符")
|
||||
@Schema(description = "父级键名")
|
||||
private String parentKey;
|
||||
|
||||
/**
|
||||
* 排序顺序
|
||||
*/
|
||||
@NotNull(message = "排序顺序不能为空")
|
||||
@Schema(description = "排序顺序")
|
||||
private Integer sortOrder;
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package com.example.demo.parser.model.dto;
|
||||
|
||||
import com.example.demo.common.domain.BaseQueryDTO;
|
||||
import cn.zhxu.bs.bean.DbField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 映射规则查询数据传输对象
|
||||
* 用于封装映射规则的查询条件
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Schema(description = "映射规则查询数据传输对象")
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class MapperRuleQueryDTO extends BaseQueryDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 关联的解析规则ID
|
||||
*/
|
||||
@DbField("parse_rule_id")
|
||||
@Schema(description = "关联的解析规则ID")
|
||||
private String parseRuleId;
|
||||
|
||||
/**
|
||||
* TXT文件中的键名
|
||||
*/
|
||||
@DbField("txt_key")
|
||||
@Schema(description = "TXT文件中的键名")
|
||||
private String txtKey;
|
||||
|
||||
/**
|
||||
* 父级键名
|
||||
*/
|
||||
@DbField("parent_key")
|
||||
@Schema(description = "父级键名")
|
||||
private String parentKey;
|
||||
|
||||
/**
|
||||
* 排序顺序开始
|
||||
*/
|
||||
@DbField("sort_order")
|
||||
@Schema(description = "排序顺序开始")
|
||||
private Integer sortOrderStart;
|
||||
|
||||
/**
|
||||
* 排序顺序结束
|
||||
*/
|
||||
@DbField("sort_order")
|
||||
@Schema(description = "排序顺序结束")
|
||||
private Integer sortOrderEnd;
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.example.demo.parser.model.dto;
|
||||
|
||||
import com.example.demo.common.domain.BaseDTO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 解析规则数据传输对象
|
||||
* 用于解析规则的创建和更新操作
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Schema(description = "解析规则数据传输对象")
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ParseRuleDTO extends BaseDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* XML标签名
|
||||
*/
|
||||
@NotBlank(message = "XML标签名不能为空")
|
||||
@Size(max = 100, message = "XML标签名不能超过100个字符")
|
||||
@Schema(description = "XML标签名")
|
||||
private String xmlTag;
|
||||
|
||||
/**
|
||||
* 标签类型:root, node, leaf
|
||||
*/
|
||||
@NotBlank(message = "标签类型不能为空")
|
||||
@Size(max = 20, message = "标签类型不能超过20个字符")
|
||||
@Schema(description = "标签类型")
|
||||
private String tagType;
|
||||
|
||||
/**
|
||||
* 是否允许为空:0-不允许,1-允许
|
||||
*/
|
||||
@Size(max = 1, message = "是否允许为空不能超过1个字符")
|
||||
@Schema(description = "是否允许为空")
|
||||
private String isNull;
|
||||
|
||||
/**
|
||||
* 节点路径
|
||||
*/
|
||||
@Size(max = 255, message = "节点路径不能超过255个字符")
|
||||
@Schema(description = "节点路径")
|
||||
private String nodePath;
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.example.demo.parser.model.dto;
|
||||
|
||||
import com.example.demo.common.domain.BaseQueryDTO;
|
||||
import cn.zhxu.bs.bean.DbField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 解析规则查询数据传输对象
|
||||
* 用于封装解析规则的查询条件
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Schema(description = "解析规则查询数据传输对象")
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class ParseRuleQueryDTO extends BaseQueryDTO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* XML标签名
|
||||
*/
|
||||
@DbField("xml_tag")
|
||||
@Schema(description = "XML标签名")
|
||||
private String xmlTag;
|
||||
|
||||
/**
|
||||
* 标签类型
|
||||
*/
|
||||
@DbField("tag_type")
|
||||
@Schema(description = "标签类型")
|
||||
private String tagType;
|
||||
|
||||
/**
|
||||
* 是否允许为空
|
||||
*/
|
||||
@DbField("is_null")
|
||||
@Schema(description = "是否允许为空")
|
||||
private String isNull;
|
||||
|
||||
/**
|
||||
* 节点路径
|
||||
*/
|
||||
@DbField("node_path")
|
||||
@Schema(description = "节点路径")
|
||||
private String nodePath;
|
||||
}
|
106
src/main/java/com/example/demo/parser/model/vo/FileRecordVO.java
Normal file
106
src/main/java/com/example/demo/parser/model/vo/FileRecordVO.java
Normal file
@ -0,0 +1,106 @@
|
||||
package com.example.demo.parser.model.vo;
|
||||
|
||||
import com.example.demo.common.domain.BaseVO;
|
||||
import cn.zhxu.bs.bean.SearchBean;
|
||||
import com.fhs.core.trans.vo.TransPojo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 文件记录视图对象
|
||||
* 用于向前端返回文件记录数据
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Schema(description = "文件记录视图对象")
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@SearchBean(
|
||||
tables = "file_record",
|
||||
autoMapTo = "a"
|
||||
)
|
||||
public class FileRecordVO extends BaseVO implements TransPojo, Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 文件名
|
||||
*/
|
||||
@Schema(description = "文件名")
|
||||
private String fileName;
|
||||
|
||||
/**
|
||||
* 文件路径
|
||||
*/
|
||||
@Schema(description = "文件路径")
|
||||
private String filePath;
|
||||
|
||||
/**
|
||||
* 文件大小
|
||||
*/
|
||||
@Schema(description = "文件大小")
|
||||
private Long fileSize;
|
||||
|
||||
/**
|
||||
* 文件类型:xml, txt
|
||||
*/
|
||||
@Schema(description = "文件类型")
|
||||
private String fileType;
|
||||
|
||||
/**
|
||||
* 文件状态:uploaded, parsed, converted
|
||||
*/
|
||||
@Schema(description = "文件状态")
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 上传时间
|
||||
*/
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description = "上传时间")
|
||||
private Date uploadTime;
|
||||
|
||||
/**
|
||||
* 处理时间
|
||||
*/
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@Schema(description = "处理时间")
|
||||
private Date processTime;
|
||||
|
||||
/**
|
||||
* 处理日志
|
||||
*/
|
||||
@Schema(description = "处理日志")
|
||||
private String processLog;
|
||||
|
||||
/**
|
||||
* 处理结果文件ID
|
||||
*/
|
||||
@Schema(description = "处理结果文件ID")
|
||||
private Long resultFileId;
|
||||
|
||||
/**
|
||||
* 关联的解析规则ID
|
||||
*/
|
||||
@Schema(description = "关联的解析规则ID")
|
||||
private Long parseRuleId;
|
||||
|
||||
/**
|
||||
* 关联的映射规则ID
|
||||
*/
|
||||
@Schema(description = "关联的映射规则ID")
|
||||
private Long mapperRuleId;
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
package com.example.demo.parser.model.vo;
|
||||
|
||||
import com.example.demo.common.domain.BaseVO;
|
||||
import cn.zhxu.bs.bean.SearchBean;
|
||||
import com.fhs.core.trans.vo.TransPojo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 映射规则视图对象
|
||||
* 用于向前端返回映射规则数据
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Schema(description = "映射规则视图对象")
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@SearchBean(
|
||||
tables = "mapper_rule",
|
||||
autoMapTo = "a"
|
||||
)
|
||||
public class MapperRuleVO extends BaseVO implements TransPojo, Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 关联的解析规则ID
|
||||
*/
|
||||
@Schema(description = "关联的解析规则ID")
|
||||
private String parseRuleId;
|
||||
|
||||
/**
|
||||
* TXT文件中的键名
|
||||
*/
|
||||
@Schema(description = "TXT文件中的键名")
|
||||
private String txtKey;
|
||||
|
||||
/**
|
||||
* 转换模板
|
||||
*/
|
||||
@Schema(description = "转换模板")
|
||||
private String template;
|
||||
|
||||
/**
|
||||
* 父级键名
|
||||
*/
|
||||
@Schema(description = "父级键名")
|
||||
private String parentKey;
|
||||
|
||||
/**
|
||||
* 排序顺序
|
||||
*/
|
||||
@Schema(description = "排序顺序")
|
||||
private Integer sortOrder;
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package com.example.demo.parser.model.vo;
|
||||
|
||||
import com.example.demo.common.domain.BaseVO;
|
||||
import cn.zhxu.bs.bean.SearchBean;
|
||||
import com.fhs.core.trans.vo.TransPojo;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 解析规则视图对象
|
||||
* 用于向前端返回解析规则数据
|
||||
*
|
||||
* @author system
|
||||
* @version 1.0
|
||||
*/
|
||||
@Schema(description = "解析规则视图对象")
|
||||
@Getter
|
||||
@Setter
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@SearchBean(
|
||||
tables = "parse_rule",
|
||||
autoMapTo = "a"
|
||||
)
|
||||
public class ParseRuleVO extends BaseVO implements TransPojo, Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* XML标签名
|
||||
*/
|
||||
@Schema(description = "XML标签名")
|
||||
private String xmlTag;
|
||||
|
||||
/**
|
||||
* 标签类型:root, node, leaf
|
||||
*/
|
||||
@Schema(description = "标签类型")
|
||||
private String tagType;
|
||||
|
||||
/**
|
||||
* 是否允许为空:0-不允许,1-允许
|
||||
*/
|
||||
@Schema(description = "是否允许为空")
|
||||
private String isNull;
|
||||
|
||||
/**
|
||||
* 节点路径
|
||||
*/
|
||||
@Schema(description = "节点路径")
|
||||
private String nodePath;
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
//package com.example.demo.parser.service;
|
||||
//
|
||||
//import com.example.demo.parser.model.bo.TemplateData;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.stereotype.Service;
|
||||
//
|
||||
//import java.io.StringWriter;
|
||||
//import java.util.HashMap;
|
||||
//import java.util.Map;
|
||||
//
|
||||
///**
|
||||
// * 动态模板生成服务
|
||||
// * 使用Jinja2模板引擎生成格式化的动态代码
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Service
|
||||
//public class DynamicTemplateService {
|
||||
//
|
||||
// // 默认的缩进空格数
|
||||
// private static final int DEFAULT_INDENT_SPACES = 4;
|
||||
//
|
||||
// /**
|
||||
// * 生成动态代码
|
||||
// * @param templateData 模板数据
|
||||
// * @return 生成的格式化代码
|
||||
// */
|
||||
// public String generateDynamicCode(TemplateData templateData) {
|
||||
// return generateDynamicCode(templateData, DEFAULT_INDENT_SPACES);
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 生成动态代码(可自定义缩进空格数)
|
||||
// * @param templateData 模板数据
|
||||
// * @param indentSpaces 缩进空格数
|
||||
// * @return 生成的格式化代码
|
||||
// */
|
||||
// public String generateDynamicCode(TemplateData templateData, int indentSpaces) {
|
||||
// try {
|
||||
// // 创建Jinja2环境
|
||||
// Jinja2Environment env = createJinja2Environment();
|
||||
//
|
||||
// // 准备模板上下文数据
|
||||
// Map<String, Object> context = prepareTemplateContext(templateData, indentSpaces);
|
||||
//
|
||||
// // 加载模板
|
||||
// Jinja2Template template = env.getTemplate("dynamic_template.j2");
|
||||
//
|
||||
// // 渲染模板
|
||||
// StringWriter writer = new StringWriter();
|
||||
// template.render(context, writer);
|
||||
//
|
||||
// return writer.toString();
|
||||
//
|
||||
// } catch (Exception e) {
|
||||
// log.error("生成动态代码时发生错误", e);
|
||||
// throw new RuntimeException("模板生成失败", e);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 创建Jinja2环境配置
|
||||
// */
|
||||
// private Jinja2Environment createJinja2Environment() {
|
||||
// // 这里使用伪代码,实际需要根据具体的Jinja2 Java实现来配置
|
||||
// // 例如使用 com.hubspot.jinjava.Jinjava
|
||||
// return new Jinja2Environment();
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 准备模板上下文数据
|
||||
// */
|
||||
// private Map<String, Object> prepareTemplateContext(TemplateData templateData, int indentSpaces) {
|
||||
// Map<String, Object> context = new HashMap<>();
|
||||
//
|
||||
// context.put("globalComment", templateData.getGlobalComment());
|
||||
// context.put("levelConfigs", templateData.getLevelConfigs());
|
||||
// context.put("conditionMap", templateData.getConditionMap());
|
||||
// context.put("indentSpaces", indentSpaces);
|
||||
// context.put("indent", " ".repeat(indentSpaces));
|
||||
//
|
||||
// return context;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 工具方法:生成缩进字符串
|
||||
// */
|
||||
// public static String generateIndent(int level, int spaces) {
|
||||
// return " ".repeat(level * spaces);
|
||||
// }
|
||||
//}
|
@ -0,0 +1,19 @@
|
||||
package com.example.demo.parser.service;
|
||||
|
||||
import com.example.demo.common.typography.BaseService;
|
||||
import com.example.demo.parser.entity.FileRecordEntity;
|
||||
import com.example.demo.parser.model.dto.FileRecordDTO;
|
||||
import com.example.demo.parser.model.dto.FileRecordQueryDTO;
|
||||
import com.example.demo.parser.model.vo.FileRecordVO;
|
||||
|
||||
/**
|
||||
* 文件记录服务接口
|
||||
* 提供文件记录的CRUD及文件上传下载等业务操作
|
||||
*
|
||||
* @author system
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface FileRecordService
|
||||
extends BaseService<FileRecordEntity, FileRecordVO, FileRecordDTO, FileRecordQueryDTO> {
|
||||
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.example.demo.parser.service;
|
||||
|
||||
import com.example.demo.common.typography.BaseService;
|
||||
import com.example.demo.parser.entity.MapperRuleEntity;
|
||||
import com.example.demo.parser.model.dto.MapperRuleDTO;
|
||||
import com.example.demo.parser.model.dto.MapperRuleQueryDTO;
|
||||
import com.example.demo.parser.model.vo.MapperRuleVO;
|
||||
|
||||
/**
|
||||
* 映射规则服务接口
|
||||
* 提供映射规则的CRUD及其他业务操作
|
||||
*
|
||||
* @author system
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface MapperRuleService
|
||||
extends BaseService<MapperRuleEntity, MapperRuleVO, MapperRuleDTO, MapperRuleQueryDTO> {
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.example.demo.parser.service;
|
||||
|
||||
import com.example.demo.common.typography.BaseService;
|
||||
import com.example.demo.parser.entity.ParseRuleEntity;
|
||||
import com.example.demo.parser.model.dto.ParseRuleDTO;
|
||||
import com.example.demo.parser.model.dto.ParseRuleQueryDTO;
|
||||
import com.example.demo.parser.model.vo.ParseRuleVO;
|
||||
|
||||
/**
|
||||
* 解析规则服务接口
|
||||
* 提供解析规则的CRUD及其他业务操作
|
||||
*
|
||||
* @author system
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public interface ParseRuleService
|
||||
extends BaseService<ParseRuleEntity, ParseRuleVO, ParseRuleDTO, ParseRuleQueryDTO> {
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
//package com.example.demo.parser.service.impl;
|
||||
//
|
||||
//import cn.zhxu.bs.BeanSearcher;
|
||||
//import com.example.demo.common.typography.BaseServiceImpl;
|
||||
//import com.example.demo.parser.entity.FileRecordEntity;
|
||||
//import com.example.demo.parser.mapper.FileRecordMapper;
|
||||
//import com.example.demo.parser.model.dto.FileRecordDTO;
|
||||
//import com.example.demo.parser.model.dto.FileRecordQueryDTO;
|
||||
//import com.example.demo.parser.model.vo.FileRecordVO;
|
||||
//import com.example.demo.parser.service.FileRecordService;
|
||||
//// import com.fhs.core.trans.TransService;
|
||||
//import com.fhs.trans.service.impl.TransService;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.stereotype.Service;
|
||||
//import org.springframework.transaction.annotation.Transactional;
|
||||
//
|
||||
///**
|
||||
// * 文件记录服务实现类
|
||||
// * 提供文件记录的CRUD和查询功能
|
||||
// *
|
||||
// * @author system
|
||||
// * @version 1.0
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Service
|
||||
//@Transactional(rollbackFor = Exception.class)
|
||||
//public class FileRecordServiceImpl
|
||||
// extends BaseServiceImpl<FileRecordEntity, FileRecordVO, FileRecordDTO, FileRecordQueryDTO, FileRecordMapper>
|
||||
// implements FileRecordService {
|
||||
//
|
||||
// public FileRecordServiceImpl(
|
||||
// BeanSearcher beanSearcher,
|
||||
// TransService transService
|
||||
// ) {
|
||||
// super(log, FileRecordServiceImpl.class.getSimpleName(), FileRecordVO.class, beanSearcher, transService);
|
||||
// }
|
||||
//}
|
@ -0,0 +1,52 @@
|
||||
//package com.example.demo.parser.service.impl;
|
||||
//
|
||||
//import cn.zhxu.bs.BeanSearcher;
|
||||
//import com.example.demo.common.exception.BusinessException;
|
||||
//import com.example.demo.common.typography.BaseServiceImpl;
|
||||
//import com.example.demo.parser.entity.FileRecordEntity;
|
||||
//import com.example.demo.parser.entity.MapperRuleEntity;
|
||||
//import com.example.demo.parser.mapper.FileRecordMapper;
|
||||
//import com.example.demo.parser.mapper.MapperRuleMapper;
|
||||
//import com.example.demo.parser.model.dto.FileRecordDTO;
|
||||
//import com.example.demo.parser.model.dto.FileRecordQueryDTO;
|
||||
//import com.example.demo.parser.model.dto.MapperRuleDTO;
|
||||
//import com.example.demo.parser.model.dto.MapperRuleQueryDTO;
|
||||
//import com.example.demo.parser.model.vo.FileRecordVO;
|
||||
//import com.example.demo.parser.model.vo.MapperRuleVO;
|
||||
//import com.example.demo.parser.service.MapperRuleService;
|
||||
//import com.example.demo.parser.service.ParseRuleService;
|
||||
//// import com.fhs.core.trans.TransService;
|
||||
//import com.fhs.trans.service.impl.TransService;
|
||||
//import com.mybatisflex.core.paginate.Page;
|
||||
//import com.mybatisflex.core.query.QueryWrapper;
|
||||
//import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
//import lombok.RequiredArgsConstructor;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.stereotype.Service;
|
||||
//import org.springframework.transaction.annotation.Transactional;
|
||||
//
|
||||
//import java.util.List;
|
||||
//
|
||||
//import static com.example.demo.parser.entity.table.MapperRuleEntityTableDef.MAPPER_RULE_ENTITY;
|
||||
//
|
||||
///**
|
||||
// * 映射规则服务实现类
|
||||
// * 提供映射规则的CRUD和查询功能
|
||||
// *
|
||||
// * @author system
|
||||
// * @version 1.0
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Service
|
||||
//@Transactional(rollbackFor = Exception.class)
|
||||
//public class MapperRuleServiceImpl
|
||||
// extends BaseServiceImpl<MapperRuleEntity, MapperRuleVO, MapperRuleDTO, MapperRuleQueryDTO, MapperRuleMapper> {
|
||||
//
|
||||
// public MapperRuleServiceImpl(
|
||||
// BeanSearcher beanSearcher,
|
||||
// TransService transService
|
||||
// ) {
|
||||
// super(log, MapperRuleServiceImpl.class.getSimpleName(), MapperRuleVO.class, beanSearcher, transService);
|
||||
// }
|
||||
//
|
||||
//}
|
@ -0,0 +1,51 @@
|
||||
//package com.example.demo.parser.service.impl;
|
||||
//
|
||||
//import cn.zhxu.bs.BeanSearcher;
|
||||
//import com.example.demo.common.exception.BusinessException;
|
||||
//import com.example.demo.common.typography.BaseServiceImpl;
|
||||
//import com.example.demo.parser.entity.FileRecordEntity;
|
||||
//import com.example.demo.parser.entity.ParseRuleEntity;
|
||||
//import com.example.demo.parser.mapper.FileRecordMapper;
|
||||
//import com.example.demo.parser.mapper.ParseRuleMapper;
|
||||
//import com.example.demo.parser.model.dto.FileRecordDTO;
|
||||
//import com.example.demo.parser.model.dto.FileRecordQueryDTO;
|
||||
//import com.example.demo.parser.model.dto.ParseRuleDTO;
|
||||
//import com.example.demo.parser.model.dto.ParseRuleQueryDTO;
|
||||
//import com.example.demo.parser.model.vo.FileRecordVO;
|
||||
//import com.example.demo.parser.model.vo.ParseRuleVO;
|
||||
//import com.example.demo.parser.service.ParseRuleService;
|
||||
//// import com.fhs.core.trans.TransService;
|
||||
//import com.fhs.trans.service.impl.TransService;
|
||||
//import com.mybatisflex.core.paginate.Page;
|
||||
//import com.mybatisflex.core.query.QueryWrapper;
|
||||
//import com.mybatisflex.spring.service.impl.ServiceImpl;
|
||||
//import lombok.RequiredArgsConstructor;
|
||||
//import lombok.extern.slf4j.Slf4j;
|
||||
//import org.springframework.stereotype.Service;
|
||||
//import org.springframework.transaction.annotation.Transactional;
|
||||
//
|
||||
//import java.util.List;
|
||||
//
|
||||
//import static com.example.demo.parser.entity.table.ParseRuleEntityTableDef.PARSE_RULE_ENTITY;
|
||||
//
|
||||
///**
|
||||
// * 解析规则服务实现类
|
||||
// * 提供解析规则的CRUD和查询功能
|
||||
// *
|
||||
// * @author system
|
||||
// * @version 1.0
|
||||
// */
|
||||
//@Slf4j
|
||||
//@Service
|
||||
//@Transactional(rollbackFor = Exception.class)
|
||||
//public class ParseRuleServiceImpl
|
||||
// extends BaseServiceImpl<ParseRuleEntity, ParseRuleVO, ParseRuleDTO, ParseRuleQueryDTO, ParseRuleMapper> {
|
||||
//
|
||||
// public ParseRuleServiceImpl(
|
||||
// BeanSearcher beanSearcher,
|
||||
// TransService transService
|
||||
// ) {
|
||||
// super(log, ParseRuleServiceImpl.class.getSimpleName(), ParseRuleVO.class, beanSearcher, transService);
|
||||
// }
|
||||
//
|
||||
//}
|
22
src/main/resources/application-h2.yml
Normal file
22
src/main/resources/application-h2.yml
Normal file
@ -0,0 +1,22 @@
|
||||
# Spring Boot 应用配置
|
||||
spring:
|
||||
# H2缓存数据库配置
|
||||
datasource:
|
||||
h2:
|
||||
url: jdbc:h2:mem:cacheDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
|
||||
driver-class-name: org.h2.Driver
|
||||
username: sa
|
||||
password:
|
||||
hikari:
|
||||
maximum-pool-size: 5
|
||||
connection-timeout: 30000
|
||||
|
||||
# H2控制台配置
|
||||
h2:
|
||||
console:
|
||||
enabled: true
|
||||
path: /h2-console
|
||||
settings:
|
||||
web-allow-others: true
|
||||
|
||||
# 缓存数据库初始化配置(由自定义配置类H2DataSourceConfig管理)
|
38
src/main/resources/application-orm.yml
Normal file
38
src/main/resources/application-orm.yml
Normal file
@ -0,0 +1,38 @@
|
||||
# Bean-Searcher 配置
|
||||
bean-searcher:
|
||||
sql:
|
||||
default-mapping:
|
||||
#表名和字段名是否驼峰转小写下划线(since v3.7.0)
|
||||
underline-case: true
|
||||
#表名和字段名是否大写
|
||||
upper-case: true
|
||||
redundant-suffixes:
|
||||
- VO
|
||||
- DTO
|
||||
|
||||
# MyBatisFlex公共配置
|
||||
# https://mybatis-flex.com/zh/base/configuration.html
|
||||
mybatis-flex:
|
||||
configuration:
|
||||
## 以下为mybatis原生配置 https://mybatis.org/mybatis-3/zh/configuration.html
|
||||
# 自动驼峰命名规则(camel case)映射
|
||||
map_underscore_to_camel_case: true
|
||||
# MyBatis 自动映射策略
|
||||
# NONE:不启用 PARTIAL:只对非嵌套 resultMap 自动映射 FULL:对所有 resultMap 自动映射
|
||||
auto_mapping_behavior: FULL
|
||||
# MyBatis 自动映射时未知列或未知属性处理策
|
||||
# NONE:不做处理 WARNING:打印相关警告 FAILING:抛出异常和详细信息
|
||||
auto_mapping_unknown_column_behavior: NONE
|
||||
# 更详细的日志输出 会有性能损耗 org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
# 关闭日志记录 org.apache.ibatis.logging.nologging.NoLoggingImpl
|
||||
# 默认日志输出 org.apache.ibatis.logging.slf4j.Slf4jImpl
|
||||
log_impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
# logImpl: org.apache.ibatis.logging.nologging.NoLoggingImpl
|
||||
cacheEnabled: true
|
||||
global-config:
|
||||
# 是否控制台打印 MyBatis-Flex 的 LOGO 及版本号
|
||||
print-banner: true
|
||||
# 全局的 ID 生成策略配置:雪花算法
|
||||
key-config:
|
||||
key-type: Generator
|
||||
value: snowFlakeId
|
17
src/main/resources/application-parser.yml
Normal file
17
src/main/resources/application-parser.yml
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
# 自定义配置
|
||||
xml-parser:
|
||||
# 文件存储配置
|
||||
file:
|
||||
upload-dir: ${user.dir}/upload
|
||||
temp-dir: ${user.dir}/temp
|
||||
|
||||
# 解析配置
|
||||
parser:
|
||||
default-encoding: UTF-8
|
||||
validate-xml: true
|
||||
|
||||
# 转换配置
|
||||
converter:
|
||||
default-encoding: UTF-8
|
||||
indent-size: 4
|
0
src/main/resources/application-rule.yml
Normal file
0
src/main/resources/application-rule.yml
Normal file
54
src/main/resources/application-springdoc.yml
Normal file
54
src/main/resources/application-springdoc.yml
Normal file
@ -0,0 +1,54 @@
|
||||
# ===== SpringDoc配置 =====#
|
||||
springdoc:
|
||||
swagger-ui:
|
||||
# 自定义的文档界面访问路径。默认访问路径是/swagger-ui.html
|
||||
path: /springdoc/docs.html
|
||||
# 字符串类型,一共三个值来控制操作和标记的默认展开设置。它可以是“list”(仅展开标记)、“full”(展开标记和操作)或“none”(不展开任何内容)。
|
||||
docExpansion: none
|
||||
# 布尔值。控制“试用”请求的请求持续时间(毫秒)的显示。
|
||||
displayRequestDuration: true
|
||||
# 布尔值。控制供应商扩展(x-)字段和操作、参数和架构值的显示。
|
||||
showExtensions: true
|
||||
# 布尔值。控制参数的扩展名(pattern、maxLength、minLength、maximum、minminimum)字段和值的显示。
|
||||
showCommonExtensions: true
|
||||
# 布尔值。禁用swagger用户界面默认petstore url。(从v1.4.1开始提供)。
|
||||
disable-swagger-default-url: true
|
||||
api-docs:
|
||||
# enabled the /v3/api-docs endpoint
|
||||
enabled: true
|
||||
# 自定义的文档api元数据访问路径。默认访问路径是/v3/api-docs
|
||||
# path: /springdoc/api-docs
|
||||
path: /v3/api-docs
|
||||
# 布尔值。在@Schema(名称name、标题title和说明description,三个属性)上启用属性解析程序。
|
||||
resolve-schema-properties: true
|
||||
paths-to-match:
|
||||
- '/parser/**'
|
||||
# 布尔值。实现OpenApi规范的打印。
|
||||
writer-with-default-pretty-printer: true
|
||||
show-actuator: true
|
||||
default-flat-param-object: true
|
||||
group-configs:
|
||||
- group: 'parser'
|
||||
pathsToMatch:
|
||||
- '/parser/**'
|
||||
packagesToScan:
|
||||
- com.example.demo.parser
|
||||
# Knife4j OpenAPI3 文档配置
|
||||
knife4j:
|
||||
#是否启用增强设置
|
||||
enable: true
|
||||
#开启生产环境屏蔽
|
||||
production: false
|
||||
#开启跨域
|
||||
cors: false
|
||||
#是否启用登录认证
|
||||
basic:
|
||||
enable: true
|
||||
username: admin
|
||||
password: 123456
|
||||
setting: # 前端UI的个性化配置属性
|
||||
language: zh_cn # 显示语言中文
|
||||
enable-version: true
|
||||
enable-swagger-models: true # 是否显示界面中SwaggerModel功能
|
||||
swagger-model-name: SwaggerModel2 # 重命名SwaggerModel名称,默认
|
||||
enable-document-manage: true # 是否显示界面中"文档管理"功能
|
15
src/main/resources/application-sqlite.yml
Normal file
15
src/main/resources/application-sqlite.yml
Normal file
@ -0,0 +1,15 @@
|
||||
# Spring Boot 应用配置
|
||||
spring:
|
||||
# 数据库配置 - SQLite(主数据库)
|
||||
datasource:
|
||||
sqlite:
|
||||
# url: jdbc:sqlite:${user.dir}/data/xml-parser.db
|
||||
url: jdbc:sqlite:parser.db
|
||||
driver-class-name: org.sqlite.JDBC
|
||||
username: sa
|
||||
password:
|
||||
hikari:
|
||||
maximum-pool-size: 5
|
||||
connection-timeout: 30000
|
||||
|
||||
# SQLite数据库初始化配置(由自定义配置类SqliteDataSourceConfig管理)
|
27
src/main/resources/application.yml
Normal file
27
src/main/resources/application.yml
Normal file
@ -0,0 +1,27 @@
|
||||
# 服务器配置
|
||||
server:
|
||||
port: 8080
|
||||
servlet:
|
||||
context-path: /parser
|
||||
|
||||
# 通用 log 输出配置
|
||||
logging:
|
||||
config: classpath:logback-spring.xml
|
||||
|
||||
# Spring Boot 应用配置
|
||||
spring:
|
||||
# 启用JAVA21虚拟线程
|
||||
threads:
|
||||
virtual:
|
||||
enabled: true
|
||||
|
||||
# 文件上传配置
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 10MB
|
||||
max-request-size: 10MB
|
||||
profiles:
|
||||
active: dev
|
||||
group:
|
||||
dev: orm,h2,sqlite,parser,rule,springdoc
|
||||
prod: orm,h2,sqlite,parser,rule
|
7
src/main/resources/data/01-作战部队武器装备/20250923_6b399e.xml
Normal file
7
src/main/resources/data/01-作战部队武器装备/20250923_6b399e.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<作战部队武器装备>
|
||||
<装备类型>武装直升机</装备类型>
|
||||
<武器装备型号>Z-10</武器装备型号>
|
||||
<武器装备名称>直-10攻击直升机</武器装备名称>
|
||||
<武器装备数量>18</武器装备数量>
|
||||
</作战部队武器装备>
|
7
src/main/resources/data/01-作战部队武器装备/20250923_6ba0d8.xml
Normal file
7
src/main/resources/data/01-作战部队武器装备/20250923_6ba0d8.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<作战部队武器装备>
|
||||
<装备类型>自行火炮</装备类型>
|
||||
<武器装备型号>PLZ-05</武器装备型号>
|
||||
<武器装备名称>05式自行榴弹炮</武器装备名称>
|
||||
<武器装备数量>36</武器装备数量>
|
||||
</作战部队武器装备>
|
7
src/main/resources/data/01-作战部队武器装备/20250923_9efa34.xml
Normal file
7
src/main/resources/data/01-作战部队武器装备/20250923_9efa34.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<作战部队武器装备>
|
||||
<装备类型>战斗机</装备类型>
|
||||
<武器装备型号>J-20</武器装备型号>
|
||||
<武器装备名称>歼-20隐形战斗机</武器装备名称>
|
||||
<武器装备数量>24</武器装备数量>
|
||||
</作战部队武器装备>
|
7
src/main/resources/data/01-作战部队武器装备/20250923_b345dd.xml
Normal file
7
src/main/resources/data/01-作战部队武器装备/20250923_b345dd.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<作战部队武器装备>
|
||||
<装备类型>主战坦克</装备类型>
|
||||
<武器装备型号>99A</武器装备型号>
|
||||
<武器装备名称>99A式主战坦克</武器装备名称>
|
||||
<武器装备数量>50</武器装备数量>
|
||||
</作战部队武器装备>
|
7
src/main/resources/data/01-作战部队武器装备/20250923_e9dd05.xml
Normal file
7
src/main/resources/data/01-作战部队武器装备/20250923_e9dd05.xml
Normal file
@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<作战部队武器装备>
|
||||
<装备类型>驱逐舰</装备类型>
|
||||
<武器装备型号>055</武器装备型号>
|
||||
<武器装备名称>055型导弹驱逐舰</武器装备名称>
|
||||
<武器装备数量>2</武器装备数量>
|
||||
</作战部队武器装备>
|
78
src/main/resources/data/01-作战部队武器装备/default.json
Normal file
78
src/main/resources/data/01-作战部队武器装备/default.json
Normal file
@ -0,0 +1,78 @@
|
||||
{
|
||||
"conditionMap": {},
|
||||
"initialIndent": "",
|
||||
"levelConfigs": [
|
||||
{
|
||||
"levelName": "platform",
|
||||
"subLevels": [
|
||||
{
|
||||
"levelName": "aux_data",
|
||||
"subLevels": [],
|
||||
"valueConfigs": [
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "string batchnumber = \"作战部队武器装备.武器装备数量\""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": []
|
||||
}
|
||||
],
|
||||
"valueConfigs": [
|
||||
{
|
||||
"valueName": "side",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "red"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"valueName": "icon",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "weasel"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"valueName": "commander",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "north_cap_lead"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"valueName": "position",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "36:38:08:13n 109:06:46:76e altitude 35000.0 ft msl"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"valueName": "heading",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"unit": "deg",
|
||||
"value": 307
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
"作战部队武器装备.武器装备名称",
|
||||
"作战部队武器装备.武器装备型号"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
11
src/main/resources/data/02-单个空中平台任务数据/20250923_199d51.xml
Normal file
11
src/main/resources/data/02-单个空中平台任务数据/20250923_199d51.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<单个空中平台任务数据>
|
||||
<机型>Z-19</机型>
|
||||
<机型名称>直-19侦察武装直升机</机型名称>
|
||||
<架数>6</架数>
|
||||
<塔康工作频道>15</塔康工作频道>
|
||||
<主挂载武器>AKD-10空地导弹</主挂载武器>
|
||||
<次挂载武器>HY-90航空火箭弹</次挂载武器>
|
||||
<平台识别码>Z19_Attack01</平台识别码>
|
||||
<平台识别号>1901</平台识别号>
|
||||
</单个空中平台任务数据>
|
11
src/main/resources/data/02-单个空中平台任务数据/20250923_5e813d.xml
Normal file
11
src/main/resources/data/02-单个空中平台任务数据/20250923_5e813d.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<单个空中平台任务数据>
|
||||
<机型>J-16</机型>
|
||||
<机型名称>歼-16多用途战斗机</机型名称>
|
||||
<架数>4</架数>
|
||||
<塔康工作频道>12</塔康工作频道>
|
||||
<主挂载武器>PL-15中距空空导弹</主挂载武器>
|
||||
<次挂载武器>PL-10近距格斗导弹</次挂载武器>
|
||||
<平台识别码>J16_Red01</平台识别码>
|
||||
<平台识别号>7801</平台识别号>
|
||||
</单个空中平台任务数据>
|
11
src/main/resources/data/02-单个空中平台任务数据/20250923_7bbb1d.xml
Normal file
11
src/main/resources/data/02-单个空中平台任务数据/20250923_7bbb1d.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<单个空中平台任务数据>
|
||||
<机型>KJ-500</机型>
|
||||
<机型名称>空警-500预警机</机型名称>
|
||||
<架数>2</架数>
|
||||
<塔康工作频道>05</塔康工作频道>
|
||||
<主挂载武器>无</主挂载武器>
|
||||
<次挂载武器>无</次挂载武器>
|
||||
<平台识别码>KJ500_Control01</平台识别码>
|
||||
<平台识别号>5001</平台识别号>
|
||||
</单个空中平台任务数据>
|
11
src/main/resources/data/02-单个空中平台任务数据/20250923_7f3eb1.xml
Normal file
11
src/main/resources/data/02-单个空中平台任务数据/20250923_7f3eb1.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<单个空中平台任务数据>
|
||||
<机型>Y-20</机型>
|
||||
<机型名称>运-20大型运输机</机型名称>
|
||||
<架数>3</架数>
|
||||
<塔康工作频道>08</塔康工作频道>
|
||||
<主挂载武器>无</主挂载武器>
|
||||
<次挂载武器>无</次挂载武器>
|
||||
<平台识别码>Y20_Blue01</平台识别码>
|
||||
<平台识别号>2101</平台识别号>
|
||||
</单个空中平台任务数据>
|
115
src/main/resources/data/02-单个空中平台任务数据/default.json
Normal file
115
src/main/resources/data/02-单个空中平台任务数据/default.json
Normal file
@ -0,0 +1,115 @@
|
||||
{
|
||||
"conditionMap": {},
|
||||
"levelConfigs": [
|
||||
{
|
||||
"levelName": "platform",
|
||||
"enableLoop": true,
|
||||
"loopCount": "单个空中平台任务数据.架数",
|
||||
"subLevels": [
|
||||
{
|
||||
"levelName": "comm",
|
||||
"subLevels": [],
|
||||
"valueConfigs": [
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "string tacanWorkChannel = \"单个空中平台任务数据.塔康工作频道\" # 塔康工作频道"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
"xxx",
|
||||
"默认通信链"
|
||||
]
|
||||
},
|
||||
{
|
||||
"levelName": "aux_data",
|
||||
"subLevels": [],
|
||||
"valueConfigs": [
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "string platformIdCardCode = \"单个空中平台任务数据.平台识别码\" # 平台识别码"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "string platformIdCardNumber = \"单个空中平台任务数据.平台识别号\" # 平台识别号"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": []
|
||||
},
|
||||
{
|
||||
"levelName": "weapon",
|
||||
"subLevels": [],
|
||||
"valueConfigs": [
|
||||
{
|
||||
"valueName": "quantity",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "2"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
"单个空中平台任务数据.主挂载武器",
|
||||
"单个空中平台任务数据.挂载类型"
|
||||
]
|
||||
},
|
||||
{
|
||||
"levelName": "weapon",
|
||||
"subLevels": [],
|
||||
"valueConfigs": [
|
||||
{
|
||||
"valueName": "quantity",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "3"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
"单个空中平台任务数据.次挂载武器",
|
||||
"单个空中平台任务数据.挂载类型"
|
||||
]
|
||||
}
|
||||
],
|
||||
"valueConfigs": [
|
||||
{
|
||||
"valueName": "side",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "red"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"valueName": "icon",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "weasel"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
"单个空中平台任务数据.平台名称",
|
||||
"单个空中平台任务数据.机型"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
15
src/main/resources/data/03-任务航线/20250923_422dc2.xml
Normal file
15
src/main/resources/data/03-任务航线/20250923_422dc2.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<任务航线>
|
||||
<航线点型号>WP003</航线点型号>
|
||||
<航线点名称>目标区域</航线点名称>
|
||||
<航线点坐标>40.0042,116.6074</航线点坐标>
|
||||
<航线点类型>目标点</航线点类型>
|
||||
<准时到达时间>08:45:00</准时到达时间>
|
||||
<转弯方式>盘旋</转弯方式>
|
||||
<转向方式>保持</转向方式>
|
||||
<坡度>15</坡度>
|
||||
<速度>350</速度>
|
||||
<高度>2500</高度>
|
||||
<高度属性>相对高度</高度属性>
|
||||
<升将率>0</升将率>
|
||||
</任务航线>
|
15
src/main/resources/data/03-任务航线/20250923_4c32c8.xml
Normal file
15
src/main/resources/data/03-任务航线/20250923_4c32c8.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<任务航线>
|
||||
<航线点型号>WP002</航线点型号>
|
||||
<航线点名称>导航点A</航线点名称>
|
||||
<航线点坐标>39.9242,116.5074</航线点坐标>
|
||||
<航线点类型>航路点</航线点类型>
|
||||
<准时到达时间>08:15:30</准时到达时间>
|
||||
<转弯方式>飞越转弯</转弯方式>
|
||||
<转向方式>右转</转向方式>
|
||||
<坡度>30</坡度>
|
||||
<速度>450</速度>
|
||||
<高度>3000</高度>
|
||||
<高度属性>绝对高度</高度属性>
|
||||
<升降率>8</升降率>
|
||||
</任务航线>
|
15
src/main/resources/data/03-任务航线/20250923_82c579.xml
Normal file
15
src/main/resources/data/03-任务航线/20250923_82c579.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<任务航线>
|
||||
<航线点型号>WP005</航线点型号>
|
||||
<航线点名称>降落点</航线点名称>
|
||||
<航线点坐标>39.9042,116.4074</航线点坐标>
|
||||
<航线点类型>降落点</航线点类型>
|
||||
<准时到达时间>09:45:00</准时到达时间>
|
||||
<转弯方式>直接进近</转弯方式>
|
||||
<转向方式>保持</转向方式>
|
||||
<坡度>10</坡度>
|
||||
<速度>250 m/s</速度>
|
||||
<高度>500</高度>
|
||||
<高度属性>相对高度</高度属性>
|
||||
<升将率>-5</升将率>
|
||||
</任务航线>
|
15
src/main/resources/data/03-任务航线/20250923_b43a26.xml
Normal file
15
src/main/resources/data/03-任务航线/20250923_b43a26.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<任务航线>
|
||||
<航线点型号>WP001</航线点型号>
|
||||
<航线点名称>起飞点</航线点名称>
|
||||
<航线点坐标>39.9042,116.4074</航线点坐标>
|
||||
<航线点类型>起飞点</航线点类型>
|
||||
<准时到达时间>08:00:00</准时到达时间>
|
||||
<转弯方式>直接转弯</转弯方式>
|
||||
<转向方式>左转</转向方式>
|
||||
<坡度>25</坡度>
|
||||
<速度>300</速度>
|
||||
<高度>1000</高度>
|
||||
<高度属性>相对高度</高度属性>
|
||||
<升将率>5</升将率>
|
||||
</任务航线>
|
15
src/main/resources/data/03-任务航线/20250923_c87aa1.xml
Normal file
15
src/main/resources/data/03-任务航线/20250923_c87aa1.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<任务航线>
|
||||
<航线点型号>WP004</航线点型号>
|
||||
<航线点名称>返航点</航线点名称>
|
||||
<航线点坐标>39.9542,116.4574</航线点坐标>
|
||||
<航线点类型>返航点</航线点类型>
|
||||
<准时到达时间>09:30:00</准时到达时间>
|
||||
<转弯方式>标准转弯</转弯方式>
|
||||
<转向方式>左转</转向方式>
|
||||
<坡度>20</坡度>
|
||||
<速度>400</速度>
|
||||
<高度>2000</高度>
|
||||
<高度属性>绝对高度</高度属性>
|
||||
<升将率>-3</升将率>
|
||||
</任务航线>
|
153
src/main/resources/data/03-任务航线/default.json
Normal file
153
src/main/resources/data/03-任务航线/default.json
Normal file
@ -0,0 +1,153 @@
|
||||
{
|
||||
"conditionMap": {},
|
||||
"levelConfigs": [
|
||||
{
|
||||
"levelName": "platform",
|
||||
"subLevels": [
|
||||
{
|
||||
"levelName": "route",
|
||||
"subLevels": [
|
||||
{
|
||||
"comment": "航线点型号为 任务航线.航线点型号 ,名称为 任务航线.航线点名称",
|
||||
"levelName": "waypoint",
|
||||
"subLevels": [],
|
||||
"valueConfigs": [
|
||||
{
|
||||
"comment": "航线点坐标",
|
||||
"valueName": "position",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "39.9242N"
|
||||
},
|
||||
{
|
||||
"combined": false,
|
||||
"value": "116.5074E"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "航线点类型",
|
||||
"valueName": "waypoint_type",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "任务航线.航线点类型"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "准时到达时间",
|
||||
"valueName": "eta",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "任务航线.准时到达时间"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "转弯方式",
|
||||
"valueName": "turn_method",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "任务航线.转弯方式"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "转向方式",
|
||||
"valueName": "turn_direction",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "任务航线.转向方式"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "坡度",
|
||||
"valueName": "bank_angle",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"unit": "deg",
|
||||
"value": "任务航线.坡度"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "速度",
|
||||
"valueName": "speed",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"unit": "km/h",
|
||||
"value": "任务航线.速度"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "高度",
|
||||
"valueName": "altitude",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"unit": "m",
|
||||
"value": "任务航线.高度"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "高度属性",
|
||||
"valueName": "altitude_type",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "任务航线.高度属性"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "升降率",
|
||||
"valueName": "climb_rate",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"unit": "m/s",
|
||||
"value": "任务航线.升降率"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
"任务航线.航线点型号",
|
||||
"任务航线.航线点名称"
|
||||
]
|
||||
}
|
||||
],
|
||||
"valueConfigs": [],
|
||||
"values": []
|
||||
}
|
||||
],
|
||||
"valueConfigs": [
|
||||
{
|
||||
"comment": "初始航向为0度",
|
||||
"valueName": "heading",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"unit": "deg",
|
||||
"value": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
"mission_plane",
|
||||
"AIRCRAFT"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
38
src/main/resources/data/04-空域数据/20250923_02d1d0.xml
Normal file
38
src/main/resources/data/04-空域数据/20250923_02d1d0.xml
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<空域数据>
|
||||
<空域ID>A001</空域ID>
|
||||
<空域名称>训练空域Alpha</空域名称>
|
||||
<协调措施所属的大类型>军事训练</协调措施所属的大类型>
|
||||
<空域的具体协调措施类型>实弹射击</空域的具体协调措施类型>
|
||||
<空域管控状态>激活</空域管控状态>
|
||||
<空域生效时间段>
|
||||
<日期时间使用模式>周期执行</日期时间使用模式>
|
||||
<开始时间>2024-06-01T08:00:00</开始时间>
|
||||
<结束时间>2024-06-01T12:00:00</结束时间>
|
||||
<结束时间标识符>绝对时间</结束时间标识符>
|
||||
<间隔频率>每日</间隔频率>
|
||||
<间隔结束时间>2024-06-30T12:00:00</间隔结束时间>
|
||||
<相对时开始时间>P0D</相对时开始时间>
|
||||
<相对时结束数据>P4H</相对时结束数据>
|
||||
<时间类型>UTC</时间类型>
|
||||
</空域生效时间段>
|
||||
<代表空域相关的控制点>
|
||||
<控制点类型>中心点</控制点类型>
|
||||
<控制点名称>训练区中心</控制点名称>
|
||||
<控制点ID>CP001</控制点ID>
|
||||
<控制点的坐标位置经度>116.4074</控制点的坐标位置经度>
|
||||
<控制点的坐标位置纬度>39.9042</控制点的坐标位置纬度>
|
||||
<控制点的顶高>10000</控制点的顶高>
|
||||
<控制点的底高>0</控制点的底高>
|
||||
<是否隐藏控制点>false</是否隐藏控制点>
|
||||
</代表空域相关的控制点>
|
||||
<空域几何数据>
|
||||
<形状类型>圆形</形状类型>
|
||||
<几何数据信息>
|
||||
<经度>116.4074</经度>
|
||||
<纬度>39.9042</纬度>
|
||||
</几何数据信息>
|
||||
<数据点数目>1</数据点数目>
|
||||
</空域几何数据>
|
||||
<空域管控状态>限制使用</空域管控状态>
|
||||
</空域数据>
|
38
src/main/resources/data/04-空域数据/20250923_3929b4.xml
Normal file
38
src/main/resources/data/04-空域数据/20250923_3929b4.xml
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<空域数据>
|
||||
<空域ID>A003</空域ID>
|
||||
<空域名称>民航走廊Gamma</空域名称>
|
||||
<协调措施所属的大类型>民航运输</协调措施所属的大类型>
|
||||
<空域的具体协调措施类型>航线管制</空域的具体协调措施类型>
|
||||
<空域管控状态>部分限制</空域管控状态>
|
||||
<空域生效时间段>
|
||||
<日期时间使用模式>定时执行</日期时间使用模式>
|
||||
<开始时间>2024-06-01T06:00:00</开始时间>
|
||||
<结束时间>2024-06-01T22:00:00</结束时间>
|
||||
<结束时间标识符>绝对时间</结束时间标识符>
|
||||
<间隔频率>每日</间隔频率>
|
||||
<间隔结束时间>2024-12-31T22:00:00</间隔结束时间>
|
||||
<相对时开始时间>P0D</相对时开始时间>
|
||||
<相对时结束数据>P16H</相对时结束数据>
|
||||
<时间类型>LOCAL</时间类型>
|
||||
</空域生效时间段>
|
||||
<代表空域相关的控制点>
|
||||
<控制点类型>入口点</控制点类型>
|
||||
<控制点名称>走廊入口</控制点名称>
|
||||
<控制点ID>CP003</控制点ID>
|
||||
<控制点的坐标位置经度>116.5000</控制点的坐标位置经度>
|
||||
<控制点的坐标位置纬度>40.0000</控制点的坐标位置纬度>
|
||||
<控制点的顶高>12000</控制点的顶高>
|
||||
<控制点的底高>8000</控制点的底高>
|
||||
<是否隐藏控制点>true</是否隐藏控制点>
|
||||
</代表空域相关的控制点>
|
||||
<空域几何数据>
|
||||
<形状类型>走廊</形状类型>
|
||||
<几何数据信息>
|
||||
<经度>116.5000</经度>
|
||||
<纬度>40.0000</纬度>
|
||||
</几何数据信息>
|
||||
<数据点数目>2</数据点数目>
|
||||
</空域几何数据>
|
||||
<空域管控状态>管制运行</空域管控状态>
|
||||
</空域数据>
|
38
src/main/resources/data/04-空域数据/20250923_5da5e9.xml
Normal file
38
src/main/resources/data/04-空域数据/20250923_5da5e9.xml
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<空域数据>
|
||||
<空域ID>A002</空域ID>
|
||||
<空域名称>禁飞区Beta</空域名称>
|
||||
<协调措施所属的大类型>安全管制</协调措施所属的大类型>
|
||||
<空域的具体协调措施类型>永久禁飞</空域的具体协调措施类型>
|
||||
<空域管控状态>持续生效</空域管控状态>
|
||||
<空域生效时间段>
|
||||
<日期时间使用模式>永久生效</日期时间使用模式>
|
||||
<开始时间>2020-01-01T00:00:00</开始时间>
|
||||
<结束时间>2099-12-31T23:59:59</结束时间>
|
||||
<结束时间标识符>绝对时间</结束时间标识符>
|
||||
<间隔频率>无</间隔频率>
|
||||
<间隔结束时间>2099-12-31T23:59:59</间隔结束时间>
|
||||
<相对时开始时间>P0D</相对时开始时间>
|
||||
<相对时结束数据>P0D</相对时结束数据>
|
||||
<时间类型>UTC</时间类型>
|
||||
</空域生效时间段>
|
||||
<代表空域相关的控制点>
|
||||
<控制点类型>边界点</控制点类型>
|
||||
<控制点名称>禁飞区西南角</控制点名称>
|
||||
<控制点ID>CP002</控制点ID>
|
||||
<控制点的坐标位置经度>116.3000</控制点的坐标位置经度>
|
||||
<控制点的坐标位置纬度>39.8000</控制点的坐标位置纬度>
|
||||
<控制点的顶高>18000</控制点的顶高>
|
||||
<控制点的底高>0</控制点的底高>
|
||||
<是否隐藏控制点>false</是否隐藏控制点>
|
||||
</代表空域相关的控制点>
|
||||
<空域几何数据>
|
||||
<形状类型>多边形</形状类型>
|
||||
<几何数据信息>
|
||||
<经度>116.3000</经度>
|
||||
<纬度>39.8000</纬度>
|
||||
</几何数据信息>
|
||||
<数据点数目>5</数据点数目>
|
||||
</空域几何数据>
|
||||
<空域管控状态>完全禁止</空域管控状态>
|
||||
</空域数据>
|
275
src/main/resources/data/04-空域数据/default.json
Normal file
275
src/main/resources/data/04-空域数据/default.json
Normal file
@ -0,0 +1,275 @@
|
||||
{
|
||||
"conditionMap": {},
|
||||
"levelConfigs": [
|
||||
{
|
||||
"levelName": "platform",
|
||||
"subLevels": [
|
||||
{
|
||||
"comment": "空域生效时间配置",
|
||||
"levelName": "time_window",
|
||||
"subLevels": [],
|
||||
"valueConfigs": [
|
||||
{
|
||||
"comment": "日期时间使用模式",
|
||||
"valueName": "mode",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域生效时间段.日期时间使用模式"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "开始时间",
|
||||
"valueName": "start",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域生效时间段.开始时间"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "结束时间",
|
||||
"valueName": "end",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域生效时间段.结束时间"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "结束时间标识符",
|
||||
"valueName": "end_type",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域生效时间段.结束时间标识符"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "间隔频率",
|
||||
"valueName": "interval",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域生效时间段.间隔频率"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "间隔结束时间",
|
||||
"valueName": "interval_end",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域生效时间段.间隔结束时间"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "相对时开始时间",
|
||||
"valueName": "relative_start",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域生效时间段.相对时开始时间"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "相对时结束数据",
|
||||
"valueName": "relative_end",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域生效时间段.相对时结束数据"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "时间类型",
|
||||
"valueName": "time_format",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域生效时间段.时间类型"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": []
|
||||
},
|
||||
{
|
||||
"comment": "控制点ID和名称",
|
||||
"levelName": "control_point",
|
||||
"subLevels": [],
|
||||
"valueConfigs": [
|
||||
{
|
||||
"comment": "控制点类型",
|
||||
"valueName": "type",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.代表空域相关的控制点.控制点类型"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "控制点坐标(纬度,经度)",
|
||||
"valueName": "position",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域几何数据.几何数据信息.纬度N 空域数据.空域几何数据.几何数据信息.经度E"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "控制点顶高",
|
||||
"valueName": "top_altitude",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"unit": "m",
|
||||
"value": "空域数据.代表空域相关的控制点.控制点的顶高"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "控制点底高",
|
||||
"valueName": "bottom_altitude",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"unit": "m",
|
||||
"value": "空域数据.代表空域相关的控制点.控制点的底高"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "是否隐藏控制点(false表示显示)",
|
||||
"valueName": "visible",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.代表空域相关的控制点.是否隐藏控制点"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
"空域数据.代表空域相关的控制点.控制点ID",
|
||||
"空域数据.代表空域相关的控制点.控制点名称"
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "空域几何形状配置",
|
||||
"levelName": "geometry",
|
||||
"subLevels": [],
|
||||
"valueConfigs": [
|
||||
{
|
||||
"comment": "形状类型",
|
||||
"valueName": "shape",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域几何数据.形状类型"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "圆心坐标",
|
||||
"valueName": "center",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.代表空域相关的控制点.控制点的坐标位置纬度N 空域数据.代表空域相关的控制点.控制点的坐标位置经度E"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "数据点数目",
|
||||
"valueName": "point_count",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域几何数据.数据点数目"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": []
|
||||
}
|
||||
],
|
||||
"valueConfigs": [
|
||||
{
|
||||
"comment": "空域ID",
|
||||
"valueName": "id",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域ID"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "空域名称",
|
||||
"valueName": "name",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域名称"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "协调措施所属的大类型",
|
||||
"valueName": "category",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.协调措施所属的大类型"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "空域的具体协调措施类型",
|
||||
"valueName": "subcategory",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域的具体协调措施类型"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "空域管控状态",
|
||||
"valueName": "status",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "空域数据.空域管控状态"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"comment": "空域管控状态",
|
||||
"valueName": "control_status",
|
||||
"values": [
|
||||
{
|
||||
"combined": false,
|
||||
"value": "limit"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"values": [
|
||||
"airspace",
|
||||
"AERIAL_REGION"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
34
src/main/resources/data/11-完整数据/20250926.xml
Normal file
34
src/main/resources/data/11-完整数据/20250926.xml
Normal file
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<指令>
|
||||
<描述>
|
||||
<!-- label = "描述信息" -->
|
||||
<!-- isNull = "true" -->
|
||||
<!-- node = "XX_01" -->
|
||||
<!-- 时间格式 2025-9-26_10:23:11 -->
|
||||
<!--
|
||||
|
||||
-->
|
||||
<空中平台任务数据>1</空中平台任务数据>
|
||||
<任务K点>2</任务K点>
|
||||
<单个空中平台></单个空中平台>
|
||||
<任务航线></任务航线>
|
||||
<空域数据></空域数据>
|
||||
<空中指挥监视></空中指挥监视>
|
||||
<所辖任务></所辖任务>
|
||||
<空中打击></空中打击>
|
||||
<空中支援></空中支援>
|
||||
<任务包指挥></任务包指挥>
|
||||
<电子战></电子战>
|
||||
<空中巡逻></空中巡逻>
|
||||
<空中加油></空中加油>
|
||||
</描述>
|
||||
<详细>
|
||||
|
||||
</详细>
|
||||
<ACO>
|
||||
|
||||
</ACO>
|
||||
<SpinSL>
|
||||
|
||||
</SpinSL>
|
||||
</指令>
|
32
src/main/resources/data/stx-demo002/large_data.xml
Normal file
32
src/main/resources/data/stx-demo002/large_data.xml
Normal file
@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<employees>
|
||||
<employee id="101">
|
||||
<name>张三</name>
|
||||
<department>技术部</department>
|
||||
<salary>15000</salary>
|
||||
<skills>
|
||||
<skill>Java</skill>
|
||||
<skill>Spring</skill>
|
||||
<skill>MySQL</skill>
|
||||
</skills>
|
||||
</employee>
|
||||
<employee id="102">
|
||||
<name>李四</name>
|
||||
<department>市场部</department>
|
||||
<salary>12000</salary>
|
||||
<skills>
|
||||
<skill>市场营销</skill>
|
||||
<skill>客户关系</skill>
|
||||
</skills>
|
||||
</employee>
|
||||
<employee id="103">
|
||||
<name>王五</name>
|
||||
<department>技术部</department>
|
||||
<salary>18000</salary>
|
||||
<skills>
|
||||
<skill>Python</skill>
|
||||
<skill>机器学习</skill>
|
||||
<skill>Docker</skill>
|
||||
</skills>
|
||||
</employee>
|
||||
</employees>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user