<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                [TOC] 應用配置,在官方文檔也稱為配置外部化,意思就是在不同的環境中使用相同的程序代碼,也就是將代碼和配置進行分離。 Spring Boot支持多種外部配置源,包括 Java 屬性文件、YAML 文件、環境變量和命令行參數。配置的屬性值可以通過使用 @Value 注釋直接注入到你的 bean 中,通過 Spring 的 Environment 抽象訪問; 也可以通過 @ConfigurationProperties 綁定到結構化對象。 ## 屬性配置的優先級 Spring Boot 使用了一個非常特殊的 PropertySource 順序,該順序旨在允許合理地覆蓋值。 屬性按以下順序考慮(后面的覆蓋前面的): 1. 默認配置: 使用 `SpringApplication.setDefaultProperties` 指定 2. @Configuration 類上的 @PropertySource 注釋。 請注意,在刷新應用程序上下文之前,此類屬性源不會添加到環境中。 配置某些屬性(例如 logging.* 和 spring.main.* 在刷新開始之前讀取)就晚了。 3. 在application.properties 等配置文件的配置數據 4. 在random.*. 中的屬性。 RandomValuePropertySource 5. OS環境變量 6. Java系統變量 (System.getProperties()) 7. 在java:comp/env 中的JNDI屬性 8. ServletContext 中的參數 9. ServletConfig 中的參數 10. SPRING_APPLICATION_JSON 的屬性(嵌入在環境變量或系統屬性中的內聯 JSON) 11. 命令行參數 12. 測試的屬性。 在@SpringBootTest 和測試注解上可用,用于測試應用程序的特定部分。 13. 測試上的@TestPropertySource 14. 當 devtools 處于活動狀態時,$HOME/.config/spring-boot 目錄中的 Devtools 全局設置屬性。 配置數據文件按以下順序考慮: 1. 打包在 jar 中的應用程序屬性(application.properties 和 YAML 變體)。 2. 打包在 jar 中的特定于配置文件的應用程序屬性(application-{profile}.properties 和 YAML 變體)。 3. 打包 jar 之外的應用程序屬性(application.properties 和 YAML 變體)。 4. 打包 jar 之外的特定于配置文件的應用程序屬性(application-{profile}.properties 和 YAML 變體)。 注意: 配置文件支持 .properties 和 .yml 兩種格式, 如果兩種格式的文件都有,則優先以 .properties 為準。 舉例來看, 假設開發了一個使用 name 屬性的 @Component,如以下所示: ``` @Component public class MyBean { @Value("${name}") private String name; // ... } ``` 在應用程序類路徑上(例如,在 jar 中)您可以擁有一個 application.properties 文件,該文件為 name 提供了一個合理的默認屬性值。 在新環境中運行時,可以在 jar 之外提供一個 application.properties 文件來覆蓋名稱。 對于一次性測試,可以使用特定的命令行開關啟動(例如,java -jar app.jar --name="Spring")。在命令行參數可以覆蓋這個配置 `java -jar app.jar --name="Spring"` 提示: env 和 configprops 端點可用于確定屬性為何具有特定值。 您可以使用這兩個端點來診斷意外的屬性值。 ## 1. 獲取命令行屬性 默認情況下,SpringApplication 將任何命令行選項參數(即以 -- 開頭的參數,例如 `--server.port=9000`)轉換為屬性并將它們添加到 Spring Environment。 如前所述,命令行屬性始終優先于基于文件的屬性源。 如果不希望將命令行屬性添加到環境中,可以使用`SpringApplication.setAddCommandLineProperties(false)`禁用。 ## 2. JSON格式應用屬性 環境變量和系統屬性通常有限制,這意味著某些屬性名稱不能使用。 為了解決這個問題,Spring Boot 允許將一組屬性編碼為JSON 格式。 應用程序啟動時,任何 spring.application.json 或 SPRING_APPLICATION_JSON 屬性都將被解析并添加到環境中。 舉例來看, SPRING_APPLICATION_JSON 屬性可以在 UN*X shell 的命令行中作為環境變量提供: `.$ SPRING_APPLICATION_JSON='{"my":{"name":"test"}}' java -jar myapp.jar` 將JSON作為系統屬性 `java -Dspring.application.json='{"my":{"name":"test"}}' -jar myapp.jar` 將JSON作為命令行參數: `$ java -jar myapp.jar --spring.application.json='{"my":{"name":"test"}}'` 如果您要部署到經典應用程序服務器,配置JNDI 變量 `java:comp/env/spring.application.json` 注意: PropertySourcesPropertyResolver 將null 作為缺省值,所以null 值無法進行覆蓋。 ## 3. 外部應用程序屬性 應用程序啟動時,Spring Boot 會自動從以下位置查找并加載 application.properties 和 application.yaml 文件: 1. 從類路徑 - 類根路徑 -類路徑 `/conifg` 目錄 2. 從當前路徑 - 當前路徑 -當前路徑 /config 子目錄 - /config 子目錄的直接子目錄 該列表按優先級排序(較低項目的值覆蓋較早的項目)。 來自加載文件的文檔作為 PropertySource 添加到 Spring Environment。 如果不喜歡 application 作為配置文件名,可以通過指定 spring.config.name 環境屬性來切換到另一個文件名。 例如,要查找 myproject.properties 和 myproject.yaml 文件,可以按如下方式運行應用程序: `java -jar myproject.jar --spring.config.name=myproject` 還可以使用 spring.config.location 環境屬性來引用顯式位置。 此屬性接受一個或多個要檢查的位置的逗號分隔列表。 以下示例顯示了如何指定兩個不同的文件: ``` java -jar myproject.jar --spring.config.location=\ optional:classpath:/default.properties,\ optional:classpath:/override.properties ``` 提示:使用前綴optional:如果位置是可選的并且不介意它們不存在。 特別注意: spring.config.name、spring.config.location 和 spring.config.additional-location 很早就用于確定必須加載哪些文件。 它們必須定義為環境屬性(通常是操作系統環境變量、系統屬性或命令行參數)。 如果 spring.config.location 包含目錄(而不是文件),它們應該以 / 結尾。 在運行時,它們將在加載之前附加從 spring.config.name 生成的名稱。 spring.config.location 中指定的文件是直接導入的。 注意: 目錄和文件位置值也被擴展以檢查特定于配置文件的文件。 例如,如果有一個 spring.config.location 的 classpath:myconfig.properties,您還會發現加載了相應的 classpath:myconfig-<profile>.properties 文件。 大多數情況下,添加的每個 spring.config.location 項都將引用單個文件或目錄。 位置按照定義的順序進行處理,后面的位置可以覆蓋前面位置的值。 如果位置設置的比較復雜,并且使用特定profile的配置文件,可以進行位置分組。 位置組是所有被視為同一級別的位置的集合。 例如,對所有類路徑位置進行分組,然后對所有外部位置進行分組。 位置組中的項目應以 ; 分隔。 有關更多詳細信息,請參閱“特定Profile的文件”部分。 使用 spring.config.location 配置的位置替換默認位置。 例如,如果使用值 optional:classpath:/custom-config/,optional:file:./custom-config/ 配置 spring.config.location,則考慮的完整位置集是: 1. `optional:classpath:custom-config/` 2. `optional:file:./custom-config/` 如果需要添加其他位置,而不是替換它們,可以使用 spring.config.additional-location。 從其他位置加載的屬性可以覆蓋默認位置中的屬性。 例如,如果 spring.config.additional-location 配置了值 optional:classpath:/custom-config/,optional:file:./custom-config/,則考慮的完整位置集是: 1. `optional:classpath:/;optional:classpath:/config/` 2. `optional:file:./;optional:file:./config/;optional:file:./config/*/` 3. `optional:classpath:custom-config/` 4. `optional:file:./custom-config/` 這種搜索順序允許在一個配置文件中指定默認值,然后在另一個配置文件中選擇性地覆蓋這些值。 可以在默認位置之一的 application.properties(或您使用 spring.config.name 選擇的任何其他基本名稱)中為應用程序提供默認值。 然后可以在運行時使用位于自定義位置之一的不同文件覆蓋這些默認值。 注意: 如果使用環境變量而不是系統屬性,大多數操作系統不允許使用句點分隔的鍵名,但可以使用下劃線代替(例如,SPRING_CONFIG_NAME 而不是 spring.config.name)。 有關詳細信息,請參閱從環境變量綁定。 注意:如果應用程序在 servlet 容器或應用程序服務器中運行,則可以使用 JNDI 屬性(在 java:comp/env 中)或 servlet 上下文初始化參數來代替或同時使用環境變量或系統屬性。 #### 1. 可選位置 optional 默認情況下,當指定的配置數據位置不存在時,Spring Boot 將拋出 ConfigDataLocationNotFoundException 并且應用程序不會啟動。 使用 `optional:` 前綴指定的配置路徑, 則該路徑的文件不存在也可以啟動, 該前綴可以和spring.config.location spring.config.additional-location 以及 spring.config.import 一起使用。 舉例來看: spring.config.import 的值指定為 `optional:file:./myconfig.properties`, 則myconfig.properties文件不存在也可以啟動。 使用spring.config.on-not-found 屬性可以設置忽略所有 ConfigDataLocationNotFoundExceptions 異常, 使應用一直可以啟動。 設置方式是通過 `SpringApplication.setDefaultProperties(…?)` 或者系統/環境變量設置這個屬性的值為 `ignore ` 。 #### 2. 通配符位置 如果配置文件位置包含最后一個路徑段的 * 字符,則將其視為通配符位置。 加載配置時會擴展通配符,以便還檢查直接子目錄。 當有多個配置屬性源時,通配符位置在 Kubernetes 等環境中特別有用。 例如,如果有一些 Redis 配置和一些 MySQL 配置,希望將這兩個配置分開,同時要求它們都存在于 application.properties 文件中。 這可能會導致兩個單獨的 application.properties 文件掛載在不同的位置,例如 /config/redis/application.properties 和 /config/mysql/application.properties。 在這種情況下,通配符位置 config/*/ 將導致兩個文件都被處理。 比如 Redis 配置文件 `/config/redis/application.properties` MySQL的配置文件 `/config/mysql/application.properties`。 使用 `spring.config.location ` 或` spring.config.additional-location` 配置 `config/*/` 。 默認情況下,Spring Boot 在默認搜索位置包含 config/*/ 。 這意味著將搜索 jar 之外的 /config 目錄的所有子目錄。 可以自己使用帶有 spring.config.location 和 spring.config.additional-location 屬性的通配符位置。 注意: 通配符位置必須僅包含一個 * 并以 */ 結尾,表示搜索位置為目錄,或以 */<filename> 結尾,表示搜索位置為文件。 帶有通配符的位置根據文件名的絕對路徑按字母順序排序。 提示:通配符路徑僅在外部路徑,不能在 `classpath` 路徑中使用。 #### 3 特定環境的配置文件 除了應用程序屬性文件,Spring Boot 還將嘗試使用命名約定 application-{profile} 加載特定于配置文件的文件。 例如,如果應用程序激活名為 prod 的配置文件并使用 YAML 文件,則 application.yml 和 application-prod.yml 都將被考慮。 特定于配置文件的屬性從與標準 application.properties 相同的位置加載,特定于配置文件的文件始終覆蓋非特定文件。 如果指定了多個配置文件,則采用最后獲勝的策略。 例如,如果配置文件 prod,live 由 spring.profiles.active 屬性指定,則 application-prod.properties 中的值可以被 application-live.properties 中的值覆蓋。 注意: 最后獲勝策略適用于位置組級別。 classpath:/cfg/,classpath:/ext/ 的 spring.config.location 不會與 classpath:/cfg/;classpath:/ext/ 具有相同的覆蓋規則。 例如,繼續上面的 prod,live 示例,可能有以下文件: ~~~ /cfg application-live.properties /ext application-live.properties application-prod.properties ~~~ 當有 classpath:/cfg/,classpath:/ext/ 的 spring.config.location 時,在所有 /ext 文件之前處理所有 /cfg 文件: 1. `/cfg/application-live.properties` 2. `/ext/application-prod.properties` 3. `/ext/application-live.properties` 當使用 classpath:/cfg/;classpath:/ext/ 代替(使用 ; 分隔符)時,在同一級別處理 /cfg 和 /ext: 1. `/ext/application-prod.properties` 2. `/cfg/application-live.properties` 3. `/ext/application-live.properties` 環境有一組默認配置文件(默認情況下使用[default]),如果沒有設置活動配置文件,則使用這些配置文件。 換句話說,如果沒有明確激活配置文件,則考慮來自 application-default 的屬性。 注意:屬性文件只加載一次。 如果已經直接導入了配置文件特定的屬性文件,則不會再次導入。 #### 4. 導入附加數據 應用程序屬性可以使用 spring.config.import 屬性從其他位置導入更多配置數據。 進口在被發現時進行處理,并被視為附加文件,緊接在聲明進口的文件之下。 例如, application.properties 文件中可能包含以下內容: ``` spring: application: name: "myapp" config: import: "optional:file:./dev.properties" ``` 這將觸發在當前目錄中導入 dev.properties 文件(如果存在這樣的文件)。 導入的 dev.properties 中的值將優先于觸發導入的文件。 在上面的示例中, dev.properties 可以將 spring.application.name 重新定義為不同的值。 一個導入無論聲明多少次都只會被導入一次。 在 properties/yaml 文件中的單個文檔中定義導入的順序無關緊要。 例如,下面的兩個示例產生相同的結果: ``` spring: config: import: my.properties my: property: value ``` ``` my: property: value spring: config: import: my.properties ``` 在上述兩個示例中,來自 my.properties 文件的值將優先于觸發其導入的文件。 可以在單個 spring.config.import 鍵下指定多個位置。 位置將按照定義的順序進行處理,以后的導入優先。 注意:還考慮導入特定于配置文件的變體。 上面的示例將同時導入 my.properties 以及任何 my-<profile>.properties 變體。 提示: Spring Boot 包含可插入的 API,允許支持各種不同的位置地址。 默認情況下,您可以導入 Java 屬性、YAML 和“配置樹”。第三方 jar 可以提供對其他技術的支持(不要求文件是本地的)。 例如,您可以想象配置數據來自外部存儲,例如 Consul、Apache ZooKeeper 或 Netflix Archaius。如果想支持自己的位置,請參閱 org.springframework.boot.context.config 包中的 ConfigDataLocationResolver 和 ConfigDataLoader 類。 #### 5. 導入無擴展名的文件 某些云平臺無法為卷掛載文件添加文件擴展名。 要導入這些無擴展名的文件,需要給 Spring Boot 一個提示,以便它知道如何加載它們。 可以通過將擴展提示放在方括號中來做到這一點。 例如,假設有一個 /etc/config/myconfig 文件希望作為 yaml 導入。 可以使用以下命令從 application.properties 導入它: ``` spring: config: import: "file:/etc/config/myconfig[.yaml]" ``` #### 6. 使用配置樹 在云平臺上(比如Kubernetes) 直接配置會不安全。 許多云平臺允許從數據卷中讀取配置, 比如Kubernetes 可以批量掛載 ConfigMaps 和Secrets。 有兩種常見的卷安裝模式: 1. 單個文件包含一組完整的屬性(通常編寫為 YAML)。 2. 多個文件被寫入目錄樹,文件名成為“鍵”,內容成為“值”。 第一種方式可以使用spring.config.import.導入其他文件,對于第二種情況,使用 configtree: 前綴,以便 Spring Boot 知道它需要將所有文件公開為屬性。 舉例來說, 文件結構: ``` etc/ config/ myapp/ username password ``` 文件username存儲用戶名, password是加密的內容。 要導入這些屬性,可以將以下內容添加到 application.properties 或 application.yaml 文件中:導入如下: ``` spring: config: import: "optional:configtree:/etc/config/" ``` 然后,您可以以通常的方式從環境中訪問或注入 myapp.username 和 myapp.password 屬性。 注意: 帶有點符號的文件名也被正確映射。 例如,在上面的示例中,/etc/config 中名為 myapp.username 的文件將導致環境中的 myapp.username 屬性。 提示: 配置樹值可以綁定到字符串 String 和 byte[] 類型。 如果有多個配置樹要從同一個父文件夾導入,可以使用通配符快捷方式。 任何以 /*/ 結尾的 configtree: location 將導入所有直接子項作為配置樹。 例如: ``` etc/ config/ dbconfig/ db/ username password mqconfig/ mq/ username password ``` 可以使用 configtree:/etc/config/*/ 作為導入位置: ``` spring: config: import: "optional:configtree:/etc/config/*/" ``` 注意: 使用通配符加載的目錄按字母順序排序。 如果您需要不同的順序,那么您應該將每個位置作為單獨的導入列出 配置樹也可用于 Docker secrets。 當 Docker swarm 服務被授予訪問機密的權限時,機密會被掛載到容器中。 例如,如果名為 db.password 的secret掛在到位置 /run/secrets/,您可以使用以下命令使 db.password 可用于 Spring 環境: ``` spring: config: import: "optional:configtree:/run/secrets/" ``` #### 7. 屬性占位符 application.properties 和 application.yml 中的值在使用時會根據環境進行過濾,因此可以參考以前定義的值(例如,來自系統屬性)。 標準的 ${name} 屬性占位符語法可以在值內的任何地方使用。 例如,以下文件會將 app.description 設置為“MyApp is a Spring Boot application”: ``` app: name: "MyApp" description: "${app.name} is a Spring Boot application" ``` 提示:可以使用此技術創建現有 Spring Boot 屬性的“短”變體。 有關詳細信息,請參閱“4. 使用“Short”(短)命令行參數”。 #### 8. 多文檔文件的處理 Spring Boot 允許將單個物理文件拆分為多個獨立添加的邏輯文檔。 文檔按順序處理,從上到下。 后面的文檔可以覆蓋在前面的文檔中定義的屬性 對于 application.yml 文件,使用標準的 YAML 多文檔語法。 三個連續的連字符代表一個文檔的結束和下一個文檔的開始。 例如下面的文件有兩個邏輯文檔: ``` spring: application: name: MyApp --- spring: application: name: MyCloudApp config: activate: on-cloud-platform: kubernetes ``` 對于 application.properties 文件,使用` #---` 注釋用于標記文檔拆分, 比如: ``` spring.application.name=MyApp #--- spring.application.name=MyCloudApp spring.config.activate.on-cloud-platform=kubernetes ``` ![](https://img.kancloud.cn/ba/34/ba34faf0cc82fdb5c99e4d51cea57b29_106x30.png)注意: 屬性文件分隔符不能有任何前導空格,并且必須正好有三個連字符。 分隔符前后的行不能是注釋。 ![](https://img.kancloud.cn/b1/2a/b12adb9ce1e7765f0ea5e264e56b8707_90x33.png)提示: 多文檔屬性文件通常與 spring.config.activate.on-profile 等激活屬性結合使用。 ![](https://img.kancloud.cn/8c/8b/8c8b191b86c066271d62c24f554d68fc_143x30.png)警告:使用 @PropertySource 或 @TestPropertySource注解的多文檔屬性文件無法加載。 #### 9. 屬性的激活 有時僅在滿足某些條件時激活給定的屬性 很有用。 例如,僅在特定配置文件處于活動狀態時才相關的屬性。 可以使用 spring.config.activate.* 有條件地激活屬性文檔。 激活屬性可以使用: | 屬性 | 說明 | | --- | --- | | on-profile | 與文檔匹配的Profile表達式會被激活| | on-cloud-platform | 要使文檔處于活動狀態,必須檢測到的 CloudPlatform。 | 例如,以下指定第二個文檔僅在 Kubernetes 上運行時才處于活動狀態,并且僅當“prod”或“staging”配置文件處于活動狀態時: ``` myprop: always-set --- spring: config: activate: on-cloud-platform: "kubernetes" on-profile: "prod | staging" myotherprop: sometimes-set ``` ## 4. 加密屬性 Spring Boot 不提供任何對加密屬性值的內置支持,但是,它提供了修改 Spring Environment 中包含的值所需的鉤子。 EnvironmentPostProcessor 接口允許您在應用程序啟動之前操作環境。 詳細參考[https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.application.customize-the-environment-or-application-context。](https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto.application.customize-the-environment-or-application-context。) 如果尋找一種安全的方式來存儲憑證和密碼,Spring Cloud Vault 項目提供了在 HashiCorp Vault 中存儲外部化配置的支持。 ## 5. YAML的使用 YAML 是 JSON 的超集,是一種用于指定分層配置數據的便捷格式。 只要在類路徑上有 SnakeYAML 庫,SpringApplication 類就會自動支持 YAML 作為屬性的替代方案 注意: 如果使用啟動器,則 SnakeYAML 由 spring-boot-starter 自動提供。 #### 1. 將 YAML 映射到屬性 YAML 文檔需要從其分層格式轉換為可與 Spring Environment 一起使用的平面結構。 例如,考慮以下 YAML 文檔: ``` environments: dev: url: https://dev.example.com name: Developer Setup prod: url: https://another.example.com name: My Cool App ``` 為了從 Environment 訪問這些屬性,它們將被展平如下: ``` environments.dev.url=https://dev.example.com environments.dev.name=Developer Setup environments.prod.url=https://another.example.com environments.prod.name=My Cool App ``` 同樣,YAML 列表也需要扁平化。 它們表示為帶有 [index] 解引用器的屬性鍵。 例如,考慮以下 YAML: ``` my: servers: - dev.example.com - another.example.com ``` 前面的示例將轉換為以下屬性: ``` my.servers[0]=dev.example.com my.servers[1]=another.example.com ``` 提示:使用 [index] 表示法的屬性可以使用 Spring Boot 的 Binder 類綁定到 Java List 或 Set 對象。 有關更多詳細信息,請參閱下面的“類型安全配置屬性”部分。 警告: 無法使用 @PropertySource 或 @TestPropertySource 批注加載 YAML 文件。 因此,如果需要以這種方式加載值,則需要使用屬性文件。 #### 2. 直接加載 YAML Spring Framework 提供了兩個方便的類,可用于加載 YAML 文檔。 YamlPropertiesFactoryBean 將 YAML 作為屬性加載,而 YamlMapFactoryBean 將 YAML 作為 Map 加載。 如果要將 YAML 作為 Spring PropertySource 加載,也可以使用 YamlPropertySourceLoader 類 ## 6. 配置隨機值 RandomValuePropertySource 可用于注入隨機值(例如,注入機密或測試用例)。 它可以生成整數、長整數、uuid 或字符串,如以下示例所示: ``` my: secret: "${random.value}" number: "${random.int}" bignumber: "${random.long}" uuid: "${random.uuid}" number-less-than-ten: "${random.int(10)}" number-in-range: "${random.int[1024,65536]}" ``` random.int* 語法是 OPEN value (,max) CLOSE,其中 OPEN,CLOSE 是任何字符,value,max 是整數。 如果提供了 max,則 value 是最小值,max 是最大值(不包括在內)。 ## 7. 配置系統環境變量 Spring Boot 支持為環境屬性設置前綴。 如果系統環境由具有不同配置要求的多個 Spring Boot 應用程序共享,這將非常有用。 系統環境屬性的前綴可以直接在 SpringApplication 上設置。 使用場景: 多個不同配置需求的Spring Boot 應用共享系統環境變量。 比如設置前綴為input,那么remote.timeout等屬性在系統環境中也會解析為input.remote.timeout。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看