feat(mms-mapping): test中添加XML字符串返回功能并优化JSON转XML性能测试
- 在IcdToXmlGenerateResult和IcdToXmlResponse中新增mappingXml字段存储生成的XML字符串 - 修改IcdToXmlResponseConverter将XML内容从savedPath改为mappingXml字段 - 更新IcdToXmlTaskAppService将XML转换结果从保存路径改为直接返回XML内容 - 重构JsonToXmlConversionService移除临时文件创建,直接返回XML字符串 - 在JsonToXmlConversionService中添加性能监控日志输出 - 新增JsonToXmlDebugRunner用于本地调试JSON转XML功能
This commit is contained in:
@@ -20,7 +20,7 @@ public class IcdToXmlResponseConverter {
|
||||
response.setLdInst(result.getLdInst());
|
||||
response.setSavedPath(result.getSavedPath());
|
||||
response.getProblems().addAll(result.getProblems());
|
||||
|
||||
response.setMappingXml(result.getMappingXml());
|
||||
if (result.getIndexAnalysis() != null && result.getIndexAnalysis().getCandidates() != null) {
|
||||
for (IndexCandidate candidate : result.getIndexAnalysis().getCandidates()) {
|
||||
IndexCandidateResponse candidateResponse = new IndexCandidateResponse();
|
||||
|
||||
@@ -55,37 +55,58 @@ public class JsonToXmlConversionService {
|
||||
List<InputStream> ruleStreams,
|
||||
IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception {
|
||||
|
||||
// 1. 反序列化JSON为MappingDocument对象
|
||||
MappingDocument mappingDocument = objectMapper.readValue(mappingJson, MappingDocument.class);
|
||||
long startTime = System.currentTimeMillis();
|
||||
System.out.println("[JSON转XML] 开始转换...");
|
||||
|
||||
// 2. 使用现有的规则引擎生成XML
|
||||
// 注意:这里复用RuleBasedXmlMappingService的核心逻辑
|
||||
// 但数据来源从ICD直接解析改为从MappingDocument提取
|
||||
String xmlContent = buildXmlFromMapping(mappingDocument, templateStream, ruleStreams, indexMapping);
|
||||
|
||||
// 3. 保存为临时文件
|
||||
Path tempPath = Files.createTempFile("converted_", ".xml");
|
||||
Files.write(tempPath, xmlContent.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
return tempPath.toString();
|
||||
try {
|
||||
MappingDocument mappingDocument = objectMapper.readValue(mappingJson, MappingDocument.class);
|
||||
|
||||
long parseTime = System.currentTimeMillis();
|
||||
System.out.println("[JSON转XML] JSON解析完成,耗时: " + (parseTime - startTime) + " ms");
|
||||
|
||||
String xmlContent = buildXmlFromMapping(mappingDocument, templateStream, ruleStreams, indexMapping);
|
||||
|
||||
long totalTime = System.currentTimeMillis() - startTime;
|
||||
System.out.println("[JSON转XML] 转换完成,总耗时: " + totalTime + " ms");
|
||||
|
||||
return xmlContent;
|
||||
} catch (Exception e) {
|
||||
long totalTime = System.currentTimeMillis() - startTime;
|
||||
System.err.println("[JSON转XML] 转换失败,已耗时: " + totalTime + " ms,错误: " + e.getMessage());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从MappingDocument构建XML内容
|
||||
*/
|
||||
private String buildXmlFromMapping(MappingDocument mappingDocument,
|
||||
InputStream templateStream,
|
||||
List<InputStream> ruleStreams,
|
||||
IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception {
|
||||
|
||||
long stepStart = System.currentTimeMillis();
|
||||
|
||||
String templateContent = readInputStreamToString(templateStream);
|
||||
|
||||
long templateTime = System.currentTimeMillis();
|
||||
System.out.println(" [步骤1] 读取模板完成,耗时: " + (templateTime - stepStart) + " ms");
|
||||
|
||||
String xmlContent = fillIedInfo(templateContent, mappingDocument);
|
||||
|
||||
long iedTime = System.currentTimeMillis();
|
||||
System.out.println(" [步骤2] 填充IED信息完成,耗时: " + (iedTime - templateTime) + " ms");
|
||||
|
||||
xmlContent = fillReportControlsFromMapping(xmlContent, mappingDocument);
|
||||
|
||||
long reportTime = System.currentTimeMillis();
|
||||
System.out.println(" [步骤3] 填充ReportControl完成,耗时: " + (reportTime - iedTime) + " ms");
|
||||
|
||||
xmlContent = applyRulesFromMapping(xmlContent, mappingDocument, ruleStreams, indexMapping);
|
||||
|
||||
long rulesTime = System.currentTimeMillis();
|
||||
System.out.println(" [步骤4] 应用规则完成,耗时: " + (rulesTime - reportTime) + " ms");
|
||||
|
||||
long totalStepTime = System.currentTimeMillis() - stepStart;
|
||||
System.out.println(" [buildXmlFromMapping] 总计耗时: " + totalStepTime + " ms");
|
||||
|
||||
return xmlContent;
|
||||
}
|
||||
|
||||
@@ -219,21 +240,40 @@ public class JsonToXmlConversionService {
|
||||
List<InputStream> ruleStreams,
|
||||
IcdToXmlMappingService.IndexMappingConfig indexMapping) throws Exception {
|
||||
|
||||
long stepStart = System.currentTimeMillis();
|
||||
|
||||
var mergedRules = mergeAllRulesDesc(ruleStreams, indexMapping);
|
||||
|
||||
long mergeTime = System.currentTimeMillis();
|
||||
System.out.println(" [规则合并] 耗时: " + (mergeTime - stepStart) + " ms,规则数: " + mergedRules.size());
|
||||
|
||||
var mappingMetrics = extractMetricsFromMapping(mappingDocument);
|
||||
|
||||
long extractTime = System.currentTimeMillis();
|
||||
System.out.println(" [指标提取] 耗时: " + (extractTime - mergeTime) + " ms,指标数: " + mappingMetrics.size());
|
||||
|
||||
System.out.println("========== 开始从JSON匹配规则 ==========");
|
||||
System.out.println("规则总数: " + mergedRules.size());
|
||||
System.out.println("JSON中指标总数: " + mappingMetrics.size());
|
||||
|
||||
var applicableRules = findApplicableRulesDesc(mergedRules, mappingMetrics);
|
||||
|
||||
long matchTime = System.currentTimeMillis();
|
||||
System.out.println(" [规则匹配] 耗时: " + (matchTime - extractTime) + " ms");
|
||||
|
||||
System.out.println("匹配成功: " + applicableRules.size() + " 条规则");
|
||||
System.out.println("匹配失败: " + (mergedRules.size() - applicableRules.size()) + " 条规则");
|
||||
|
||||
String resultXml = applyRulesToXml(xmlContent, applicableRules);
|
||||
|
||||
long applyTime = System.currentTimeMillis();
|
||||
System.out.println(" [规则应用] 耗时: " + (applyTime - matchTime) + " ms");
|
||||
|
||||
long totalApplyTime = System.currentTimeMillis() - stepStart;
|
||||
System.out.println(" [applyRulesFromMapping] 总计耗时: " + totalApplyTime + " ms");
|
||||
System.out.println("========== JSON规则匹配结束 ==========\n");
|
||||
|
||||
return applyRulesToXml(xmlContent, applicableRules);
|
||||
return resultXml;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,17 @@ public class IcdToXmlGenerateResult {
|
||||
private MappingDocument mappingDocument;
|
||||
private String savedPath;
|
||||
private List<String> problems = new ArrayList<String>();
|
||||
/** 生成成功后的 Xml 字符串。 */
|
||||
private String mappingXml;
|
||||
public String getMappingXml() {
|
||||
return mappingXml;
|
||||
}
|
||||
|
||||
public void setMappingXml(String mappingXml) {
|
||||
this.mappingXml = mappingXml;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public GenerateStatus getStatus() { return status; }
|
||||
public void setStatus(GenerateStatus status) { this.status = status; }
|
||||
|
||||
@@ -16,6 +16,16 @@ public class IcdToXmlResponse {
|
||||
private MappingDocumentResponse mappingDocument;
|
||||
private List<IndexCandidateResponse> indexCandidates = new ArrayList<IndexCandidateResponse>();
|
||||
private List<String> problems = new ArrayList<String>();
|
||||
/** 生成成功后的 Xml 字符串。 */
|
||||
private String mappingXml;
|
||||
public String getMappingXml() {
|
||||
return mappingXml;
|
||||
}
|
||||
|
||||
public void setMappingXml(String mappingXml) {
|
||||
this.mappingXml = mappingXml;
|
||||
}
|
||||
|
||||
public GenerateStatus getStatus() { return status; }
|
||||
public void setStatus(GenerateStatus status) { this.status = status; }
|
||||
public String getMessage() { return message; }
|
||||
|
||||
@@ -160,14 +160,14 @@ public class IcdToXmlTaskAppService {
|
||||
|
||||
|
||||
// 3. 从 JSON 转换为 XML
|
||||
String xmlPath = jsonToXmlConversionService.convertFromJson(
|
||||
String xmlContent = jsonToXmlConversionService.convertFromJson(
|
||||
mappingJson,
|
||||
templateStream,
|
||||
ruleStreams,
|
||||
icdToXmlMappingService.getIndexMapping()
|
||||
);
|
||||
|
||||
result.setSavedPath(xmlPath);
|
||||
result.setMappingXml(xmlContent);
|
||||
result.setStatus(GenerateStatus.SUCCESS);
|
||||
result.setMessage("XML 生成成功");
|
||||
return result;
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
package com.njcn.gather.icd.mapping.debug;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.njcn.gather.icd.mapping.component.IcdToXmlResponseConverter;
|
||||
import com.njcn.gather.icd.mapping.pojo.bo.IcdToXmlGenerateResult;
|
||||
import com.njcn.gather.icd.mapping.pojo.enums.GenerateStatus;
|
||||
import com.njcn.gather.icd.mapping.service.impl.IcdToXmlTaskAppService;
|
||||
import org.springframework.boot.Banner;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* JSON 转 XML 本地调试入口。
|
||||
*
|
||||
* 使用方式:
|
||||
* 1. 先通过 GetIcdMmsJsonDebugRunner 获取 mappingJson,或使用已有的 JSON 文件。
|
||||
* 2. 修改 MMS_JSON_FILE_PATH 指向包含 mappingJson 的文件路径。
|
||||
* 3. 直接运行 main,查看生成的 XML 内容。
|
||||
* 4. 可选:设置 SAVE_XML_TO_DISK = true 将 XML 保存到磁盘。
|
||||
*/
|
||||
public class JsonToXmlDebugRunner {
|
||||
|
||||
/**
|
||||
* 包含 mappingJson 的文件路径。
|
||||
* 文件格式:纯文本,内容为 getIcdMmsJson 接口返回的 mappingJson 字段值。
|
||||
* 或者完整的 MappingTaskResponse JSON(会自动提取 mappingJson 字段)。
|
||||
*/
|
||||
private static final String MMS_JSON_FILE_PATH = "D:/temp/mms-output/mapping.json";
|
||||
|
||||
/** 是否输出格式化 XML,便于人工查看。 */
|
||||
private static final boolean PRETTY_XML = true;
|
||||
|
||||
/** 是否把生成的 XML 写入磁盘。 */
|
||||
private static final boolean SAVE_XML_TO_DISK = true;
|
||||
|
||||
/** saveXmlToDisk=true 时使用的输出文件路径。 */
|
||||
private static final String OUTPUT_XML_PATH = "D:/temp/mms-output/generated-config.xml";
|
||||
|
||||
/** 是否打印详细的转换过程日志。 */
|
||||
private static final boolean VERBOSE_LOG = true;
|
||||
|
||||
public static void main(String[] args) {
|
||||
try (ConfigurableApplicationContext context = new SpringApplicationBuilder(DebugApplication.class)
|
||||
.web(WebApplicationType.NONE)
|
||||
.bannerMode(Banner.Mode.OFF)
|
||||
.logStartupInfo(false)
|
||||
.run(args)) {
|
||||
|
||||
IcdToXmlTaskAppService icdToXmlTaskAppService = context.getBean(IcdToXmlTaskAppService.class);
|
||||
IcdToXmlResponseConverter responseConverter = context.getBean(IcdToXmlResponseConverter.class);
|
||||
ObjectMapper objectMapper = createObjectMapper();
|
||||
|
||||
if (VERBOSE_LOG) {
|
||||
System.out.println("========== JSON 转 XML 调试开始 ==========");
|
||||
System.out.println("输入文件: " + MMS_JSON_FILE_PATH);
|
||||
System.out.println("输出文件: " + (SAVE_XML_TO_DISK ? OUTPUT_XML_PATH : "(不保存)"));
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
// 读取 JSON 文件
|
||||
String jsonContent = readJsonFile();
|
||||
if (VERBOSE_LOG) {
|
||||
System.out.println("✓ JSON 文件读取成功,长度: " + jsonContent.length() + " 字符");
|
||||
}
|
||||
|
||||
// 提取 mappingJson(可能是完整响应或纯 mappingJson)
|
||||
String mappingJson = extractMappingJson(jsonContent, objectMapper);
|
||||
if (VERBOSE_LOG) {
|
||||
System.out.println("✓ MappingJSON 提取成功,长度: " + mappingJson.length() + " 字符");
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
// 调用服务生成 XML
|
||||
if (VERBOSE_LOG) {
|
||||
System.out.println("正在转换 JSON 为 XML...");
|
||||
}
|
||||
IcdToXmlGenerateResult result = icdToXmlTaskAppService.generateXmlFromJson(mappingJson);
|
||||
|
||||
// 输出结果
|
||||
printResult(result, objectMapper);
|
||||
|
||||
// 保存 XML 到磁盘
|
||||
if (SAVE_XML_TO_DISK && result.getStatus() == GenerateStatus.SUCCESS) {
|
||||
saveXmlToDisk(result.getMappingXml());
|
||||
}
|
||||
|
||||
if (VERBOSE_LOG) {
|
||||
System.out.println();
|
||||
System.out.println("========== JSON 转 XML 调试结束 ==========");
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException("JSON 转 XML 调试失败:" + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 读取 JSON 文件内容。
|
||||
*/
|
||||
private static String readJsonFile() {
|
||||
Path jsonPath = Paths.get(MMS_JSON_FILE_PATH);
|
||||
if (!Files.exists(jsonPath)) {
|
||||
throw new IllegalArgumentException("JSON 文件不存在:" + jsonPath.toAbsolutePath());
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] bytes = Files.readAllBytes(jsonPath);
|
||||
return new String(bytes, StandardCharsets.UTF_8);
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalArgumentException("读取 JSON 文件失败:" + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 JSON 内容中提取 mappingJson。
|
||||
* 支持两种格式:
|
||||
* 1. 完整的 MappingTaskResponse JSON(包含 mappingJson 字段)
|
||||
* 2. 纯 mappingJson 字符串
|
||||
*/
|
||||
private static String extractMappingJson(String jsonContent, ObjectMapper objectMapper) {
|
||||
try {
|
||||
// 尝试解析为对象,看是否包含 mappingJson 字段
|
||||
if (jsonContent.trim().startsWith("{")) {
|
||||
java.util.Map<String, Object> jsonMap = objectMapper.readValue(
|
||||
jsonContent,
|
||||
java.util.Map.class
|
||||
);
|
||||
|
||||
if (jsonMap.containsKey("mappingJson")) {
|
||||
Object mappingJsonObj = jsonMap.get("mappingJson");
|
||||
if (mappingJsonObj != null) {
|
||||
return mappingJsonObj.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果不是对象或不包含 mappingJson,则假设整个内容就是 mappingJson
|
||||
return jsonContent;
|
||||
} catch (Exception ex) {
|
||||
// 如果解析失败,也假设整个内容就是 mappingJson
|
||||
return jsonContent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印转换结果。
|
||||
*/
|
||||
private static void printResult(IcdToXmlGenerateResult result, ObjectMapper objectMapper) {
|
||||
System.out.println();
|
||||
System.out.println("===== 转换结果 =====");
|
||||
System.out.println("状态: " + result.getStatus());
|
||||
System.out.println("消息: " + result.getMessage());
|
||||
|
||||
if (result.getProblems() != null && !result.getProblems().isEmpty()) {
|
||||
System.out.println("问题列表:");
|
||||
for (String problem : result.getProblems()) {
|
||||
System.out.println(" - " + problem);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.getStatus() == GenerateStatus.SUCCESS) {
|
||||
System.out.println();
|
||||
System.out.println("----- 生成的 XML 内容 -----");
|
||||
String xmlContent = result.getMappingXml();
|
||||
|
||||
if (PRETTY_XML) {
|
||||
// 简单格式化:每个标签独占一行
|
||||
xmlContent = formatXml(xmlContent);
|
||||
}
|
||||
|
||||
System.out.println(xmlContent);
|
||||
System.out.println("--------------------------");
|
||||
System.out.println();
|
||||
System.out.println("XML 长度: " + result.getMappingXml().length() + " 字符");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 简单的 XML 格式化。
|
||||
*/
|
||||
private static String formatXml(String xml) {
|
||||
if (xml == null || xml.isEmpty()) {
|
||||
return xml;
|
||||
}
|
||||
|
||||
// 在标签前后添加换行
|
||||
String formatted = xml.replaceAll(">", ">\n")
|
||||
.replaceAll("<", "\n<")
|
||||
.replaceAll("\n\n", "\n");
|
||||
|
||||
// 简单的缩进处理
|
||||
StringBuilder result = new StringBuilder();
|
||||
int indentLevel = 0;
|
||||
String[] lines = formatted.split("\n");
|
||||
|
||||
for (String line : lines) {
|
||||
line = line.trim();
|
||||
if (line.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 如果是闭合标签,减少缩进
|
||||
if (line.startsWith("</") && !line.endsWith("/>")) {
|
||||
indentLevel = Math.max(0, indentLevel - 1);
|
||||
}
|
||||
|
||||
// 添加缩进
|
||||
for (int i = 0; i < indentLevel; i++) {
|
||||
result.append(" ");
|
||||
}
|
||||
result.append(line).append("\n");
|
||||
|
||||
// 如果是开始标签且不是自闭合,增加缩进
|
||||
if (line.startsWith("<") && !line.startsWith("</")
|
||||
&& !line.endsWith("/>") && !line.endsWith(">")) {
|
||||
indentLevel++;
|
||||
}
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存 XML 到磁盘。
|
||||
*/
|
||||
private static void saveXmlToDisk(String xmlContent) {
|
||||
try {
|
||||
Path outputPath = Paths.get(OUTPUT_XML_PATH);
|
||||
|
||||
// 创建父目录
|
||||
if (outputPath.getParent() != null && !Files.exists(outputPath.getParent())) {
|
||||
Files.createDirectories(outputPath.getParent());
|
||||
}
|
||||
|
||||
Files.write(outputPath, xmlContent.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
System.out.println("✓ XML 已保存到: " + outputPath.toAbsolutePath());
|
||||
System.out.println(" 文件大小: " + Files.size(outputPath) + " 字节");
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalStateException("保存 XML 文件失败:" + ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static ObjectMapper createObjectMapper() {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
return objectMapper;
|
||||
}
|
||||
|
||||
@SpringBootApplication(scanBasePackages = "com.njcn.gather.icd.mapping")
|
||||
public static class DebugApplication {
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user