diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed8368a --- /dev/null +++ b/.gitignore @@ -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 diff --git a/src/main/java/com/alihealth/d2d/provtest/controller/ProvTestServerController.java b/src/main/java/com/alihealth/d2d/provtest/controller/ProvTestServerController.java index f59ff6b..da29b5b 100644 --- a/src/main/java/com/alihealth/d2d/provtest/controller/ProvTestServerController.java +++ b/src/main/java/com/alihealth/d2d/provtest/controller/ProvTestServerController.java @@ -100,17 +100,16 @@ public class ProvTestServerController { // List 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 producers = xmlParserService.parseMultiDataXml( - xml, - VTTSBasic.class, - DomesticProducer.class - ); +// List producers = xmlParserService.parseMultiDataXml( +// xml, +// DomesticProducer.class +// ); - logger.info("解析后的数据条数:{}", producers.size()); + logger.info("解析后的数据条数:{}", ""); return ResponseBuilder.success(); }catch (Exception e){ diff --git a/src/main/java/com/alihealth/d2d/provtest/domain/DomesticProducer.java b/src/main/java/com/alihealth/d2d/provtest/domain/DomesticProducer.java index a6b0614..0664632 100644 --- a/src/main/java/com/alihealth/d2d/provtest/domain/DomesticProducer.java +++ b/src/main/java/com/alihealth/d2d/provtest/domain/DomesticProducer.java @@ -131,7 +131,8 @@ public class DomesticProducer extends BaseEntity{ @Override public String getDatasetName() { - return "境内药品生产企业基本信息数据子集"; + return "境内药品生产企业基本信息数据子集1111"; } -} \ No newline at end of file + +} diff --git a/src/main/java/com/alihealth/d2d/provtest/entity/VTTSBasic.java b/src/main/java/com/alihealth/d2d/provtest/entity/VTTSBasic.java index 1e87ce7..dd430ec 100644 --- a/src/main/java/com/alihealth/d2d/provtest/entity/VTTSBasic.java +++ b/src/main/java/com/alihealth/d2d/provtest/entity/VTTSBasic.java @@ -14,20 +14,17 @@ import java.util.List; @XmlRootElement(name = "VTTSBasic") @XmlAccessorType(XmlAccessType.FIELD) @Data +@XmlSeeAlso({DomesticProducer.class}) public class VTTSBasic { @XmlElement(name = "datasetName") private String datasetName; @XmlElementWrapper(name = "dataset") + //@XmlElements(@XmlElement(name = "data")) @XmlElement(name = "data") - private List dataset = new ArrayList<>(); // 必须初始化集合 + // private List dataset; // 必须初始化集合 + private List dataset; // 确保有无参构造器 public VTTSBasic() {} - - // 添加@XmlSeeAlso指定实现类 - @XmlSeeAlso({ - DomesticProducer.class - }) - public static class KnownTypes {} } diff --git a/src/main/java/com/alihealth/d2d/provtest/service/XmlParserService.java b/src/main/java/com/alihealth/d2d/provtest/service/XmlParserService.java index 3695b7c..bacdee8 100644 --- a/src/main/java/com/alihealth/d2d/provtest/service/XmlParserService.java +++ b/src/main/java/com/alihealth/d2d/provtest/service/XmlParserService.java @@ -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, JAXBContext> CONTEXT_CACHE = new ConcurrentHashMap<>(); + /** * 解析包含多个data节点的XML * @param xml 完整XML内容 - * @param wrapperClass 外层包装类(如VTTSBasic.class) * @param dataClass 内部data节点对应的实体类 */ - public List parseMultiDataXml( + public List parseMultiDataXml( String xml, - Class wrapperClass, Class 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 root = unmarshaller.unmarshal(xsr, VTTSBasic.class); +// +// // 5. 获取解析结果 +// VTTSBasic wrapper = root.getValue(); +// List 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 root = unmarshaller.unmarshal(xsr, VTTSBasic.class); - @SuppressWarnings("unchecked") - List result = (List) datasetField.get(root.getValue()); + // 获取解析结果 + VTTSBasic wrapper = root.getValue(); + List result = wrapper.getDataset(); - return result != null ? result : Collections.emptyList(); + return result; + } + } + + + @SuppressWarnings("unchecked") + public static VTTSBasic parseXml(String xml, Class dataType) throws Exception { + JAXBContext context = getOrCreateContext(VTTSBasic.class, dataType); + + Unmarshaller unmarshaller = context.createUnmarshaller(); + JAXBElement element = unmarshaller.unmarshal( + new StreamSource(new StringReader(xml)), + VTTSBasic.class + ); + + return element.getValue(); + } + + public static String toXml(VTTSBasic vttsBasic, Class 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); + } + }); } } diff --git a/target/classes/com/alihealth/d2d/provtest/controller/ProvTestServerController.class b/target/classes/com/alihealth/d2d/provtest/controller/ProvTestServerController.class index 898b51c..1ae921d 100644 Binary files a/target/classes/com/alihealth/d2d/provtest/controller/ProvTestServerController.class and b/target/classes/com/alihealth/d2d/provtest/controller/ProvTestServerController.class differ diff --git a/target/classes/com/alihealth/d2d/provtest/domain/DomesticProducer.class b/target/classes/com/alihealth/d2d/provtest/domain/DomesticProducer.class index 85407ce..5fe019f 100644 Binary files a/target/classes/com/alihealth/d2d/provtest/domain/DomesticProducer.class and b/target/classes/com/alihealth/d2d/provtest/domain/DomesticProducer.class differ diff --git a/target/classes/com/alihealth/d2d/provtest/entity/VTTSBasic$KnownTypes.class b/target/classes/com/alihealth/d2d/provtest/entity/VTTSBasic$KnownTypes.class deleted file mode 100644 index f32ab9e..0000000 Binary files a/target/classes/com/alihealth/d2d/provtest/entity/VTTSBasic$KnownTypes.class and /dev/null differ diff --git a/target/classes/com/alihealth/d2d/provtest/entity/VTTSBasic.class b/target/classes/com/alihealth/d2d/provtest/entity/VTTSBasic.class index 3f0b50d..8bbf188 100644 Binary files a/target/classes/com/alihealth/d2d/provtest/entity/VTTSBasic.class and b/target/classes/com/alihealth/d2d/provtest/entity/VTTSBasic.class differ diff --git a/target/classes/com/alihealth/d2d/provtest/service/XmlParserService.class b/target/classes/com/alihealth/d2d/provtest/service/XmlParserService.class index 8a9fd91..5db6331 100644 Binary files a/target/classes/com/alihealth/d2d/provtest/service/XmlParserService.class and b/target/classes/com/alihealth/d2d/provtest/service/XmlParserService.class differ diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst index e69de29..c79b389 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -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