根據XML生成實體類


  因為對接系統的XML所需映射的實體類有幾十個,自己來處理不太現實,於是一直找尋找這樣的工具,終於讓我發現了jaxb2-maven-plugin:

  http://www.mojohaus.org/jaxb2-maven-plugin/Documentation/v2.2/

  一鍵生成,使用也比較方便,但是需要在maven環境下,下面將介紹如果使用

  在maven工程下的pom.xml導入:

             <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxb2-maven-plugin</artifactId>
                <version>2.5.0</version>
                <executions>
                    <execution>
                        <id>id1</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>xjc</goal>
                        </goals>
                        <configuration>
                            <!-- XSD源文件 -->
                            <sources>
                                <source>src/main/xsd</source>
                            </sources>
                            <!-- 源碼輸出目錄 -->
                            <outputDirectory>target/generated-sources/jaxb</outputDirectory>
                            <!-- 指定文件生產 -->
                            <!--<schemaFiles>client_centric_data.xsd</schemaFiles>-->
                            <packageName>com.zgz.adsr</packageName>
                        </configuration>
                    </execution>
                </executions>
                <!--<configuration>-->
                    <!--&lt;!&ndash; The package of your generated sources &ndash;&gt;-->
                    <!--<packageName>com.zgz</packageName>-->
                <!--</configuration>-->
            </plugin>

  然后,在工程中是用mvn clean install就會生成源碼了。

  

  如果有多個XSD文件,可以不指定packageName,會自動分類,如果指定了,就所有實體類都在一起了,挺不方便的。可能是不清楚怎么設置,有清楚怎么設置的,麻煩評論讓我學習一下。

  下面說說,映射父節點的東東,因為請求的XML父節點要設置前綴以及各種東東的,例如下圖:

  

  可在生成的package-info.java文件中添加注解:

@javax.xml.bind.annotation.XmlSchema(
     // 注意這里,下面的XmlNs匹配了,就顯示ie前綴 namespace
= "http://www.shkf.com/rootelement", //子節點的設置 //elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, xmlns={ @XmlNs(prefix="ie", namespaceURI="http://www.xxx.com/rootelement"), @XmlNs(prefix="ie1", namespaceURI="http://www.xxx.com/subaccount"), @XmlNs(prefix="ie2", namespaceURI="http://www.xxx.com/ccd"), @XmlNs(prefix="simple", namespaceURI="http://www.xxx.com/simple"), @XmlNs(prefix="tcl", namespaceURI="http://www.xxx.com/tcl"), @XmlNs(prefix="xsi", namespaceURI="http://www.w3.org/2001/XMLSchema-instance")} )

  但是schemaLocation的設置就在請求實體轉換為XML的時候做設置:

  marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.xxx.com/rootelement root_elements.xsd ");

  或者在父節點實體類加個屬性值:

  @XmlAttribute(name ="xsi:schemaLocation")

  public String schemaLocation="http://www.xxx.com/rootelement root_elements.xsd ";

  還有一種方式設置前綴,繼承NamespacePrefixMapper,但跟着上面的屬性設置,好像會有點問題,具體還沒怎么研究。

  使用這方式需要引用依賴,不然會報錯。

        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.2.4-1</version>
        </dependency>

  如要去掉standalone,可參考:

  https://stackoverflow.com/questions/14152523/remove-standalone-yes-from-jaxb-generated-xml

  https://blog.csdn.net/weixin_39964562/article/details/79072277

import java.io.*;
import javax.xml.bind.*;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.stream.*;

@XmlRootElement
public class Login {

    private JAXBContext jaxbContext;
    private XMLOutputFactory xmlOutputFactory;

    public Login() {
        try {
            jaxbContext = JAXBContext.newInstance(Login.class);
            xmlOutputFactory = XMLOutputFactory.newFactory();
        } catch(Exception e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        Login demo = new Login();
        System.out.println(demo.getMessage());
    }

    public final String getMessage() {
        try {
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
            jaxbMarshaller.setProperty("jaxb.encoding", "ISO-8859-1");
            jaxbMarshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);

            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            XMLStreamWriter xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(baos, (String) jaxbMarshaller.getProperty(Marshaller.JAXB_ENCODING));
            xmlStreamWriter.writeStartDocument((String) jaxbMarshaller.getProperty(Marshaller.JAXB_ENCODING), "1.0");
            jaxbMarshaller.marshal(this, xmlStreamWriter);
            xmlStreamWriter.writeEndDocument();
            xmlStreamWriter.close();
            return new String(baos.toByteArray());
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

}

  JaxbUtil類:

package xxxx.util;


import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
//import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper;
import org.apache.commons.lang.StringUtils;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;

/**
 * @author GuangZe
 * @version v1.0
 * @project: vedio
 * @description: 這里描述類的用處
 * @copyright: © 2020
 * @company:
 * @date 2020/12/16 15:00
 */
public class JaxbUtil {

    public static String validate(String xml, String xsdPath) {
        String errMsg = null;
        String[] xmlArr;
        int lineNum;
        try {
            Source root = new StreamSource(JaxbUtil.class.getClassLoader()
                    .getResourceAsStream("xsd/root_elements.xsd"));

            Source code = new StreamSource(JaxbUtil.class.getClassLoader()
                    .getResourceAsStream("xsd/code_lists.xsd"));

            Source simple = new StreamSource(JaxbUtil.class.getClassLoader()
                    .getResourceAsStream("xsd/simple_types.xsd"));

            Source ccd = new StreamSource(JaxbUtil.class.getClassLoader()
                    .getResourceAsStream("xsd/client_centric_data.xsd"));

            Source customer = new StreamSource(JaxbUtil.class.getClassLoader()
                    .getResourceAsStream("xsd/customer_account.xsd"));

            Source sub = new StreamSource(JaxbUtil.class.getClassLoader()
                    .getResourceAsStream("xsd/sub_account.xsd"));

            Source trade = new StreamSource(JaxbUtil.class.getClassLoader()
                    .getResourceAsStream("xsd/trading_account.xsd"));

            Source[] sourceArr = {code, simple, ccd, customer, sub, trade, root};

            Schema schema = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(sourceArr);
            Validator validator = schema.newValidator();
            Source s = new StreamSource(new StringReader(xml));
            validator.validate(s);
        }catch (SAXParseException e){
            e.printStackTrace();
            xmlArr = xml.split("\n");
            lineNum = e.getLineNumber();
            errMsg = e.getMessage();
            if(lineNum<=xmlArr.length && StringUtils.isNotBlank(xmlArr[lineNum-1])){
                errMsg +="["+xmlArr[lineNum-1].trim()+"]";
            }
            System.out.println(errMsg);
        } catch (SAXException e1) {
            e1.printStackTrace();
            errMsg = e1.getMessage();
            System.out.println(errMsg);
        } catch (IOException e2) {
            e2.printStackTrace();
            errMsg = e2.getMessage();
            System.out.println(errMsg);
        }
        return errMsg;
    }

    /**
     * 序列化
     * @param object
     * @throws JAXBException
     */
    public static String marshall(Object object) throws JAXBException {
        // 通過映射的類創建XMLContext上下文對象,其中參數為映射的類。
        JAXBContext jaxbContext = JAXBContext.newInstance(object.getClass());
        // 通過JAXBComtext上下文對象的createMarshaller()方法,創建一個對象java格式轉化成XML的格式
        Marshaller marshaller = jaxbContext.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        //自定義前綴
//        NamespacePrefixMapper mapper = new PreferredMapper();
//        marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", mapper);
        marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://www.xxx.com/rootelement root_elements.xsd ");
        // 最后,將JAVA對象轉換到制定的輸出位置,其中的object為java對象。
        StringWriter writer = new StringWriter();
        marshaller.marshal(object, writer);
        return writer.toString();
    }

    /**
     * 解析
     * @param clazz
     * @param xml
     * @return
     * @throws Exception
     */
    public static Object unmarshaller(Class<?> clazz, String xml) throws Exception {
        if (StringUtils.isEmpty(xml)) {
            return null;
        }
        // 通過映射的類創建XMLComtext上下文對象,其中參數為映射的類。
        JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
        // 通過JAXBContext上下文對象創建createUnmarshaller()方法,創建XML轉換成JAVA對象的格式。
        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        // 最后,將XML轉換成對映的類,轉換后需要強制性轉換成映射的類
        StringReader stringReader = new StringReader(xml);
        Object object = unmarshaller.unmarshal(stringReader);
        return object;
    }

    public static class PreferredMapper extends NamespacePrefixMapper {
        @Override
        public String getPreferredPrefix(String namespaceUri,
                                         String suggestion, boolean requirePrefix) {
            if ("http://www.xxx.com/rootelement".equals(namespaceUri)) {
                return "ie";
            }
            return suggestion;
        }

    }

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM