您好,登錄后才能下訂單哦!
小編給大家分享一下Nacos+Spring Cloud Gateway動(dòng)態(tài)路由如何配置實(shí)現(xiàn),希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
Nacos最近項(xiàng)目一直在使用,其簡(jiǎn)單靈活,支持更細(xì)粒度的命令空間,分組等為麻煩復(fù)雜的環(huán)境切換提供了方便;同時(shí)也很好支持動(dòng)態(tài)路由的配置,只需要簡(jiǎn)單的幾步即可。在國(guó)產(chǎn)的注冊(cè)中心、配置中心中比較突出,容易上手,本文通過(guò)gateway、nacos-consumer、nacos-provider三個(gè)簡(jiǎn)單模塊來(lái)展示:Nacos下動(dòng)態(tài)路由配置。
博文中源碼已上傳至github(https://github.com/Jian0110/learning-cloudalibaba),歡迎小伙伴們star
具體的Nacos怎么配置就不介紹了,可以參考阿里巴巴的官方介紹,這里通過(guò)windows直接本地啟動(dòng)開啟單機(jī)模式,登錄Nacos Console,創(chuàng)建dev的namespace,在dev下的默認(rèn)分組下創(chuàng)建gateway-router的dataId
gateway-router的主要初始化配置如下:關(guān)于gateway的組成(id,order、predicates斷言,uri)這里就不詳細(xì)說(shuō)明的了,可以自行百度下
[{ "id": "consumer-router", "order": 0, "predicates": [{ "args": { "pattern": "/consume/**" }, "name": "Path" }], "uri": "lb://nacos-consumer" },{ "id": "provider-router", "order": 2, "predicates": [{ "args": { "pattern": "/provide/**" }, "name": "Path" }], "uri": "lb://nacos-provider" }]
通常在項(xiàng)目中配置“配置中心”往往都是在bootstrap.propertis(yaml)中配置,這樣才能保證項(xiàng)目中路由配置從Nacos Config中讀取。
# nacos配置中心配置建議在bootstrap.properties中配置 spring.cloud.nacos.config.server-addr=127.0.0.1:8848 #spring.cloud.nacos.config.file-extension=properties # 配置中心的命名空間:dev 的命名空間(環(huán)境) spring.cloud.nacos.config.namespace=08ecd1e5-c042-410a-84d5-b0a8fbeed8ea
Application啟動(dòng)類中增加注解@EnableDiscoveryClient,才能保證連接到Nacos Config
@SpringBootApplication @EnableDiscoveryClient public class GatewayApplication { public static void main( String[] args ) { SpringApplication.run(GatewayApplication.class, args); } }
創(chuàng)建簡(jiǎn)單的springboot多模塊結(jié)構(gòu),推薦使用idea創(chuàng)建
1)Nacos父模塊:
<groupId>com.springcloud</groupId> <artifactId>nacos</artifactId> <version>0.0.1-SNAPSHOT</version> <name>nacos</name> <description>Nacos Demo</description>
首先pom文件引入Spring Cloud Alibaba Nacos組件:注冊(cè)中心nacos-discovery與配置中心nacos-config
<!--nacos 客戶端 注冊(cè)中心--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <version>${alibaba-nacos.version}</version> </dependency> <!--nacos 客戶端 配置中心--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>${alibaba-nacos.version}</version> </dependency>
其次再引入Spring Cloud相關(guān)組件依賴
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
其它組件依賴引入(修正:如果引入了nacos-api相關(guān)的JSON依賴,那么fastjson就不需要再引入了,否則可能沖突):
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>${fastjson.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
注意,這里有個(gè)坑,spring cloud gateway使用的web框架為webflux,和springMVC不兼容。所以不要引入(修正:只有g(shù)ateway服務(wù)不用引入springMVC,其他需要引入)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
2)三個(gè)子模塊:gateway、nacos-consumer、nacos-provider
<modules> <module>nacos-provider</module> <module>nacos-consumer</module> <module>gateway</module> </modules>
結(jié)構(gòu)截圖如下所示:
3)三個(gè)服務(wù)的端口分別為:
nacos-consume:6001
nacos-provider:6002
gateway:6003
4)服務(wù)架構(gòu)如下:
(1)在gateway模塊中主要實(shí)現(xiàn)以下功能:
第一,從Nacos配置中心中加載動(dòng)態(tài)路由的相關(guān)配置,就需要讀取Nacos的命名空間namespace,通過(guò)dataId獲取配置
/** * 路由類配置 */ @Configuration public class GatewayConfig { public static final long DEFAULT_TIMEOUT = 30000; public static String NACOS_SERVER_ADDR; public static String NACOS_NAMESPACE; public static String NACOS_ROUTE_DATA_ID; public static String NACOS_ROUTE_GROUP; @Value("${spring.cloud.nacos.discovery.server-addr}") public void setNacosServerAddr(String nacosServerAddr){ NACOS_SERVER_ADDR = nacosServerAddr; } @Value("${spring.cloud.nacos.discovery.namespace}") public void setNacosNamespace(String nacosNamespace){ NACOS_NAMESPACE = nacosNamespace; } @Value("${nacos.gateway.route.config.data-id}") public void setNacosRouteDataId(String nacosRouteDataId){ NACOS_ROUTE_DATA_ID = nacosRouteDataId; } @Value("${nacos.gateway.route.config.group}") public void setNacosRouteGroup(String nacosRouteGroup){ NACOS_ROUTE_GROUP = nacosRouteGroup; } }
properties配置關(guān)于Nacos下讀取gateway-router的配置:
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 spring.cloud.nacos.discovery.namespace=08ecd1e5-c042-410a-84d5-b0a8fbeed8ea nacos.gateway.route.config.data-id=gateway-router nacos.gateway.route.config.group=DEFAULT_GROUP
第二,初始化路由,監(jiān)聽動(dòng)態(tài)路由配置的數(shù)據(jù)源變化(2020.12.28解決刪除路由不生效問(wèn)題);
/** * * 通過(guò)nacos下發(fā)動(dòng)態(tài)路由配置,監(jiān)聽Nacos中g(shù)ateway-route配置 * */ @Component @Slf4j @DependsOn({"gatewayConfig"}) // 依賴于gatewayConfig bean public class DynamicRouteServiceImplByNacos { @Autowired private DynamicRouteServiceImpl dynamicRouteService; private ConfigService configService; @PostConstruct public void init() { log.info("gateway route init..."); try{ configService = initConfigService(); if(configService == null){ log.warn("initConfigService fail"); return; } String configInfo = configService.getConfig(GatewayConfig.NACOS_ROUTE_DATA_ID, GatewayConfig.NACOS_ROUTE_GROUP, GatewayConfig.DEFAULT_TIMEOUT); log.info("獲取網(wǎng)關(guān)當(dāng)前配置:\r\n{}",configInfo); List<RouteDefinition> definitionList = JSON.parseArray(configInfo, RouteDefinition.class); for(RouteDefinition definition : definitionList){ log.info("update route : {}",definition.toString()); dynamicRouteService.add(definition); } } catch (Exception e) { log.error("初始化網(wǎng)關(guān)路由時(shí)發(fā)生錯(cuò)誤",e); } dynamicRouteByNacosListener(GatewayConfig.NACOS_ROUTE_DATA_ID,GatewayConfig.NACOS_ROUTE_GROUP); } /** * 監(jiān)聽Nacos下發(fā)的動(dòng)態(tài)路由配置 * @param dataId * @param group */ public void dynamicRouteByNacosListener (String dataId, String group){ try { configService.addListener(dataId, group, new Listener() { @Override public void receiveConfigInfo(String configInfo) { log.info("進(jìn)行網(wǎng)關(guān)更新:\n\r{}",configInfo); List<RouteDefinition> definitionList = JSON.parseArray(configInfo, RouteDefinition.class); log.info("update route : {}",definitionList.toString()); dynamicRouteService.updateList(definitionList); } @Override public Executor getExecutor() { log.info("getExecutor\n\r"); return null; } }); } catch (NacosException e) { log.error("從nacos接收動(dòng)態(tài)路由配置出錯(cuò)!!!",e); } } /** * 初始化網(wǎng)關(guān)路由 nacos config * @return */ private ConfigService initConfigService(){ try{ Properties properties = new Properties(); properties.setProperty("serverAddr",GatewayConfig.NACOS_SERVER_ADDR); properties.setProperty("namespace",GatewayConfig.NACOS_NAMESPACE); return configService= NacosFactory.createConfigService(properties); } catch (Exception e) { log.error("初始化網(wǎng)關(guān)路由時(shí)發(fā)生錯(cuò)誤",e); return null; } } }
第三,刷新最新的動(dòng)態(tài)路由變化,實(shí)現(xiàn)動(dòng)態(tài)增刪改路由(2020.12.28解決刪除路由不生效問(wèn)題)
/** * 動(dòng)態(tài)更新路由網(wǎng)關(guān)service * 1)實(shí)現(xiàn)一個(gè)Spring提供的事件推送接口ApplicationEventPublisherAware * 2)提供動(dòng)態(tài)路由的基礎(chǔ)方法,可通過(guò)獲取bean操作該類的方法。該類提供新增路由、更新路由、刪除路由,然后實(shí)現(xiàn)發(fā)布的功能。 */ @Slf4j @Service public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware { @Autowired private RouteDefinitionWriter routeDefinitionWriter; @Autowired private RouteDefinitionLocator routeDefinitionLocator; /** * 發(fā)布事件 */ @Autowired private ApplicationEventPublisher publisher; @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.publisher = applicationEventPublisher; } /** * 刪除路由 * @param id * @return */ public String delete(String id) { try { log.info("gateway delete route id {}",id); this.routeDefinitionWriter.delete(Mono.just(id)).subscribe(); this.publisher.publishEvent(new RefreshRoutesEvent(this)); return "delete success"; } catch (Exception e) { return "delete fail"; } } /** * 更新路由 * @param definitions * @return */ public String updateList(List<RouteDefinition> definitions) { log.info("gateway update route {}",definitions); // 刪除緩存routerDefinition List<RouteDefinition> routeDefinitionsExits = routeDefinitionLocator.getRouteDefinitions().buffer().blockFirst(); if (!CollectionUtils.isEmpty(routeDefinitionsExits)) { routeDefinitionsExits.forEach(routeDefinition -> { log.info("delete routeDefinition:{}", routeDefinition); delete(routeDefinition.getId()); }); } definitions.forEach(definition -> { updateById(definition); }); return "success"; } /** * 更新路由 * @param definition * @return */ public String updateById(RouteDefinition definition) { try { log.info("gateway update route {}",definition); this.routeDefinitionWriter.delete(Mono.just(definition.getId())); } catch (Exception e) { return "update fail,not find route routeId: "+definition.getId(); } try { routeDefinitionWriter.save(Mono.just(definition)).subscribe(); this.publisher.publishEvent(new RefreshRoutesEvent(this)); return "success"; } catch (Exception e) { return "update route fail"; } } /** * 增加路由 * @param definition * @return */ public String add(RouteDefinition definition) { log.info("gateway add route {}",definition); routeDefinitionWriter.save(Mono.just(definition)).subscribe(); this.publisher.publishEvent(new RefreshRoutesEvent(this)); return "success"; } }
分別啟動(dòng)gateway、nacos-consumer、nacos-provider三個(gè)服務(wù),觀察是否已經(jīng)在Nacos上正確注冊(cè)
注意:需要指定注冊(cè)中心的namespace為dev的空間,即spring.cloud.nacos.discovery.namespace=08ecd1e5-c042-410a-84d5-b0a8fbeed8ea
(1)查看gateway服務(wù)的初始化啟動(dòng)日志:會(huì)發(fā)現(xiàn)可以正常從Nacos獲取配置gateway-router網(wǎng)關(guān)配置文件內(nèi)容,并進(jìn)行正確路由加載...
2020-05-10 14:33:44.557 INFO 1272 --- [ main] c.g.r.DynamicRouteServiceImplByNacos : gateway route init... 2020-05-10 14:33:44.578 INFO 1272 --- [ main] c.g.r.DynamicRouteServiceImplByNacos : 獲取網(wǎng)關(guān)當(dāng)前配置: [{ "id": "consumer-router", "order": 0, "predicates": [{ "args": { "pattern": "/consume/**" }, "name": "Path" }], "uri": "lb://nacos-consumer" },{ "id": "provider-router", "order": 2, "predicates": [{ "args": { "pattern": "/provide/**" }, "name": "Path" }], "uri": "lb://nacos-provider" }] 2020-05-10 14:33:44.691 INFO 1272 --- [ main] c.g.r.DynamicRouteServiceImplByNacos : update route : RouteDefinition{id='consumer-router', predicates=[PredicateDefinition{name='Path', args={pattern=/consume/**}}], filters=[], uri=lb://nacos-consumer, order=0, metadata={}} 2020-05-10 14:33:44.691 INFO 1272 --- [ main] c.g.service.DynamicRouteServiceImpl : gateway add route RouteDefinition{id='consumer-router', predicates=[PredicateDefinition{name='Path', args={pattern=/consume/**}}], filters=[], uri=lb://nacos-consumer, order=0, metadata={}} 2020-05-10 14:33:45.192 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [After] 2020-05-10 14:33:45.192 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Before] 2020-05-10 14:33:45.192 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Between] 2020-05-10 14:33:45.193 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Cookie] 2020-05-10 14:33:45.193 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Header] 2020-05-10 14:33:45.193 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Host] 2020-05-10 14:33:45.194 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Method] 2020-05-10 14:33:45.194 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Path] 2020-05-10 14:33:45.194 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Query] 2020-05-10 14:33:45.194 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [ReadBodyPredicateFactory] 2020-05-10 14:33:45.194 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [RemoteAddr] 2020-05-10 14:33:45.194 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Weight] 2020-05-10 14:33:45.194 INFO 1272 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [CloudFoundryRouteService] 2020-05-10 14:33:45.335 INFO 1272 --- [ main] c.g.r.DynamicRouteServiceImplByNacos : update route : RouteDefinition{id='provider-router', predicates=[PredicateDefinition{name='Path', args={pattern=/provide/**}}], filters=[], uri=lb://nacos-provider, order=2, metadata={}} 2020-05-10 14:33:45.335 INFO 1272 --- [ main] c.g.service.DynamicRouteServiceImpl : gateway add route RouteDefinition{id='provider-router', predicates=[PredicateDefinition{name='Path', args={pattern=/provide/**}}], filters=[], uri=lb://nacos-provider, order=2, metadata={}} 2020-05-10 14:33:45.336 INFO 1272 --- [ main] c.g.r.DynamicRouteServiceImplByNacos : update route : RouteDefinition{id='github-router', predicates=[PredicateDefinition{name='Path', args={pattern=/github}}], filters=[], uri=https://github.com, order=3, metadata={}} 2020-05-10 14:33:45.336 INFO 1272 --- [ main] c.g.service.DynamicRouteServiceImpl : gateway add route RouteDefinition{id='github-router', predicates=[PredicateDefinition{name='Path', args={pattern=/github}}], filters=[], uri=https://github.com, order=3, metadata={}}
但這只能說(shuō)明是初始化靜態(tài)路由,下面我們改變gateway-router網(wǎng)關(guān)配置內(nèi)容,追加github-router路由
[{ "id": "consumer-router", "order": 0, "predicates": [{ "args": { "pattern": "/consume/**" }, "name": "Path" }], "uri": "lb://nacos-consumer" },{ "id": "provider-router", "order": 2, "predicates": [{ "args": { "pattern": "/provide/**" }, "name": "Path" }], "uri": "lb://nacos-provider" },{ "id": "github-router", "order": 2, "predicates": [{ "args": { "pattern": "/github/**" }, "name": "Path" }], "uri": "https://github.com" }]
之后點(diǎn)擊發(fā)布更新路由配置
觀察gateway服務(wù)日志,有沒(méi)有監(jiān)聽,并且進(jìn)行正確的路由更新:如下日志所示,最新路由配置立馬被打印,并且進(jìn)行正確路由更新
2020-05-10 14:42:27.576 INFO 1272 --- [d5-b0a8fbeed8ea] c.g.r.DynamicRouteServiceImplByNacos : 進(jìn)行網(wǎng)關(guān)更新: [{ "id": "consumer-router", "order": 0, "predicates": [{ "args": { "pattern": "/consume/**" }, "name": "Path" }], "uri": "lb://nacos-consumer" },{ "id": "provider-router", "order": 2, "predicates": [{ "args": { "pattern": "/provide/**" }, "name": "Path" }], "uri": "lb://nacos-provider" },{ "id": "github-router", "order": 2, "predicates": [{ "args": { "pattern": "/github/**" }, "name": "Path" }], "uri": "https://github.com" }] 2020-05-10 14:42:27.576 INFO 1272 --- [d5-b0a8fbeed8ea] c.g.r.DynamicRouteServiceImplByNacos : update route : RouteDefinition{id='consumer-router', predicates=[PredicateDefinition{name='Path', args={pattern=/consume/**}}], filters=[], uri=lb://nacos-consumer, order=0, metadata={}} 2020-05-10 14:42:27.576 INFO 1272 --- [d5-b0a8fbeed8ea] c.g.service.DynamicRouteServiceImpl : gateway update route RouteDefinition{id='consumer-router', predicates=[PredicateDefinition{name='Path', args={pattern=/consume/**}}], filters=[], uri=lb://nacos-consumer, order=0, metadata={}} 2020-05-10 14:42:27.578 INFO 1272 --- [d5-b0a8fbeed8ea] c.g.r.DynamicRouteServiceImplByNacos : update route : RouteDefinition{id='provider-router', predicates=[PredicateDefinition{name='Path', args={pattern=/provide/**}}], filters=[], uri=lb://nacos-provider, order=2, metadata={}} 2020-05-10 14:42:27.578 INFO 1272 --- [d5-b0a8fbeed8ea] c.g.service.DynamicRouteServiceImpl : gateway update route RouteDefinition{id='provider-router', predicates=[PredicateDefinition{name='Path', args={pattern=/provide/**}}], filters=[], uri=lb://nacos-provider, order=2, metadata={}} 2020-05-10 14:42:27.580 INFO 1272 --- [d5-b0a8fbeed8ea] c.g.r.DynamicRouteServiceImplByNacos : update route : RouteDefinition{id='github-router', predicates=[PredicateDefinition{name='Path', args={pattern=/github/**}}], filters=[], uri=https://github.com, order=2, metadata={}} 2020-05-10 14:42:27.580 INFO 1272 --- [d5-b0a8fbeed8ea] c.g.service.DynamicRouteServiceImpl : gateway update route RouteDefinition{id='github-router', predicates=[PredicateDefinition{name='Path', args={pattern=/github/**}}], filters=[], uri=https://github.com, order=2, metadata={}}
其實(shí),還有辦法可以知道我們的gateway服務(wù)有沒(méi)有監(jiān)聽Nacos的gateway-router配置,那就是在Nacos Console--->監(jiān)聽查詢----->選擇配置---->輸入配置文件的namespace與Group:可以發(fā)現(xiàn)我本地IP地址127.0.0.1對(duì)配置文件gateway-router進(jìn)行了監(jiān)聽
(2)訪問(wèn)gateway網(wǎng)關(guān)服務(wù):http://localhost:6003/consume/sayHello/nacos
查看consumer服務(wù)日志:
2020-05-10 14:55:07.257 INFO 6552 --- [nio-6001-exec-2] c.n.c.controller.ConsumeController : I'm calling nacos-consumer service by dynamic gateway...
發(fā)現(xiàn)跳轉(zhuǎn)至consumer服務(wù),并且訪問(wèn)了consumer服務(wù)的CosnumerController
(3)訪問(wèn)gateway網(wǎng)關(guān)服務(wù):http://localhost:6003/provider/sayHello/nacos
查看provider服務(wù)日志:
2020-05-10 14:56:56.144 INFO 10024 --- [nio-6002-exec-1] c.n.p.controller.ProviderController : I'm calling nacos-provider service by dynamic gateway...
發(fā)現(xiàn)跳轉(zhuǎn)至consumer服務(wù),并且訪問(wèn)了provider服務(wù)的ProviderController
(4)訪問(wèn)訪問(wèn)gateway網(wǎng)關(guān)服務(wù):http://localhost:6003/github,正確跳轉(zhuǎn)至github頁(yè)面
1)Spring Cloud Gateway作用不光只是簡(jiǎn)單的跳轉(zhuǎn)重定向,還可以實(shí)現(xiàn)用戶的驗(yàn)證登錄,解決跨域,日志攔截,權(quán)限控制,限流,熔斷,負(fù)載均衡,黑名單和白名單機(jī)制等。是微服務(wù)架構(gòu)不二的選擇;
2)Nacos的配置中心支持動(dòng)態(tài)獲取配置文件,可以將一些全局的經(jīng)常變更的配置文件放在Nacos下,需要到微服務(wù)自行獲取。
2020.12.28解決刪除路由不生效問(wèn)題,主要是利用RouteDefinitionLocator先讀取變化之前的RouteDefinition,之后刪除重新再更新,或者可以實(shí)現(xiàn)routeDefinitionWriter、RouteDefinitionLocator重寫如下方法:
Mono<Void> save(Mono<RouteDefinition> route); Mono<Void> delete(Mono<String> routeId); Flux<RouteDefinition> getRouteDefinitions();
看完了這篇文章,相信你對(duì)“Nacos+Spring Cloud Gateway動(dòng)態(tài)路由如何配置實(shí)現(xiàn)”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責(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)容。