99精品久久精品一区二区-亚洲熟妇无码?v在线播放-日本国产精品无码字幕在线观看-久久久亚洲永夜AV-亚洲一级无码一区二区一-免费国产成高清人在线视频-中文字幕乱码免费观看-国产毛片精品妇女久久久

ARTICLE DETAIL

資訊詳情

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

MyBatis全局配置文件解析全流程:從XML到Configuration對象

MyBatis全局配置文件解析全流程:從XML到Configuration對象 我剛?cè)胄心菚旱谝淮畏璵ybatis-config.xml滿腦子都是“這玩意兒到底怎么跑起來的”。網(wǎng)上搜出來的教程清一色在教你寫settings、mappers但沒人告訴你這些標(biāo)簽從 XML 變成Configuration對象的過程中MyBatis 到底做了哪些事。后來因?yàn)橐挪橐粋€(gè)啟動(dòng)報(bào)錯(cuò)被逼著把XMLConfigBuilder的源碼從頭到尾啃了一遍才發(fā)現(xiàn)這條解析鏈路遠(yuǎn)比我想象中精巧。這篇文章就把我整理的“全局配置文件解析全流程”完整拆給你看包括解析順序、核心類職責(zé)、配置項(xiàng)背后的設(shè)計(jì)意圖以及我踩過的幾個(gè)坑。不管是想看明白源碼、準(zhǔn)備面試還是想排查配置問題應(yīng)該都能用得上。1. 全局配置文件的角色與整體設(shè)計(jì)思路1.1 為什么需要全局配置文件MyBatis 的核心對象是SqlSessionFactory而SqlSessionFactory又是基于Configuration構(gòu)建的。Configuration這個(gè)類幾乎承載了 MyBatis 運(yùn)行期的全部狀態(tài)數(shù)據(jù)源、事務(wù)管理器、映射器注冊表、類型別名、類型處理器、插件攔截器、全局緩存開關(guān)、懶加載策略……可以說MyBatis所有運(yùn)行時(shí)行為都能在Configuration上找到對應(yīng)的字段。全局配置文件mybatis-config.xml的作用就是用一種聲明式的方式把這些運(yùn)行期狀態(tài)從代碼里剝離出來。你不用在 Java 里一個(gè)個(gè)set而是寫一段 XML由框架負(fù)責(zé)把 XML 解析成Configuration對象。這樣做的好處很直接配置與代碼解耦環(huán)境切換開發(fā)、測試、生產(chǎn)只需要換配置文件不需要重新編譯。很多初學(xué)者會把全局配置文件和 Mapper XML 配置文件搞混。其實(shí)兩者是不同層級的東西全局配置負(fù)責(zé)“框架本身怎么跑”Mapper 配置負(fù)責(zé)“某一條 SQL 怎么執(zhí)行”。全局配置的解析入口是XMLConfigBuilderMapper 配置的解析入口是XMLMapperBuilder后者的調(diào)用時(shí)機(jī)多數(shù)發(fā)生在全局配置解析到mappers標(biāo)簽時(shí)。理解這條主鏈路后面的源碼讀起來就順了。1.2 配置文件的整體分層MyBatis 全局配置文件的解析有一個(gè)顯著特征對配置項(xiàng)順序極其敏感。這不是 MyBatis 故意搞事而是因?yàn)閄MLConfigBuilder在解析時(shí)用了XNode的evalNode來逐個(gè)獲取子節(jié)點(diǎn)而底層依賴的 XML 解析器在定位節(jié)點(diǎn)時(shí)也依賴文檔結(jié)構(gòu)。從官網(wǎng)的 DTD 定義的順序來看configuration下允許出現(xiàn)的子元素順序是!ELEMENT configuration (properties?, settings?, typeAliases?, typeHandlers?, objectFactory?, objectWrapperFactory?, reflectorFactory?, plugins?, environments?, databaseIdProvider?, mappers?)也就是說properties必須放在最前面接著是settings、typeAliases、typeHandlers、objectFactory等最后才是mappers。為什么順序這么關(guān)鍵因?yàn)榻馕鲞^程是“邊解析邊構(gòu)建”的。解析到typeAliases時(shí)Configuration的TypeAliasRegistry需要已經(jīng)被初始化解析到settings時(shí)Configuration需要已經(jīng)準(zhǔn)備好對應(yīng)的屬性 setter。如果順序亂了比如把mappers放到settings前面解析器在解析 Mapper 時(shí)可能依賴某些尚未注冊的別名或類型處理器就會直接報(bào)錯(cuò)。從我實(shí)際排查過的案例來看TypeAlias 注冊順序?qū)е碌膯栴}最隱蔽。.xml配置里mappers使用package方式掃描時(shí)如果 XML 文件里有未注冊的 resultType 簡寫別名而 typeAliases 又排在后面MyBatis 解析 Mapper 時(shí)就會拋出TypeException提示找不到對應(yīng)的別名。所以我的建議是嚴(yán)格按照 DTD 順序書寫別耍小聰明調(diào)整順序。2. XML 解析鏈路拆解從 XML 到 Configuration 對象2.1 入口SqlSessionFactoryBuilder 與 XMLConfigBuilder使用 MyBatis 時(shí)最常見的一段啟動(dòng)代碼是這樣String resource mybatis-config.xml; InputStream inputStream Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(inputStream);很多人沒意識到Resources.getResourceAsStream這一步其實(shí)已經(jīng)干了件大事它通過類加載器把mybatis-config.xml從 classpath 中定位并打開成二進(jìn)制流。這里有一個(gè)很容易被忽略的細(xì)節(jié)Resources會嘗試多個(gè)類加載器包括當(dāng)前線程的contextClassLoader、當(dāng)前類的加載器、系統(tǒng)類加載器逐個(gè)試錯(cuò)直到成功。這在高動(dòng)態(tài)類加載環(huán)境比如應(yīng)用服務(wù)器里很關(guān)鍵如果只用一個(gè)類加載器資源可能就找不到了。SqlSessionFactoryBuilder.build()里發(fā)生的事情更集中。它會創(chuàng)建XMLConfigBuilder并調(diào)用它的parse()方法得到Configuration對象再用這個(gè)Configuration構(gòu)建DefaultSqlSessionFactory。public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { XMLConfigBuilder parser new XMLConfigBuilder(inputStream, environment, properties); return build(parser.parse()); }XMLConfigBuilder的構(gòu)造過程本身就有玄機(jī)。它會先創(chuàng)建一個(gè)XPathParser然后在構(gòu)造方法里立刻調(diào)用parserContext.getXPathParser().evalNode(/configuration)把根節(jié)點(diǎn)拿出來再通過new Configuration()初始化一個(gè)全新的Configuration實(shí)例。這一步同時(shí)決定了后面所有配置項(xiàng)的落點(diǎn)。2.2 parse() 方法的執(zhí)行流程XMLConfigBuilder.parse()是解析全流程的核心源碼邏輯非常清晰public Configuration parse() { if (parsed) { throw new BuilderException(Each XMLConfigBuilder can only be used once.); } parsed true; parseConfiguration(parser.evalNode(/configuration)); return configuration; }注意parsed標(biāo)識位這個(gè)字段是用來防止同一個(gè)XMLConfigBuilder實(shí)例被重復(fù)使用的。如果你在代碼里手動(dòng)創(chuàng)建XMLConfigBuilder并調(diào)了兩次parse()第二次直接拋BuilderException。真正的干活方法是parseConfiguration它把每個(gè)子標(biāo)簽的解析拆成了獨(dú)立方法private void parseConfiguration(XNode root) { try { propertiesElement(root.evalNode(properties)); Properties settings settingsAsProperties(root.evalNode(settings)); loadCustomVfs(settings); loadCustomLogImpl(settings); typeAliasesElement(root.evalNode(typeAliases)); pluginsElement(root.evalNode(plugins)); objectFactoryElement(root.evalNode(objectFactory)); objectWrapperFactoryElement(root.evalNode(objectWrapperFactory)); reflectorFactoryElement(root.evalNode(reflectorFactory)); settingsElement(settings); environmentsElement(root.evalNode(environments)); databaseIdProviderElement(root.evalNode(databaseIdProvider)); typeHandlerElement(root.evalNode(typeHandlers)); mappersElement(root.evalNode(mappers)); } catch (Exception e) { throw new BuilderException(Error parsing SQL Mapper Configuration. Cause: e, e); } }看到?jīng)]有雖然parseConfiguration內(nèi)部按順序執(zhí)行但實(shí)際執(zhí)行順序和 DTD 順序略有出入。尤其是typeHandlers居然排在environments之后才解析這在配置的使用層面很容易產(chǎn)生誤區(qū)。很多人寫配置文件時(shí)把 typeHandlers 放在 settings 之后以為解析順序也是如此其實(shí)源碼里它是在后面才被加載的。如果你在 typeHandlers 里注冊了一個(gè)自定義 TypeHandler而在 environments 階段就想用它做數(shù)據(jù)源連接配置那必然是不行的。還有一個(gè)細(xì)節(jié)settingsAsProperties會先把所有 settings 的值讀成Properties對象然后傳給settingsElement統(tǒng)一設(shè)置到Configuration上。這中間做了一步容錯(cuò)——如果某個(gè)屬性名在Configuration上沒有對應(yīng)的 setter會直接跳過而不報(bào)錯(cuò)。這個(gè)“靜默忽略”的設(shè)計(jì)我后面再展開講。2.3 XPathParserMyBatis 自研 XML 解析器XMLConfigBuilder之所以能這么從容地逐段解析底層依賴的是 MyBatis 自研的XPathParser。這個(gè)類封裝了 Java 標(biāo)準(zhǔn)庫的XMLMapperEntityResolver和XPath表達(dá)式求值能力。XPathParser的核心是createDocument方法它使用 Java 的DocumentBuilderFactory創(chuàng)建 DOM 文檔對象。這里有個(gè)關(guān)鍵配置factory.setFeature(http://apache.org/xml/features/disallow-doctype-decl, false); factory.setFeature(http://xml.org/sax/features/external-general-entities, false); factory.setFeature(http://xml.org/sax/features/external-parameter-entities, false); factory.setXIncludeAware(false); factory.setExpandEntityReferences(false);這套配置是為了在解析 XML 時(shí)禁用外部實(shí)體和 XInclude防止 XXE 攻擊。同時(shí)它注冊了XMLMapperEntityResolver——這個(gè)類的作用是當(dāng) XML 文件里出現(xiàn)http://mybatis.org/dtd/mybatis-3-config.dtd這類 DTD 引用時(shí)不真正去網(wǎng)絡(luò)上下載而是從 MyBatis jar 包里的本地資源直接加載。這既保證了配置合法性校驗(yàn)又避免了啟動(dòng)時(shí)依賴外網(wǎng)。理解了XPathParser你就知道 MyBatis 解析 XML 不是用一堆正則硬拆字符串而是把整個(gè)文檔加載成 DOM再用 XPath 精準(zhǔn)定位節(jié)點(diǎn)。這樣的好處是標(biāo)簽嵌套結(jié)構(gòu)天然合法屬性值可以走標(biāo)準(zhǔn) XML 轉(zhuǎn)義解析邏輯寫起來也清晰得多。3. 核心配置項(xiàng)逐個(gè)解析與背后原理3.1 settings全局行為開關(guān)settings標(biāo)簽是日常開發(fā)里用得最多的配置像mapUnderscoreToCamelCase、cacheEnabled、lazyLoadingEnabled都在這里。前面說過settingsAsProperties會先把子標(biāo)簽拼成Properties然后通過settingsElement統(tǒng)一設(shè)置。settingsElement里面有個(gè)很有意思的機(jī)制它先給Configuration設(shè)了一堆默認(rèn)值再用反射逐個(gè)匹配屬性名調(diào)用 setter。Properties defaults new Properties(); defaults.put(cacheEnabled, true); defaults.put(lazyLoadingEnabled, false); defaults.put(aggressiveLazyLoading, true); defaults.put(multipleResultSetsEnabled, true); defaults.put(useColumnLabel, true); defaults.put(useGeneratedKeys, false); defaults.put(autoMappingBehavior, PARTIAL); defaults.put(autoMappingUnknownColumnBehavior, NONE); // ... 還有一堆核心邏輯是Configuration configuration new Configuration(environments); for (Map.EntryObject, Object entry : props.entrySet()) { MetaObject metaObject configuration.getSystemMetaObject(); Object value convertValue(metaObject, entry.getKey().toString(), entry.getValue().toString()); metaObject.setValue(entry.getKey().toString(), value); }這里用的是MetaObject反射工具。convertValue會根據(jù)目標(biāo)屬性的類型做轉(zhuǎn)換比如布爾值、Integer、Long 等。所以哪怕配置文件里寫的是字符串true最終也能賦給boolean類型的屬性。如果Configuration上根本沒有這個(gè)屬性setValue會拋出反射異常。但前面說它“靜默忽略”是因?yàn)樵趕ettingsAsProperties階段已經(jīng)對未知配置做過過濾并不是所有非法配置都會直接成功——具體行為取決于 MyBatis 版本和異常處理方式。但這引出一個(gè)常見誤區(qū)MyBatis 對拼錯(cuò)的配置項(xiàng)名稱容忍度很高拼錯(cuò)了可能不會報(bào)錯(cuò)但配置不生效排查起來非常惡心。最好啟動(dòng)后主動(dòng)打印一份生效配置做對照。3.2 typeAliases 與 typeHandlers注冊規(guī)則與加載時(shí)機(jī)typeAliases解析時(shí)有三種寫法typeAliases typeAlias aliasuser typecom.example.model.User/ package namecom.example.model/ /typeAliases解析邏輯有兩個(gè)分支typeAlias標(biāo)簽逐個(gè)注冊package標(biāo)簽則掃描包下的所有類。對于包掃描MyBatis 會過濾掉匿名類、內(nèi)部類、接口并且只注冊能被class.isAnnotationPresent(Alias.class)注解標(biāo)記的類如果沒有注解就用類名首字母小寫作為別名。這里有個(gè)細(xì)節(jié)包掃描默認(rèn)不注冊沒有Alias注解的類但如果有Alias注解就以注解值為準(zhǔn)。typeHandlers的解析比 typeAliases 晚但策略類似。它支持三種注冊方式typeHandlers typeHandler handlercom.example.MyTypeHandler/ typeHandler javaTypejava.time.LocalDate handlercom.example.LocalDateTypeHandler jdbcTypeDATE/ package namecom.example.handler/ /typeHandlers源碼里typeHandlerElement會根據(jù)是否有javaType屬性決定注冊范圍。沒有javaType時(shí)只會把 handler 和對應(yīng)的MappedJdbcTypes如果存在注冊有javaType時(shí)則用typeHandlerRegistry.register(javaType, jdbcType, handler)做精確注冊。自定義 TypeHandler 最容易被坑的點(diǎn)是如果你既沒有在 handler 類上寫MappedJdbcTypes也沒有在 XML 里指定javaType和jdbcType那么注冊后 MyBatis 并不知道這個(gè) handler 該用在哪種類型上結(jié)果就是怎么都不生效。3.3 plugins攔截器解析與動(dòng)態(tài)代理鏈全局配置里的plugins就是很多人說的 MyBatis 攔截器配置入口。它的解析代碼很短private void pluginsElement(XNode parent) throws Exception { if (parent ! null) { for (XNode child : parent.getChildren()) { String interceptor child.getStringAttribute(interceptor); Properties properties child.getChildrenAsProperties(); Interceptor interceptorInstance (Interceptor) resolveClass(interceptor).getDeclaredConstructor().newInstance(); interceptorInstance.setProperties(properties); configuration.addInterceptor(interceptorInstance); } } }注意它在這里只是把攔截器實(shí)例化并放進(jìn)configuration的攔截器鏈里真正創(chuàng)建動(dòng)態(tài)代理是在后面構(gòu)建Executor、StatementHandler、ParameterHandler、ResultSetHandler時(shí)才發(fā)生。這是很多面試官愛問的點(diǎn)插件解析不是“配置完就代理”而是延遲到對象創(chuàng)建時(shí)通過InterceptorChain.pluginAll()一步步包裝。3.4 environments數(shù)據(jù)源與事務(wù)工廠的組裝environments標(biāo)簽我單獨(dú)拿出來講是因?yàn)樗慕馕鲋苯雨P(guān)系到最后SqlSessionFactory使用哪個(gè)數(shù)據(jù)源、哪種事務(wù)管理器。源碼先是讀取default屬性確定默認(rèn)環(huán)境 ID然后遍歷子節(jié)點(diǎn)找匹配的environmentprivate void environmentsElement(XNode context) throws Exception { if (context ! null) { if (environment null) { environment context.getStringAttribute(default); } for (XNode child : context.getChildren()) { String id child.getStringAttribute(id); if (isSpecifiedEnvironment(id)) { TransactionFactory txFactory transactionManagerElement(child.evalNode(transactionManager)); DataSourceFactory dsFactory dataSourceElement(child.evalNode(dataSource)); DataSource dataSource dsFactory.getDataSource(); Environment.Builder environmentBuilder new Environment.Builder(id).transactionFactory(txFactory).dataSource(dataSource); configuration.setEnvironment(environmentBuilder.build()); break; } } } }這里DataSourceFactory有三種內(nèi)置實(shí)現(xiàn)UNPOOLED、POOLED、JNDI。POOLED是 MyBatis 自帶的連接池實(shí)現(xiàn)很多人以為 MyBatis 只依賴第三方連接池其實(shí)它自己有一套簡易連接池。UnpooledDataSource則是每用一次連接就新建一個(gè)Connection性能開銷大多用于測試環(huán)境。3.5 mappers映射器的加載與綁定mappers是解析流程的壓軸環(huán)節(jié)也是最容易引發(fā)級聯(lián)問題的地方。mappersElement支持四種子標(biāo)簽mapper resource、mapper url、mapper class、package name。resource從 classpath 加載 Mapper XML 文件最常見。url從文件系統(tǒng)或網(wǎng)絡(luò) URL 加載測試時(shí)常用。class直接指定 Mapper 接口如果接口和 XML 同包同名能自動(dòng)找到 XML。package掃描整個(gè)包按接口關(guān)聯(lián) XML需要接口和 XML 同名同路徑。解析到resource時(shí)會調(diào)用XMLMapperBuilder.parse()。這一步會把 Mapper XML 里的cache、resultMap、sql、select|insert|update|delete全部解析注冊進(jìn)Configuration。同時(shí)bindMapperForNamespace()會做接口綁定。如果 Mapper XML 的 namespace 對應(yīng)的接口存在會調(diào)用configuration.addMapper()最終通過MapperAnnotationBuilder解析接口上的注解 SQL。這里常會遇到一個(gè)經(jīng)典報(bào)錯(cuò)Invalid bound statement (not found)。大部分原因就是 Mapper XML 沒被加載進(jìn)來。你可以檢查全局配置里mappers的resource路徑是否和 classpath 對得上或者用package方式時(shí)接口和 XML 是否放在同一目錄、同名文件。4. 解析過程中的擴(kuò)展點(diǎn)與設(shè)計(jì)精髓4.1 為什么 MyBatis 要自研 XPathParser 而不是直接用 DOM/SAX很多初學(xué)者會問既然 Java 自帶DocumentBuilderFactoryMyBatis 為什么不直接用非得搞個(gè)XPathParser其實(shí)XPathParser本質(zhì)上還是用 JAXP 的 DOM 能力但包了一層“XPath 友好”的 API。原來的DocumentBuilderFactory用起來要用NodeList反復(fù)遍歷子節(jié)點(diǎn)代碼寫一大坨。XPathParser直接用evalNode(/configuration/settings)一步到位再通過XNode封裝了getStringAttribute、getChildrenAsProperties、evalString這些常用操作。XNode這個(gè)類是閱讀配置解析源碼時(shí)繞不開的它把 DOM 的Node包裝成更實(shí)用的模型底層存了xpathParser、node、attributes、name、body、children等字段所有取值操作都經(jīng)過它。我在讀源碼時(shí)最佩服的一點(diǎn)是XNode的evalString方法會調(diào)用PropertyParser做變量替換。這意味著你在配置里寫的${jdbc.url}這類占位符不是靠 Spring 處理而是PropertyParser從Properties里查出來替換掉。這跟properties標(biāo)簽里配置的外部文件、property子項(xiàng)以及構(gòu)造時(shí)傳入的Properties參數(shù)都有關(guān)系。解析順序不同占位符能否解析成功也不一樣。理解這一點(diǎn)你就明白為什么properties要放在配置最前面了。4.2 懶加載資源與失敗容忍機(jī)制XMLConfigBuilder里還有兩個(gè)容易被忽視的細(xì)節(jié)VFS和Log的加載。loadCustomVfs(settings)允許你通過配置vfsImpl自定義虛擬文件系統(tǒng)。MyBatis 默認(rèn)用DefaultVFS掃描包下的類文件但在某些容器環(huán)境比如老的 WebLogic里默認(rèn)掃描不到需要自定義 VFS。loadCustomLogImpl(settings)根據(jù)配置的logImpl決定使用 Slf4j、Log4j2、JDK Logging 還是 StdOut。沒有配置時(shí)會按優(yōu)先級自動(dòng)探測這個(gè)探測結(jié)果會全局決定你看到的 SQL 日志長什么樣。這兩個(gè)加載動(dòng)作同樣走“反射實(shí)例化 設(shè)置屬性”的套路失敗會拋BuilderException。但相比 settings 的“靜默容錯(cuò)”它們對錯(cuò)誤更敏感。畢竟 VFS 和日志實(shí)現(xiàn)掛了后面解析和運(yùn)行都沒法玩。4.3 二級緩存初始化與解析的關(guān)系想搞懂 MyBatis 二級緩存建議從Configuration的cacheEnabled字段看起。settingsElement里會把它設(shè)成true但二級緩存的真正注冊發(fā)生在 Mapper XML 解析時(shí)也就是說全局配置只負(fù)責(zé)開關(guān)每個(gè) Mapper 里要不要開緩存、用什么淘汰策略都是在mappers解析階段完成的。XMLMapperBuilder.cacheElement()會讀取cache標(biāo)簽的eviction、flushInterval、size、readOnly、blocking等屬性并用CacheBuilder構(gòu)建緩存實(shí)例。perpetualCache是所有緩存的底層層結(jié)構(gòu)再按配置包裹上LruCache、FifoCache、SoftCache、WeakCache等裝飾器。很多人面試被問“MyBatis 一級二級緩存有什么區(qū)別”如果只背結(jié)論不如順著這個(gè)解析鏈路理解一級緩存是Executor內(nèi)部自帶的LocalCache二級緩存是Configuration上維護(hù)的Cache對象兩者生命周期完全不同。我遇到過一個(gè)問題某個(gè) Mapper 明明配置了cache但查詢結(jié)果一直沒走二級緩存。后來排查發(fā)現(xiàn)全局配置的cacheEnabled被設(shè)置成了false導(dǎo)致Executor構(gòu)建時(shí)直接繞過了二級緩存邏輯。所以排查緩存問題時(shí)第一件事永遠(yuǎn)是看cacheEnabled到底是不是true再看 Mapper 有沒有flushCachefalse、有沒有在增刪改后清緩存。只盯著全局配置或只盯著 Mapper 配置都會掉坑。5. 實(shí)戰(zhàn)配置調(diào)優(yōu)與自定義擴(kuò)展點(diǎn)5.1 啟動(dòng)后打印實(shí)際生效的 Configuration前面提到 settings 對拼寫錯(cuò)誤容忍度高那怎么快速知道實(shí)際配置最簡單的方法是寫一個(gè)啟動(dòng)監(jiān)聽器或直接在初始化代碼里輸出SqlSessionFactory factory new SqlSessionFactoryBuilder().build(inputStream); Configuration configuration factory.getConfiguration(); System.out.println(cacheEnabled configuration.isCacheEnabled()); System.out.println(lazyLoadingEnabled configuration.isLazyLoadingEnabled()); System.out.println(mapUnderscoreToCamelCase configuration.isMapUnderscoreToCamelCase()); System.out.println(defaultExecutorType configuration.getDefaultExecutorType());像我前面說的熱詞里“mybatis配置打印”相關(guān)的問題多半就是想搞清楚當(dāng)前生效值。除了逐個(gè) getter也可以看Configuration類的settings相關(guān)字段或反射遍歷所有屬性。不過日常排查用 getter 就足夠了重點(diǎn)對照你想驗(yàn)證的那幾個(gè)開關(guān)。5.2 自定義 TypeHandler 的正確姿勢我建議自定義 TypeHandler 時(shí)統(tǒng)一用BaseTypeHandler這比實(shí)現(xiàn)TypeHandler接口省事得多。比如定義一個(gè)把LocalDateTime轉(zhuǎn)成字符串的 handlerMappedTypes(LocalDateTime.class) MappedJdbcTypes(JdbcType.VARCHAR) public class LocalDateTimeStringTypeHandler extends BaseTypeHandlerLocalDateTime { private static final DateTimeFormatter FORMATTER DateTimeFormatter.ofPattern(yyyy-MM-dd HH:mm:ss); Override public void setNonNullParameter(PreparedStatement ps, int i, LocalDateTime parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, parameter.format(FORMATTER)); } Override public LocalDateTime getNullableResult(ResultSet rs, String columnName) throws SQLException { String value rs.getString(columnName); return value null ? null : LocalDateTime.parse(value, FORMATTER); } Override public LocalDateTime getNullableResult(ResultSet rs, int columnIndex) throws SQLException { String value rs.getString(columnIndex); return value null ? null : LocalDateTime.parse(value, FORMATTER); } Override public LocalDateTime getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { String value cs.getString(columnIndex); return value null ? null : LocalDateTime.parse(value, FORMATTER); } }注冊時(shí)建議用 XML 顯式指定javaType和jdbcType不要只靠注解。注解只在 MyBatis 掃描時(shí)生效而MappedJdbcTypes的值如果沒匹配上實(shí)際 JDBC 類型還是會走默認(rèn)處理器。也別在包掃描的目錄里放太多“半成品” handler掃描到非TypeHandler類型會直接注冊失敗拖慢啟動(dòng)。5.3 自定義配置項(xiàng)直接改源碼還是另起爐灶有時(shí)候全局配置滿足不了團(tuán)隊(duì)定制需求比如想在配置里加一個(gè)audit標(biāo)簽。直接改XMLConfigBuilder源碼是最徹底的方案但升級 MyBatis 時(shí)會有沖突。更推薦的做法是不要在全局配置里亂加標(biāo)簽而是在 Spring 里用ConfigurationCustomizer或者在構(gòu)建完成后手動(dòng)往Configuration里塞自定義對象。如果你確實(shí)需要完整的自定義解析鏈路一種思路是復(fù)制一份XMLConfigBuilder在parseConfiguration里插入自定義節(jié)點(diǎn)解析邏輯然后讓SqlSessionFactoryBuilder使用自定義 Builder。但這種方案離“改框架”不遠(yuǎn)團(tuán)隊(duì)里必須有人持續(xù)維護(hù)。我的經(jīng)驗(yàn)是除非需求極其特殊否則盡可能復(fù)用 MyBatis 已有的擴(kuò)展點(diǎn)比如Interceptor、TypeHandler、ObjectFactory這些擴(kuò)展點(diǎn)覆蓋了絕大多數(shù)字段映射和 SQL 執(zhí)行場景。6. 常見問題與排查技巧實(shí)錄6.1 “元素類型必須由匹配的結(jié)束標(biāo)記終止”我見過最多人問的報(bào)錯(cuò)就是The element type settings must be terminated by the matching end-tag /settings。絕大多數(shù)情況是標(biāo)簽閉合寫錯(cuò)了或者標(biāo)簽之間大小寫不對。MyBatis 的 DTD 對大小寫敏感settings寫成了Settings一樣報(bào)錯(cuò)。另一個(gè)常見原因是 XML 注釋沒寫好!-- 這里注釋了 settings 標(biāo)簽但沒注釋完整 -- settings setting namemapUnderscoreToCamelCase valuetrue/ !-- /settings --這種注釋錯(cuò)誤很難發(fā)現(xiàn)建議用 IDE 的 XML 校驗(yàn)功能提前檢查。6.2 Configuration 解析順序報(bào)錯(cuò)嚴(yán)格按 DTD 順序?qū)懪渲檬亲钍⌒牡牧?xí)慣。我見過一個(gè)項(xiàng)目把mappers寫在settings前面結(jié)果啟動(dòng)時(shí) Mapper 里引用的別名還沒注冊直接拋TypeException。這里記一個(gè)排查技巧看到BuilderException: Error parsing SQL Mapper Configuration先不要急大概率不是 Mapper 的 SQL 寫錯(cuò)了而是全局配置階段有問題。用--debug啟動(dòng)應(yīng)用在XMLConfigBuilder.parseConfiguration打上斷點(diǎn)一步步看是哪個(gè)方法拋的異常。順序相關(guān)的報(bào)錯(cuò)還有一個(gè)The content of element type configuration must match ...這是 DTD 校驗(yàn)直接攔截了順序錯(cuò)誤。這時(shí)去看 XML 中 configuration 下的子元素順序按 DTD 調(diào)整即可。6.3 typeAliases/typeHandlers 不生效不生效基本只有三種情況包掃描路徑寫錯(cuò)掃描不到目標(biāo)類。類上沒有注解并且沒在 XML 里顯式指定 type。注意包掃描對沒有Alias的類默認(rèn)不按短類名注冊但如果你顯式使用typeAlias指定是可以注冊的。字段類型和 TypeHandler 的javaType對不上。調(diào)試方法很簡單在啟動(dòng)代碼里打印configuration.getTypeAliasRegistry().getTypeAliases()或者configuration.getTypeHandlerRegistry().getTypeHandlers()。這些 Map 的 key 就是當(dāng)前能識別的別名和處理器類型一眼就能看出注冊結(jié)果。我踩過一次最離譜的坑是在typeHandlers里包掃描配置了某個(gè)目錄但目錄里連著一個(gè)舊的、異常的 handler 類MyBatis 掃描時(shí)直接拋了InstantiationException整個(gè)啟動(dòng)流程掛掉。排查時(shí)才意識到掃描機(jī)制會把目錄下所有滿足條件的類都實(shí)例化這個(gè)行為相當(dāng)于“有多少注冊多少”目錄別放無關(guān)類。6.4 settings 配置“靜默失效”拼錯(cuò)配置名、值類型不對、格式不對都可能導(dǎo)致 settings 配置不生效。比如lazyLoadingEnabled寫成lazyLoadingEnableMyBatis 很大概率不會報(bào)錯(cuò)但功能不生效。為了避免這種“不知道改沒改上”的困惑我建議團(tuán)隊(duì)統(tǒng)一在啟動(dòng)日志里輸出關(guān)鍵配置項(xiàng)或者寫個(gè)單測去讀SqlSessionFactoryBuilder得到的Configuration對象斷言關(guān)鍵開關(guān)的值。如果遇到 “配置了mapUnderscoreToCamelCasetrue但查詢結(jié)果 map 的 key 仍然帶下劃線” 這種問題還有一個(gè)可能你在代碼里手動(dòng)用ResultSetHandler或Map接收結(jié)果MyBatis 并不會對Map的 key 做駝峰轉(zhuǎn)換這個(gè)開關(guān)只對自動(dòng)映射到 POJO 屬性時(shí)生效。很多人忽略了這個(gè)邊界。6.5 不同版本之間解析差異MyBatis 3.4、3.5 這些大版本之間配置解析的容錯(cuò)行為有明顯差異。比如早期版本遇到未知 settings 配置項(xiàng)可能直接拋異常后續(xù)版本改成了更寬松的處理。升級版本后如果發(fā)現(xiàn)“之前跑得好好的配置文件突然報(bào)錯(cuò)”多半是版本差異導(dǎo)致的。建議升級時(shí)先讀一下對應(yīng)版本的release notes重點(diǎn)看Configuration類字段和XMLConfigBuilder的解析邏輯有沒有變化。另外mybatis-config.dtd里的元素順序也可能調(diào)整如果升級后 DTD 校驗(yàn)報(bào)錯(cuò)直接重新生成一份配置文件別手動(dòng)猜。下面整理一個(gè)速查表方便直接對照報(bào)錯(cuò)現(xiàn)象大概率原因快速解法The content of element type configuration must matchconfiguration 子元素順序不符合 DTD按 properties - settings - typeAliases - ... - mappers 順序調(diào)整BuilderException: Error parsing SQL Mapper Configuration全局配置階段出錯(cuò)常見為別名/TypeHandler 未注冊斷點(diǎn)定位XMLConfigBuilder.parseConfiguration看具體方法TypeException: Could not resolve type alias類型別名未注冊或包掃描路徑錯(cuò)誤打印TypeAliasRegistry的注冊表核對路徑Invalid bound statement (not found)Mapper XML 沒被mappers加載檢查 resource 路徑、package 掃描目錄、namespace 與接口全限定名自定義 TypeHandler 不生效缺少javaType/jdbcType指定或MappedJdbcTypes不匹配顯式在 XML 中指定并在注冊后打印 TypeHandlerRegistrysettings 配置未生效配置名拼錯(cuò)或值類型不對用Configuration的 getter 打印實(shí)際值斷點(diǎn)調(diào)試settingsElement7. 從源碼回到日常我的幾點(diǎn)實(shí)操體會把XMLConfigBuilder這段源碼啃完最大的收獲不是“哦原來有個(gè)類叫這個(gè)”而是以后看到配置相關(guān)報(bào)錯(cuò)腦子里會自動(dòng)浮現(xiàn)出解析流程的先后順序知道該在哪個(gè)環(huán)節(jié)打斷點(diǎn)。我個(gè)人的習(xí)慣是新建項(xiàng)目時(shí)永遠(yuǎn)保持一份最小可用的mybatis-config.xml里面只放當(dāng)前真正需要的配置項(xiàng)。MyBatis 有大量默認(rèn)值不需要的配置不寫反而能減少拼寫錯(cuò)誤和配置漂移的問題。等線上出現(xiàn)性能或行為異常再按需往里面加配置并用啟動(dòng)日志驗(yàn)證。最后再分享一個(gè)小技巧讀這類源碼時(shí)先跑一個(gè)最簡單的 Demo用--debug跟著SqlSessionFactoryBuilder進(jìn)一遍再回到XMLConfigBuilder.parseConfiguration()里逐行看每個(gè)方法的執(zhí)行路徑比你對著源碼干想效率高得多。親自跑一遍比我在這里講一萬字都管用。
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
激情五月综合亚洲另类| 丁香五月 综合| 婷婷六月香| 亚洲精品色色| 色欲一区二区三区精品A片| 五月久久婷婷| 丰满少妇猛烈A片免费看观看| 久久这里面只有精品视频| 亚洲色综合| jiqingtaose五月天| 一级精品999WWW| 亚洲AV成人片无码网站| 人妻视频在线| 日本三级日本三级99| 天天添天天摸天天天天做| 国产肥白大熟妇BBBB视频| 天天狠狠夜夜狠狠2023| 亚洲精品操一操、噜一噜、摸一摸、爽 | 99燥99日| 丁香五月色五月| 91视频一起草| 激情五月天天| 婷婷久久五月天亚洲欧美国产日韩在线观看 | 九九婷婷网五月天| 深爱激情六月| 婷婷爱综合| 国产激情一区| a久久| 婷婷五月精品在线| 九九热精品| 99久久精品免费精品国产_国产精品久久久久久_国产在线|日韩_久久国产精品电影 | 五月狠狠| 99热精品少| 久久人五月| 91精品丝袜久久久久久| 五月色影院| 亚州精品色情无码A片| 日操夜操天天操不卡| 亚洲综合无码| 51XX午夜影福利| 这里只有精品久| 99啪啪网| 日本9区视频| 久久久久久人妻| 色色cOm| aaaaa黄色| 九九九九中文字幕| 激情亚洲婷婷| 操碰97| 五月丁香六月激情综合| 国产亚洲99久久| 亚洲色欲AAAAAA| 色婷婷在线影院| 久久婷婷视频| 天天做天天爱天天高潮| 成人国产欧美大片一区| 白人荫道BBWBBB大荫道| 国色天香成人网| 五月天激情小说网| 亚洲精品视频在线播放| 超碰日韩人妻在线| 日本色色影片| 婷婷丁香色性爱| 日韩精品色| 丁香五月亭亭六月综合激情网| 婷婷五月色情天| 亚洲无码AV片| 久久九九99桃花视频| 五月婷婷六月综合| 人人干天天舔| 色五月婷婷五月久久| 色五月天堂| 99热色无码| 欧美婷婷日本| 五月社区婷婷激情| 激情婷婷丁香色五月| 777.色色| 思思久久精品| 丁香五月首页| 亚洲天堂99| 亚洲国产精品二二三三区| 亚洲V国产V欧美V久久久久久| 操碰色一区就去操| 这里只有精品在线观看视频| 开心激情五月天网| 超碰2021| 三区激情四射av| 色综合综合色| 久久五月天综合| 91婷婷在线| 成片免费播放| 欧美激情中文字幕| 91大操| 激情久久丁香| 丁香五月 六月婷婷首页| 99热在线这里| 激情四射网| 五月婷在线| 7777久久亚洲中文字幕| 综合久久久| 无码毛片992367| 玖玖九九99| 国精产品久久| 综合99久久天天综合| 蜜臀99精品| 丁香五月综合无码趴趴| 大波美女VA网站| 99热在线播放| 婷婷99| WWW.国产| 99热欧美精品| 玖玖资源天天无码| 色婷婷亚洲| 国产欧美性成人精品午夜| 日本三级片片| 天天操天天草天天草天天| 五月激情六月宗合| 色婷婷六月综合| 日日夜夜狠狠| 成人AV在线电影| 欧美黄色韩日网| 五月激情五月丁香| 深夜A片| 婷婷五月色情天| 久9久9热久热| 久久ri精品| 色99在线视频| 五月丁香婷婷网网网网| 久久超级碰碰| 这里只有精彩视频| 激情丁香图片| 日日夜夜天天| 五月天婷婷自拍图片在线观看| 日韩精品超碰在线观看| 99热综合| 婷婷六月激情在线视频| 日本强伦片中文字幕免费看| 九九久久污| 丁香五月激情宗合| 丁香六月啪啪| 天干干夜夜操| 无码99| 六月丁香激情| 婷婷综合网| 日熟女| 国产精品久久欧美久久一区| 色小说五月婷婷| 婷婷伊人激情婷婷| 色色六月| 任你搞网站| 色爱综合五月| 丁香五月天AV在线| 日日杆天天| 婷婷精品免费久久| 成人网址在线观看| 九九热在线视频观看| 9久久网| 久久婷综| 五月天激情影院| 亚洲无码yw| 国产精品久久久99视频| 久久思思热| 婷婷五月天色色| 欧日韩成人| 久久免费高| 九九热123| 五月丁香六月婷婷色情| 影音先锋毛片网站| 99热这里是精品| 99精品色| 欧美大片免费观看| 久久婷婷五月综合伊人| 久热9| 久9无码视频| 激情综合激情综合| 久久精彩免费视频精彩免费视频| 国产国产乱老熟女视频网站97| 久久丁香五月婷婷激情综合网| 久操热线| 五月天天天色| 五月丁香综合啪啪| 婷婷丁香大香蕉| va婷婷| 国产成人精品亚洲线观看| 色婷婷五月天av在线| 色爱亚洲| 久久九九热视频| 99五月婷| 五月色情| 九九热AV| 国产精品人人妻人人爽| 婷婷日| 99精品视频播放| 国产成人亚洲综合A∨婷婷| 五月婷婷激情| 国产精品大香蕉| www.99热这里精品| 九九Av| 99思思热只有在这里看| 久热婷婷| 国产亚洲99久久精品| 影音先锋按摩| 97资源碰碰在线| 五月丁香六月婷| 婷婷精品性性性性性性性| 亚洲成人中文字幕| 成人做爰A片免费看视频| 99久久综合| 五月婷婷激情四季| 色色色激情网| 久久98热re| 五月丁香色婷婷伊人| 久久婷婷综合五月| 操操碰| 色五月五月婷婷| 婷婷激情伍月网| 欧美色激情四射| 四色永久成人网站| 激情五月婷婷视频一区二区三区| 天天爽夜夜爽| 天天做天天要天天爽| 免费观看18视频网站| 日狠狠| 丁香五月天天日| 激情五月天啪啪| 久久久91精品| 日本91在线| 色六月视频| 五月丁香婷婷在线综合蜜桃| 天天操天天曰| 激情爱爱网站| WWW.婷婷五月天.COM| 激情综合五月色丁香婷婷| 亚洲小视频免费播放| 色噜婷婷| 9久热在线精品| 久久艹 五月天| 色色com| 亚洲无码另类| 九月婷婷久久| 九九热在线精品视频| 婷婷成人五月天成人文学| 色情久久久| 六月欧美综合色情| 日日天天操| 异能之下短剧免费观看全集| 久99久视频| 丁香五月婷婷激情尤物| 涩涩五月天| 天天插,天天射| 国产精品A片| 五月婷婷婷婷婷婷艺术| 99热这里只有在线| 99色网站| 色五月天激情| 婷婷五月激情小说| 黑人巨粗进入警花疼哭A片| 日本综合色图| 久爱综合| 日韩淑女人妻luan伦激情精品一区二| 日本操片| 成人五月天在线观看| 综合激情伊人影视在线| 丁香五月婷婷六月婷| 99热网站在线观看| 亚洲色综合性| 六月婷婷色色色| 大香蕉婷婷久久| 碰97久久| 丁香九月婷婷| 狠狠爱丁香婷| 99九九热视频| www色色色com| 五五月五月| 97操男人的天堂| 亚洲不卡123| a久久| 超碰免费人人| 国产操B| 久久精品日| 九9九9无码| 97久久精品| 综合久久婷婷| WWW.夜夜| 丁香五月婷婷色情综合| A片试看50分钟做受视频| 国产黄色在线观看| 91凹凸在线| 国产激情综合五月| 五月天开心激情综合网| 人人爽天天爽| 色色色五月| 五月丁香精品| 蜜乳国产网站| 色五月综合在线| 婷婷五月花| 665566 无码| 五月婷婷久久大香蕉| 97人妻碰碰中文无码久热丝袜| 国产色色网站网址| 五月婷婷丁香六月| 婷婷激情五月综合| 狠狠狠激情网| 超碰91在线| 亚洲精品无人区| 4399高清无码视频| 久久久99精品| 色色a| 墨西哥毛片内射精| 色综合久久44| 色女伊人| 免费看欧美成人A片无码| 久久中国毛毛片爱久久| 婷婷永久在线| 人妻久久久| 激情婷婷五月在线合集| 婷婷爱综合| 激情五月天网站| 国产精品18久久久| 久久五月天合网| 天天色噜| 婷婷九月丁香中文| caopeng97日韩| 色色色色色色色色色色色色色97| 99热综合在线观看| 四五月婷婷| 激情六月婷婷| 亚洲人妻Av| 99精品22| 婷婷丁香18| 综合亚洲六月婷婷在线| 五月色丁香| 色黄啪啪| 亚洲欧美另类在线23p| 99免费在线视频| 99热99操| 久久丁香五月| 色七七九九| 亚洲激情精品| 性爱视频99| 国产成人精品一区二三区熟女在线 | 大香蕉视频婷| 深爱五月最新网址| 大香焦A∨| 婷婷深爱五月亚洲综合| 国产毛片精品一区二区色欲黄A片| 久久Xx| 天天狠狠干| 欧类av怡春院| 婷婷色五月情| 另类婷婷五月天啪帕帕| 五月花婷婷丁香| av国产精品| 欧日美女Va| 国产成人av在线| 99视频35精品视频在线观看| 超碰在线精品| 婷婷欧美偷拍综合| 国产精品久久久久久久久久久久| 激情丁香五月激情婷婷| 婷婷色色综合| 五月婷婷综合在线视频小说| 亚洲精品午夜国产va久久成人| 久噜久噜| 天天干天天日蜜臀av| 色噜噜,噜噜色| 丁香五月偷拍| 开心五月色婷婷综合开心网| 久久婷婷草| 99这里都是精品| 99九九中文字幕视频| 五月婷婷69| 天天综合91入口| 人人干女人| 超碰九九热| 亚洲99热| 玖玖福利视频资源| 色色色色色综合| 综合性爱网| 五月天婷婷久久| 性爱久久| 婷婷情色激情| -91九色大屁股| 久久激情网| 五月天成人伊人| 荫道BBWBBB高潮潮喷| 99热这里只有精品50| 99性爱视频| 亚洲午夜一区二区| 成人精品在线| 思思re99视频在线观看| 人妻综合网| 婷婷五月丁香五月| 色五月xxx| 欧美槡BBBB槡BBB少妇| www.99热. com这里只有精品| 精品动漫 无码av| 伊人久久大香线蕉av一区| 亚洲思思热久| 欧美碰碰碰| 99热人人| 婷婷五月天激情五月天网站| 欧美婷婷丁香五月社区| 大香蕉婷婷色| 丁香五月婷婷激情蜜桃| 亚洲啪啪视频| 日日操天天| 久久婷婷五月综合色奶水99啪| 色五月欧美| 日日爱699| 99在线视频精品| 91丨九色丨东北熟女| 这里只有精品2| 操碰97| 久久男人网婷婷| 午夜成人AV在线| 深爱五月天婷综合| 成人午夜无码视频| 久久成人亚洲欧美电影| 五月天开心网| 9久国产精品| 。久久久久久久久久久久久久人妻| 99热九九在线| 狠狠色噜噜| 丁香色情五月天| 人妻在线网站| 日本性视频| 久久五月天婷婷| 99色色色色| 丁香色六月婷婷| 光棍影院日韩精品| 91婷婷视频| 丁香五月天啪啪| 丁香五月偷拍| 99热这里只有精品在线播放 | 啊V视频在线观看| 日日夜夜噜噜爽爽| 国产综合激情五月久久| WWW色综合| 久久婷婷久久| 一操久久| 色五月婷婷五月天激情综合| 亚洲成人av在线观看| 亚洲国产无线乱码在线观看| 久久久久人妻网址| 99ri在线| 婷婷成人综合| 爆乳熟妇一区二区三区爆乳照片| 久草热在线视频| 色噜噜婷婷| 天天操天天爽天天爱| 日韩1区2区| xx久久| 五月天婷婷在线AN| 五月久久婷婷成人网| 日批在线看| 天天爱天天做天天舔| 超碰九色| 六月色日韩| AV伊人青草丁香六月| 色婷婷激情| 五月丁香六月婷婷久久肏| 一本九九色| 91在线资源| www.丁香黄色五月天人与| 亚洲日韩乱码一区二区三区四区| 久久电影五月天丁香电影| 亚洲精品色| 开心网五月色婷婷| 人妻狠狠操| 337p大胆噜噜噜噜噜91Av| 亚洲第一成人无码A片| 日本精品人妻无码77777| 色色色色色日韩午夜激情| www.久久五月天.com| 久久久婷丁香五月| 日韩二区搞逼插逼毛片| 欧美色必爱| 99热大全在线观看| 狠狠色色| 亚洲综合激情五月| 五月激激激情综合网| 久久小视频免费| 青青热久久综合| 色九月婷婷| 六月婷婷六月天天在线免费| 五月婷婷香蕉| 五月婷婷婷婷| 五月丁香综合| 国产成人精品一区二三区熟女在线| 国产精品涩涩涩视频网站| 丁香五月婷婷呀| 五月丁香婷婷AV天堂| 天天草天天舔| 日本色婷婷| 91viP在线看| 日本色婷婷| 色插人人| 在线色色| 无码人妻一区二区三区免费九色| 亚洲碰碰碰| 国产这里只有精品| 婷婷久久爱| 六月色播| 开心五月婷婷激情网| 五月激情六月综合| 99色在线视频| 五月婷免费视频| 婷婷亚洲综合| 五月成人综合| 九九精品热| 夂夂夂夂夂夂夂夂夂夂夂夂夂夂夂夂夂夂夂亚洲亚洲亚洲亚洲亚洲亚洲亚洲亚洲色 | 精品夜夜澡人妻无码AV| 久久国产AV| 91碰碰碰| 婷婷狠狠干| 超碰精品在线| 五月丁香久久呀| 9999热精品在线免费播放| 亚洲国产va| 亚洲激情在线| 97超级操操| 色综合久久五月| 日日噜噜夜夜狠狠久久丁香五月| 中文字幕日产A片在线看| 婷婷终合色图| www.99热. com这里只有精品| 综合亚洲六月婷婷在线| 婷婷激情视频欧美视频自拍视频欧美剧| 婷婷操逼| 五月丁香少妇| 丁香五月天在线| 激情小说婷婷| 4399在线日本A片| 97丁香五月| 亚洲视频在线观看| 伊人久久艹| 久久丁香五月天| 99年操人人爽| 久久亚洲网| 色综合丁香婷婷| 国产av天天插天天操天天爽| 情欲综合网| 九九RE视频在线精品| 91黄色五月天视频| 久久五月天激情视频| 91色婷婷综合久久中文字幕二区| 秋霞少妇毛片| 婷婷丁香色情| av婷婷丁香| 色欲五月天| 亚洲操逼网| 欧美精品99久久久| 五月天久久久| 五月天激情国产综合婷婷婷就去爱| 日本欧美成人片AAAA| 五月婷婷综合成人| 国产精品久久7777777精品无码| 色婷婷丁香| 色综合久| 婷婷五月天福利| 97在线视频观看| 1024国产| 热中文字幕| 无码激情| 欧美极品999| 色综合久久888| 色婷婷av在线| 五月婷婷大香蕉| 9l视频自拍九色9l视频自拍九色9l社区| 激情婷婷五月天| 69人妻人人澡人人爽久久| 五月婷av| www、丁香五月天| 丁香久月| 婷婷五月天久久久| 五月天综合缴情网网站0| 夜夜撸日日操| 91热er| 成人无码精品1区2区3区免费看| 色欲操| 日产精品久久久久久久蜜臀| 99re这里有精品手机在线| 欧美综合激情| 激情丁香五月天图片| 99欧美三级视频| 桃色五月天| av网址在线| 天天操天天插| 五月婷婷丁香av| 色婷婷aV四虎| 成人在线精品| 五月天影院婷婷在线观看| 不卡在线中文字幕无| 日韩欧美骚货| 99热在线观看精品| 亚洲精品99| 久久aaaa片一区二区| 888久久久| 爱射综合| 五月天黄色激情小说| 国产婷婷久久| 99热只有| 激情伊人五月天| 91干视频| 婷婷五月丁香基| 狠狠色丁香| 综合婷婷| 日日操夜夜操中国无码| 亚洲色网络| 天天日天天操天天干| 超碰精品国产首页| 色色五月丁香| 日本3级片一区2区| 狠狠va| 91丨九色丨老农村| 桃色五月天| xxx.色婷婷| 操操操操操操婷婷五月天| 色色色色色色综合网| 超碰人人干| 任你操精品免费| 九九久久精品| 97碰碰视频| 天天天天天操| 91色久| 99re久热| 男妓跪趴把舌头伸进我的嘴巴| 亚洲另类视频| 五月天五月色| 99热精品在线播放| 免费看片在线观看| 中文字幕免费高清电视剧| 26uuu欧美| 亚洲精品性色| 五月丁香啪啪| 色婷六月| 日本在线wwww| 成人草榴视频| 婷婷五月色| 狼人婷婷久久| 久久性爱视频网站| 婷婷五月天综合色| 日日夜夜青青草| 丁香婷婷久久 | 思思热久久阴99| 超碰9在| 97人碰人操| 婷婷五月天小说| 991精品在线视频| 日韩精品无码99| a69在线视频| 五月丁香啪啪啪| 久婷久婷激情肉| 91国产精品视频播放| 成人精品在线| 久久婷婷热| 欧美精品999| 色偷偷五月天| 婷婷五月激情丁香| 激情五月天伊人影院| 久久婷婷欧美| 深爱五月天天| 五月天色官网| 亚洲九九九九| 激情影院免费视频婷婷五月天| 五月天日日操夜夜操 | 色黑鬼导航| 91欧美| 婷婷激情综合| 色色五月丁香| 这里只有精品视频222| 九九热re99re6在线精品| 久久久A级视频| 97热超碰| 国产精品人妻在线网址| www.五月天婷婷| www91在线| www.黄色片-久久成人国产精品在线播放-999AV| 日韩成人影片在线观看| 丁香青青五月天| 亚洲av无码影院| 97精品综合久久内射| 天天插天天爽| www.色婷婷| 四LLL少妇BBBB槡BBBB| 精品一二三区久久AAA片| 国产精品18久久久| 影音先锋自拍网| 懂色av粉嫩AV蜜臀AV| 亚洲日比视频| 婷婷五月天情色| 色色五月天网站| 九月婷婷| 五月丁香亚洲综合网| 久久久久思思热| 性爱视频久久| 激情五月天在线视频| www.久久爱| 丁香五月婷婷激情四射深爱激情| 青青草原爱爱网| 97欧美在线| 99re99在线看| 久久在线人妻| 超碰网站在线观看| 五月丁香六月在线| 超碰成人黄色网| 亚洲成人无码免费| 国产激情久久久| 亚洲色欲欧美一区二区三区| 丁香五月婷婷影院| 婷婷久久网| 久久久久久久久久久久久9| 91精品视频男人的天堂| 91九色在线| 开心日韩丁香婷婷五月| 久热 91| 久久五月天精品视频| 五月开心激情网| 超碰资源在线| 色五月情| 五月色色网| 婷婷五月综合在线视频| 超碰色综合| 国产精品久久欧美久久一区| 五月天激情图片网| 天天做天天爰天天爽天天无遮挡| 激情六月婷婷| 国产成人精品一区二三区熟女在线 | 六月婷婷久久| 色99综合视频| 久久婷婷五月天懂色| 五月J香蕉婷婷| 六月丁香色色| 精品久久久久久久人妻| 依人大香蕉| 一本狠婷婷综合| 丁香五月婷婷啪| 六月丁香婷婷大香蕉| 99re66热这里只有精品| 五月婷婷69| 久热在线中文字幕色999舞| 非洲一级AV| 久久AV电影| 开心五月激情网| 91人人澡人人爽人人看| 五区毛片七区毛片| www.五月天| 国産精品| 丁香婷婷情色五月天| 日本一級黃色一級片| 99热精品在线观看| 99色视频| 噜噜五月天综合| 欧美一区二区三区不卡影视| 久久这里只有精品热在99| 六月婷婷网| 五月天影院| 免费看欧美成人A片无码| 五月婷丁香| 久99视频在线观看| 影音先锋 一区| 99爱无码| 天天久综合网永久入口18| 蜜乳9188| 亚洲丁香五月天在线视频| 婷婷操久久| 激情久久综合网| 色综合色综合色综合| 亚洲深喉aV| 久草五月天电影网| 婷婷五月天伊人| 丁香五月六月久久综合| 99视频精品在线| 97色干| 超碰av在线| 婷婷99狠狠躁天天| 婷婷永久在线| 大香蕉婷婷色| 天天干夜夜想| 99热99成人| 久久婷婷视频| 热热久久精品视频| 亚洲综合激情五月久久| 亚洲色五月天在线| 98国产精品综合一区二区三区| 九九视频这里只有精品在线播放 | 国产真实乱了老女人视频| 久久杏爱视频| 小香蕉av| 色综合色综合色综合| 色天使色综合| 天天澡天天狠天天天做| 538任你爽视频不一样的| 国产精品国产| 久99视频| 精品亚洲国产成AV人片传媒| 激情五月天www| 亚洲婷婷综合视频| 99色精品| 亚洲区,视频区,视频区免费| AV九九| 严洲天天插| 9 1 A v久久久| 五月天久久综合| 久久激情视频99| 性无码专区无码| 丁香综合网| 丁香五月停停基地| 久久综合五月| 色色色.com| 久久久精品99| 丁香六月在线| 婷婷综合激情五月综合| 婷婷丁香五月天大香蕉| 九九色精品| 色亚洲婷婷| 久久精品天| 操91| 天天色综合网1| 婷婷九月狠狠色| 99亚洲精品视频| 丁香五月欧美色综合| 久草五月婷| 色色a| 日韩操逼小电影| 变态另类9| 国产美女无遮挡裸体毛片A片| 婷婷五月天高清无码| av色婷婷| 亚洲欧美综合7777色亭亭| 日韩一级网站| 婷婷五月丁香激情色情| a在线免费v| 99国产精品久久久久久久久久久 | 亚洲无码影音| 激情五月天色网站| 色婷婷五月天小说网| 超碰色色综合| 五月丁小婷婷激情四射| 婷婷六月色开| 中文字幕色色| 久久99热只有精品| 久久一伦| 荫道BBWBBB高潮潮喷| 97碰人人操| 五月综合激情综合久| 五月 成人 婷婷| 伊久大香蕉| 色婷婷狠狠爱| 色五月在线观看| 深爱激情四射| 五月婷婷99热| 丁香五月www| 国产日产亚系列精品版优势| 丁香五月香蕉| 日本五月婷婷| 五月丁香六月色婷婷| 男女99免费视频| 日韩AV中文字幕在线| 丁香,开心成人,久久| 国产色色视频| www.99婷婷| 十月色综合| 中文字幕色色色| 欧洲亚洲最新精品| 亚洲中文字幕网| 91好好热日本在线| 色综久久久| 亚洲精品V天堂中文字幕| 久久九九综合| 色欲天天综合| 五月婷婷综合网| 色婷五月天综合网| 色香五月天| 久久久久久天天日天天爱| 色域五月婷婷丁香| 丁乡久久| www.久久久久久久久久久| 影音先锋一区二区资源站| 国产精品VIDEOSSEX久久发布| 天天玩夜夜操天天爽| 91综合在线视频| 天天艹| 伊人大香久久| 99re视频在线精品| www.99色在线| 91在线视频观看午夜福利| 色狠狠色噜噜AV天堂五区| 国产成人网| 狠狠操狠狠插| 极品少妇XXXX精品少妇偷拍| 丝袜大香蕉| 九九热九九| 99性爱视频| 精品夜夜澡人妻无码AV| 国产亚洲精品AAAA片APP| 丁香婷婷啪啪| 日本人妻伦在线中文字幕| 国产看真人毛片爱做A片| 99热精品在线| 丰满少妇乱A片无码| 双性美人被调教到喷水A片| 少妇高潮A片无套内谢麻豆传| AA丁香综合激情| 噼里啪啦完整版中文在线观看| 国产av天堂| 777米奇影视第四色| 久久精品A片777777| 久久大国产香蕉| 99re资源在线视频导航| 五月婷天堂视频| 综合五月丁香六月婷婷| AV网站免费在线| 亚洲人妻av| 这里只有精9| www.minyis.com【JT】币址百万U预算可预付QQ2101460746 | 国成人网| av成人在线播放| 五月婷婷色影院| 欧美激情 日韩无码 婷婷 五月天| 亚洲天天免费| 开心五月激情婷婷| 亚洲色另类| 97人人草| av中文网| 97干婷婷| 日韩 欧美 国产 一区 二区| 婷婷干| www五月天com| 五月丁香啪啪啪啪| 激情五月深爱五月| 五月色俺婷婷| 婷婷激情在线| 国产亚洲精品久久久久久牛牛| 伊人热在线大香蕉| www.久久久久久| 婷婷丁香视频在线观看免费| 天天射夜夜骑| 久久婷婷啪啪视频| 日韩精品视频中文字幕| 金品在线视频99| 五月丁香婷婷无码中文| 五月综合六月婷婷| 97碰| www.seqingwuyuetian| 色五月欧美| 婷婷五月丁香高清无码| 久久狠狠干| 9999久久久久| 免费啪啪啪网站| caopeng超碰| 五月天桃色深爱网| 丁香五月天啪啪| 五月丁香综合影院| 色五月婷婷丁香国产在线| 五月丁香另类图片| 婷婷综合久久| 亚韩在线视频| 欧美 色婷婷| 91人妻PORNY九色大屁股| 激情五月亚洲| 狠狠干婷婷| 大香蕉狼人久久| 亚洲久久婷婷丁香五月天| 色综合区| 黄色aa观看aaguochan| 欧美日本综合网| 激情丁香五月天| 日本精品人妻无码77777| 婷婷丁香97| 2025色婷婷| 成人国产欧美大片一区| 婷婷五月天av| 国产精品久久久海的味道| 国产偷人爽久久久久久老妇APP| 超碰二区| 激情综合网五月婷婷| 天天射影院| 99色在线| 九艹在线| 大香蕉欧美在线| 色射婷婷五月天| 丁香激情五月天| 欧美色五月| 九九大香蕉黄色影院| 综合 激情 婷婷| 丁香 婷婷五月| 天天色宗合| 一区二区免费看| 久久狠狠干| 四虎99热在线观看网站| 天天综合插插| 婷婷啪啪| 五月丁香激情综合啪| 人人摸人人操人人爽| 色五月大| 久久人人妻| 国产精品成人网站| 五月天停婷基地| 天天舔天天摸视频| 五月婷婷丁香日韩在线| 色婷婷六月激情| 操91| 五月丁香久久综合| 婷婷五月天小说| 色情五月天视频网| 玖玖热视频| 婷婷99狠狠躁天天躁| 丁香五月欧美成人| 无码啪啪| 依人大香蕉| 丁香五月婷婷深爱综合激情| wwwss在线观看| 久久99久久99久久99人受| 91久久久久久| 久久欧洲久久| 婷婷综合网站| 丁香五月图片| 人妻体体内射精一区二区| 五月激情网五月综合网| 久久精品国产AV一区二区三区 | 六月婷婷AV| 荷兰av一级| 五月天激情图片| 99热激情| 欧美综合婷婷欧美综| 国产精产国品一二三在观看| 激情五月天之六月婷婷| 日韩av变天就操逼不卡区| 日本nghangse中文字幕| 丁香婷婷色情社区成人小说| 日本三级片片| 91超碰在线播放| 五月丁香六月激情综合网| 激情五月天色播| 天天干天天干天天干天天干天天干天天| 99燥99日| 五月天色丁香| aa久久| 五月婷婷六月激情| 永久地址 色| 欧美婷婷精品激| 99久久99九九九99九他书对| 婷婷激情五月天7| 婷婷五月丁香综合网| 婷婷六月天激情| 婷婷亚洲天堂| 俺也去五月婷婷丁| 色欲一二三| 超碰久热| 大香蕉色婷婷伊人在线| 99这里只有精品|v| 91avse| 亚洲精品久久久无码| 丁香五月a| 五月丁香无码| 久久精品一区二区三区四区| 天天干天天干天天干天天干天| 热99精品视频五月| 国自产拍偷拍精品啪啪一区二区| 久久99性爱| 久久xx| 91在线资源| 涩涩涩.com| www.ppypp| 99视频在线| 中文字幕丁香五月| 久久密臀婷婷| 在线国产精品色| 六月久久婷婷| www.丁香黄色五月天人与| 99这里有精品视频3| 亚洲中文字幕AV| 狠狠干狠狠操狠狠爱| 69激情小说| 狠狠狠狠狠| 狠狠狠狠狠狠草| 影音先锋xfplay资源男人网| 一级性感毛片| 国产密乳av一区二区三区四区| 99视频自拍| 精品一区久热| 色999亚洲人成色| SESE无码AV| 涩涩涩,com| 91岛国片| 丁香五月之久操视频| 天天看A片| 五月第四色| 好好日激情五月天| 婷婷五月综合网| 色色丁香婷婷五月天| 夜夜骑夜夜操| 97热在线精品| 美英法精品无码免费视频| 青青.com| 99亚洲精美视频在线观看| 九九综合影音先锋| 天天爽夜爽| 九九99精品视频| 五月丁香欧美综合| 激情婷婷丁香五月| www.色婷婷| 欧美激情五月天| 婷婷爱婷婷| 亚洲精品操一操、噜一噜、摸一摸、爽 | 精品国产一区二区三区四区阿崩 | 91人人爽久久涩噜噜噜| 丁香五月综合在线| 九九热a| 91尤物九色在线| 人人叉久| 亚洲视频在线网| 色噜噜丁香| AA片在线观看视频在线播放| 免费视频99| 久久99综合| 丁香婷婷基地| 91凹凸在线| 五月丁香婷婷综合视频| 天天干天天操天天拍| 深爱五月日韩| 天天檫天天爽| 五月社区丁香| 99热思思在线观看| 天天插天天插天天操| 99激情在线| -91九色大屁股| 9l视频自拍9l九色9l成人| 九9九9无码| 九九偷拍网| 超碰人人操| 性色婷婷| 97视频91| 久热91| 伊人91| 天天综合久久| 99这里有精品免费| www.99热最新视频8| 这里只有精品视频国产| 丁香五月天天日| 亚洲丁香五月美女| 深爱丁香激情| 激情婷婷综合五月少妇| 久久思思精品| 五月天婷婷乱论小说| 丁香美女五月天婷婷| 天天综合久久| 狠狠色婷婷777| 深爱激情五月天| 少妇高潮A片无套内谢麻豆传| 老师的粉嫩小又紧水又多A片视频 欧美三级巜人妻互换 | 99九九在线观看免费| 大香蕉五月天婷婷| 久久99热这里只有| 婷婷区日本| 99热成人在线观看| 99热这里只有精品9| 在线观看的av| 深爱激情综合| 人妻第九页| 五月天久久激情| 97色片| 伍月激情天| 99热99色| 丁香五月天堂| 一本道在线电影| 在线五月婷| 国产脫衣舞一区二区三区| 狠狠色婷婷在线| 99爱免费在线视频| 天天插天天爱| 青青草成人网| www.99精品日操伊人乱碰在线| 少妇搡BBBB搡BBB搡毛茸茸 | 日韩一级片| 99热这里有精品| 99久久婷婷精品视频| 91九色视频在线观看| jiqingtaose五月天| 婷婷色五月色妇| 九九热免费视频| 五月天色色网站| 久草婷妨| 成人av免费观看| 99热这里只有精品1998| 综合色色婷婷| 人妻体体内射精一区二区 | 五月丁小婷婷激情四射| 五月天伊人久久久久| 另类五月婷婷| 开心网五月色婷婷| 99热8| 97操碰免费视频| 色一情一乱一乱一区91Av| 色情久久久| 人妻人人操| 色婷婷呢狠禁久禁| 婷婷情色五月天| 丁香五月久久综合| 激情综合在线观看| 婷婷丁香日韩五月| 久九色| 亚洲天堂aaa| 丁香五月久久| www,超碰| 丁香婷婷啪啪啪| 五月激情啪啪啪| 国产色色色色色| 月月AV| 九色91视频| 大香久久综合网| 思思热在线视频观看精品| 色色国产| 99九九精品视频推荐| 天天操夜夜啊| 婷婷激情在线| 日韩精品一曲二曲三曲四曲五曲| 亚洲丁香婷婷五月天综合色| 天天综合久久| 天天干天天玩天天夜天天射天天操天天日蜜臀少妇 | 欧美图片丁香五月天| 99re这里只有精品在线观看| 亚洲综合五月天婷婷| 欧美婷婷九月| 五月丁香六月情亚洲| 亚洲色婷婷五月天| 久操干| av操一操| 91久久精品国产91性色TV| 丁香五月天在线观看视频| 婷婷色片| 91窝窝| 婷婷丁香五月,狠狠综合| 91久久久久久| 超碰在线看| 婷婷五月天激情电影| 99资源人人| 欧美爆乳一区二区三区| 蜜桃成语时李时珍 免费| 一级片sese片.COM| 97在线/亚洲| 亚洲xx网| 色色色com| 亚洲欧洲小视频9| 欧美3AaAa大片| 五月丁香花成人社区| 丁香 婷婷五月| 狠狠五月天| 婷婷激情伍月网| 日日.c| 色五月婷婷婷婷婷婷婷婷婷婷| 色婷婷激情| 激情六月丁香| 国产成人AV在线| 激情综合五月天| 色玖玖综合网| 伊人色综合影院视频| av在线激情| 99热老司机| 婷婷激情五月综合| 久久这里只有精品久久| 丁香色婷婷| 婷婷五月激情六月丁香| 丁香网站|