微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

java.lang.IllegalStateException:Marshaller 必须支持编组对象的类

如何解决java.lang.IllegalStateException:Marshaller 必须支持编组对象的类

我在 spring-boot 应用程序中使用 spring batch。 Spring Boot 版本是 2.3.3.RELEASE我有一个复杂的 XML,其中包含 header文件信息)和 body(交易列表)。我使用 XJC toolXSD 获取 java 类。

为了重现这个错误,我在 Github spring-batch-xml-to-xml

添加代码

我需要做:我必须阅读(unmarshal) XML,在正文中做一些business logic on each transaction element,然后最后写({{1} }) 具有相同标题和更新正文的 XML 文件

当我尝试编组一个子元素对象时,我得到 IllegalStateException: Marshaller must support the class of the marshalled object。

示例 XML 文件

marshal

Spring 批量配置

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<reportFile xmlns="http://deutsche-boerse.com/DBRegHub" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://deutsche-boerse.com/DBRegHub regulatoryHubUpload_MiFIR_001.60.xsd">
    <fileinformation>
        <sender>11003220</sender>
        <timestamp>2020-12-23T09:05:34Z</timestamp>
        <environment>LOCAL</environment>
        <version>1.0</version>
    </fileinformation>
    <record>
        <transaction>
        </transaction>
        <transaction>
        </transaction>
        <transaction>
        </transaction>
    </record>
</reportFile>

从 XJC 工具生成的事务、报告和报告文件 java 类

package com.trax.europeangateway.config;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.itemprocessor;
import org.springframework.batch.item.ItemStreamReader;
import org.springframework.batch.item.support.Compositeitemprocessor;
import org.springframework.batch.item.support.CompositeItemWriter;
import org.springframework.batch.item.xml.StaxEventItemWriter;
import org.springframework.batch.item.xml.builder.StaxEventItemReaderBuilder;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.task.TaskExecutor;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.oxm.xstream.XStreamMarshaller;
import org.springframework.util.ClassUtils;
import org.springframework.web.client.RestTemplate;

import com.trax.europeangateway.itemprocessor.omegaxml.PIExtractoritemprocessor;
import com.trax.europeangateway.itemprocessor.omegaxml.PIRemoveritemprocessor;
import com.trax.europeangateway.itemwriter.omegaxml.EdsClientItemWriter;
import com.trax.europeangateway.itemwriter.omegaxml.ExtendedStaxEventItemWriter;
import com.trax.europeangateway.itemwriter.omegaxml.OmegaXmlFileWriter;
import com.trax.europeangateway.itemwriter.omegaxml.OmegaXmlFooterCallBack;
import com.trax.europeangateway.itemwriter.omegaxml.OmegaXmlHeaderCallBack;
import com.trax.europeangateway.listener.JobResultListener;
import com.trax.europeangateway.listener.StepResultListener;
import com.trax.europeangateway.model.dto.FileinformationHeaderDto;
import com.trax.europeangateway.model.dto.ProcessorWriterDto;
import com.trax.europeangateway.model.dto.xsd.omega.TransactionPositionReport;
import com.trax.europeangateway.service.ExtractHeaderOmegaXml;
import com.trax.europeangateway.util.FileUtils;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Configuration
@EnableBatchProcessing
public class BatchConfiguration {
    
    @Autowired
    PIExtractoritemprocessor pIExtractoritemprocessor;
    
    @Autowired
    StepResultListener stepResultListener;
    
    @Autowired
    JobBuilderFactory jobBuilderFactory;
     
    @Autowired
    StepBuilderFactory stepBuilderFactory;
    
    @Autowired
    private FileUtils fileUtils;
    
    @Qualifier("europeanGatewayJobExecutor")
    @Autowired
    private TaskExecutor taskExecutor;
    
    @Value( "${eugateway.batch.chunk.size}" )
    private int chunkSize;
    
    @Qualifier("euGatewayJobLauncher")
    @Bean
    public JobLauncher euGatewayJobLauncher(JobRepository jobRepository) throws Exception {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(jobRepository);
        jobLauncher.setTaskExecutor(taskExecutor);
        jobLauncher.afterPropertiesSet();
        return jobLauncher;
    }
    
    @JobScope
    @Bean (name = "extractHeaderStep")
    public Step extractHeaderStep(StepBuilderFactory steps,@Value("#{jobParameters['file.path']}") String path) {
        return steps.get("extractHeaderStep")
                .tasklet((contribution,chunkContext) -> {
                    FileinformationHeaderDto fileinformation = new ExtractHeaderOmegaXml().readHeader(path);
                    ExecutionContext jobExecutionContext =  chunkContext.getStepContext().getStepExecution().getJobExecution().getExecutionContext();
                    jobExecutionContext.put("file.information",fileinformation);
                    return RepeatStatus.FINISHED;
                }).build();
    }
    
    @JobScope
    @Bean (name = "extractAndReplacePersonalDataStep")
    public Step jobStep(ItemStreamReader<TransactionPositionReport> reader,Compositeitemprocessor<TransactionPositionReport,ProcessorWriterDto> processor,CompositeItemWriter<ProcessorWriterDto> writer,StepBuilderFactory stepBuilderFactory) {
        return stepBuilderFactory.get("extractAndReplacePersonalDataStep")
                .<TransactionPositionReport,ProcessorWriterDto>chunk(chunkSize)
                .reader(reader)
                .processor(processor)
                .writer(writer)
                .listener(stepResultListener)
                .build();
    }

    @Qualifier("omegaXmlJob")
    @Bean
    public Job extractPersonalDataJob(Step extractHeaderStep,Step extractAndReplacePersonalDataStep,JobResultListener jobListener,JobBuilderFactory jobBuilderFactory) {
        return jobBuilderFactory.get("extractAndReplacePersonalDataJob")
                .incrementer(new RunIdIncrementer())
                .start(extractHeaderStep)
                .next(extractAndReplacePersonalDataStep)
                .listener(jobListener)
                .build();
    }

    @Bean
    @StepScope
    public ItemStreamReader<TransactionPositionReport> itemReader(@Value("#{jobParameters['file.path']}") String path) {
        Jaxb2Marshaller transactionMarshaller = new Jaxb2Marshaller();
        transactionMarshaller.setMappedClass(TransactionPositionReport.class);
        transactionMarshaller.setPackagesToScan(ClassUtils.getPackageName(TransactionPositionReport.class));
        transactionMarshaller.setSupportJaxbElementClass(true);
        transactionMarshaller.setSupportDtd(true);
        log.debug("Generating StaxEventItemReader");
 
        return new StaxEventItemReaderBuilder<TransactionPositionReport>()
                .name("transactionPositionReport")
                .resource(new FileSystemResource(path))
                .addFragmentRootElements("transaction")
                .unmarshaller(transactionMarshaller)
                .build();
    }
    
    @Bean
    @JobScope
    OmegaXmlHeaderCallBack getomegaXmlHeaderCallBack(@Value("#{jobExecutionContext['file.information']}") FileinformationHeaderDto fileinformation){
        return new OmegaXmlHeaderCallBack(fileinformation);
    }
    
    @Bean
    OmegaXmlFooterCallBack getomegaXmlFooterCallBack(){
        return new OmegaXmlFooterCallBack();
    }
    
    @StepScope
    @Bean(name = "staxTransactionWriter")
    public StaxEventItemWriter<TransactionPositionReport> staxTransactionItemWriter(OmegaXmlHeaderCallBack omegaXmlHeaderCallBack,@Value("#{jobParameters['file.path']}") String path,@Value("#{jobParameters['submission.account']}") String submissionAccount) {
        Resource exportFileResource = new FileSystemResource(fileUtils.getoutputFilePath(path,submissionAccount));
 
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setSupportJaxbElementClass(true);
        marshaller.setClassesToBeBound(TransactionPositionReport.class);
        HashMap<String,String> rootElementAttribs = new HashMap<String,String>();
        rootElementAttribs.put("xmlns","http://deutsche-boerse.com/DBRegHub");
        rootElementAttribs.put("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
        rootElementAttribs.put("xsi:schemaLocation","http://deutsche-boerse.com/DBRegHub regulatoryHubUpload_MiFIR_001.60.xsd");
        
         ExtendedStaxEventItemWriter<TransactionPositionReport> writer = new ExtendedStaxEventItemWriter<TransactionPositionReport>();
         writer.setName("transactionWriter");
         writer.setVersion("1.0");
         writer.setResource(exportFileResource);
         writer.setMarshaller(marshaller);
         writer.setRoottagName("reportFile");
         writer.setRootElementAttributes(rootElementAttribs);
         writer.setHeaderCallback(omegaXmlHeaderCallBack);
         writer.setFooterCallback(getomegaXmlFooterCallBack());
         writer.setShouldDeleteIfEmpty(true);
         writer.setIndenting(true);
         return writer;
    }
    
    @StepScope
    @Bean
    public PIExtractoritemprocessor extractitemprocessor() {
        log.debug("Generating PIExtractoritemprocessor");
        return new PIExtractoritemprocessor();
    }
    
    @Bean
    public PIRemoveritemprocessor removeitemprocessor() {
        log.debug("Generating PIRemoveritemprocessor");
        return new PIRemoveritemprocessor();
    }
    
    @Bean
    @StepScope
    Compositeitemprocessor<TransactionPositionReport,ProcessorWriterDto> extractAndRemoveitemprocessor() {
        log.debug("Generating Compositeitemprocessor");
        Compositeitemprocessor<TransactionPositionReport,ProcessorWriterDto> itemprocessor = new Compositeitemprocessor<>();
        itemprocessor.setDelegates((List<? extends itemprocessor<?,?>>) Arrays.asList(extractitemprocessor(),removeitemprocessor()));
        return itemprocessor;
    }
    
    @Bean
    public EdsClientItemWriter<ProcessorWriterDto> edsClientItemWriter() {
        log.debug("Generating EdsClientItemWriter");
        return new EdsClientItemWriter<>();
    }
    
    @Bean
    @StepScope
    public OmegaXmlFileWriter<ProcessorWriterDto> omegaXmlFileWriter(OmegaXmlHeaderCallBack omegaXmlHeaderCallBack,@Value("#{jobParameters['submission.account']}") String submissionAccount) {
        log.debug("Generating OmegaXmlFileWriter");
        return new OmegaXmlFileWriter(staxTransactionItemWriter(omegaXmlHeaderCallBack,path,submissionAccount));
    }
    
    
    @Bean
    @StepScope
    public CompositeItemWriter<ProcessorWriterDto> compositeItemWriter(OmegaXmlHeaderCallBack omegaXmlHeaderCallBack,@Value("#{jobParameters['submission.account']}") String submissionAccount) {
        log.debug("Generating CompositeItemWriter");
        CompositeItemWriter<ProcessorWriterDto> compositeItemWriter = new CompositeItemWriter<>();
        compositeItemWriter.setDelegates(Arrays.asList(edsClientItemWriter(),omegaXmlFileWriter(omegaXmlHeaderCallBack,submissionAccount)));
        return compositeItemWriter;
    }
    
    @Bean
    public RestTemplate restTemplate() {
        log.debug("Generating RestTemplate");
        return new RestTemplate();
    }
}

尝试编组时得到的异常堆栈跟踪

//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation,v2.2.8-b130911.1802 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2021.05.18 at 02:21:55 PM BST 
//

   
import javax.xml.bind.annotation.XmlAccesstype;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;


/**
 * <p>Java class for transactionPositionReport complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType name="transactionPositionReport">
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="processingDetails" type="{http://deutsche-boerse.com/DBRegHub}processingDetails"/>
 *         &lt;element name="configurableFields" type="{http://deutsche-boerse.com/DBRegHub}configurableFields" minOccurs="0"/>
 *         &lt;element name="mifir" type="{http://deutsche-boerse.com/DBRegHub}mifirDetails" minOccurs="0"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccesstype.FIELD)
@XmlType(name = "transactionPositionReport",propOrder = {
    "processingDetails","configurableFields","mifir"
})
public class TransactionPositionReport {

    @XmlElement(required = true)
    protected ProcessingDetails processingDetails;
    protected ConfigurableFields configurableFields;
    protected MifirDetails mifir;

    /**
     * Gets the value of the processingDetails property.
     * 
     * @return
     *     possible object is
     *     {@link ProcessingDetails }
     *     
     */
    public ProcessingDetails getProcessingDetails() {
        return processingDetails;
    }

    /**
     * Sets the value of the processingDetails property.
     * 
     * @param value
     *     allowed object is
     *     {@link ProcessingDetails }
     *     
     */
    public void setProcessingDetails(ProcessingDetails value) {
        this.processingDetails = value;
    }

    /**
     * Gets the value of the configurableFields property.
     * 
     * @return
     *     possible object is
     *     {@link ConfigurableFields }
     *     
     */
    public ConfigurableFields getConfigurableFields() {
        return configurableFields;
    }

    /**
     * Sets the value of the configurableFields property.
     * 
     * @param value
     *     allowed object is
     *     {@link ConfigurableFields }
     *     
     */
    public void setConfigurableFields(ConfigurableFields value) {
        this.configurableFields = value;
    }

    /**
     * Gets the value of the mifir property.
     * 
     * @return
     *     possible object is
     *     {@link MifirDetails }
     *     
     */
    public MifirDetails getMifir() {
        return mifir;
    }

    /**
     * Sets the value of the mifir property.
     * 
     * @param value
     *     allowed object is
     *     {@link MifirDetails }
     *     
     */
    public void setMifir(MifirDetails value) {
        this.mifir = value;
    }

}


//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation,v2.2.8-b130911.1802 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2021.05.18 at 02:21:55 PM BST 
//


import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccesstype;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;


/**
 * <p>Java class for record complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType name="record">
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;choice>
 *         &lt;element name="transaction" type="{http://deutsche-boerse.com/DBRegHub}transactionPositionReport" maxOccurs="unbounded" minOccurs="0"/>
 *         &lt;element name="referencePartyDetails" type="{http://deutsche-boerse.com/DBRegHub}referencePartyDetails" maxOccurs="unbounded" minOccurs="0"/>
 *       &lt;/choice>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccesstype.FIELD)
@XmlType(name = "record",propOrder = {
    "transaction","referencePartyDetails"
})
public class Record {

    protected List<TransactionPositionReport> transaction;
    protected List<ReferencePartyDetails> referencePartyDetails;

    /**
     * Gets the value of the transaction property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,* not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the transaction property.
     * 
     * <p>
     * For example,to add a new item,do as follows:
     * <pre>
     *    getTransaction().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link TransactionPositionReport }
     * 
     * 
     */
    public List<TransactionPositionReport> getTransaction() {
        if (transaction == null) {
            transaction = new ArrayList<TransactionPositionReport>();
        }
        return this.transaction;
    }

    public List<ReferencePartyDetails> getReferencePartyDetails() {
        if (referencePartyDetails == null) {
            referencePartyDetails = new ArrayList<ReferencePartyDetails>();
        }
        return this.referencePartyDetails;
    }

}


import javax.xml.bind.annotation.XmlAccesstype;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;


/**
 * <p>Java class for anonymous complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType>
 *   &lt;complexContent>
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
 *       &lt;sequence>
 *         &lt;element name="fileinformation" type="{http://deutsche-boerse.com/DBRegHub}fileinformation"/>
 *         &lt;element name="record" type="{http://deutsche-boerse.com/DBRegHub}record"/>
 *       &lt;/sequence>
 *     &lt;/restriction>
 *   &lt;/complexContent>
 * &lt;/complexType>
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccesstype.FIELD)
@XmlType(name = "",propOrder = {
    "fileinformation","record"
})
@XmlRootElement(name = "reportFile")
public class ReportFile {

    @XmlElement(required = true)
    protected Fileinformation fileinformation;
    @XmlElement(required = true)
    protected Record record;

    /**
     * Gets the value of the fileinformation property.
     * 
     * @return
     *     possible object is
     *     {@link Fileinformation }
     *     
     */
    public Fileinformation getFileinformation() {
        return fileinformation;
    }

    /**
     * Sets the value of the fileinformation property.
     * 
     * @param value
     *     allowed object is
     *     {@link Fileinformation }
     *     
     */
    public void setFileinformation(Fileinformation value) {
        this.fileinformation = value;
    }

    /**
     * Gets the value of the record property.
     * 
     * @return
     *     possible object is
     *     {@link Record }
     *     
     */
    public Record getRecord() {
        return record;
    }

    /**
     * Sets the value of the record property.
     * 
     * @param value
     *     allowed object is
     *     {@link Record }
     *     
     */
    public void setRecord(Record value) {
        this.record = value;
    }

}

仅供参考:生成的 Java 类中,只有 java.lang.IllegalStateException: Marshaller must support the class of the marshalled object at org.springframework.util.Assert.state(Assert.java:76) ~[spring-core-5.2.8.RELEASE.jar:5.2.8.RELEASE] at org.springframework.batch.item.xml.StaxEventItemWriter.write(StaxEventItemWriter.java:767) ~[spring-batch-infrastructure-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.batch.item.xml.StaxEventItemWriter$$FastClassBySpringcglib$$d105dd1.invoke(<generated>) ~[spring-batch-infrastructure-4.2.4.RELEASE.jar:4.2.4.RELEASE] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.8.RELEASE.jar:5.2.8.RELEASE] at org.springframework.aop.framework.cglibAopProxy$cglibMethodInvocation.invokeJoinpoint(cglibAopProxy.java:771) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE] at org.springframework.aop.framework.cglibAopProxy$cglibMethodInvocation.proceed(cglibAopProxy.java:749) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE] at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:136) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE] at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE] at org.springframework.aop.framework.cglibAopProxy$cglibMethodInvocation.proceed(cglibAopProxy.java:749) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE] at org.springframework.aop.framework.cglibAopProxy$DynamicAdvisedInterceptor.intercept(cglibAopProxy.java:691) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE] at org.springframework.batch.item.xml.StaxEventItemWriter$$EnhancerBySpringcglib$$25cb8145.write(<generated>) ~[spring-batch-infrastructure-4.2.4.RELEASE.jar:4.2.4.RELEASE] at com.trax.europeangateway.itemwriter.omegaxml.OmegaXmlFileWriter.write(OmegaXmlFileWriter.java:37) ~[classes/:?] at com.trax.europeangateway.itemwriter.omegaxml.OmegaXmlFileWriter$$FastClassBySpringcglib$$48e7f3da.invoke(<generated>) ~[classes/:?] at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.8.RELEASE.jar:5.2.8.RELEASE] 类使用 ReportFile 进行注释。但是如果我用 @XmlRootElement 注释 transaction 类,我可以生成一个 XML 文件,但是输出文件中的所有事务标记都带有命名空间信息。

@XmlRootElement

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。