您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)Spring Boot 中Profile配置體系的示例分析,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
配置體系是基于 Spring Boot 框架開(kāi)發(fā)應(yīng)用程序的基礎(chǔ),而自動(dòng)配置也是該框架的核心功能之一,梳理使用 Spring Boot 配置體系的系統(tǒng)方法.
接下來(lái),我們?yōu)檫@個(gè)代碼工程添加一些支持 RESTful 風(fēng)格的 HTTP 端點(diǎn),在這里我們同樣創(chuàng)建一個(gè) CustomerController 類,如下所示
@RestController @RequestMapping(value="customers") public class CustomerController { @RequestMapping(value = "/{id}", method = RequestMethod.GET) public CustomerTicket getCustomerTicketById(@PathVariable Long id) { CustomerTicket customerTicket = new CustomerTicket(); customerTicket.setId(1L); customerTicket.setAccountId(100L); customerTicket.setOrderNumber("Order00001"); customerTicket.setDescription("DemoOrder"); customerTicket.setCreateTime(new Date()); return customerTicket; } }
請(qǐng)注意,這里是為了演示方便,我們才使用了硬編碼完成了一個(gè) HTTP GET 請(qǐng)求的響應(yīng)處理。
現(xiàn)在 RESTful 端點(diǎn)已經(jīng)開(kāi)發(fā)完成,我們需要對(duì)這個(gè)應(yīng)用程序進(jìn)行打包?;?Spring Boot 和 Maven,當(dāng)我們使用 mvn package 命令構(gòu)建整個(gè)應(yīng)用程序時(shí),將得到一個(gè) customerservice-0.0.1-SNAPSHOT.jar 文件,而這個(gè) jar 文件就是可以直接運(yùn)行的可執(zhí)行文件,內(nèi)置了 Tomcat Web 服務(wù)器。也就是說(shuō),我們可以通過(guò)如下命令直接運(yùn)行這個(gè) Spring Boot 應(yīng)用程序:
java –jar customerservice-0.0.1-SNAPSHOT.jar
通過(guò) Postman 訪問(wèn)“http://localhost:8083/customers/1”端點(diǎn),可以得到如下圖所示的HTTP響應(yīng)結(jié)果,說(shuō)明整個(gè)服務(wù)已經(jīng)啟動(dòng)成功。
在 Spring Boot 中,其核心設(shè)計(jì)理念是對(duì)配置信息的管理采用約定優(yōu)于配置。在這一理念下,則意味著開(kāi)發(fā)人員所需要設(shè)置的配置信息數(shù)量比使用傳統(tǒng) Spring 框架時(shí)還大大減少。
當(dāng)然,今天我們關(guān)注的主要是如何理解并使用 Spring Boot 中的配置信息組織方式,這里就需要引出一個(gè)核心的概念,即 Profile。
Profile 本質(zhì)上代表一種用于組織配置信息的維度,在不同場(chǎng)景下可以代表不同的含義。例如,如果 Profile 代表的是一種狀態(tài),我們可以使用 open、halfopen、close 等值來(lái)分別代表全開(kāi)、半開(kāi)和關(guān)閉等。再比如系統(tǒng)需要設(shè)置一系列的模板,每個(gè)模板中保存著一系列配置項(xiàng),那么也可以針對(duì)這些模板分別創(chuàng)建 Profile。這里的狀態(tài)或模版的定義完全由開(kāi)發(fā)人員自主設(shè)計(jì),我們可以根據(jù)需要自定義各種 Profile,這就是 Profile 的基本含義。
為了達(dá)到集中化管理的目的,Spring Boot 對(duì)配置文件的命名也做了一定的約定,分別使用 label 和 profile 概念來(lái)指定配置信息的版本以及運(yùn)行環(huán)境,其中 label 表示配置版本控制信息,而 profile 則用來(lái)指定該配置文件所對(duì)應(yīng)的環(huán)境
在 Spring Boot 中,配置文件同時(shí)支持 .properties 和 .yml 兩種文件格式,結(jié)合 label 和 profile 概念,如下所示的配置文件命名都是常見(jiàn)和合法的:
/{application}.yml /{application}-{profile}.yml /{label}/{application}-{profile}.yml /{application}-{profile}.properties /{label}/{application}-{profile}.properties
Yaml 的語(yǔ)法和其他高級(jí)語(yǔ)言類似,并且可以非常直觀地表達(dá)各種列表、清單、標(biāo)量等數(shù)據(jù)形態(tài),特別適合用來(lái)表達(dá)或編輯數(shù)據(jù)結(jié)構(gòu)和各種配置文件。在這里,我們指定了如下所示的數(shù)據(jù)源配置,這里使用了 . yml 文件,如下所示:
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/account username: root password: root
如果采用 .propertie 配置文件,那么上述配置信息將表示為如下的形式:
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://127.0.0.1:3306/account spring.datasource.username=root spring.datasource.password=root
顯然,類似這樣的數(shù)據(jù)源通常會(huì)根據(jù)環(huán)境的不同而存在很多套配置。假設(shè)我們存在如下所示的配置文件集合:
注意,這里有一個(gè)全局的 application.yml 配置文件以及多個(gè)局部的 profile 配置文件。
那么,如何指定當(dāng)前所使用的那一套配置信息呢?
在 Spring Boot 中,我們可以在主 application.properties 中使用如下的配置方式來(lái)激活當(dāng)前所使用的 Profile:
spring.profiles.active = test
上述配置項(xiàng)意味著系統(tǒng)當(dāng)前會(huì)讀取 application-test.yml 配置文件中的配置內(nèi)容。同樣,如果使用 .yml 文件,則可以使用如下所示的配置方法:
spring: profiles: active: test
事實(shí)上,我們也可以同時(shí)激活幾個(gè) Profile,這完全取決于你對(duì)系統(tǒng)配置的需求和維度:
spring.profiles.active: prod, myprofile1, myprofile2
當(dāng)然,如果你想把所有的 Profile 配置信息只保存在一個(gè)文件中而不是分散在多個(gè)配置文件中, Spring Boot 也是支持的,需要做的事情只是對(duì)這些信息按 Profile 進(jìn)行組織、分段,如下所示:
spring: profiles: test #test 環(huán)境相關(guān)配置信息 spring: profiles: prod #prod 環(huán)境相關(guān)配置信息
推薦按多個(gè)配置文件的組織方法管理各個(gè) Profile 配置信息,這樣才不容易混淆和出錯(cuò)。
最后,如果我們不希望在全局配置文件中指定所需要激活的 Profile,而是想把這個(gè)過(guò)程延遲到運(yùn)行這個(gè)服務(wù)時(shí),那么我們可以直接在 java –jar 命令中添加“–spring.profiles.active”參數(shù),如下所示
java –jar customerservice-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
這種實(shí)現(xiàn)方案在通過(guò)腳本進(jìn)行自動(dòng)化打包和部署的場(chǎng)景下非常有用。
在 Spring Boot 中,Profile 這一概念的應(yīng)用場(chǎng)景還包括動(dòng)態(tài)控制代碼執(zhí)行流程。為此,我們需要使用 @Profile 注解,先來(lái)看一個(gè)簡(jiǎn)單的示例。
@Configuration public class DataSourceConfig { @Bean @Profile("dev") public DataSource devDataSource() { //創(chuàng)建 dev 環(huán)境下的 DataSource } @Bean() @Profile("prod") public DataSource prodDataSource(){ //創(chuàng)建 prod 環(huán)境下的 DataSource } }
可以看到,我們構(gòu)建了一個(gè) DataSourceConfig 配置類來(lái)專門管理各個(gè)環(huán)境所需的 DataSource。注意到這里使用 @Profile 注解來(lái)指定具體所需要執(zhí)行的 DataSource 創(chuàng)建代碼,通過(guò)這種方式,可以達(dá)到與使用配置文件相同的效果。
更進(jìn)一步,能夠在代碼中控制 JavaBean 的創(chuàng)建過(guò)程為我們根據(jù)各種條件動(dòng)態(tài)執(zhí)行代碼流程提供了更大的可能性。
例如,在日常開(kāi)發(fā)過(guò)程中,一個(gè)常見(jiàn)的需求是根據(jù)不同的運(yùn)行環(huán)境初始化數(shù)據(jù),常見(jiàn)的做法是獨(dú)立執(zhí)行一段代碼或腳本?;?@Profile 注解,我們就可以將這一過(guò)程包含在代碼中并做到自動(dòng)化,如下所示:
@Profile("dev") @Configuration public class DevDataInitConfig { @Bean public CommandLineRunner dataInit() { return new CommandLineRunner() { @Override public void run(String... args) throws Exception { //執(zhí)行 Dev 環(huán)境的數(shù)據(jù)初始化 }; }
這里用到了 Spring Boot 所提供了啟動(dòng)時(shí)任務(wù)接口 CommandLineRunner,實(shí)現(xiàn)了該接口的代碼會(huì)在 Spring Boot 應(yīng)用程序啟動(dòng)時(shí)自動(dòng)進(jìn)行執(zhí)行 。
@Profile 注解的應(yīng)用范圍很廣,我們可以將它添加到包含 @Configuration 和 @Component 注解的類及其方法,也就是說(shuō)可以延伸到繼承了 @Component 注解的 @Service、@Controller、@Repository 等各種注解中。
下面來(lái)看幾個(gè)常見(jiàn)的配置示例 , 加深對(duì) Spring Boot 中配置體系的理解。
對(duì)于一個(gè) Web 應(yīng)用程序而言,最常見(jiàn)的配置可能就是指定服務(wù)暴露的端口地址,如下所示:
server: port: 8080
同時(shí),數(shù)據(jù)庫(kù)訪問(wèn)也是 Web 應(yīng)用程序的基本功能,因此,關(guān)于數(shù)據(jù)源的設(shè)置也是常見(jiàn)的一種配置場(chǎng)景,上一篇博文時(shí)給出了一個(gè)基本的示例。
這里再以 JPA 為例,給出如下所示的一種配置方案:
spring: jpa: hibernate: ddl-auto: create show-sql: true
顯然,這里使用了 Hibernate 作為 JPA 規(guī)范的實(shí)現(xiàn)框架,并設(shè)置了 show-sql 等相關(guān)屬性。然后,開(kāi)發(fā)人員一般也需要設(shè)置日志級(jí)別和對(duì)象,如下所示的就是一個(gè)典型的配置示例:
logging.level.root=WARN logging.level.com.springcss.customer=INFO
我們?cè)O(shè)置了系統(tǒng)的全局日志級(jí)別為 WARN,而針對(duì)自定義的 com.springcss.customer 包下的日志則將其級(jí)別調(diào)整到 INFO。
這里需要注意的是,Spring Boot 基于 application.properties 或 application.yml 全局配置文件已經(jīng)自動(dòng)內(nèi)置了很多默認(rèn)配置。即使我們不設(shè)置上述配置內(nèi)容,Spring Boot 仍然可以基于這些默認(rèn)配置完成系統(tǒng)的初始化。
自動(dòng)配置是 Spring Boot 中的一個(gè)核心概念,我們會(huì)在后續(xù)內(nèi)容中給出詳細(xì)的實(shí)現(xiàn)原理分析。
我們知道 Spring Boot 通過(guò)自動(dòng)配置機(jī)制內(nèi)置了很多默認(rèn)的配置信息,而在這些配置信息中,有一部分系統(tǒng)配置信息也可以反過(guò)來(lái)作為配置項(xiàng)應(yīng)用到我們的應(yīng)用程序中。
例如,如果想要獲取當(dāng)前應(yīng)用程序的名稱并作為一個(gè)配置項(xiàng)進(jìn)行管理,那么很簡(jiǎn)單,我們直接通過(guò) ${spring.application.name} 占位符就可以做到這一點(diǎn),如下所示:
myapplication.name : ${spring.application.name}
通過(guò) ${} 占位符
同樣可以引用配置文件中的其他配置項(xiàng)內(nèi)容,如在下列配置項(xiàng)中,最終“system.description”配置項(xiàng)的值就是“The system springcss is used for health”。
system.name=springcss system.domain=health system.description=The system ${name} is used for ${domain}.
再來(lái)看一種場(chǎng)景,假設(shè)我們使用 Maven 來(lái)構(gòu)建應(yīng)用程序,那么可以按如下所示的配置項(xiàng)來(lái)動(dòng)態(tài)獲取與系統(tǒng)構(gòu)建過(guò)程相關(guān)的信息:
info: app: encoding: @project.build.sourceEncoding@ java: source: @java.version@ target: @java.version@
上述配置項(xiàng)的效果與如下所示的靜態(tài)配置是一樣的:
info: app: encoding: UTF-8 java: source: 1.8.0_31 target: 1.8.0_31
根據(jù)不同的需求,在應(yīng)用程序中嵌入系統(tǒng)配置信息是很有用的,特別是在一些面向 DevOps 的應(yīng)用場(chǎng)景中。
在現(xiàn)實(shí)的開(kāi)發(fā)過(guò)程中,面對(duì)紛繁復(fù)雜的應(yīng)用場(chǎng)景,Spring Boot 所提供的內(nèi)置配置信息并不一定能夠完全滿足開(kāi)發(fā)的需求,這就需要開(kāi)發(fā)人員創(chuàng)建并管理各種自定義的配置信息。
例如,對(duì)于一個(gè)電商類應(yīng)用場(chǎng)景,為了鼓勵(lì)用戶完成下單操作,我們希望每完成一個(gè)訂單給就給到用戶一定數(shù)量的積分。從系統(tǒng)擴(kuò)展性上講,這個(gè)積分應(yīng)該是可以調(diào)整的,所以我們創(chuàng)建了一個(gè)自定義的配置項(xiàng),如下所示:
springcss.order.point = 10
這里,我們?cè)O(shè)置了每個(gè)訂單對(duì)應(yīng)的積分為 10,那么應(yīng)用程序該如何獲取這個(gè)配置項(xiàng)的內(nèi)容呢?通常有兩種方法。
使用 @Value 注解來(lái)注入配置項(xiàng)內(nèi)容是一種傳統(tǒng)的實(shí)現(xiàn)方法。針對(duì)前面給出的自定義配置項(xiàng),我們可以構(gòu)建一個(gè) SpringCssConfig 類,如下所示:
@Component public class SpringCssConfig { @Value("${springcss.order.point}") private int point; }
在 SpringCssConfig 類中,我們要做的就是在字段上添加 @Value 注解,并指向配置項(xiàng)的名稱即可。
相較 @Value 注解,更為現(xiàn)代的一種做法是使用 @ConfigurationProperties 注解。在使用該注解時(shí),我們通常會(huì)設(shè)置一個(gè)“prefix”屬性用來(lái)指定配置項(xiàng)的前綴,如下所示:
@Component @ConfigurationProperties(prefix = "springcss.order") public class SpringCsshConfig { private int point; //省略 getter/setter }
相比 @Value 注解只能用于指定具體某一個(gè)配置項(xiàng),@ConfigurationProperties 可以用來(lái)批量提取配置內(nèi)容。只要指定 prefix,我們就可以把該 prefix 下的所有配置項(xiàng)按照名稱自動(dòng)注入業(yè)務(wù)代碼中。
我們考慮一種更常見(jiàn)也更復(fù)雜的場(chǎng)景:假設(shè)用戶根據(jù)下單操作獲取的積分并不是固定的,而是根據(jù)每個(gè)不同類型的訂單會(huì)有不同的積分,那么現(xiàn)在的配置項(xiàng)的內(nèi)容,如果使用 Yaml 格式的話就應(yīng)該是這樣:
springcss: points: orderType[1]: 10 orderType[2]: 20 orderType[3]: 30
如果想把這些配置項(xiàng)全部加載到業(yè)務(wù)代碼中,使用 @ConfigurationProperties 注解同樣也很容易實(shí)現(xiàn)。我們可以直接在配置類 SpringCssConfig 中定義一個(gè) Map 對(duì)象,然后通過(guò) Key-Value 對(duì)來(lái)保存這些配置數(shù)據(jù),如下所示:
@Component @ConfigurationProperties(prefix="springcss.points") public class SpringCssConfig { private Map<String, Integer> orderType = new HashMap<>(); //省略 getter/setter }
可以看到這里通過(guò)創(chuàng)建一個(gè) HashMap 來(lái)保存這些 Key-Value 對(duì)。類似的,我們也可以實(shí)現(xiàn)常見(jiàn)的一些數(shù)據(jù)結(jié)構(gòu)的自動(dòng)嵌入。
如果你已經(jīng)使用過(guò) Spring Boot 中的配置文件,并添加了一些內(nèi)置的配置項(xiàng),你就會(huì)發(fā)現(xiàn),當(dāng)我們輸入某一個(gè)配置項(xiàng)的前綴時(shí),諸如 IDEA、Eclipse 這樣的,IDE 就會(huì)自動(dòng)彈出該前綴下的所有配置信息供你進(jìn)行選擇,效果如下:
上圖的效果對(duì)于管理自定義的配置信息非常有用。如何實(shí)現(xiàn)這種效果呢?當(dāng)我們?cè)?application.yml 配置文件中添加一個(gè)自定義配置項(xiàng)時(shí),會(huì)注意到 IDE 會(huì)出現(xiàn)一個(gè)提示,說(shuō)明這個(gè)配置項(xiàng)無(wú)法被 IDE 所識(shí)別,如下所示:
遇到這種提示時(shí),我們是可以忽略的,因?yàn)樗粫?huì)影響到任何執(zhí)行效果。
但為了達(dá)到自動(dòng)提示效果,我們就需要生成配置元數(shù)據(jù)。生成元數(shù)據(jù)的方法也很簡(jiǎn)單,直接通過(guò) IDE 的“Create metadata for ‘springcss.order.point'”按鈕,就可以選擇創(chuàng)建配置元數(shù)據(jù)文件,這個(gè)文件的名稱為 additional-spring-configuration-metadata.json,文件內(nèi)容如下所示:
{"properties": [{ "name": "springcss.order.point", "type": "java.lang.String", "description": "A description for 'springcss.order.point'" }]}
現(xiàn)在,假如我們?cè)?application.properties 文件中輸入“springcss”,IDE 就會(huì)自動(dòng)提示完整的配置項(xiàng)內(nèi)容,效果如下所示:
另外,假設(shè)我們需要為 springcss.order.point 配置項(xiàng)指定一個(gè)默認(rèn)值,可以通過(guò)在元數(shù)據(jù)中添加一個(gè)"defaultValue"項(xiàng)來(lái)實(shí)現(xiàn),如下所示:
{"properties": [{ "name": "springcss.order.point", "type": "java.lang.String", "description": "'springcss.order.point' is userd for setting the point when dealing with an order.", "defaultValue": 10 }]}
這時(shí)候,在 IDE 中設(shè)置這個(gè)配置項(xiàng)時(shí),就會(huì)提出該配置項(xiàng)的默認(rèn)值為 10,效果如下所示:
Profile 可以認(rèn)為是管理配置信息中的一種有效手段。
下面,我們繼續(xù)介紹另一種組織和整合配置信息的方法,這種方法同樣依賴于前面介紹的 @ConfigurationProperties 注解。
在使用 @ConfigurationProperties 注解時(shí),我們可以和 @PropertySource 注解一起進(jìn)行使用,從而指定從哪個(gè)具體的配置文件中獲取配置信息。
例如,在下面這個(gè)示例中,我們通過(guò) @PropertySource 注解指定了 @ConfigurationProperties 注解中所使用的配置信息是從當(dāng)前類路徑下的 application.properties 配置文件中進(jìn)行讀取。
@Component @ConfigurationProperties(prefix = "springcss.order") @PropertySource(value = "classpath:application.properties") public class SpringCssConfig { }
既然我們可以通過(guò) @PropertySource 注解來(lái)指定一個(gè)配置文件的引用地址,那么顯然也可以引入多個(gè)配置文件,這時(shí)候用到的是 @PropertySources 注解,使用方式如下所示:
@PropertySources({ @PropertySource("classpath:application.properties "), @PropertySource("classpath:redis.properties"), @PropertySource("classpath:mq.properties") }) public class SpringCssConfig {
這里,我們通過(guò) @PropertySources 注解組合了多個(gè) @PropertySource 注解中所指定的配置文件路徑。SpringCssConfig 類可以同時(shí)引用所有這些配置文件中的配置項(xiàng)。
另一方面,我們也可以通過(guò)配置 spring.config.location 來(lái)改變配置文件的默認(rèn)加載位置,從而實(shí)現(xiàn)對(duì)多個(gè)配置文件的同時(shí)加載。例如,如下所示的執(zhí)行腳本會(huì)在啟動(dòng) customerservice-0.0.1-SNAPSHOT.jar 時(shí)加載D盤下的 application.properties 文件,以及位于當(dāng)前類路徑下 config 目錄中的所有配置文件:
java -jar customerservice-0.0.1-SNAPSHOT.jar --spring.config.location=file:///D:/application.properties, classpath:/config/
通過(guò) spring.config.location 指定多個(gè)配置文件路徑也是組織和整合配置信息的一種有效的實(shí)現(xiàn)方式。
通過(guò)前面的示例,我們看到可以把配置文件保存在多個(gè)路徑,而這些路徑在加載配置文件時(shí)具有一定的順序。Spring Boot 在啟動(dòng)時(shí)會(huì)掃描以下位置的 application.properties 或者 application.yml 文件作為全局配置文件:
–file:./config/ –file:./ –classpath:/config/ –classpath:/
以下是按照優(yōu)先級(jí)從高到低的順序,如下所示:
Spring Boot 會(huì)全部掃描上圖中的這四個(gè)位置,掃描規(guī)則是高優(yōu)先級(jí)配置內(nèi)容會(huì)覆蓋低優(yōu)先級(jí)配置內(nèi)容。而如果高優(yōu)先級(jí)的配置文件中存在與低優(yōu)先級(jí)配置文件不沖突的屬性,則會(huì)形成一種互補(bǔ)配置,也就是說(shuō)會(huì)整合所有不沖突的屬性。
關(guān)于 Spring Boot 配置體系,最后值得介紹的就是如何覆寫(xiě)它所提供的配置類。我們已經(jīng)反復(fù)強(qiáng)調(diào) Spring Boot 內(nèi)置了大量的自動(dòng)配置,如果我們不想使用這些配置,就需要對(duì)它們進(jìn)行覆寫(xiě)。
覆寫(xiě)的方法有很多,我們可以使用配置文件、Groovy 腳本以及 Java 代碼。這里,我們就以Java代碼為例來(lái)簡(jiǎn)單演示覆寫(xiě)配置類的實(shí)現(xiàn)方法。
以Spring Security為例
在 Spring Security 體系中,設(shè)置用戶認(rèn)證信息所依賴的配置類是 WebSecurityConfigurer 類。顧名思義,這是一個(gè)設(shè)置 Web 安全的配置類。
Spring Security 提供了 WebSecurityConfigurerAdapter 這個(gè)適配器類來(lái)簡(jiǎn)化該配置類的使用方式,我們可以繼承 WebSecurityConfigurerAdapter 類并且覆寫(xiě)其中的 configure() 的方法來(lái)完成自定義的用戶認(rèn)證配置工作。
典型的 WebSecurityConfigurerAdapter 子類及其代碼實(shí)現(xiàn)如下所示
@Configuration public class SpringHCssWebSecurityConfigurer extends WebSecurityConfigurerAdapter { @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override @Bean public UserDetailsService userDetailsServiceBean() throws Exception { return super.userDetailsServiceBean(); } @Override protected void configure(AuthenticationManagerBuilder builder) throws Exception { builder.inMemoryAuthentication().withUser("springcss_user").password("{noop}password1").roles("USER").and() .withUser("springcss_admin").password("{noop}password2").roles("USER", "ADMIN"); } }
這里我們只需要知道,在 Spring Boot 中,提供了一些類的內(nèi)置配置類,而開(kāi)發(fā)人員可以通過(guò)構(gòu)建諸如上述所示的 SpringCssWebSecurityConfigurer 類來(lái)對(duì)這些內(nèi)置配置類進(jìn)行覆寫(xiě),從而實(shí)現(xiàn)自定義的配置信息。
關(guān)于“Spring Boot 中Profile配置體系的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。