免费国产精品自在自线-91精品国产色综合久久久浪潮-99热久久免费频精品-国产精品国模在线观看-久久亚洲国产精品成人?V秋霞-久久国产一级A片免费播放-亚洲国产欧洲综合97久久-久久国产白嫩美女呻吟高潮

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營的一線實(shí)戰(zhàn)洞察。

XSD到Java:用XJC代碼生成器高效解析XML Schema實(shí)戰(zhàn)指南

XSD到Java:用XJC代碼生成器高效解析XML Schema實(shí)戰(zhàn)指南 前陣子對接一個(gè)外部供應(yīng)商接口對方丟了個(gè) XSD-7 數(shù)據(jù)契約文檔過來沒有現(xiàn)成的 SDK只給了一份 XML Schema 規(guī)范和樣例報(bào)文。當(dāng)時(shí)項(xiàng)目時(shí)間很緊報(bào)文結(jié)構(gòu)特別復(fù)雜嵌套十幾個(gè)層級還有一堆枚舉、擴(kuò)展類型和 choice 分支。如果按老套路手寫 Java 映射類光對字段就得耗掉小一周而且容易出現(xiàn)類型對不上、枚舉漏掉值這種低級錯(cuò)誤。后來直接上了 XJC 代碼生成器JAXB 編譯器把 XSD-7 文檔喂進(jìn)去一套 Java Bean 全部自動(dòng)生成幾分鐘就把這個(gè)硬骨頭啃下來了。如果你也是做 Java 服務(wù)端對接、處理 XML 報(bào)文、或者被各種 XSD 文檔折磨過的開發(fā)者這篇文章應(yīng)該能幫你少走不少彎路。我會(huì)把 XSD 如何映射成 Java 類的底層邏輯、XJC 命令行的完整使用姿勢、以及我實(shí)戰(zhàn)中踩過的坑和對應(yīng)的外部綁定文件寫法都整理出來算是一份可以直接拿去用的實(shí)操筆記。這篇文章基于我自己在實(shí)際項(xiàng)目里使用 XJC 的經(jīng)驗(yàn)結(jié)合一份名為 XSD-7 的 XML Schema 契約文檔逐步展開。所有示例均為虛構(gòu)數(shù)據(jù)但處理思路和命令用法都是實(shí)打?qū)嵉摹?. XSD-7 這份數(shù)據(jù)契約到底在描述什么先別急著敲命令我建議任何人拿到 XSD 文件的第一件事都不是生成代碼而是先把這份 Schema 從頭到尾讀一遍。以 XSD-7 為例這其實(shí)是一份交易報(bào)文級的 XML Schema 文檔定義了多個(gè)全局元素和復(fù)雜類型。XML SchemaXSD本身就是用來描述 XML 文檔結(jié)構(gòu)的“合同”它會(huì)告訴你哪些元素存在、元素之間的嵌套關(guān)系、數(shù)據(jù)類型、取值范圍、是否必填、出現(xiàn)次數(shù)等等。XJC 所做的就是把這份“合同”用 Java 語言重新表達(dá)一遍生成一套對應(yīng)的 Java 類核心就是把 XML 世界里的復(fù)雜類型映射成 Java 里的類把元素和屬性映射成字段把簡單類型映射成 String、Integer 之類的 Java 類型然后通過 JAXB 注解把這些映射關(guān)系記錄下來。1.1 讀懂 XSD-7 里最常見的三種類型聲明XSD-7 這種文檔大量出現(xiàn)的無非是這幾種聲明xs:element、xs:complexType、xs:simpleType。xs:element就是定義某個(gè) XML 元素的名稱和類型xs:complexType代表一個(gè)結(jié)構(gòu)體內(nèi)部可以有子元素或?qū)傩詘s:simpleType則是一個(gè)約束了取值范圍的簡單類型通常配合xs:restriction使用比如限制成一個(gè)枚舉。比如 XSD-7 里經(jīng)常能看到類似下面這種片段xs:complexType nameOrderInfo xs:sequence xs:element nameorderId typexs:string/ xs:element nameamount typexs:decimal/ xs:element namecurrency typeCurrencyCode/ /xs:sequence xs:attribute nameversion typexs:string userequired/ /xs:complexType這個(gè)OrderInfo復(fù)雜類型翻譯成人話就是一個(gè)訂單信息結(jié)構(gòu)體里面依次有訂單號字符串、金額小數(shù)、幣種枚舉并且掛著 一個(gè)必填的 version 屬性。XJC 拿到這段定義之后會(huì)生成一個(gè)名為OrderInfo的 Java 類類里有orderId、amount、currency三個(gè)字段以及一個(gè)version屬性字段全部用XmlElement、XmlAttribute注解標(biāo)注清楚。1.2 別忽略 targetNamespace 和 import/includeXSD-7 這種正式契約文檔幾乎一定會(huì)有targetNamespace這決定了生成 Java 類的包名級 XML 命名空間映射。比如聲明了targetNamespacehttp://example.com/trade/order默認(rèn)情況下 XJC 會(huì)根據(jù)這個(gè)命名空間生成一個(gè)包名。還有xs:include和xs:import這種跨文件引用——XSD-7 很可能是由主文件加若干子 Schema 組成的主文件 include 了其他文件里的公共類型。處理這種多文件結(jié)構(gòu)時(shí)不要用單個(gè) xjc 命令去裸編譯而是要把整個(gè)文件集合放在同一個(gè)目錄、直接用主文件作為入口參數(shù)否則會(huì)出現(xiàn)找不到類型的報(bào)錯(cuò)。拿到一份 XSD先花 20 分鐘把頂層設(shè)計(jì)、命名空間、include 關(guān)系理清楚這比上來就跑命令省事得多。因?yàn)?XJC 報(bào)錯(cuò)的很多問題本質(zhì)上都是文檔結(jié)構(gòu)沒理清導(dǎo)致的。2. 從 XSD 到 Java 的映射算法XJC 編譯器的底層工作邏輯很多人用過 XJC但它內(nèi)部到底按什么規(guī)則把 XSD 轉(zhuǎn)換成 Java其實(shí)說不清楚。這塊搞明白了后面很多坑你都能提前避開因?yàn)閹缀跛械摹盀槭裁瓷沙鰜硎沁@樣的類”都能在這個(gè)映射邏輯里找到答案。2.1 復(fù)雜類型和元素類與字段的對應(yīng)規(guī)則在 XJC 的世界里一個(gè)xs:complexType大多數(shù)情況下會(huì)被映射成一個(gè) Java 類。這里的“大多數(shù)情況”是有講究的如果這個(gè)復(fù)雜類型是有name的那么直接生成一個(gè)以該名字命名的類如果它是嵌在某個(gè)xs:element內(nèi)部、沒有顯式名字的匿名復(fù)雜類型XJC 會(huì)依據(jù)元素名派生出一個(gè)類名。比如xs:element namecustomerxs:complexType...XJC 通常會(huì)生成一個(gè)叫Customer的類。復(fù)雜類型內(nèi)部的xs:sequence、xs:all、xs:choice里的每個(gè)子元素都會(huì)變成類里的一個(gè)字段。xs:sequence是順序敏感的子元素序列映射成 Java 字段時(shí)按 Schema 里聲明順序排好xs:all是一組無序但每個(gè)出現(xiàn)一次的子元素映射成一個(gè)普通字段集合xs:choice是幾個(gè)分支中只能出現(xiàn)其中一個(gè)XJC 會(huì)生成一個(gè)帶XmlElements注解的字段列表Java 類型是ListObject或者泛型化的JAXBElement?。minOccurs和maxOccurs也直接決定字段類型——maxOccursunbounded或大于 1 時(shí)字段是 ListminOccurs0時(shí)會(huì)生成XmlElement(required false)并允許空值。2.2 簡單類型枚舉、約束和 Java 基礎(chǔ)類型的映射xs:simpleType配合xs:restriction是 XSD-7 里最常見的數(shù)據(jù)校驗(yàn)手段也是最容易被忽視的部分。比如xs:simpleType nameCurrencyCode xs:restriction basexs:string xs:enumeration valueCNY/ xs:enumeration valueUSD/ xs:enumeration valueEUR/ /xs:restriction /xs:simpleTypeXJC 默認(rèn)會(huì)把這種類型生成成一個(gè) Java 枚舉類CurrencyCode枚舉常量就是 CNY、USD、EUR。這里有一個(gè)關(guān)鍵點(diǎn)默認(rèn)生成的枚舉值名稱來自 XSD 里的value屬性如果value里有空格、連字符或者數(shù)字開頭比如USD-1、EUR(2024)XJC 會(huì)做一次名稱清理但往往不太好看而且可能會(huì)有兩個(gè)不同取值被轉(zhuǎn)成同一個(gè)合法的 Java 標(biāo)識符直接導(dǎo)致編譯失敗。對于普通的xs:restriction比如限制長度、限制正則但沒有 enumerationXJC 不會(huì)生成特殊類型而是把它映射為基于base類型的 Java 基礎(chǔ)類型。簡單類型映射規(guī)則我用表格總結(jié)一下XSD 類型Java 類型默認(rèn)備注xs:stringString最常見無歧義xs:integerjava.math.BigInteger注意不是 int/longxs:intint受限于 32 位整數(shù)xs:longlong64 位xs:decimaljava.math.BigDecimal金額類必用xs:booleanboolean默認(rèn) false容器對象時(shí)用 Booleanxs:dateTimejavax.xml.datatype.XMLGregorianCalendar默認(rèn)映射后文詳談xs:datejavax.xml.datatype.XMLGregorianCalendar默認(rèn)映射不適合直接序列化xs:base64Binarybyte[]字節(jié)數(shù)組xs:anyTypeObject最泛用的類型xs:integer默認(rèn)映射成 BigInteger 是很多人第一次用會(huì)驚訝的地方因?yàn)檫@在 Java 里有點(diǎn)重但為了兼容 XML 里的任意整數(shù)精度JAXB 把它設(shè)計(jì)成 BigInteger。如果你確信業(yè)務(wù)上精度夠用可以在 binding 文件里做定制后面會(huì)專門寫。2.3 namespace 與包名生成的默認(rèn)策略XSD-7 文檔里的targetNamespace是包名生成的核心依據(jù)。比如http://example.com/trade/order這種 URIXJC 會(huì)根據(jù)逆域名規(guī)則生成包名通常是com.example.trade.order之類。但如果你的命名空間寫得不規(guī)范比如帶上了版本號http://example.com/order/v1生成的包名就會(huì)包含v1再比如命名空間里包含不是標(biāo)準(zhǔn)域名的局部生成結(jié)果可能是一長串下劃線橫線的奇怪包名。XJC 官方設(shè)計(jì)是把 URI 拆解并反轉(zhuǎn)但結(jié)果往往不符合 Java 包命名直覺。所以我的建議是除非迫不得已生成代碼時(shí)永遠(yuǎn)用-p參數(shù)顯式指定目標(biāo)包名不要讓 XJC 從命名空間推導(dǎo)。這樣能完全避免包名失控的問題。比如xjc -p dev.example.xsd7.model xsd-7.xsd這個(gè)-p參數(shù)就是用來覆蓋自動(dòng)包名推導(dǎo)的。我每次對接外部 Schema 都會(huì)把它設(shè)成項(xiàng)目內(nèi)獨(dú)立的 model 包方便后期整體管理。3. 命令行生成實(shí)戰(zhàn)把 XSD-7 編譯成 Java 類的完整操作前面的理論部分搞明白之后進(jìn)入實(shí)操環(huán)節(jié)。XJC 這個(gè)命令說簡單也簡單就是一個(gè)命令行工具說復(fù)雜也復(fù)雜因?yàn)樗泻芏鄥?shù)和隱藏行為。我以一份本地的 xsd-7.xsd 主文件為例展示我從拿到文件到生成代碼落地的全過程。3.1 環(huán)境準(zhǔn)備JDK 版本和 JAXB 依賴的取舍先看一個(gè)大前提JDK 8 自帶了 JAXB 和 XJC直接在命令行敲xjc就能用編出來的代碼也是基于javax.xml.bind注解的。但是如果你用的是 JDK 11 或更高版本Oracle 已經(jīng)從標(biāo)準(zhǔn) JDK 里移除了 JAXB 模塊命令行里沒有現(xiàn)成的 xjc 可用得單獨(dú)引入依賴或者下載插件。JDK 17 以后尤其明顯。我們項(xiàng)目里用的是 JDK 17所以我處理 XSD-7 時(shí)直接在 Maven 里集成了org.jvnet.jaxb2:maven-jaxb2-plugin插件這個(gè)插件會(huì)在構(gòu)建階段自動(dòng)調(diào)用 XJC 生成代碼不需要單獨(dú)裝工具。如果你只是想快速生成一次代碼看看效果也可以下載獨(dú)立的 JAXB 工具包但我更推薦直接走構(gòu)建插件因?yàn)樯纱a和構(gòu)建流程可以保持同步Schema 一變就重新生成。依賴配置大概長這樣按當(dāng)前主流 JAXB 版本dependency groupIdorg.glassfish.jaxb/groupId artifactIdjaxb-runtime/artifactId version2.3.8/version /dependency如果是新版 Jakarta namespace 的項(xiàng)目需要改用jakarta.xml.bind的坐標(biāo)這里不展開但你必須意識到 JAXB 已經(jīng)被 Java EE 轉(zhuǎn)移到 Jakarta EE 了不同項(xiàng)目的包名前綴不同。3.2 用命令行 xjc 完成第一次生成假設(shè)我在項(xiàng)目的xsd/目錄下放了三個(gè)文件xsd-7.xsd、xsd-7-common.xsd、xsd-7-enum.xsd主文件 include 了后兩個(gè)。最直接的命令是xjc -d ./generated -p dev.example.xsd7.model xsd/xsd-7.xsd參數(shù)解釋-d指定生成 Java 文件的輸出目錄-p指定生成類的包名末尾緊跟主 Schema 文件路徑執(zhí)行完成之后generated/dev/example/xsd7/model/下會(huì)出現(xiàn)一堆.java文件。每個(gè)復(fù)雜類型一個(gè)文件每個(gè)枚舉一個(gè)文件可能還包含ObjectFactory.java和package-info.java。ObjectFactory是 JAXB 上下文創(chuàng)建時(shí)用于創(chuàng)建各類實(shí)例的工廠類package-info.java里則攜帶了命名空間信息包含XmlSchema注解。第一次跑成功之后先把生成的類放到 IDE 里編譯一下看看有沒有編譯錯(cuò)誤。這里我要特別提一個(gè)最常見的問題多個(gè)文件互相引用時(shí)類名沖突。比如xsd-7-common.xsd里定義了一個(gè)叫Status的復(fù)雜類型xsd-7.xsd里也定義了一個(gè)叫Status的復(fù)雜類型而且兩個(gè)類型語義不同。這種情況下 XJC 在一開始就會(huì)報(bào)“類沖突”之類的錯(cuò)誤你需要先在 Schema 層面解決命名沖突或者用 binding 文件給其中一個(gè)重命名否則永遠(yuǎn)生成不了代碼。我會(huì)在下一章節(jié)詳細(xì)寫這些坑的排查思路。3.3 Maven 插件集成構(gòu)建期自動(dòng)生成代碼命令行生成一次可以但 Schema 一旦更新手動(dòng)重新生成代碼并提交到倉庫里很容易產(chǎn)生大 diff也容易忘記同步。我更推薦把 XSD-7 的代碼生成放到 Maven 構(gòu)建生命周期里配置如下plugin groupIdorg.jvnet.jaxb2/groupId artifactIdmaven-jaxb2-plugin/artifactId version0.14.0/version executions execution goals goalgenerate/goal /goals /execution /executions configuration schemaDirectoryxsd/schemaDirectory schemaIncludes includexsd-7.xsd/include /schemaIncludes generatePackagedev.example.xsd7.model/generatePackage generateDirectory${project.build.directory}/generated-sources/jaxb/generateDirectory /configuration /plugin這個(gè)配置里最關(guān)鍵的是generateDirectory放在target/generated-sources/jaxb下這樣的話生成的代碼不會(huì)進(jìn) Git 倉庫每次構(gòu)建都是全新的。同時(shí) IDE 會(huì)自動(dòng)把target/generated-sources加進(jìn) classpath開發(fā)時(shí)調(diào)用生成的類不會(huì)有任何區(qū)別。這種做法最大的好處是代碼生成和 Schema 源文件強(qiáng)一致Schema 改了重新編譯就自動(dòng)更新不用手動(dòng)維護(hù)一坨生成出來的 Java 代碼。個(gè)人經(jīng)驗(yàn)是讓xsd/目錄納入版本控制生成目錄不納入版本控制。這樣別人拉下代碼也能直接編譯。如果遇到需在 CI 構(gòu)建機(jī)上跑的情況插件會(huì)自動(dòng)下載 XJC 依賴無需額外安裝。4. 第一批生成代碼里的坑命名沖突、非法標(biāo)識符與編碼問題每次生成完代碼我?guī)缀醵家幚硪慌鷨栴}。這些問題不是 XJC 的 bug而是 XML Schema 世界的自然規(guī)則和 Java 語言規(guī)則之間的摩擦。如果你提前知道它們排查起來會(huì)快很多。我挑幾個(gè)高概率遇到的講一講。4.1 XML 名稱與 Java 關(guān)鍵字的碰撞XSD-7 里出現(xiàn)過這種情況某個(gè)元素叫xs:element nameclass ...比如字段名就叫class。這在 XML 里完全合法但映射成 Java 字段時(shí)就成了關(guān)鍵字直接編譯不過。XJC 遇到這種情況一般會(huì)做某種轉(zhuǎn)義有時(shí)會(huì)自動(dòng)生成一個(gè)類似classValue或_class的字段名但有時(shí)又不會(huì)結(jié)果就是編譯錯(cuò)誤。真正的解決方式是在綁定文件里自定義屬性名。類似地還有abstract、interface、native等。我遇到過最離譜的一個(gè)是元素名叫package生成字段變成了_package——這還是 XJC 默認(rèn)給加了下劃線前綴的結(jié)果。所以生成完代碼之后第一件事就是在 IDE 里全局編譯把所有語法錯(cuò)誤揪出來。4.2 兩個(gè)Status類的生死沖突多 Schema 文件項(xiàng)目中命名沖突概率比我預(yù)想的高很多。XSD-7 主文件里定義了一個(gè)Status復(fù)雜類型某個(gè)被 include 的子 Schema 里又定義了一個(gè)Status簡單類型這就是典型的“同名不同類型”。XJC 在遇到這兩個(gè)類型時(shí)如果恰好被分配到了同一個(gè) Java 包就會(huì)產(chǎn)生同名類沖突命令執(zhí)行到一半就報(bào)錯(cuò)。這種情況我建議優(yōu)先在 XML Schema 層面解決也就是讓 Schema 提供方改名。但如果外部系統(tǒng)不規(guī)范、沒法推動(dòng)那就只能在 binding 文件里對其中一個(gè)類型額外指定類名。綁定文件的內(nèi)容類似jaxb:bindings version1.0 xmlns:jaxbhttp://java.sun.com/xml/ns/jaxb xmlns:xshttp://www.w3.org/2001/XMLSchema jaxb:bindings schemaLocationxsd-7.xsd node/xs:schema jaxb:bindings nodexs:complexType[nameStatus] jaxb:class nameOrderStatus/ /jaxb:bindings /jaxb:bindings /jaxb:bindings這段綁定的意思是在xsd-7.xsd里找到名為Status的復(fù)雜類型把它生成的 Java 類名改為OrderStatus。這樣兩個(gè) Status 就能共存了。4.3 枚舉值里的空格、連字符和數(shù)字開頭枚舉值的坑我在前面提到過。XSD-7 的幣種枚舉還算常規(guī)但有一段報(bào)文里的枚舉值居然是HIGH-RISK、LOW_VALUE、3RD_PARTY這種風(fēng)格。XJC 默認(rèn)生成枚舉常量時(shí)會(huì)做非法字符替換比如HIGH-RISK會(huì)變成HIGH_RISK3RD_PARTY會(huì)變成_3RD_PARTY。單個(gè)看沒問題但萬一你有兩個(gè)枚舉值分別叫HIGH-RISK和HIGH_RISK一個(gè)是連字符一個(gè)是下劃線XJC 替換之后兩個(gè)都指向HIGH_RISK就沖突了。我的處理辦法是在綁定文件里給每個(gè)枚舉值顯式指定成員名用typesafeEnumMemberName或者typesafeEnumMember。到了這一步你也會(huì)發(fā)現(xiàn)外部系統(tǒng)發(fā)的枚舉里“同含義不同寫法”的情況特別多手動(dòng)指定反而是最穩(wěn)妥的。4.4 編碼問題漢化注釋和亂碼XSD-7 里如果帶有中文注釋、中文描述性文檔XJC 默認(rèn)生成的 Java 文件里的注釋通常能保留但前提是文件編碼一致。我遇到過 XSD 文件里聲明?xml version1.0 encodingUTF-8?但文件本身是 GBK 編碼的情況導(dǎo)致生成的注釋全是亂碼。更常見的坑是 Windows 平臺(tái)下命令行 xjc 默認(rèn)輸出編碼不匹配Java 源碼里出現(xiàn)奇怪的字符。我的建議所有 Schema 文件統(tǒng)一轉(zhuǎn)成 UTF-8 編碼命令行上加-encoding UTF-8參數(shù)Maven 插件側(cè)也要配置項(xiàng)目編碼為 UTF-8。這塊是純環(huán)境問題但真遇到了會(huì)浪費(fèi)不少時(shí)間。xjc -d ./generated -p dev.example.xsd7.model -encoding UTF-8 xsd/xsd-7.xsd5. 外部綁定文件實(shí)戰(zhàn)讓 XJC 按你的規(guī)范生成代碼XJC 默認(rèn)生成的代碼能滿足“能用”的要求但往往不滿足“好用”的要求。比如日期類型映射成XMLGregorianCalendar就非常難用序列化 JSON 時(shí)也很別扭。好在 JAXB 提供了強(qiáng)大的外部綁定機(jī)制你可以寫一個(gè).xjb文件來覆蓋各種默認(rèn)映射讓代碼更符合項(xiàng)目的實(shí)際需要。5.1 日期時(shí)間類型從 XMLGregorianCalendar 換到 LocalDate/LocalDateTimeXSD 里的xs:date、xs:dateTime默認(rèn)映射成javax.xml.datatype.XMLGregorianCalendar。這個(gè)類本身沒問題但日常開發(fā)用起來極其繁瑣和 JSON 序列化、數(shù)據(jù)庫操作都不搭。我強(qiáng)烈建議通過javaType定制把日期映射為 Java 8 時(shí)間類型。實(shí)現(xiàn)方式有兩種一種是在jaxb:globalBindings里直接定制全局類型映射另一種是寫一個(gè)XmlAdapter并配合XmlJavaTypeAdapter注解。全局綁定的例子jaxb:bindings version1.0 xmlns:jaxbhttp://java.sun.com/xml/ns/jaxb xmlns:xshttp://www.w3.org/2001/XMLSchema jaxb:globalBindings jaxb:javaType namejava.time.LocalDate xmlTypexs:date parseMethodcom.example.adapter.JaxbDateAdapter.unmarshal printMethodcom.example.adapter.JaxbDateAdapter.marshal/ /jaxb:globalBindings /jaxb:bindings這里parseMethod和printMethod指向一個(gè)自定義類里的兩個(gè)靜態(tài)方法。對應(yīng)適配器類類似這樣public class JaxbDateAdapter { public static LocalDate unmarshal(String v) { return v null ? null : LocalDate.parse(v); } public static String marshal(LocalDate v) { return v null ? null : v.toString(); } }這樣從 XML 反序列化時(shí)XJC 就會(huì)自動(dòng)調(diào)用unmarshal把字符串轉(zhuǎn)成LocalDate序列化時(shí)調(diào)用marshal輸出標(biāo)準(zhǔn)字符串。改造過后生成的 Java 類字段類型就是LocalDate了讀寫和業(yè)務(wù)層面都干凈很多。5.2 金額類型確保 decimal 映射到 BigDecimal 而不是 doubleXSD-7 里金額字段用的都是xs:decimal默認(rèn)映射是BigDecimal這個(gè)沒問題。但常見的問題是自定義類型里寫了basexs:double或basexs:float這會(huì)導(dǎo)致金額字段變成double精度上很容易出問題。外部系統(tǒng)如果這么設(shè)計(jì)我一般會(huì)在 binding 文件里把該簡單類型強(qiáng)制改掉jaxb:bindings schemaLocationxsd-7.xsd node/xs:schema jaxb:bindings nodexs:simpleType[nameMoneyType] jaxb:javaType namejava.math.BigDecimal xmlTypexs:decimal parseMethodcom.example.adapter.DecimalAdapter.unmarshal printMethodcom.example.adapter.DecimalAdapter.marshal/ /jaxb:bindings /jaxb:bindings雖然xs:decimal默認(rèn)就是 BigDecimal但顯式聲明一次能防止某些插件版本或者 XSD 變體把它降級也能給人提示這個(gè)字段是金額不是普通小數(shù)。5.3 重命名類和字段的通用姿勢前面講了用jaxb:class name.../修改類名。對于字段名可以在對應(yīng)元素節(jié)點(diǎn)上用jaxb:property name.../修改jaxb:bindings schemaLocationxsd-7.xsd node/xs:schema jaxb:bindings nodexs:complexType[nameOrderInfo] jaxb:bindings node.//xs:element[nameclass] jaxb:property nameclassField/ /jaxb:bindings /jaxb:bindings /jaxb:bindings這種 node 路徑的寫法和 XPath 非常像其中.//表示從這個(gè)復(fù)雜類型下任意層級找元素名為class的節(jié)點(diǎn)。注意property name的值需要遵循 Java 字段命名規(guī)范一般用小駝峰。這里我提醒一點(diǎn)綁定文件本身也要納入版本控制并確保每次 XJC 運(yùn)行時(shí)都通過-b參數(shù)指定。命令行是xjc -d ./generated -p dev.example.xsd7.model -b binding.xjb -encoding UTF-8 xsd/xsd-7.xsd如果 binding 文件里寫錯(cuò)了 XPathXJC 會(huì)報(bào)錯(cuò)說找不到節(jié)點(diǎn)這時(shí)多半是schemaLocation或者node寫得不精確。可以把 XSD 文件在 XML 工具里格式化之后用瀏覽器或編輯器自帶的 XPath 輔助確認(rèn)路徑。5.4 用 extension 模式處理 XML Schema 1.1 特性XSD-7 這種新版本契約有時(shí)候會(huì)用上 XML Schema 1.1 的xs:assert、xs:alternative、xs:openContent等特性。默認(rèn)的 XJC 對 1.1 支持并不好特別是xs:assert因?yàn)樗鼘儆诩s束規(guī)則XJC 基本不會(huì)轉(zhuǎn)換到 Java 端。應(yīng)對方法是給 XJC 開啟-extension參數(shù)這樣它能解析更多 1.1 語法避免因?yàn)橛龅讲徽J(rèn)識的元素直接報(bào)錯(cuò)。xjc -extension -d ./generated -p dev.example.xsd7.model xsd/xsd-7.xsd注意-extension不是萬能鑰匙它只是讓 XJC 放寬了解析范圍對于xs:assert這類規(guī)則JAXB 沒有對應(yīng)的運(yùn)行時(shí)校驗(yàn)機(jī)制生成代碼不會(huì)自動(dòng)做這些斷言檢查。如果用得上你仍然需要在業(yè)務(wù)層或者實(shí)際 schema 校驗(yàn)里去處理這些業(yè)務(wù)規(guī)則。6. 生成代碼之后的生產(chǎn)力工作流從“能用”到“好用”XJC 生成完代碼工作其實(shí)只完成了 40%。把生成代碼整合進(jìn)實(shí)際項(xiàng)目并保證長期可維護(hù)性才是接下來真正花時(shí)間的地方。這塊我講講自己積累的工作流和習(xí)慣。6.1 生成代碼只讀策略用擴(kuò)展方法而不是改生成文件剛接觸 XJC 的時(shí)候我也干過直接修改生成類來加業(yè)務(wù)邏輯的事。結(jié)果就是 Schema 一更新代碼重新生成我改過的邏輯全沒了。后來我定了一個(gè)紀(jì)律生成代碼一律不手動(dòng)修改需要擴(kuò)展行為時(shí)要么用XmlJavaTypeAdapter、要么在生成類基礎(chǔ)上做包裝類/擴(kuò)展類、要么用繼承覆蓋共性邏輯。對序列化輸出有特殊要求時(shí)優(yōu)先用注解定制而不是改代碼。維護(hù)這份紀(jì)律的最大好處是生成目錄隨時(shí)可以刪了重新生成完全無痛。比如需要給訂單類加一個(gè)業(yè)務(wù)方法totalAmountWithTax()我不會(huì)去動(dòng)OrderInfo類而是在業(yè)務(wù)層建一個(gè)輔助服務(wù)或者用abstract父類做模板。6.2 多模塊項(xiàng)目里把生成代碼隔離成獨(dú)立模塊單模塊項(xiàng)目里把生成代碼放在target/generated-sources直接編譯問題不大。但如果你在做一個(gè)多模塊的微服務(wù)項(xiàng)目我建議把 XJC 生成邏輯單獨(dú)放到一個(gè) Maven 模塊里比如xsd-api-model。這個(gè)模塊只負(fù)責(zé)承接 Schema 和生成代碼對外只暴露生成的 Java 類型。業(yè)務(wù)模塊依賴這個(gè)模塊即使 Schema 更新頻繁、類名發(fā)生變動(dòng)影響面也只在接口層不會(huì)牽扯到所有服務(wù)代碼。這么做還有一個(gè)額外好處你可以在xsd-api-model里統(tǒng)一存放 binding 文件和適配器類做到生成邏輯和調(diào)用方隔離。如果未來換了 Schema 版本或改用了新協(xié)議只需要改這個(gè)模塊。6.3 自動(dòng)化校驗(yàn)把 schema 變更納入構(gòu)建門禁我們團(tuán)隊(duì)后來還加了一步在 CI 構(gòu)建里跑mvn generate-sources之后會(huì)做一個(gè)編譯檢查和 spotbugs 掃描保證生成的代碼沒有低級問題并且和業(yè)務(wù)模塊兼容。Schema 一旦被外部供應(yīng)商修改了本地編譯直接失敗提醒開發(fā)者需要重新評審和適配而不是等代碼里出現(xiàn)一堆不明所以的編譯錯(cuò)誤才發(fā)現(xiàn)。這種門禁很實(shí)用。我遇到過不止一次外部供應(yīng)商悄悄改了 XSD-7 里某個(gè)字段的 minOccurs從 0 改成 1本地沒注意結(jié)果上線之后報(bào)文反序列化到處報(bào)錯(cuò)。如果每次 Schema 變更都能通過構(gòu)建記錄展示變更差異你就能第一時(shí)間發(fā)現(xiàn)這些隱性破壞。6.4 處理 equals、hashCode 和 toString默認(rèn)生成的 JAXB 類是不帶 equals/hashCode/toString 的這給日志打印、斷言測試帶來很大麻煩。插件社區(qū)有兩個(gè)常用方案一個(gè)是依賴 Lombok在生成后手工補(bǔ)充注解——但這就違反了“不改生成代碼”的原則另一個(gè)是使用 JAXB 的XmlTransient基類或者干脆在業(yè)務(wù)層統(tǒng)一寫工具函數(shù)來比較對象字段。我自己常用的方式是寫一個(gè)公共工具類用反射比較兩個(gè)生成對象的所有字段值。雖然反射有點(diǎn)性能開銷但測試環(huán)境和開發(fā)環(huán)境足夠用。線上如果有復(fù)雜對象比對需求建議用 JSON 序列化之后的字符串來比較直觀且不依賴字段順序。6.5 從舊版 JAXB 遷移到新命名空間的注意點(diǎn)如果你在維護(hù)一個(gè)老項(xiàng)目從javax.xml.bind遷移到j(luò)akarta.xml.bindXJC 生成的代碼注解也會(huì)變。這個(gè)過程看著只是包名替換但實(shí)際涉及很多細(xì)節(jié)XmlRootElement、XmlType、XmlAccessorType等注解的包名都要換ObjectFactory和package-info里的命名空間常量也有變化。最簡單的方式是把 XSD 重新喂給對應(yīng)版本的 XJC 插件生成一遍而不是用文本替換去硬改。我在一次項(xiàng)目升級里試過硬改結(jié)果就是大量編譯錯(cuò)誤和運(yùn)行時(shí)ClassCastException。現(xiàn)在 JAXB 生態(tài)已經(jīng)分叉了你用的 XJC 版本必須和項(xiàng)目里的 JAXB 運(yùn)行時(shí)版本保持同一條主線否則生成的注解和運(yùn)行時(shí)對不上啟動(dòng)時(shí)會(huì)出現(xiàn)各種“找不到注解”的坑。7. 最后說幾個(gè)比較偏門但關(guān)鍵時(shí)刻能救命的參數(shù)XJC 命令還有很多參數(shù)我平時(shí)用不著但遇到特殊情況能派上大用場。這里列幾個(gè)我覺得值得記住的。-nv參數(shù)表示不執(zhí)行嚴(yán)格校驗(yàn)。默認(rèn)情況下 XJC 會(huì)對 Schema 做驗(yàn)證如果 Schema 本身寫得不太規(guī)范比如用了過時(shí)的語法或者缺少某些聲明命令會(huì)直接中止。加-nv可以讓它在盡量寬松的模式下完成編譯。不過要注意跳過校驗(yàn)的結(jié)果是生成的代碼質(zhì)量可能存疑適合在“明知 Schema 有問題但必須先拿到代碼看看”的場景下使用。-catalog參數(shù)用來指定一個(gè) XML Catalog 文件很多項(xiàng)目里會(huì)有本地的 DTD/XSD 文件解析依賴。遇到 XSD 文件里的 import 指向一個(gè)互聯(lián)網(wǎng)地址公司內(nèi)網(wǎng)又訪問不了時(shí)寫一個(gè) catalog 把這些 URL 映射到本地文件就能解掉。-no-header參數(shù)可以生成的 Java 文件不附帶生成時(shí)間、版本信息之類的頭部注釋這樣代碼 diff 更干凈也避免每次發(fā)布版本時(shí)生成代碼的頭部注釋變化導(dǎo)致無意義的 diff。另外還有-quiet參數(shù)可以減少輸出信息適合在腳本里調(diào)用避免日志被大量警告刷屏。我一般在 CI 腳本里會(huì)把-quiet加上方便在全是生成日志的構(gòu)建輸出里快速檢索真正的問題。如果你用的是 Maven 插件這些參數(shù)都有對應(yīng)的 XML 配置項(xiàng)可以對照插件文檔逐一映射。命令行驗(yàn)證好參數(shù)效果之后再落到插件配置里。還有一個(gè)值得提的點(diǎn)是XJC 處理xs:any類型時(shí)默認(rèn)會(huì)生成一個(gè)org.w3c.dom.Element成員如果你非要讓那個(gè)字段變成Object或者接進(jìn)某個(gè)自定義類型只能借助插件或者二次處理。這個(gè)問題比較底層大多數(shù)情況下用默認(rèn)的Element類型也夠用但要知道它為什么不是業(yè)務(wù)可以直接使用的強(qiáng)類型對象。8. 一次完整對接流程的實(shí)際操作清單最后我把一次典型的“拿到 XSD-7 到代碼可用”的完整流程列出來給各位一個(gè)參照。我?guī)缀趺看螌佣际前催@個(gè)清單走穩(wěn)定可靠極少出岔子。第一步先把整個(gè) Schema 文件集放到統(tǒng)一目錄比如項(xiàng)目下的xsd/同時(shí)確認(rèn)文件編碼都為 UTF-8。第二步通讀主 Schema重點(diǎn)記錄targetNamespace、外部 include/import 文件、全局復(fù)雜類型和全局簡單類型數(shù)量判斷是否存在命名沖突風(fēng)險(xiǎn)。第三步確認(rèn) JDK 版本和 JAXB 坐標(biāo)選擇命令行還是 Maven 插件生成。如果項(xiàng)目本身就是 Maven 項(xiàng)目我強(qiáng)烈建議直接配插件。第四步準(zhǔn)備好 binding 文件顯式指定目標(biāo)包名并對日期、枚舉、沖突命名做定制。第五步執(zhí)行生成命令把生成代碼刷新到 IDE編譯排查語法錯(cuò)誤。第六步找一個(gè)真實(shí)樣例報(bào)文寫 JUnit 測試做一次反序列化和序列化的雙向驗(yàn)證確認(rèn)生成代碼可以和實(shí)際報(bào)文正確匹配。第七步調(diào)整 Schema 版本管理策略正式納入構(gòu)建流程。這套清單看起來簡單但每一步都會(huì)攔住一部分人。特別是第六步很多同學(xué)生成完代碼直接就開始寫業(yè)務(wù)等聯(lián)調(diào)的時(shí)候才發(fā)現(xiàn)字段映射不對通用的做法是先拿一段真實(shí)報(bào)文跑通Unmarshaller再寫業(yè)務(wù)邏輯。Unmarshaller的使用方式也順便放這里JAXBContext context JAXBContext.newInstance(OrderEnvelope.class); Unmarshaller unmarshaller context.createUnmarshaller(); try (InputStream in new FileInputStream(sample-request.xml)) { OrderEnvelope envelope (OrderEnvelope) unmarshaller.unmarshal(in); OrderInfo order envelope.getOrderInfo(); // 業(yè)務(wù)邏輯... }這樣能確認(rèn)生成類與真實(shí)報(bào)文的字段對應(yīng)關(guān)系是否正確。如果字段類型配錯(cuò)了或者枚舉對不上在這里就能直接暴露出來不用等到線上。試過這么多方案之后我的核心體會(huì)是XJC 生成代碼只是起點(diǎn)真正考驗(yàn)功力的是你如何把綁定文件、構(gòu)建流程、測試驗(yàn)證和代碼隔離這套體系搭好。XSD-7 這類文檔以后還會(huì)有新的版本但對 Java 開發(fā)者來說核心邏輯不會(huì)變先理解 Schema 結(jié)構(gòu)再用 XJC 把重復(fù)勞動(dòng)自動(dòng)化最后用 binding 文件持續(xù)優(yōu)化類型細(xì)節(jié)。這套能力一次投入后面每次對接都能復(fù)用。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
欧美日朝成人| 特级西西4444www无码| 久综合九综合99| 狠狠操狠狠做| 丁香婷婷人妻| 超碰网站在线观看| 欧美性猛交AAAA片黑人 | 婷婷五月天成人基地| 超级碰碰碰久久网站| 五月婷婷激情性爱| 五月丁香六月婷婷在线| 天天 日综合| 久久久久久久久久久月丁| 亚洲综合婷婷六月丁香五月| 婷婷六月丁香激情综合| 伊人婷婷五月天av| 日本天天色| 婷婷网五月| 日韩一级A片黄色| 91丁香色| XX色综合| 亚洲AV成人在线| 色五月丁香五月婷婷五月成人网| 精品一二三区视频立| 黄页免费一级视频懂色| 九九精品免费视频99| 激情综合五月| 丁香五月香蕉| 激情五月丁香亭亭| 五月人妻婷婷视频| 情婷婷五月天| 五月综合激情久久| 色色网站观看| 婷婷五月丁香综合激情小说| 伦99热| 亚洲成人在线播放| 狼人久草| 天天干天天干天天干| 婷婷 丁香 精品| 色五月五月天| 天天 青草 丝袜制服 在线| 色色婷婷色色| 七七色综合| 五月婷婷激情| 午夜69成人做爰视频| 中文字幕在线不卡| 在线不卡视频| 精品久热| 成人做爰黄A片免费看直播室男男| 99在线播放视频| 激情第四色| 人妻操逼视频。| 在线99精品| 五月天自拍视频| 婷久久| 亚洲视频在线观看区| 日日干日日| 啪啪91| 六月丁香婷婷综合狠狠爱夜夜爱| 亚洲成人AV在线播放| 色爱亚洲| 97色婷婷成人综合在线观看| 色婷婷丁香五月| 9精品在线| 岛国av电影网站| 婷婷五月综合激情小说| 日日天天干| 激情婷婷五月天日本系列| 久久久97| 开心久久xxx色| 色欲婷婷五月天丁香| 色婷婷色丁香色欲av| www超碰| 色色亚洲| 97五月天婷婷综合激情网| 99热线观看9| 99九九在线视频| 99热综合色图| 欧美日韓成人亚洲精品另类| 色婷婷小说| 99爱在线视频| www.99热| 婷婷成人av| 五月天啪啪网| 日本一级一级一级一级| 国产熟女日日骚五月丁香爱| 99免费视频在线观看爱| 婷婷五月激情图片| 日韩限制级大尺度黑料泄密大尺度视频一区二区在线观看 | 黄色aaaaa| 婷婷九月丁香| 婷婷色情小说| 五月婷av| 色婷婷在线视频观看| 婷婷综合在线视频| 九九热10| 91干视频| 韩日AV片| 国产成人VA| 亭亭五月激情亚洲在线| 91碰碰| 国产人妻人伦精品一区二区| 丁香五月激情棕合| 婷婷.com| 中文中文在线| 热99国产精品| WWW,五月| 色色99| www.一区二区三区| 99热久久这里只有精品| 五月婷婷综合视频| 无码AV久久久久久久久| 久久久www| 婷婷伊人激情婷婷| 亚洲热综合| 九久久婷婷| 五月天另类小说久久小说网| 五月在线婷色| 婷婷色导航| 成人无码精品1区2区3区免费看| 9 1大香蕉| 婷婷五月天受日本法律保护| 亚洲成人av在线| 国产在线aaa片一区二区99| 夜夜AVV| 天天久综合网永久入口17v| 玖玖伦理电影| 成人电影一区| 日韩黄色电影| 亚洲另类噜噜| 狠狠插.com| 网色99| 99久久免费精品| 五月丁香啪啪| 人妻熟妇国产精品| 激情综合五月| 影音先锋偷偷色男人站| 亚洲人妻电影| 婷婷俺去也| 欧美在线| 美女要搞搞天天搞搞搞网站| 免费黄色视频网址| 人妻视频在线| 99久精品视频| 97超碰在线免费观看| 99热精品6| 六月丁丁香| 美欧日韩国产成人在战| 狼人狠狠操| 久9热插入| 亚洲婷婷丁香五月亚洲| 色欲一区二区三区精品A片| 婷婷五月天黄色| 五月丁香影院| 成人AV在线网站| 五月天久久婷婷| 久久久天堂国产精品女人| 亚洲国产婷婷色五月| 九九综合| 九月婷婷综合| 无码AV免费精品一区二区三区| 91久久久久久| 99精品偷自拍| 五月丁香六月综合激情网| 色五月五月婷婷| 啊V视频在线观看| 先锋资源婷婷| 国产女生爱爱AA| 天天热夜夜操| 五月天之色情综合网| 亚洲中文字幕翔田千里| 丁香婷婷情色五月天| 五月丁香花激情啪啪网| 六月色播| peg 2区三区四区的| www,com,五月色色| 久久这里这里有精品免费视频| 超碰碰碰碰| 久久作爱| 少妇AB又爽又紧无码网站| 欧美97p| 久草免费福利视频| 九九RE视频在线精品| 色五月婷婷色| 色欲AVV| 五月丁香六月婷婷综合网站| 91玖玖| www.婷婷亚洲基地| 久久成人天| 无毒黄色网址| 亚洲综合激情五月久久| www.夜夜.com| 伊人99热| 91色欲综合| 热99这就是精品视频| 超碰色婷婷| 性爱久久| 婷婷五月天a| 超碰啪啪网| 亚洲永久免费| 深爱激情网综合| 啪色综合| 亚洲黄色网址| 小视频久久久aaa| 天天激情夜夜干| 色婷婷AV久久| 人人操AV| 成人丁香五月| 激情深爱五月| 天天爽—爽| 婷婷中文综合网| 91人人操人人爱| 最新热中文字幕| 九九色video| 日本一毛片| 婷婷久久五月天亚洲欧美国产日韩在线观看 | 丁香六月婷婷色XXXXX| 婷婷五月天影视| 99热在线看| 这里只有精品视频| 婷婷色色丁香五月天| 26uuu淫色| 婷婷干六月综合旧址| 亚洲另类电影| 婷婷97碰碰| 亚洲九九99精品视频在线播放| 久久婷婷综合国产| 久久丁香网| 成年人丁香五月| 人人摸人人摸| 婷婷精品综合| 五月丁香久久久| 91在线日| 性色婷婷| 久久天堂网| AⅤ网站在线看| 五月丁香无码| 五月婷婷六月丁香玖玖玫瑰91| 六月丁香婷婷综合狠狠爱夜夜爱| 97碰91| 久久98| 色五月色五天免费视频| www夜夜操comwww| 这里只有精品99视频| 精品9久| 久久久婷| 激情网五月天| av中文在线| 99视频在线| 天堂综合久| 激情五月天电影| 五月丁香亭亭成人电影| 九九成人高清视频| 情五月亚洲婷婷| 婷婷五月天AV| 只有精品视频在线观看| 九九热这里只有精品首页| 九九超碰人人| 婷婷丁香花五月天| 欧美 日韩 成人 在线| 色伊人91在线视频| 182无码| 少妇高潮呻吟A片免费看软件 | 激情婷婷五月天| 狠狠色色| 天天日,天天插| 99精品久久久久| 五月天婷婷乱论小说| 美女美女美女三级色天天天天天| 色婷婷丁香五月综合| ji'qing'luan'ren'lun| 五月天中文网| 五月天亚洲色| 综合久久97| AV在线免费播放| 夜夜久久综合网| 激情五月天天狠狠久久| 婷婷丁香五月激情| 亚洲精品久久久无码| 色色色网站| 色播五月丁香| 毛片新网地| 五月丁香网站| 伊人狠狠丁香婷婷综合尤物| 五月天婷婷基地| 日本久久99| 中文毛片无遮挡高潮免费| 香蕉久久国产AV一区二区| 成人在线二区| 大香蕉九九热| 人人人人人人人人人草| 日日撸夜夜操| 色五月综合| 亚洲中文字幕翔田千里| 综合久久首页| 五月激情在线| 六月婷婷毛片| 七七九色| 激情综合网亚洲色图| 久久九九蜜| 婷婷五月天开心网| 99热欧美| 久久天堂婷婷五月| 五月婷婷丁香五月亚洲色| 美女激情婷婷| 99啪啪视频| 五月丁香色综合| 在线免费视频caop| 香蕉五月婷婷| 久久99热这里| 99碰碰中文| 超碰资源在线| 九九视频这里只有精品在线播放| 久久丁香五月| 人妻熟女一区二区AV| 久久久九九视频精品18| 玖玖伦理电影| 五月天六月色| 日韩AV在线影片| 婷婷色色综合| 青草青草久热这里只有精品| 色婷婷亚洲五月天| 中文毛片无遮挡高潮免费| 九一牛视频探花| 岛囯综合激情网| 免费AV在线网址| 丁香六月婷月91婷月| 色五狠狠| 黄急一级视频| 狠狠狠狠狠狠草| 美女五月狠狠| 99在线资源视频| 婷婷久久五月| 亚洲网站999| 影音 五月 婷婷 久久| 丁香五月123| 久久婷婷色丁香| 99在线视频精品| 我淫我色婷婷五月天激情四射| 97综合在线| 丁香五月天网友自拍啪啪啪视频| 极品少妇高潮啪啪AV无码| 婷婷五月色惰| 婷婷99狠狠躁| 极品少妇XXXX精品少妇偷拍| 99黄色性生活| 五月久久网| 五月丁香激情欧洲啪啪| 国产成人精品一区二区三区视频| 婷婷久久网| 九九在线精点品| 色五月丁香com| 五月婷五月婷伊人伊人五月婷| 亚洲男女激情| A1片久久| 婷婷五月色播| 久久密臀婷婷| 色99热| 国产亚洲成AV人片在线观黄桃| 日韩欧美颜射| 思思热在线播放| 亚洲AV无码一区二| 婷婷中文字幕| 五月婷久久草| 婷婷欧美综合| 超碰精品在线| 天天肏夜夜肏| 天天做天天爱天天爽在| www.99热| 色狠狠综合网| 亚州成人综合在线| 999热成人在线综合网| 亚洲精品久久久无码| 亚洲激情淫网| yazhoujiqingav| 99操碰| 婷婷射图| 亚洲色婷婷色| 91精品国产综合久久久不卡电影| 婷婷五月天免费| 亚洲精品无码99热| www.狠狠艹| 国产在线视频1234| 五月婷婷久久综合| 翔田千里 50岁 无码| 伊人激情综合网| 亚洲va欧美va国产综合久久久| 中文字幕无线久必| 开心婷婷五月中文字幕组| 人妻在线观看视频| 91丁香五月| 97人妻碰碰碰久久香蕉| 丁香色五月 97干| 色综合爱综合| 99热很操老逼| 国产亚洲在线观看| 26UUU欧美激情一区二区| 丁香婷婷九月在线| 亚洲天天| 精品久色| 无语停婷丁香网| 日日撸夜夜操| 欧亚色色| www亚洲无码| 色婷婷免费观看| 婷婷 久综合| 97 天堂| 色婷婷六月丁香综合欲精品| 99啪啪视频| 国产欧美性成人精品午夜| 五月丁香基地| WWW99视频| 五月婷婷深深爱| 国产精品久久99| 婷婷.com| 五月天社区| 天天日夜夜高潮| 欧美叉叉叉BBB网站| 天天综合亚洲| 婷婷情色五月天| 日本色色色| 婷婷色激情网| 激情九月天天天天婷婷| 人人摸人人| A网在线欧洲| 中文字幕人妻在线| 五月婷婷久久爱| 五月天综合久久| 26UUU在线观看| 亚洲超级碰| 免费看成人AA片无码视频吃奶| 人人爽天天爽| 狠色狠色综合久久| 婷婷5月色| 亚洲色五月婷婷| 婷婷五月天成人动漫 | 五月丁香六月婷| 国产在线6| 熟美女麻豆| 日产精品久久久久久久蜜臀| 亚洲操B| 色综合久久伊伊婷婷五月| 亚洲成人av在线播放| 99热| 五月天开心网| 久久婷婷热| 婷婷五月婷| 激情婷婷五月天伊人在线观看| 五月天婷综合| 中文字幕视频色婷婷| 亚洲午夜一区二区| 深爱五月激情| 狠狠狠夜夜夜| 午夜无码精品色综合久久| 99热碰碰热| 中文字幕av久久爽| www.第四色99| 天天插操| 狠狠噪| 中字幕视频在线永久在线观看免费| 久久久大香蕉| 丁香五月另类色婷婷麻豆| 99精品小视频| 米奇影视资源婷婷狠狠色激情欧美五月丁香 | 久久久人人人妻丝丝丝| 婷婷五日b| 久久色在线视频| 日韩狠狠色| 99热色婷婷| 五月丁香婷婷伊人日韩| 丁香五月婷婷色综合| 五月丁香啪啪啪| 五月天婷婷基地| 97福利视频| 丁香五月激情婷婷| www激情| 99亚洲精品视频| 色色综合网站| 婷婷综合| 色综合激情图区| 亚洲人操亚洲人| 99亚洲精品综合在线| 伊人久久大香线蕉精品| 色五月婷婷五月天| 亚洲视频在线观看| 九月色婷婷综合亚洲| 五月丁香无码| 久久久免费精彩视频| 色综合色色色| 91热久久| 精品一二三区久久AAA片| 操碰99| 婷婷五月天亚洲| 青草五月天| 大香蕉天堂| a在线观看| 久热99| 婷婷激情社区| 欧美性猛交XXXX乱大交极品| 97性高潮久久久| 欧美大道不卡| 婷婷五月成人有| 五月丁香成人| 色五月五月天色婷婷色五月| 久久只有18视频| 国产AV一区二区三区最新精品| 啊v视频在线观看| 香蕉AV777XXX色综合一区| 黄色片avv| 九久久婷婷| 午夜天堂一区人妻| 九九偷拍网| 大香蕉久久| 婷婷91| 五月丁香天堂网婷婷| 狠狠色丁香久久婷婷综合五月| 婷婷五月天在线视频网站| 综合色99| 婷婷五月精品| 无码九九| 五月综合激情视频| 久9视频| 天堂成人A片永久免费网站| 20253AV| 欧美在线视频9| 69热在线| 婷婷色五月综合| 伊人干综合| 国产一二区爆乳_1国产日韩一区二区三-成人AV| 新激情五月天| 天堂AV三级| 六月激情婷婷| 久久久精品人妻| 色婷婷丁香AV综合| 久久久er热| 色婷婷电影网| 99人人干| 丁香五月激情综合| 婷婷五月丁香综合网| 日韩精品999| 久色网五月| 激情都市丁香婷婷| 337久久| 天天日日人| 丁香六月婷婷久久综合| 国产一级黄色影片,| 激情五月婷婷视频一区二区三区| 色色色色色色色色色999| 超碰99在线观看| 九久热| 色播丁香五月婷婷操:屄| 亚洲99热| 婷婷色五月大香蕉在线| 天天干夜夜操A片| 人人操人人爰人人一天天碰夜夜拍夜夜爽-中国A级毛片天天看天天谢… | 国产另类综合| www.9操| 婷婷五月激情四月综合 | 丁六月激情| 亚洲成人在线免费| 婷婷亚洲在线| 开心五月婷婷在线| 爱超碰性| 成人欧美Va| 婷婷99狠狠躁天天躁| 好看的国产精品| 99热这里全都是精品| 婷婷色色网站| 丁香六月婷婷激情综合| 99精品久久久久久久婷婷| 97久操| 丁香五月天视频在线播放| 精品无码久久久久久久久 | 国产成人99久久亚洲综合精品| 六月色激情| 色婷婷五月天激情综合| 少妇水多A片太爽了| 丁香综合伊人| 色婷婷基地 | 丁香五月在线人妻| 天天操人人干| 铁牛TV人妻| 97色五月婷婷在线| 五月天停停成人网| 91窝窝| 色五月婷婷在线观看| 青青色com久久| 亚洲成人五月天| 另类图片五月天激情| www激情com| 大香蕉丁香| www.久久66| 国产婷伊人| 涩涩五月天综合| 大香蕉婷婷五月| 色综合丁香| 色屌丝中文字幕| 麻豆科斗777| 欧美成人AAA片一区国产精品| 五月丁香在线婷婷蜜桃| 超碰A V在线| www五月| 九月婷婷激情| 九九色婷婷| 新激情五月开心五月婷婷五月丁香五月| 狠狠干综合| 开心久久xxx色| AA片在线观看视频在线播放| 五月丁香婷婷成人网| 操逼巨乳91| 五月天亭亭俺也| 伦99热| 亚州AV超碰人人操| 白人荫道BBWBBB大荫道| 99热免| 激情六月丁香| 久久99久久99精品,久国产,久久精品免费,99久在线,久久久久国产精品免费网站,9 | 婷婷五月天成人| 婷婷成人丁香色情基地30| 中文字幕在线人妻| 亚洲情a| 日本久久婷婷| 久久se 综合网 | 色五月婷婷大香蕉| 久99久视频精品| 成人丁香五月天Av| 丁香六月婷婷综合麻豆| 久色激情| 无码人妻一区二区一牛影视| 99这里只有精品|v| 夜夜操夜夜爽| WWW久| 天天爽天天操| 操操自拍| 日韩操逼小电影| 国产99久久久| 岛国资源站| 日韩婷婷| 久久免费操| 中文网AV| 人人操人人爰人人一天天碰夜夜拍夜夜爽-中国A级毛片天天看天天谢… | 99久热视频在线| 久久五月激情综合| 丁香六月色婷婷| 琪琪理论片| 久久婷婷五月天激情新地址| 亚洲1区| 五月丁香六月婷婷久久久综合| 婷婷五月综合网| 婷婷五月丁香国产| 国产成人精品一区二区三区视频| 大香蕉中文| 色级停停| 国产精品久久久久久妇女6080| 丁香五月激情啪| 欧美丁香五月| 综合网五月天123| 3pAV| 超碰国产在线| 丁香五月色情av| 免费看欧美成人A片无码| www久久99| 人人草人人看| 狠狠狠狠狠狠狠狠| 99热在线精品观看| 五月间天堂综合| 97精品人人A片免费看| 91丁香五月| 婷婷在线视频| 久久98热re| 久久久久久18| 九九色插| 丁香五月瑟瑟| 亚洲无码影音| 丁香六月婷婷久久综合| 99热在这里只有精品| 亚洲第一黄网| 大香蕉综合| 久久婷五月| 美女激情综合| 色久女| 99在线精品观看99| 激情五月小说婷婷| 五月天桃色深爱网| 国精产品一区一区三区免费视频| 婷婷色色五月天| 色婷婷在线视频| 人妻久久久久久久| 久久五月综合| 婷婷色情 | 大香蕉五月婷婷丁香| 人人操超碰| 91无码一区人妻A片蜜| 亚洲激情综合| 丁香婷婷九月在线| 久久婷婷青青| 三级99热| 婷婷丁香熟妇综合网| 久久er视频6| AⅤ色区| 5月婷婷五月天| 九九色综合九九色| 色五月婷婷亚洲| 天天爱天天操| 99草在线免费观看视频| www99久久| 色噜噜狠狠色综合AV兰草影视| 婷色人人狠| 色情一区二区播放| 99色在线视频| 成功精品影院| 五月婷婷精品视频| 99热国产精品| 人人天堂操| 天天爽天天| 亚洲综合五月| 婷婷五月丁香99| 色色免费网站| 天天射影视综合网| 婷婷五月丁香超碰| 色婷婷操逼| 婷婷五月天免费99| 1024婷婷综合久久五月天| 久一网站| 人人看人人要| 亚洲五月天婷婷| 高清无码网址| 五月丁香自拍| 色五月婷婷天天操夜夜操| 99这里有精品视频| 91男人操女人视频| 玖玖爱综合网| 五月天婷婷黄色| 日韩人妻无码专区| 色99久草在线| 五月天婷婷xxx| 丁香五月在线| 中文字幕无码人妻少妇免费视频| 色五月琪琪| 这里只有精品在线视频在线观看| 色婷婷中文字母五月丁香| Www.Av网9| www.激情| 欧美日韩精品人妻狠狠躁免费视频| 国产亚洲精品久久久久苍井松| 九九热免费视频| 天堂A∨在线| 婷婷五月丁香国产| 好色婷婷| 久久ab| 色色六月| 综合亚洲五月天| 日本波多野结衣视频| 99视频精品| 99色亚洲| 国精产品一区一区三区免费视频| 久久综合99| 丁香五月婷婷六月丁香| 97色五月婷婷在线| 人人添人人| 综合激情站| 午夜日日| 人妻精品一区二区三区| 夜色五月天| 激情涩涩网| www.狠狠操| 99热久草| 2020日日干| 久久的爱大香蕉| 久热中文字幕在线线观看| 99视频在线| 久久香蕉影院| 亲子乱AV一区二区三区下载| 亚洲AV无码一区二| 色综合色综合色综合色综合| 99国产99| 欧美婷婷五月天综合| 色噜噜狠狠色综无码久久合欧美| 综合五月草| 色啪影院| 五月色婷婷影院| 天堂网啪啪| 色色九区| 综合久久9| 色99自拍| 久婷婷婷| 成人午夜无码视频| 丁香婷婷色五月| 久久婷婷热| 婷婷五月天影院| 亚洲国产精品成人免费一区久久久在线观看AAAA | av操B网站| 婷婷丁香色情| 亚洲视频1区| 天天干天天干天天操| 久久新地此| 人妻九九九九| 婷婷五月丁香综合桃花色网| www.日韩国产| 超碰人人操人人干| 激情第四色| 成人狠狠成人狠狠成人狠狠成人狠狠 | www 五月天 com| 97碰精品| 可以免费观看的AV| 天天干,天天舔| 91色色色| 狠狠干综合| 天天爽夜夜爽天天爽夜夜爽| www.cao.com久久| 这里只有精品无码| 婷婷丁香五月天哟啪| 99免费视频| 天天草天天日| 五月天婷婷激情在线色图| 97香蕉久久超级碰碰高清版| 秋霞三级色戒| 青青草伊人婷婷| 开心深爱激情网| 久久久这里都是精品| 第四色在线观看| 亚洲激情97五月天| 成人视频一区| 少妇水多A片太爽了| 综合XX网| 色五月丁香五月五月婷婷| 牛牛热这里只有jingpin| 天堂网啪啪| 久久成人性爱| 99久高清视频| 91丨九色丨东北熟女| 婷婷丁香激情| 91超级碰碰| 最近中文字幕2019视频1| 色噜噜五月天| 五月婷免费视频久久久| 亚洲色五月婷婷| 五月成人网站| 婷婷综合五月天亚洲综合| 九九热欧美| 性色九九| 婷婷色在线视频| 五月婷综合网| 九九99免费视频| 久久99久久99www| 日韩AV大全| 女人天堂 AV| 丁香五月综合激情久久潮喷| 色婷婷香蕉丁丁网| 日本不卡高字幕在线2019| 这里只有精品视频在线| 成人五月天在线视频在线观看| 大香蕉狼人久久| 91 欧美| 色婷网| 丁香五月在线观看| 狠狠va| 色色激情五月天| 97偷拍对白视频| 丁香激情五月天| 超碰久热| 五月激情婷婷播播开心| 亚洲色综久久五月| 亚洲 综合中文| 丁香久月婷| 五月婷婷亚洲综合在线 | 午夜一区| 99色在线视频| 婷婷社区五月天| 五月婷婷激情综合视频| 99这里只有免费的精品| 亚洲在线综合| 久热99热| 国产在线视频1234| 韩国97天堂| 大香蕉久久青青| 丁香婷婷激情| 伊人色综合网| 丁香六月啪| 综合视频久久| 五月丁香综合激情| 激情婷婷网| 欧美va欧美va差| 中文字幕日韩无码制服诱或| 国产精品五月丁香| 丁香午月AV中文字幕| 人妻AV在线观看| 91视频一起草| 97超碰在线免费观看| 日本久久极品| 伊人影院久久网| 丁香五月 性爱| 天天色凹凸| 国产性爱大片久久| 色开心五月婷婷丁香HD| 色九月综合| 91色性感五月婷婷丁香| 六月婷欧美丁香综合| 五月天大香蕉av| 91热久88| 黄色激情网站在线观看| 少妇被下春药玩弄A片| 日本视频久久| 9色婷婷| ady狠狠入| 日韩黄色AV无码| 啪啪婷婷五月天激情| 五月丁香好婷婷A片网| 久久婷婷五月天激情四射| 九热...av| 久久视网36| 伊人六月无码视频| 五月婷婷乱| 五月激情婷婷开心| 激情五月婷| 人人97碰| 开心五月天激情网| 91妻人人爽人人看片| A片试看120分钟做受图片| 五月天丁香久久综合 | 国产97在线日韩亚洲女人被黑人巨大| 久久综合站| 日本久久精品18| 五月婷婷欧美| 色五月无码| 色播婷婷五月天| 99热这里只有精品5| 激情五月天丁香| 99久久亚洲精品视频| 色九九七七| 激情小说婷婷小说| 开心综合激情综合| 一区视频网站| 开心五月天激情网| 色色综合热| 日本精品99网站| 夜夜做天天爽| 婷婷九月丁香| 婷婷五月激情五月激情| 婷婷五月丁香综合网| 久久久久久久久久久月丁| 激情五月天黄色小说| 美女主播野战视步页| 五月丁香激情深爱婷婷| 婷婷色片| 五月天开心网| 五月婷婷九九热| www.粉嫩av.com| 婷婷五月天黄色小说| 久久久久久久97| 大香蕉综合| 影音先锋五月天婷婷丁香在线观看| 丁香六月婷婷综合欧美| 九九视频精品在线免费| 天天日夜夜| 成人.在线日韩| 五月天激情网址| 欧美va| 五月丁香精品| 91se视频| 精品五月视频婷婷在线观看| 九九精品在线网| 97热这里只有精品| 久9草在线观看视频| 六月婷婷网| 五月丁香影视| 丁香五月婷婷欧美性爱| 99久.| 天天摸人人摸| 开心五月色婷婷综合开心网| 欧美精品A片一区在线观看| 国产熟女日日骚五月丁香爱| www.婷婷亚洲基地| 九九热青青草| 无码G高清天| 色五月琪琪| 日韩AV在线免费| aaaaaa片| 色色网站| 亚洲一级AV在线免费播放| 天天热夜夜操| 色啪网| a在线观看| 99这里只有精品视频| 婷婷激情五月呦呦| 五月天婷婷激情网| 精品久久久人妻| 4399无码视频| 人人人操Av| 婷婷五月激情综合| 五月婷婷色啪| 人妻内射视频| 超碰人人摸人人操| 久久五月丁香六月婷| 婷婷激情四射| 久久婷婷综合基地| 第四色大香蕉| 97婷婷狠狠久久综合9色| 五月丁香六月激情综合在线| 另类在线| 亚洲网视屏| 操日视频| 六月久久婷婷| 久狠狠狠| 26uuu偷拍亚洲欧洲综合| 79色色色色| 五月婷婷精品视频| 99热中国| 久久蜜臀婷婷| 丁香五月六月婷婷怡红院| 久久涩视频| 婷婷五月AV| 婷婷成人av| 精品51XX| 99热久久日本| 色色亚洲五月天| 7777精品伊人久久久大香线蕉最新版| 色婷婷社区| 国产肥白大熟妇BBBB视频| 亚洲视频丁香网va| 国产精品18久久久| 国产26uuu视频| 夫妇交换刺激做爰| 天天夜天天色天天| 欧美日本不卡黄色片| 俺去也五月天婷婷| 99在线一区| 97在线/亚洲| 99热爱爱干干日| 久热免费| 无码网| 激情涩播| 日本五月天婷婷丁香| 久久色五月天| 婷婷丁香成人| 亚洲天天免费| 国产美女无遮挡裸体毛片A片| 99热精品综合| 色五月天 丁香| 丁香 亚洲 久久| 亚洲国产成人在线| 无码人妻一区二区三区四区| 曰韩五月丁香色婷婷无码| 综合狠狠五月婷婷| 色婷婷综合电影| 日韩色久| 婷婷六月丁香久| 激情六月婷婷啪啪| 91九色在线视频| 国产亚洲99| 久热99视频在线观看| 中文在线视频久1| 婷婷伊人网| 公的粗大挺进了我的密道| 五月天 另类图片| 国产成人在线不卡AV| 亚洲色啪| 激情性五月天免费小说视频| 99色色| 国产日韩精品SUV| 婷婷久久色| 超碰人人草| 亚洲AV成人在线观看| 人人九色| 五月天综合区| 色婷婷五月天偷拍| BBWCUCKOLD精品熟妇| 婷婷色五月天在线| 在线va网站| 97超级免费无码| 五月天桃色深爱网| www.亚洲激情| 婷婷色婷婷亚洲成人| 亚洲成人AV高清字幕| 亚洲操精品| 午夜爱爱爱成人| 九色自拍| 欧美综合五月天婷婷tin| 伊人久久五月天| 日韩狠狠色婷婷| 狼人婷婷综合| 超碰免费在线| 91视频一起草| 襙比视频| 亚洲99综合| av在线不卡播放| 大香蕉九九| 亚洲婷婷丁香| 五月天欧美激情| 99er这里只有精品视频| 超碰人人妻| 少妇高潮呻吟A片免费看软件| www.狠狠| 性日本精品| 99在线爽| 丁香五月性爱| www久久久久久| 丁香婷婷五月色综合| 色婷婷五月在线| 久久久精品AV| 亚洲aV写真天天综合网久久| 2020久久婷婷五月| 蜜乳人妻一区二区三区| 色五月天 丁香| 丁香五月花| 91超级碰碰| 99爽视频| 五月丁查人人| av人人操| 色。 日日日| 久久久久亚洲A∨成人乱码电影| 九九十99视频| 九九99在线| 成人久碰| 亚洲精品a成人在线播放| 99在线小视频| 色色激情五月天| 99在线观看精品视频| 国产另类综合| 日撸夜撸日操| 丁香五月激情综合在线观看| 欧洲亚洲最新精品| 婷婷丁香五月亚洲欧美| 无码啪啪| 婷婷六月天天| 狠狠色97| 草榴视频网| 色九月欧美| 日本97人人| 婷婷丁香精品视频在线观看| 伊人狼人干| 五月Huangsewang| 夜夜操加勒比| 中国操逼99| 97操碰人免费| 99爱操| 99re在线免费视频| 香蕉AV777XXX色综合一区| 国产做爰视频免费播放| 国产av一区二区三区| 99精品国产乱码久久久人妻| 欧美黑人巨大性生话| 婷婷五月天小说| 成人在线观看精品| 亚洲成人无码专区| 碰人人97| 久久精品五月| 91视频一起草| 九九热这里有精品视频| 久久永久网址| 婷婷五月天日逼| 五月天激情日色在线| 丁香五月六月婷婷怡红院| 激情深爱五月| 综激情网| 久久综合激情| 欧美大片| 91啦丨九色丨刺激中文| 极品少妇婷婷五月| 91丨九色|PRNY熟妇| 大香蕉婷婷五月| www.天天干.com| 丁香婷婷伊人| 亚洲成人婷婷| 任你草| 99免费在线视频| 久久九九99.www| 人妻激情视频| 五月天婷婷六月激情网| 深爱激情av| 精品久久久人妻| 久久大香蕉| 欧美激情性做爰免费视频| 97婷婷五月丁香| 99久久久精品| 欧美精品999| 伊人婷婷五月| 夜夜爱网站| 天天操天天插| 婷婷综合仓库中文| 激情婷婷久久| 欧美性爱特黄一级aaaassss| 四色AVwww| 深爱激情丁香| 丁香五月综合网| 亚洲乱码在线观看| 99这里只有精品在线| 亚洲激情婷婷| 丁香五月成人| 91热在线观看视频| 高潮毛片遮挡费高一百度| 五月天激情网图片 - 百度| 五月丁香婷婷五月| 国产激情视频在线观看| 激情婷婷丁香| www,婷婷| 日日噜狠狠色综合久| 久久精彩视频| 婷婷五月丁香色综合| 色五月xxx| 久久99精品久久久久久三级| www.夜夜操| 99九九中文字幕视频| 桃色伊人在线| 亚洲人成色A777777在线观看 | 激情国产综合| 中文字幕簧片| 综合狠狠干| 九九色婷| 丁香五月情| 丁香五月亚洲综合| 天天色天天操天天射| 影音先锋91视频| 五月天无码视屏播放| 久久人妻伊人| 久久伊人大香蕉| av久热| 日日操天天爽| 人妻体体内射精一区二区| 91男同| 五月天婷婷在线播放| 日本一級黃色一級片| 99久久久免费| 天天做天天爱| 玖玖@三月天天丁香婷婷| 人人爽在线视频综合网| 在线天堂9| 99欧美热| 99热这里只有精品13| www.色综合| 色综合丁香婷婷| 亚洲最大视频| 人人操婷婷| 四色 爱 婷婷 精品 亚洲 五月天| 色婷操逼| 亚洲色图日韩网址| 五月丁香淫淫婷婷婷| 丁香婷婷欧美综合| 噜噜噜噜噜久| 四色99久久| 五月激情综合网| 97色啪| 激情中文在线| ji'qi'luan'ren'lun| 日韩av在线播放综合网| www.思思99热| AA片在线观看视频在线播放| 丁香婷婷综合激情五月色,开心五月丁香花综合网,激情综合五月亚洲婷婷,五月天 | 天天操夜夜操| 久热这里只有精品6官网亚洲| 人妻熟妇国产精品| 婷婷丁香五月天影院| 六月丁香网| 久在热99| 五月丁香狠狠| 色婷综合| 五月天五月天成人网亭亭成人色网站| 热99视频精品在线| 久久性爰视频这里只有精品| 青柠影视免费高清电视剧 | 丁香五月天婷婷中文| AⅤ网站在线看| 日日夜夜小色哥| 91色综合网站在线| 天天综合网网欲色| 性色综合网|