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());
|
// List<DomesticPharmaBaseInfo> list= XmlStringParser.parseVaccineManufacturers(xml,eventPojo.getSubType());
|
||||||
|
|
||||||
//解析并保存数据
|
//解析并保存数据
|
||||||
// XmlStringParser.parseXml(xml, "1011", data -> {
|
XmlStringParser.parseXml(xml, "1011", data -> {
|
||||||
// domesticPharmaBaseInfoService.save((DomesticPharmaBaseInfo) data);
|
domesticPharmaBaseInfoService.save((DomesticPharmaBaseInfo) data);
|
||||||
// });
|
});
|
||||||
|
|
||||||
List<DomesticProducer> producers = xmlParserService.parseMultiDataXml(
|
// List<DomesticProducer> producers = xmlParserService.parseMultiDataXml(
|
||||||
xml,
|
// xml,
|
||||||
VTTSBasic.class,
|
// DomesticProducer.class
|
||||||
DomesticProducer.class
|
// );
|
||||||
);
|
|
||||||
|
|
||||||
logger.info("解析后的数据条数:{}", producers.size());
|
logger.info("解析后的数据条数:{}", "");
|
||||||
|
|
||||||
return ResponseBuilder.success();
|
return ResponseBuilder.success();
|
||||||
}catch (Exception e){
|
}catch (Exception e){
|
||||||
|
|
|
@ -131,7 +131,8 @@ public class DomesticProducer extends BaseEntity<DomesticProducer>{
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getDatasetName() {
|
public String getDatasetName() {
|
||||||
return "境内药品生产企业基本信息数据子集";
|
return "境内药品生产企业基本信息数据子集1111";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -14,20 +14,17 @@ import java.util.List;
|
||||||
@XmlRootElement(name = "VTTSBasic")
|
@XmlRootElement(name = "VTTSBasic")
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
@XmlAccessorType(XmlAccessType.FIELD)
|
||||||
@Data
|
@Data
|
||||||
|
@XmlSeeAlso({DomesticProducer.class})
|
||||||
public class VTTSBasic<T> {
|
public class VTTSBasic<T> {
|
||||||
@XmlElement(name = "datasetName")
|
@XmlElement(name = "datasetName")
|
||||||
private String datasetName;
|
private String datasetName;
|
||||||
|
|
||||||
@XmlElementWrapper(name = "dataset")
|
@XmlElementWrapper(name = "dataset")
|
||||||
|
//@XmlElements(@XmlElement(name = "data"))
|
||||||
@XmlElement(name = "data")
|
@XmlElement(name = "data")
|
||||||
private List<T> dataset = new ArrayList<>(); // 必须初始化集合
|
// private List<T> dataset; // 必须初始化集合
|
||||||
|
private List<DomesticProducer> dataset;
|
||||||
|
|
||||||
// 确保有无参构造器
|
// 确保有无参构造器
|
||||||
public VTTSBasic() {}
|
public VTTSBasic() {}
|
||||||
|
|
||||||
// 添加@XmlSeeAlso指定实现类
|
|
||||||
@XmlSeeAlso({
|
|
||||||
DomesticProducer.class
|
|
||||||
})
|
|
||||||
public static class KnownTypes {}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,24 @@
|
||||||
package com.alihealth.d2d.provtest.service;
|
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.springframework.stereotype.Service;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
import javax.xml.XMLConstants;
|
import javax.xml.XMLConstants;
|
||||||
import javax.xml.bind.JAXBContext;
|
import javax.xml.bind.*;
|
||||||
import javax.xml.bind.JAXBElement;
|
|
||||||
import javax.xml.bind.Unmarshaller;
|
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
import javax.xml.stream.XMLInputFactory;
|
import javax.xml.stream.XMLInputFactory;
|
||||||
import javax.xml.stream.XMLStreamReader;
|
import javax.xml.stream.XMLStreamReader;
|
||||||
|
import javax.xml.transform.stream.StreamSource;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.List;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Jason
|
* @author Jason
|
||||||
|
@ -26,35 +27,104 @@ import java.util.List;
|
||||||
@Service
|
@Service
|
||||||
public class XmlParserService {
|
public class XmlParserService {
|
||||||
|
|
||||||
|
private static final Map<Class<?>, JAXBContext> CONTEXT_CACHE = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析包含多个data节点的XML
|
* 解析包含多个data节点的XML
|
||||||
* @param xml 完整XML内容
|
* @param xml 完整XML内容
|
||||||
* @param wrapperClass 外层包装类(如VTTSBasic.class)
|
|
||||||
* @param dataClass 内部data节点对应的实体类
|
* @param dataClass 内部data节点对应的实体类
|
||||||
*/
|
*/
|
||||||
public <T> List<T> parseMultiDataXml(
|
public <T> List<DomesticProducer> parseMultiDataXml(
|
||||||
String xml,
|
String xml,
|
||||||
Class<?> wrapperClass,
|
|
||||||
Class<T> dataClass) throws Exception {
|
Class<T> dataClass) throws Exception {
|
||||||
|
|
||||||
JAXBContext context = JAXBContext.newInstance(wrapperClass, dataClass);
|
// 1. 参数校验
|
||||||
Unmarshaller unmarshaller = context.createUnmarshaller();
|
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();
|
XMLInputFactory xif = XMLInputFactory.newInstance();
|
||||||
xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
|
xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
|
||||||
xif.setProperty(XMLInputFactory.SUPPORT_DTD, 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();
|
||||||
|
|
||||||
|
// 解析 XML
|
||||||
|
XMLStreamReader xsr = xif.createXMLStreamReader(reader);
|
||||||
|
JAXBElement<VTTSBasic> root = unmarshaller.unmarshal(xsr, VTTSBasic.class);
|
||||||
|
|
||||||
|
// 获取解析结果
|
||||||
|
VTTSBasic wrapper = root.getValue();
|
||||||
|
List<DomesticProducer> result = wrapper.getDataset();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
JAXBElement<?> root = unmarshaller.unmarshal(xsr, wrapperClass);
|
|
||||||
Field datasetField = wrapperClass.getDeclaredField("dataset");
|
|
||||||
datasetField.setAccessible(true);
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
List<T> result = (List<T>) datasetField.get(root.getValue());
|
public static <T> VTTSBasic<T> parseXml(String xml, Class<T> dataType) throws Exception {
|
||||||
|
JAXBContext context = getOrCreateContext(VTTSBasic.class, dataType);
|
||||||
|
|
||||||
return result != null ? result : Collections.emptyList();
|
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