代码拉取完成,页面将自动刷新
########################## 测试 nacos 注册中心 & 配置中心 start ########################## nacos-test01 // 简单使用nacos,使用openFeign进行生产者和消费者之间调用 测试: 1、运行nacos:下载nacos包,并修改startup.cmd文件内容:set MODE="standalone",修改后双击startup.cmd运行 2、创建spring cloud项目,先后运行 ProducerApplication 和 ConsumerApplication 类 3、登录nacos,查看服务是否注册成功 4、输入http://localhost:2001/service,显示:生产者运行 5、输入http://localhost:3001/service,显示:消费者运行,调用生产者服务:生产者运行 nacos-test02 // 测试 nacos 注册中心 && 配置中心 步骤(参考producer-service): 1、引入jar包spring-cloud-starter-alibaba-nacos-config 2、添加bootstrap.yml配置文件,并添加配置信息spring.cloud.nacos.config(可以查看控制台看它使用哪个配置文件,如底下输出) 2022-08-27 23:46:47.332 INFO 17064 --- [ main] c.a.nacos.client.config.impl.CacheData : [fixed-localhost_8848] [add-listener] ok, tenant=, dataId=producer-service-dev.yaml, group=DEFAULT_GROUP, cnt=1 3、根据步骤2输出的配置文件在nacos配置中心新增配置: DataId:producer-service-dev.yaml Group:DEFAULT_GROUP 配置格式:yaml 配置内容:user.username: testAA 4、使用:@RefreshScope @Value("${user.username}")private String username; 测试1: http://localhost:2001/service 输出:生产者信息,我是testAA 测试2:修改nacos配置 producer-service-dev.yaml,修改为:user.username: testAABBB http://localhost:2001/service 输出:生产者信息,我是testAABBB 结果:修改配置文件内容,能直接生效! 测试3:启动两个相同服务,端口号不同(勾选Allow parallel run,VM options: -Dserver.port=2002) 结果:修改nacos配置信息,能看到两个服务的内容都能立即更新 附:多服务运行:勾选Allow parallel run,VM options: -Dserver.port=2002 nacos-test03 // 测试nacos整合spring cloud gateway 测试:使用与spring cloud整合的一样 consumer调用:http://localhost:3001/service gateway调用:http://localhost:5001/consumer-service/service actuator查看路由:http://localhost:5001/actuator/gateway/routes 测试2:测试nacos下线功能 先启动两个producer服务,端口号不同,再点击nacos上的【服务列表-服务详情-下线】功能停掉某个producer服务,不断刷新gateway调用。 结果:一开始还是会一直轮询调用producer服务,过了一会后只会调用仅在线的producer服务了。 nacos-test04 // 测试nacos配置中心的命名空间 && 测试docker-compose部署 1、创建三个命名空间:yjy-dev,yjy-test,yjy-prod,分别代表开发环境、测试环境、生产环境 示例:命名空间ID、命名空间名、描述 都等于 yjy-dev,表示为dev环境配置 2、添加各环境中配置,文件名分别为xx-dev.yaml,xx-test.yaml,xx-prod.yaml,xx代表服务名。 如yjy-prod的producer-service应用的配置文件为producer-service-prod.yaml。 注:每个环境放在同一文件夹内,这样方便nacos直接导入。 3、每个环境植入不同环境变量:默认dev开发环境 切换测试环境:idea-》https://console.cloud.tencent.com/lighthouse/instance项目启动类-》右键选择“Edit Configuration”-》在VM options输入:-DJAVA_ACTIVE=test 4、在nacos的服务列表中,选择test命名空间,能看到三个服务都注册在里面,相关接口调用正常 producer调用:http://localhost:2001/service,显示producer-service-test.yaml配置的内容 consumer调用:http://localhost:3001/service gateway调用:http://localhost:5001/consumer-service/service 5、测试公共配置文件 公共配置文件统一放在spring.cloud.nacos.config.shared-configs配置项下,如redis、rocketmq等中间件配置信息可以放在这里 6、producer为test环境,consumer为prod环境时,consumer调用接口会报错。 原因:两个服务属于不同环境,不能进行调用。 ### 日志打印追踪 添加traceId进行日志追踪,gateway-》manager-》order-》producer。 父子线程不实现日志追踪,暂无需求 ### 测试使用docker-compose运行微服务应用 》》》使用“java -jar xxx.jar”命令测试打包的jar是否能正常启动 可能会出现错误:没有主清单属性 原因:因为我使用spring-boot-dependencies这个BOM代替了spring-boot-starter-parent这个parent POM,导致spring-boot-maven-plugin的配置项丢失,使得打包后的jar中的MANIFEST.MF文件缺少Main-Class。 解决:所有项目都引入spring-boot-maven-plugin >>> 使用Dockerfile部署项目(提前安装docker desktop工具) 1、pom.xml文件添加docker插件,编写Dockerfile文件 2、打包(打包好后使用"docker images"查看): mvn clean package -e -U -Dmaven.test.skip=true dockerfile:build 3、运行镜像(运行后使用“docker logs 容器id”查看日志): docker run --name=producer-service -d --restart=always -p 2001:2001 -e "nacosServerAddr=192.168.63.241:8848" -e "SPRING_PROFILES_ACTIVE=prod" suerfly/springcloud-test/nacos-test04/producer-service docker run --name=consumer-service -d --restart=always -p 3001:3001 -e "nacosServerAddr=192.168.63.241:8848" -e "SPRING_PROFILES_ACTIVE=prod" suerfly/springcloud-test/nacos-test04/consumer-service docker run --name=gateway-service -d --restart=always -p 5001:5001 -e "nacosServerAddr=192.168.63.241:8848" -e "SPRING_PROFILES_ACTIVE=prod" suerfly/springcloud-test/nacos-test04/gateway-service 4、验证:发现所有项目正常运行 producer调用:http://localhost:2001/service,显示producer-service-prod.yaml配置的内容 consumer调用:http://localhost:3001/service gateway调用:http://localhost:5001/consumer-service/service nacos-test04-v2-sentinel # 整合sentinel nacos-test05-sentinel # 整合sentinel,限流规则在nacos配置 sentinel配置规则默认在内存中,每次重启业务服务都会把规则内容清空,可将配置持久化到nacos中。 1)整合sentinel流程: 1、添加jar包和配置 2、定义资源 1)可用注解定义资源:@SentinelResource(value = "producerResource1", blockHandler = "product1BlockHandler") 2)根据【sentinel-》簇点链路-》url】作为资源,如producer-service服务的/product2接口 两者区别:注解定义的资源粒度更小,可以在service层定义 3、定义限流规则(当前配置规则在服务重启后会消失,可配合nacos保存规则) sentinel控制台-》簇点链路-》找到对应资源-》点击【+流控】,进行添加限流-》添加完成后,能在流控规则显示 4、测试,多次调用会出现限流,且限流时走降级逻辑。 http://localhost:5001/consumer-service/service1 http://localhost:5001/consumer-service/service2 5、查看拒绝QPS数:sentinel控制台-》【服务名】-》实时监控 2)引入mybatis-plus & mybatis自动生成代码 测试数据库增删改查操作 测试mybatis自动生成代码 打印mybatis中SQL执行时间,告警处理!! 3)引入knife4j接口文档 访问:http://ip:port/doc.html 4)升级spring cloud版本为 2021.0.6 5)gateway整合sentinel: 1.引入3个jar包 2.添加配置内容 3.添加流控规则文件 避坑点1:通过Spring Cloud Alibaba接入sentinel需要将spring.cloud.sentinel.filter.enabled 配置项置为 false(网关流控默认粒度为route和自定义API分组维度,不支持URL粒度) 避坑点2:通过Spring Cloud Alibaba Sentinel 数据源模块,网关流控规则数据源类型是 gw-flow而不是flow 4.测试: 多次输入http://localhost:5001/consumer/service,会出现:{"code": 429,"message": "前方拥堵,请稍后再试!"} 5.其他 -- 测试producer限流 http://localhost:2001/product1 http://localhost:3001/service -- 测试gateway限流配置 http://localhost:5001/consumer-service/service -- 测试返回值,全局日志追踪标识 http://localhost:5001/producer/person/get -- 测试数据库 http://localhost:5001/producer/user/testUserPage 6)通过docker-compose启动服务 1.新增docker-compose.yaml文件 2.打包每个服务 mvn clean install -DskipTests=true cd producer-service && mvn clean package -DskipTests=true dockerfile:build cd consumer-service && mvn clean package -DskipTests=true dockerfile:build cd gateway-service && mvn clean package -DskipTests=true dockerfile:build 3.启动 docker-compose up -d # 启动全部服务 docker-compose up -d producer-service # 启动指定服务 4.修改producer服务代码后,重新打包,然后重启 cd consumer-service && mvn clean package -DskipTests=true dockerfile:build docker-compose up -d producer-service ########################## 测试 nacos 注册中心 & 配置中心 end ########################## ########################## 测试 spring cloud 相关 start ########################## spring-cloud-test: --项目参考教程:https://github.com/forezp/SpringCloudLearning 测试服务注册中心、服务提供者、服务消费者、断路器、路由转发、配置中心、消息总线、网关 1.服务注册中心与服务提供者(eureka): 创建项目spring-cloud-test,并创建两个子模块:注册中心(eureka-server)、服务提供者(service-provider) 注册中心(eureka server): 1)引入依赖:spring-cloud-starter-eureka-server 2)启动类添加@EnableEurekaServer注解,表明是个注册中心 3)配置文件(application.yml) 默认情况下eureka Server也是eureka Client,通过registerWithEureka、fetchRegistry都为false表明自己是一个eureka Server。 4)启动 浏览器输入:http://localhost:1001 这个时候是没有服务被发现的。 服务提供者(eureka client): 1)引入依赖:spring-cloud-starter-eureka 2)启动类添加@EnableEurekaClient注解,表明自己是一个服务提供者 3)配置文件(application.yml) --配置端口号、服务名称、服务中心地址等信息 4)启动 刷新eureka server项目,看到有一个已注册的服务,服务名为service-provider,端口为2001 测试: 启动注册中心,输入:http://localhost:1001/ 启动服务提供者,输入:http://localhost:2001/hi?name=testAA 再次回到注册中心页,能看到有服务注册上去 服务提供者集群: 启动eureka-server项目; 启动service-provider项目,端口为2001 将service-provider项目端口号改成2002后启动,能在eureka-server中看到2个服务被注册,这相当于一个小的集群。 2.服务消费者(ribbbon/feign): 1、service-consumer-ribbon //ribbon+restTemplate版服务消费者 测试: 启动注册中心,启动两次服务提供者(端口号不同,形成集群),最后启动服务消费者 输入:http://localhost:3001/hi?name=testAA 能看到下面内容交替出现,说明两个服务已做了负载均衡,访问了不同端口号的服务实例。 hello testAA,I am from port:2002 hello testAA,I am from port:2002 2、service-consumer-feign //feign版服务消费者 测试: 启动注册中心,启动两次服务提供者(端口号不同,形成集群),最后启动服务消费者 输入:http://localhost:3002/hi?name=testAA 能看到下面内容交替出现,说明两个服务已做了负载均衡,访问了不同端口号的服务实例。 hello testAA,I am from port:2002 hello testAA,I am from port:2002 3、此时架构 1个服务注册中心eureka-server,端口号为1001 2个服务提供者service-provider,端口号为2001和2002,都向服务注册中心注册 2个服务消费者service-consumer-ribbon和service-consumer-feign,端口号为3001和3002,向服务中心注册。 服务消费者通过restTemplate调用服务提供者的hi接口时,因为ribbon进行了负载均衡,会轮流调用两个服务提供者的接口。 3.断路器(hystrix) 测试1:改造service-consumer-ribbon成为service-consumer-ribbon-hystrix 测试2:改造service-consumer-feign成为service-consumer-feign-hystrix 1)在application.properties中添加配置 feign.hystrix.enabled=true 2)创建fallback类,继承HelloRemote并实现回调方法 3)@FeignClient中添加fallback属性 @FeignClient(name= "SPRING-CLOUD-PRODUCER", fallback = HelloRemoteFallBack.class) 输入:http://localhost:3004/hi?name=testAA testAA sorry error! --可能会出现 hello testAA,I am from port:2001 hello testAA,I am from port:2002 4.路由转发和过滤器(zuul) 路由转发:比如输入/api/user转发到到user服务,/api/shop转发到shop服务。 测试: 分别启动:注册中心、启动2次端口不同的服务提供者、服务消费者service-consumer-ribbon、服务消费者service-consumer-feign、路由转发service-zuul 分别输入: http://localhost:4001/api-a/hi?name=testAA #该请求转发给service-consumer-ribbon服务 http://localhost:4001/api-b/hi?name=testAA #该请求转发给service-consumer-feign服务 测试过滤器: 分别输入: http://localhost:4001/api-a/hi?name=testAA #该请求转发给service-consumer-ribbon服务 http://localhost:4001/api-b/hi?name=testAA #请求被拦截 分布式配置中心(config) --未测试 描述:分布式系统的服务数量巨多,为了将配置文件统一管理,实时更新,需要配置中心组件。 --相关依赖: spring-cloud-config-server #服务端 spring-cloud-starter-config #客户端 描述:config-client从config-server 中获取 foo 的属性值,而config-server是从git仓库读取。 消息总线(bus) 配置中心修改了某个属性值,此时客户端会发送一个消息,由消息总线向其他服务传递,从而使整个微服务集群都达到更新配置文件。 网关(gateway) Spring Cloud Gateway是官方推出的第二代网关框架,取代了zuul网关。 网关常见功能:路由转发、权限校验、限流控制等作用。 作用: 协议转换,路由转发 流量聚合,对流量进行监控,日志输出 作为整个系统的前端工程,对流量进行控制,有限流的作用 作为系统的前端边界,外部流量只能通过网关才能访问系统 可以在网关层做权限的判断 可以在网关层做缓存 ******************************************************************** spring-cloud-test01 //测试eureka的注册中心和服务注册功能 先启动eureka-server,再启动service-provider01,能看到在注册中心已经注册 service-provider01 服务 注册中心:http://localhost:1001/ 服务提供方:http://localhost:2001/hi?name=testAA spring-cloud-test01-v2 //测试eureka 注册中心集群 步骤: 1、eurekaServer01向eurekaServer02注册自己,eurekaServer02向eurekaServer01注册自己,这样便能做到注册中心集群。 2、eurekaClient 向所有 eurekaServer 注册 3、服务以“ip+端口”形式显示 测试: 依次启动 eureka-server、eureka-server02、service-provider01,能看到 注册中心存在两个服务 访问两个注册中心: http://localhost:1001/ 或 http://localhost:1002/ 访问服务提供方: http://localhost:2001/hi?name=testAA spring-cloud-test02 //测试服务调用 项目基于spring-cloud-test01 ribbon版:新增service-consumer-ribbon项目 启动注册中心eureka-server 启动服务提供者:service-provider01,修改端口后再次启动,做一个集群。 启动服务消费者:service-consumer-ribbon 发送http://localhost:3001/hi?name=testAA,能看到会循环调用200x的请求 feign版:新增service-consumer-feign项目 启动注册中心eureka-server 启动服务提供者:service-provider01,修改端口后再次启动,做一个集群。 启动服务消费者:service-consumer-feign 发送http://localhost:3002/hi?name=testAA,能看到会循环调用200x的请求 spring-cloud-test02-v2 //测试服务调用(消费负载均衡) ribbon版: 有三种实现服务消费方式 discoveryClient方式: http://localhost:3001/hi1?name=user1 loadBalancerClient方式: http://localhost:3001/hi2?name=user2 @LoadBalanced注解: http://localhost:3001/hi3?name=user3 feign版:不变,跟 spring-cloud-test02 的一样,命名规则以 feign结尾(类似于Service层) spring-cloud-test03 //测试断路器hystrix 项目基于spring-cloud-test02改造 ribbon版:改造service-consumer-ribbon为service-consumer-ribbon-hystrix项目 需要引入hystrix包 发送http://localhost:3001/hi?name=testAA,当200x节点都宕机后,会调用fallback函数 feign版:改造service-consumer-feign为service-consumer-feign-hystrix项目 自带hystrix,需要再application.yml开启 发送http://localhost:3002/hi?name=testAA,当200x节点都宕机后,会调用fallback函数 spring-cloud-test04 //测试网关zuul 项目基于spring-cloud-test03改造,新增service-zuul项目 ribbon版:http://localhost:4001/api-a/hi?name=testAA feign版:http://localhost:4001/api-b/hi?name=testAA 自定义ZuulFilter: http://localhost:4001/api-b/hi?name=testAA --校验不通过 http://localhost:4001/api-b/hi?name=testAA&token=222 --校验通过 spring-cloud-test05 //测试配置中心(confug server) ConfigServer端: 远程仓库https://github.com/yanjingyun/SpringCloudConfig/ 中有个文件config-client-dev.properties文件 foo = foo version 3 测试:http://localhost:8888/foo/dev ConfigClient端: 测试:http://localhost:8881/hi,输出内容:foo version 3 spring-cloud-test06 //高可用的分布式配置中心 项目基于spring-cloud-test05改造,新建eureka服务端,ConfigClient通过服务发现ConfigServer 测试:http://localhost:8881/hi,输出内容:foo version 3 spring-cloud-test06-v2 //配置中心(native版本) 描述: 将ConfigClient中的端口号,注册中心等信息放在ConfigServer中,方便统一进行管理。 直接将配置文件放在ConfigServer中,然后ConfigClient得到配置文件并指定环境(如dev、prod等) 测试: --先后启动:EurekaServer、ConfigServer、ConfigClient三个项目 http://localhost:2001/config-client/dev --测试配置中心的配置文件访问(访问shared下有个config-client-dev.yml文件) http://localhost:3001/foo --ConfigClient读取config-client-*.yml文件的foo属性 http://localhost:3001/user --读取user属性 http://localhost:3002/foo --ConfigClient2读取config-client2-*.yml文件的foo属性 http://localhost:3002/user --读取user属性 --测试动态刷新配置(单节点) 1、config-client2添加actuator包,并添加actuator配置信息,在需要刷新的地方添加@RefreshScope注解 2、修改config-server里面的config-client2配置信息,并重启 3、config-client2节点发送(POST http://localhost:3002/actuator/refresh)请求,刷新配置信息(无需重启,做到刷新配置) 4、测试:关闭config-server服务,config-client2也没有影响 spring-cloud-test07 //消息总线Spring Cloud Bus https://www.fangzhipeng.com/springcloud/2018/08/08/sc-f8-bus.html --未完成 依次启动eureka-server、config-server,启动两个config-client,端口为:8881、8882 访问http://localhost:8881/hi 或者http://localhost:8882/hi 浏览器显示:foo version 3 这时我们去代码仓库将foo的值改为“foo version 4”,即改变配置文件foo的值。如果是传统的做法,需要重启服务,才能达到配置文件的更新。此时,我们只需要发送post请求:http://localhost:8881/actuator/bus-refresh,你会发现config-client会重新读取配置文件 这时我们再访问http://localhost:8881/hi 或者http://localhost:8882/hi 浏览器显示:foo version 4 另外,/actuator/bus-refresh接口可以指定服务,即使用”destination”参数,比如 “/actuator/bus-refresh?destination=customers:**” 即刷新服务名为customers的所有服务。 spring-cloud-test08 // 新增admin监控 依次运行eurekaServer、AdminClient、AdminServer项目,访问:http://localhost:3001/ spring-cloud-test10 //测试网关gateway Spring Cloud Gateway的Predict(断言)、Filter(过滤器)介绍。 用户的请求首先经过service-gateway,根据路径由gateway的predict去断言进到哪一个router,router经过各种过滤器处理后,最后路由到具体的业务服务,比如 service-hi。 依次启动eureka-server、service-provider01、service-provider01、service-gateway项目,service-hi为服务名 测试:http://localhost:8082/demo/hi?name=1323 #会自动路由到service-hi服务的/hi路径中 spring.cloud.gateway.discovery.locator.enabled为true时可访问http://localhost:8082/service-hi/hi?name=1323 spring-cloud-test10-v1 //测试gateway三大法宝(路由route、断言predicate、过滤器filter) --测试路由(route): >>>指定spring.profiles.active: route-test1 http://localhost:8082/service-hi/servicehi/hello?name=TestAA --多次输入,能看到低下轮流切换 hello TestAA ,i am from port:2001 hello TestAA ,i am from port:2002 >>>指定spring.profiles.active: route-test2 http://localhost:8082/demo/servicehi/hello?name=TestAA --多次输入,能看到低下轮流切换 hello TestAA ,i am from port:2001 hello TestAA ,i am from port:2002 --测试断言(predicate): --参考配置文件的predicates属性相关,官网有11种断言 --测试过滤器(filter): 编写步骤:注册到spring容器,并实现GlobalFilter,Ordered接口 MyFirstGlobalFilter 第一个过滤器测试 http://localhost:8082/demo/hello --返回异常 http://localhost:8082/demo/hello?name=TestBB --能正常访问 AccessLogFilter 打印请求路径:{},客户端远程IP地址:{},请求方法:{},目标URI:{},响应码:{} ModifyRequestFilter 修改请求地址(应用场景:同一使用/openGateway接口接收,通过method判断属于那个服务的地址) spring-cloud-test10-v2 //测试网关gateway降级 --步骤: 1.gaeway引入hystrix包 2.application.yml配置hystrix信息 3.新增降级处理类 4.service项目新建controller层方法(睡眠5秒) 5.测试:http://localhost:8082/demo/timeout #会调用降级处理类的处理方法 spring-cloud-test10-v3 //测试网关gateway限流 --步骤: 1.引入redis、限流包 2.新建限流配置类 3.添加限流配置信息(application.yml) 4.测试: http://localhost:8082/demo/hi --目前每秒产生2个令牌 多次刷新使用gateway内置令牌算法使用gateway内置令牌算法,总有几次会报429错误 spring-cloud-test10-v4 // 使用actuator实现动态路由 整合actuator: --详情参考GatewayControllerEndpoint.java文件 1.引入jar包 2.配置文件新增management.endpoint配置信息 获取路由: http://localhost:8082/actuator/gateway/routes 创建路由: /actuator/gateway/routes/{id} post请求 删除路由: /actuator/gateway/routes/{id} delete方式 刷新路由: /actuator/gateway/refresh post方式 测试参考:gateway实现动态路由.postman_collection.json 应用场景:设置动态路由,设置动态限流内容(需要更多测试用例) 自定义监听事件(SystemEventListener): 监听从eureka server获取心跳 自定义动态添加路由: 测试: http://localhost:8081/demo222/hi //无输出 添加路由:发送请求【postman-自定义添加动态路由】 http://localhost:8081/demo222/hi //显示结果 spring-cloud-test10-v6 测试:切换到新路径 --修改请求地址 http://localhost:8082/service-hi?name=TestAA&path=/test/hi --多次输入,能看到底下轮流切换,说明已切换到新路径 hi TestAA ,i am from port:2001 hi TestAA ,i am from port:2002 spring-cloud-test10-v7 测试切换新路由和新路径 http://localhost:8082/openGateway?name=TestAA&service=service-hi&path=/test/hi --多次输入,能看到底下轮流切换 hi TestAA ,i am from port:2001 hi TestAA ,i am from port:2002 http://localhost:8082/openGateway?name=TestAA&service=service-default&path=/test/hi --多次输入,能看到底下轮流切换 hi TestAA ,i am from port:3001 hi TestAA ,i am from port:3002 spring-cloud-knife4j // spring cloud gateway聚合所有swagger微服务文档 详情:https://doc.xiaominfo.com/guide/ui-front-gateway.html 依次启动eureka-server、service-user、service-order、service-gateway服务 访问:http://localhost:10003/doc.html spring-cloud-seata // 测试seata 相关技术:springcloud eureka mybatis seata 测试1:http://localhost:8180/order/create?userId=1&productId=1&count=10&money=100 测试2:模拟account方法执行超时,全局回滚 ########################## 测试 spring cloud OAuth2 start ########################## spring-cloud-oauth //spring cloud + spring security + oauth2 统一认证和鉴权 测试参考spring-cloud-oauth.postman_collection.json --详情:https://blog.csdn.net/zhenghongcs/article/details/107776948 1.自定义登录认证结果返回(AuthController) 2.认证失败结果返回(Oauth2ExceptionHandler) 3.自定义网关鉴权失败结果(ResourceServerConfig) 4.兼容白名单访问(IgnoreUrlsRemoveJwtFilter) spring-cloud-oauth-v2 // 优化上一个版本,代码调整 测试参考spring-cloud-oauth.postman_collection.json 1.jwt公钥采用本地获取 2.新增用户注销接口,用户注销后,不能再次使用注销token访问资源 3.新增“手机验证码”登录方式,登录后获取的token跟其它登陆方式一样 spring-cloud-oauth-v3 // 编写公共配置文件 1.common-core # 存放公共实体类 2.common-file # 存放上传文件api ########################## 测试 spring cloud OAuth2 end ##########################
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。