This commit is contained in:
parent
9b6996e024
commit
2857b0c4d7
|
@ -0,0 +1,47 @@
|
|||
######################################################################
|
||||
# Build Tools
|
||||
|
||||
.gradle
|
||||
/build/
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
######################################################################
|
||||
# IDE
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### JRebel ###
|
||||
rebel.xml
|
||||
|
||||
### NetBeans ###
|
||||
nbproject/private/
|
||||
build/*
|
||||
nbbuild/
|
||||
dist/
|
||||
nbdist/
|
||||
.nb-gradle/
|
||||
|
||||
######################################################################
|
||||
# Others
|
||||
*.log
|
||||
*.xml.versionsBackup
|
||||
*.swp
|
||||
|
||||
!*/build/*.java
|
||||
!*/build/*.html
|
||||
!*/build/*.xml
|
|
@ -100,17 +100,16 @@ public class ProvTestServerController {
|
|||
// List<DomesticPharmaBaseInfo> list= XmlStringParser.parseVaccineManufacturers(xml,eventPojo.getSubType());
|
||||
|
||||
//解析并保存数据
|
||||
// XmlStringParser.parseXml(xml, "1011", data -> {
|
||||
// domesticPharmaBaseInfoService.save((DomesticPharmaBaseInfo) data);
|
||||
// });
|
||||
XmlStringParser.parseXml(xml, "1011", data -> {
|
||||
domesticPharmaBaseInfoService.save((DomesticPharmaBaseInfo) data);
|
||||
});
|
||||
|
||||
List<DomesticProducer> producers = xmlParserService.parseMultiDataXml(
|
||||
xml,
|
||||
VTTSBasic.class,
|
||||
DomesticProducer.class
|
||||
);
|
||||
// List<DomesticProducer> producers = xmlParserService.parseMultiDataXml(
|
||||
// xml,
|
||||
// DomesticProducer.class
|
||||
// );
|
||||
|
||||
logger.info("解析后的数据条数:{}", producers.size());
|
||||
logger.info("解析后的数据条数:{}", "");
|
||||
|
||||
return ResponseBuilder.success();
|
||||
}catch (Exception e){
|
||||
|
|
|
@ -131,7 +131,8 @@ public class DomesticProducer extends BaseEntity<DomesticProducer>{
|
|||
|
||||
@Override
|
||||
public String getDatasetName() {
|
||||
return "境内药品生产企业基本信息数据子集";
|
||||
return "境内药品生产企业基本信息数据子集1111";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,20 +14,17 @@ import java.util.List;
|
|||
@XmlRootElement(name = "VTTSBasic")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@Data
|
||||
@XmlSeeAlso({DomesticProducer.class})
|
||||
public class VTTSBasic<T> {
|
||||
@XmlElement(name = "datasetName")
|
||||
private String datasetName;
|
||||
|
||||
@XmlElementWrapper(name = "dataset")
|
||||
//@XmlElements(@XmlElement(name = "data"))
|
||||
@XmlElement(name = "data")
|
||||
private List<T> dataset = new ArrayList<>(); // 必须初始化集合
|
||||
// private List<T> dataset; // 必须初始化集合
|
||||
private List<DomesticProducer> dataset;
|
||||
|
||||
// 确保有无参构造器
|
||||
public VTTSBasic() {}
|
||||
|
||||
// 添加@XmlSeeAlso指定实现类
|
||||
@XmlSeeAlso({
|
||||
DomesticProducer.class
|
||||
})
|
||||
public static class KnownTypes {}
|
||||
}
|
||||
|
|
|
@ -1,23 +1,24 @@
|
|||
package com.alihealth.d2d.provtest.service;
|
||||
|
||||
import com.alihealth.d2d.provtest.domain.DomesticProducer;
|
||||
import com.alihealth.d2d.provtest.entity.VTTSBasic;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.bind.*;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Jason
|
||||
|
@ -26,35 +27,104 @@ import java.util.List;
|
|||
@Service
|
||||
public class XmlParserService {
|
||||
|
||||
private static final Map<Class<?>, JAXBContext> CONTEXT_CACHE = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* 解析包含多个data节点的XML
|
||||
* @param xml 完整XML内容
|
||||
* @param wrapperClass 外层包装类(如VTTSBasic.class)
|
||||
* @param dataClass 内部data节点对应的实体类
|
||||
*/
|
||||
public <T> List<T> parseMultiDataXml(
|
||||
public <T> List<DomesticProducer> parseMultiDataXml(
|
||||
String xml,
|
||||
Class<?> wrapperClass,
|
||||
Class<T> dataClass) throws Exception {
|
||||
|
||||
JAXBContext context = JAXBContext.newInstance(wrapperClass, dataClass);
|
||||
Unmarshaller unmarshaller = context.createUnmarshaller();
|
||||
// 1. 参数校验
|
||||
if (xml == null || xml.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("XML内容不能为空");
|
||||
}
|
||||
|
||||
// 使用StAX提高安全性
|
||||
// 2. 创建包含包装类和数据类的JAXB上下文
|
||||
JAXBContext context = JAXBContext.newInstance(
|
||||
VTTSBasic.class,
|
||||
dataClass // 包含实际要解析的数据类型
|
||||
);
|
||||
// 3. 配置安全的Unmarshaller(防止XXE攻击)
|
||||
Unmarshaller unmarshaller = context.createUnmarshaller();
|
||||
XMLInputFactory xif = XMLInputFactory.newInstance();
|
||||
xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
|
||||
xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
|
||||
|
||||
XMLStreamReader xsr = xif.createXMLStreamReader(new StringReader(xml));
|
||||
// 4. 解析XML
|
||||
try (StringReader reader = new StringReader(xml)) {
|
||||
// XMLStreamReader xsr = xif.createXMLStreamReader(reader);
|
||||
// JAXBElement<VTTSBasic> root = unmarshaller.unmarshal(xsr, VTTSBasic.class);
|
||||
//
|
||||
// // 5. 获取解析结果
|
||||
// VTTSBasic<T> wrapper = root.getValue();
|
||||
// List<T> result = wrapper.getDataset();
|
||||
//
|
||||
// // 6. 类型安全检查
|
||||
// if (!result.isEmpty() && !dataClass.isInstance(result.get(0))) {
|
||||
// throw new ClassCastException("XML中包含类型不匹配的数据");
|
||||
// }
|
||||
//
|
||||
// return result;
|
||||
// 创建 JAXBContext 时包含所有相关类
|
||||
// JAXBContext jc = JAXBContext.newInstance(VTTSBasic.class, Data.class);
|
||||
//Unmarshaller unmarshaller = jc.createUnmarshaller();
|
||||
|
||||
JAXBElement<?> root = unmarshaller.unmarshal(xsr, wrapperClass);
|
||||
Field datasetField = wrapperClass.getDeclaredField("dataset");
|
||||
datasetField.setAccessible(true);
|
||||
// 解析 XML
|
||||
XMLStreamReader xsr = xif.createXMLStreamReader(reader);
|
||||
JAXBElement<VTTSBasic> root = unmarshaller.unmarshal(xsr, VTTSBasic.class);
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
List<T> result = (List<T>) datasetField.get(root.getValue());
|
||||
// 获取解析结果
|
||||
VTTSBasic wrapper = root.getValue();
|
||||
List<DomesticProducer> result = wrapper.getDataset();
|
||||
|
||||
return result != null ? result : Collections.emptyList();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> VTTSBasic<T> parseXml(String xml, Class<T> dataType) throws Exception {
|
||||
JAXBContext context = getOrCreateContext(VTTSBasic.class, dataType);
|
||||
|
||||
Unmarshaller unmarshaller = context.createUnmarshaller();
|
||||
JAXBElement<VTTSBasic> element = unmarshaller.unmarshal(
|
||||
new StreamSource(new StringReader(xml)),
|
||||
VTTSBasic.class
|
||||
);
|
||||
|
||||
return element.getValue();
|
||||
}
|
||||
|
||||
public static <T> String toXml(VTTSBasic<T> vttsBasic, Class<T> dataType) throws Exception {
|
||||
JAXBContext context = getOrCreateContext(VTTSBasic.class, dataType);
|
||||
|
||||
Marshaller marshaller = context.createMarshaller();
|
||||
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
marshaller.marshal(vttsBasic, writer);
|
||||
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
private static JAXBContext getOrCreateContext(Class<?>... classes) throws JAXBException {
|
||||
String key = Arrays.stream(classes)
|
||||
.map(Class::getName)
|
||||
.sorted()
|
||||
.collect(Collectors.joining("|"));
|
||||
|
||||
return CONTEXT_CACHE.computeIfAbsent(key.getClass(), k -> {
|
||||
try {
|
||||
// 为泛型类型创建JAXB上下文
|
||||
return JAXBContext.newInstance(classes);
|
||||
} catch (JAXBException e) {
|
||||
throw new RuntimeException("Failed to create JAXBContext", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,27 @@
|
|||
com\alihealth\d2d\provtest\entity\BaseEntity.class
|
||||
com\alihealth\d2d\provtest\factory\EntityFactoryManager.class
|
||||
com\alihealth\d2d\provtest\utils\XmlStringParser.class
|
||||
com\alihealth\d2d\provtest\service\impl\DomesticPharmaBaseInfoServiceImpl.class
|
||||
com\alihealth\d2d\provtest\service\XmlParserService.class
|
||||
com\alihealth\d2d\provtest\mapper\DomesticPharmaBaseInfoMapper.class
|
||||
com\alihealth\d2d\provtest\service\IDomesticPharmaBaseInfoService.class
|
||||
com\alihealth\d2d\provtest\utils\RequestWrapper$1.class
|
||||
com\alihealth\d2d\provtest\utils\RequestWrapper.class
|
||||
com\alihealth\d2d\provtest\domain\DomesticPharmaBaseInfo.class
|
||||
com\alihealth\d2d\provtest\utils\BouncyCastlePFXGenerator.class
|
||||
com\alihealth\d2d\provtest\utils\EventPojo.class
|
||||
com\alihealth\d2d\provtest\factory\DomesticPharmaBaseInfoFactory.class
|
||||
com\alihealth\d2d\provtest\utils\Base64.class
|
||||
com\alihealth\d2d\provtest\utils\StreamUtil.class
|
||||
com\alihealth\d2d\provtest\controller\ProvTestServerController.class
|
||||
com\alihealth\d2d\provtest\factory\EntityFactory.class
|
||||
com\alihealth\d2d\provtest\utils\EntityProcessor.class
|
||||
com\alihealth\d2d\provtest\entity\XmlEntity.class
|
||||
com\alihealth\d2d\provtest\utils\KeyStoreUtil.class
|
||||
com\alihealth\d2d\provtest\enums\BuzStatusEnum.class
|
||||
com\alihealth\d2d\provtest\enums\StatusEnum.class
|
||||
com\alihealth\d2d\provtest\domain\DomesticProducer.class
|
||||
com\alihealth\d2d\provtest\ProvtestApplication.class
|
||||
com\alihealth\d2d\provtest\entity\VTTSBasic.class
|
||||
com\alihealth\d2d\provtest\ProvTestClient.class
|
||||
com\alihealth\d2d\provtest\utils\ResponseBuilder.class
|
Loading…
Reference in New Issue