当前位置: 首页 > news >正文

长春做网站seo的中华网军事网

长春做网站seo的,中华网军事网,深圳彩票网站建设,宝塔面板wordpress静态化目录 前言 一、登录存在的问题归纳 二、*微服务网关整体方案 三、认识微服务网关 四、网关鉴权实现 五、OpenFeign微服务间用户标识信息传递实现 六、微服务网关知识追问巩固 前言 本篇文章具体讲解微服务中网关的实现逻辑、用于解决什么样的问题。其中标题中标注* 涉…目录 前言 一、登录存在的问题归纳 二、*微服务网关整体方案 三、认识微服务网关 四、网关鉴权实现  五、OpenFeign微服务间用户标识信息传递实现 六、微服务网关知识追问巩固 前言 本篇文章具体讲解微服务中网关的实现逻辑、用于解决什么样的问题。其中标题中标注* 涉及到非常巧妙的设计或者核心配置。需要仔细阅读并理解相信对你理解微服务、学习微服务会有很大的帮助 通过这篇文章学习后希望你能回答第六节中所有的问题。 当前微服务项目大致是被我们拆分出来了分别是以下几个模块 用户服务、商品服务、购物车服务、交易服务、支付服务 但是拆分模块后还是会出现不少问题主要的问题归纳如下 一、登录存在的问题归纳 1. 请求不同数据时要访问不同的入口需要维护多个入口地址。 原先单体项目的时候前端只需要将请求转发到8080端口就可以访问单体项目中所有的方法了。但是现在多入口模式下前端要如何维护请求的转发呢 2. 前端无法调用nacos无法实时更新服务列表 前端nginx无法直接和nacos交互怎么知道这个入口地址还可用如果宕机了还怎么发送 3.每个微服务都需要编写登录校验、用户信息获取的功能 最简单的做法是每一个需要校验的微服务模块都配置一个JWT校验。但是这样明显不太优雅本节是为了提供一种统一校验的方法。利用网关解决这个问题。 4. 微服务模块如何获取用户标识信息? 只有通过JWT校验才会有用户标识信息。也就是说通过网关校验后微服务模块又要如何获取到这些用户标识信息呢 5. 微服务内如何使用用户标识信息 可以使用TreadLocal保存用户信息供本模块方法使用。 6. 微服务间进行调用OpenFeign如何发送用户标识信息 我们需要想办法将用户标识信息写到请求头中随着OpenFeign请求一同发送。 想要解决上述问题我们需要引入“网关”的概念。 二、*微服务网关整体方案 提前将整体方案总结如果能看得明白接下来的具体实现想必也不是问题 2.1 后端黑盒 解决问题一。我们在前端和后端微服务项目之中添加了一层网关微服务。并且设置网关微服务的端口为8080。这样一来前端代码无需修改只需将所有请求发送到8080接着由我们的网关微服务进行请求转发和负载均衡。实现了黑盒效果 2.2 网关模块的作用 1. 实现前端请求的统一处理转发、微服务列表维护、负载均衡 网关直接和Nacos注册中心进行交互,获取实时的服务列表。自动完成服务的转发和负载均衡。 2. 网关过滤器实现鉴权统一认证(JWT令牌) 既然所有的前端请求都会访问到网关模块那我们完全可以在网关模块添加一个过滤器用于JWT令牌的统一校验。只有通过了JWT令牌校验的请求才会被转发。否则网关会返回401权限不足的异常。 2.3 微服务拦截器作用 实现用户标识信息的保存 具体的。当网关通过了JWT令牌校验后我们需要通过拦截器将网关传递的用户标识信息保存到ThreadLocal中供当前微服务模块使用。 然而如果在每一个微服务都编写一个拦截器还是太不优雅了。对此我们可以将MVC的拦截器编写到公共模块 common-service中其他模块引用即可。 2.4 OpenFeign拦截器作用 实现微服务间调用的用户标识信息传递 前面微服务拦截器解决了如何保存用户标识信息的问题。但是这种拦截器能够保存用户标识信息的前提是——请求必须通过网关转发而来。 然而微服务间的调用是通过OpenFeign工具完成的。因此无法使用MVC拦截器获取到用户标识信息。这就要求我们在微服务请求发送前要想办法给请求添加上用户标识信息。 如何呢一样是利用拦截器将OpenFeign请求先拦截下来将用户标识信息添加到请求头。 三、认识微服务网关 3.1 网关模式的演示 前端我到底该发给谁 网关你发给我就行了接下来的事你不用管 网关我要怎么知道我管理的微服务的列表呢 注册中心别担心你找我就行了 3.2 *编写网关模块 【实现底层】 在SpringCloud中网关的实现包括两种 使用GateWay更好喔 【使用步骤】 创建网关模块引入网关依赖——SpringCloudGateway、NacosDiscovery编写网关启动类配置网关转发规则——路由规则 1. 创建网关模块 2. 引入网关依赖 dependencies!--common--dependencygroupIdcom.heima/groupIdartifactIdhm-common/artifactIdversion1.0.0/version/dependency!--网关--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-gateway/artifactId/dependency!--nacos discovery--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-discovery/artifactId/dependency!--负载均衡--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-loadbalancer/artifactId/dependency/dependenciesbuildfinalName${project.artifactId}/finalNamepluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactId/plugin/plugins/build 3. 编写启动类 package com.hmall.gateway;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;SpringBootApplication public class GateWayApplication {public static void main(String[] args) {SpringApplication.run(GateWayApplication.class, args);} }4. 编写路由规则 server:port: 8080 # 网关端口 前端请求统一处理spring:application:name: hm-gateway # 微服务名称cloud:nacos:server-addr: 192.168.186.140:8848 # nacos地址gateway:routes:- id: cart # 路由id自定义uri: lb://cart-service # 目标服务地址 lb://服务名称 lb表示负载均衡predicates:- Path/carts/** # 断言路径匹配 路径以/api/cart/开头都会被路由到cart-service- id: itemuri: lb://item-servicepredicates:- Path/items/**,/search/** # 多路径匹配以逗号分割- id: payuri: lb://pay-servicepredicates:- Path/pay-orders/**- id: tradeuri: lb://trade-servicepredicates:- Path/orders/**- id: useruri: lb://user-servicepredicates:- Path/users/**,/addresses/**3.3 测试网关转发功能 3.4 *网关路由属性 前面我们初步配置了网关路由规则。实际上Gateway路由还有很多功能我们窥探一下源码了解一下吧 网关路由对应的Java类型是RouteDefinition其中常见的属性有 id路由唯一标示uri路由目标地址predicates路由断言判断请求是否符合当前路由。filters路由过滤器对请求或响应做特殊处理。 【路由断言】 在Java中以工厂模式实现Spring提供了12种基本的RoutePredicateFactory实现 Spring Cloud Gatewayhttps://docs.spring.io/spring-cloud-gateway/docs/3.1.7/reference/html/#gateway-request-predicates-factories 名称 说明 示例 After 是某个时间点后的请求 - After2037-01-20T17:42:47.789-07:00[America/Denver] Before 是某个时间点之前的请求 - Before2031-04-13T15:14:47.43308:00[Asia/Shanghai] Between 是某两个时间点之前的请求 - Between2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver] Cookie 请求必须包含某些cookie - Cookiechocolate, ch.p Header 请求必须包含某些header - HeaderX-Request-Id, \d Host 请求必须是访问某个host域名 - Host**.somehost.org,**.anotherhost.org Method 请求方式必须是指定方式 - MethodGET,POST Path 请求路径必须符合指定规则 - Path/red/{segment},/blue/** Query 请求参数必须包含指定参数 - Queryname, Jack或者- Queryname RemoteAddr 请求者的ip必须是指定范围 - RemoteAddr192.168.1.1/24 weight 权重处理 - Weightgroup1, 2 XForwarded Remote Addr基于请求的来源IP做判断- XForwardedRemoteAddr192.168.1.1/24 【过滤器】 网关中提供了33种路由过滤器每种过滤器都有独特的作用Spring Cloud Gatewayhttps://docs.spring.io/spring-cloud-gateway/docs/3.1.7/reference/html/#gateway-request-predicates-factories 四、网关鉴权实现  我们的登录是基于JWT来实现的校验JWT的算法复杂而且需要用到秘钥。如果每个微服务都去做登录校验这就存在着两大问题 每个微服务都需要知道JWT的秘钥不安全 每个微服务重复编写登录校验代码、权限校验代码麻烦 所以我们把JWT校验提前到网关模块来做成功则请求到对应的模块失败则返回401报错信息。 4.1 网关请求处理流程分析 我们采取的网关gateway底层是如何进行处理的呢 客户端请求进入网关后由HandlerMapping对请求做判断找到与当前请求匹配的路由规则Route然后将请求交给WebHandler去处理。 WebHandler则会加载当前路由下需要执行的过滤器链Filter chain然后按照顺序逐一执行过滤器后面称为Filter。 图中Filter被虚线分为左右两部分是因为Filter内部的逻辑分为pre和post两部分分别会在请求路由到微服务之前和之后被执行。 只有所有Filter的pre逻辑都依次顺序执行通过后请求才会被路由到微服务。 微服务返回结果后再倒序执行Filter的post逻辑。 最终把响应结果返回。 这里我们主要关注过滤器。有以下特点 第一过滤器的PRE部分在发送请求到微服务之前执行因此时候在这部分实现JWT校验第二过滤器有先后顺序之分默认Netty路由过滤器是优先级最低的。用于请求转发。第三我们编写的JWT鉴权过滤器要确保优先级比Netty路由器高。 4.2 自定义过滤器实践  自定义过滤器分为两种 GatewayFilter路由过滤器作用于任意指定的路由默认不生效要配置到路由后生效。GlobalFilter全局过滤器作用范围是所有路由声明后自动生效。 其中全局过滤器的实现更加简单两者的过滤方法同名同参数 /*** 处理请求并将其传递给下一个过滤器* param exchange 当前请求的上下文其中包含request、response等各种数据* param chain 过滤器链基于它向下传递请求* return 根据返回值标记当前请求是否被完成或拦截chain.filter(exchange)就放行了。*/ MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain); 4.2.1 GlobalFilter实现 1. 创建过滤器继承GlobalFilter 和 Ordered类编写filter方法 2. 测试执行情况 4.2.2 GatewayFilter实现 【过滤器模板】、【简单无参过滤器】 【装饰模式】、【配置过滤器优先级】 【过滤器模板】、【有参过滤器的实现】 【生效范围配置】 4.3 *实现网关登录校验 使用简单的GlodalFilter实现登录校验过滤器基本步骤如下 配置JWT校验工具编写登录校验过滤器测试网关拦截效果 1. 导入JWT相关工具类 AuthProperties配置登录校验需要拦截的路径因为不是所有的路径都需要登录才能访问 JwtProperties定义与JWT工具有关的属性比如秘钥文件位置 SecurityConfig工具的自动装配 JwtToolJWT工具其中包含了校验和解析token的功能 hmall.jks秘钥文件 2. 编写登录校验过滤器 使用构造器注入配置获取请求头判断请求路径是否在放行白名单里获取请求头中的token解析并校验token 如果token无效只需拦截设置响应状态码401TODO token有效传递用户标识信息放行 package com.hmall.gateway.fliters;import cn.hutool.core.collection.CollUtil; import com.hmall.common.exception.UnauthorizedException; import com.hmall.gateway.config.AuthProperties; import com.hmall.gateway.utils.JwtTool; import lombok.RequiredArgsConstructor; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpHeaders; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.util.AntPathMatcher; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono;import java.util.List;Component // 将过滤器交给Spring管理 RequiredArgsConstructor // 采用构造器注入(只会注入 final) EnableConfigurationProperties(AuthProperties.class) // 开启属性配置 public class AuthGlobalFilter implements GlobalFilter, Ordered {// 注入Jwt工具类private final JwtTool jwtTool;// 注入配置文件中的属性private final AuthProperties authProperties;// **(重要) 路径匹配器,用于匹配路径是否在白名单中private final AntPathMatcher antPathMatcher new AntPathMatcher();Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 登录校验开始//1. 获取requestServerHttpRequest request exchange.getRequest();//2. 判断路径是否在白名单中if(isExclude(request.getURI().getPath())){// 无需拦截 直接放行return chain.filter(exchange);}//3. 获取请求头中的tokenString token null;ListString headers request.getHeaders().get(HttpHeaders.AUTHORIZATION);if(!CollUtil.isEmpty(headers)){ // 请求头中存在tokentoken headers.get(0); // 获取token}//4. 解析并校验tokenLong userId null;try{userId jwtTool.parseToken(token);}catch (UnauthorizedException e){// 如果token无效拦截返回401即可ServerHttpResponse response exchange.getResponse();response.setRawStatusCode(401);return response.setComplete(); // 直接返回响应,不会再往下走了}//TODO 5. 如果有效传递用户标识信息System.out.println(userId userId);//6. 放行return chain.filter(exchange);}/*** 判断路径是否在白名单中* param path* return*/private boolean isExclude(String path) {for(String pathPattern : authProperties.getExcludePaths()){ // 遍历白名单if(antPathMatcher.match(pathPattern,path)) { // 如果路径匹配上了则返回truereturn true;}}return false;}// 过滤器优先级值越小优先级越高Overridepublic int getOrder() {return 0;} } 3. 测试网关拦截效果  4.4 通过网关传递用户标识信息 上一节中我们还有一步没有完成 网关已经可以完成登录校验并获取登录用户身份信息。但是当网关将请求转发到微服务时微服务又该如何获取用户身份呢 由于网关发送请求到微服务依然采用的是Http请求因此我们可以将用户信息以请求头的方式传递到下游微服务。然后微服务可以从请求头中获取登录用户信息。考虑到微服务内部可能很多地方都需要用到登录用户信息因此我们可以利用SpringMVC的拦截器来实现登录用户信息获取并存入ThreadLocal方便后续使用。 4.4.1 *改造网关过滤器 在获取用户信息后保存到请求头转发到下游微服务 Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 登录校验开始//1. 获取requestServerHttpRequest request exchange.getRequest();//2. 判断路径是否在白名单中if(isExclude(request.getURI().getPath())){// 无需拦截 直接放行return chain.filter(exchange);}//3. 获取请求头中的tokenString token null;ListString headers request.getHeaders().get(HttpHeaders.AUTHORIZATION);if(!CollUtil.isEmpty(headers)){ // 请求头中存在tokentoken headers.get(0); // 获取token}//4. 解析并校验tokenLong userId null;try{userId jwtTool.parseToken(token);}catch (UnauthorizedException e){// 如果token无效拦截返回401即可ServerHttpResponse response exchange.getResponse();response.setRawStatusCode(401);return response.setComplete(); // 直接返回响应,不会再往下走了}//5. 如果有效将userId放到请求头中继续往下走String userInfo userId.toString();ServerWebExchange ex exchange.mutate().request(b - b.header(user-info,userInfo)).build();//6. 放行return chain.filter(ex);} 4.4.2 *编写微服务拦截器 拦截请求获取用户信息保存到ThreadLocal后放行。 为了提高代码复用我们SpringMVC的拦截器最好写在通用模块中hm-common。 在hm-common中已经有一个用于保存登录用户的ThreadLocal工具——UserContext我们只需要编写拦截器将用户信息保存到UserContext即可。 【基本步骤】 定义SpringMVC拦截器编写拦截器代码注册拦截器 注意啦 拦截器中记得一定要加上这么两个注解 Configuration ConditionalOnClass(DispatcherServlet.class) 其中第二个注解不能少少了马上报错原因如下 第二个配置表示 当DispatcherServlet类存在时这个配置类才会生效* 为什么要这么做呢 因为网关模块也依赖了common模块而网关模块底层gateway是没有走spring mvc的 * 所以这个配置类在网关模块中是不需要的所以需要加上这个注解 * 不加这个注解的话在网关模块启动的时候会报错因为配置不生效 配置自动装配使配置类生效 这个配置类默认是不会生效的因为它所在的包是com.hmall.common.config与其它微服务的扫描包不一致无法被扫描到因此无法生效。 基于SpringBoot的自动装配原理我们要将其添加到resources目录下的META-INF/spring.factories文件让其自动装配 编写拦截器代码只做判断不拦截 package com.hmall.common.interceptor;import cn.hutool.core.util.StrUtil; import com.hmall.common.utils.UserContext; import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;public class UserInfoInterceptor implements HandlerInterceptor {/*** 在请求处理之前进行调用Controller方法调用之前* param request* param response* param handler* return* throws Exception*/Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1. 获取请求头中的用户信息String userInfo request.getHeader(userInfo);//2. 判断用户信息是否为空if(StrUtil.isNotBlank(userInfo)){// 不为空将用户信息存入到ThreadLocal中UserContext.setUser(Long.valueOf(userInfo));}// 3. 放行return true;}/*** 在请求处理之后进行调用但是在视图被渲染之前Controller方法调用之后* param request* param response* param handler* param ex* throws Exception*/Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 清除ThreadLocal中的用户信息UserContext.removeUser();} }注册拦截器 package com.hmall.common.config;import com.hmall.common.interceptor.UserInfoInterceptor; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import java.text.DecimalFormat;Configuration // 配置类/*** mvc配置类 当DispatcherServlet类存在时这个配置类才会生效* 为什么要这么做呢 因为网关模块也依赖了common模块而网关模块底层gateway是没有走spring mvc的* 所以这个配置类在网关模块中是不需要的所以需要加上这个注解* 不加这个注解的话在网关模块启动的时候会报错因为配置不生效*/ ConditionalOnClass(DispatcherServlet.class) public class MvcConfig implements WebMvcConfigurer {/*** 添加拦截器* param registry*/public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new UserInfoInterceptor());} }配置自动装配使配置类生效 测试网关作用 五、OpenFeign微服务间用户标识信息传递实现 5.1 网关请求 和 OpenFeign请求的区别 前端发起的请求都会经过网关再到微服务由于我们之前编写的过滤器和拦截器功能微服务可以轻松获取登录用户信息。 但是这也是一种局限。只有通过网关转发的请求才有用户信息的传递。而在微服务项目中有很多稍微复杂点的业务需要多个微服务模块协调此时请求是通过OpenFeign发送的而不是网关转发的。自然而然地无法传递用户标识信息。 但是如果不传递用户标识信息业务就无法正常进行。例如购物车微服务在下单结算后需要调用商品微服务清除购物车信息但是如果不传递当前购物车用户的ID信息如何正确清除商品信息呢 因此我们本节就是为了解决微服务间传递用户标识信息的。 5.2 如何使OpenFeign请求携带用户信息 将UserContext中的用户表示信息在发送OpenFeign请求前存入请求头一并发出给目标微服务。 5.3 如何使所有OpenFeign请求的请求头携带用户信息 使用Feign中提供的一个拦截器接口feign.RequestInterceptor确保请求在发出之前都能携带上用户标识信息。 5.4 *编写OpenGeign拦截器 创建拦截器 该写在哪呢为了让所有微服务调用OpenFeign请求都能添加上请求用户信息我们需要将拦截器写在hm-api 这个ClientAPI模块中编写拦截器代码 这个拦截器需要像前一节写的拦截器一样先注册再使用么不需要的哦因为这个拦截器的底层并不是走SpringMvc那套的直接使用即可测试 /*** 拦截器 将登录用户信息放入请求头中传递给下游微服务* return*/Beanpublic RequestInterceptor userInfoRequestInterceptor(){return new RequestInterceptor() {Overridepublic void apply(RequestTemplate template) {// 获取登录用户Long userId UserContext.getUser();if(userId null) {// 如果为空则直接跳过return;}// 如果不为空则放入请求头中传递给下游微服务template.header(user-info, userId.toString());}};} 测试清除选中的购物车信息 好了现在微服务之间通过OpenFeign调用时也会传递登录用户信息了。 六、微服务网关知识追问巩固 1. 拆分微服务模块后前端如何知道要请求到哪个模块如何解决这个问题 2. 请你概述一下网关模块的基本方案是什么 3. 微服务为什么添加网关层谈谈网关层的作用是什么 4. 微服务网关方案动用了“一个过滤器、两个拦截器”它们分别的用途是什么底层的实现有有什么不同 5. 微服务中是如何更好地解决登录校验问题的应该在哪里实现登录校验功能 6. 谈谈gateway网关过滤器有几种实现形式实现的步骤分别是什么 6. 微服务模块如何获取用户标识信息 7. 微服务中是怎么解决跨微服务请求中用户标识信息传递问题的应该在哪里实现该功能 8. 请你谈谈一下SpringMvc拦截器的使用步骤 9. 假设配置的拦截器不在包扫描范围下你要如何配置从而确保拦截器生效呢
文章转载自:
http://www.morning.bswxt.cn.gov.cn.bswxt.cn
http://www.morning.kjmws.cn.gov.cn.kjmws.cn
http://www.morning.pbzgj.cn.gov.cn.pbzgj.cn
http://www.morning.nhzxr.cn.gov.cn.nhzxr.cn
http://www.morning.cftkz.cn.gov.cn.cftkz.cn
http://www.morning.hytr.cn.gov.cn.hytr.cn
http://www.morning.mbnhr.cn.gov.cn.mbnhr.cn
http://www.morning.gnfkl.cn.gov.cn.gnfkl.cn
http://www.morning.tpnxj.cn.gov.cn.tpnxj.cn
http://www.morning.ygmw.cn.gov.cn.ygmw.cn
http://www.morning.ngmjn.cn.gov.cn.ngmjn.cn
http://www.morning.kggxj.cn.gov.cn.kggxj.cn
http://www.morning.cjsnj.cn.gov.cn.cjsnj.cn
http://www.morning.bzjpn.cn.gov.cn.bzjpn.cn
http://www.morning.mgmyt.cn.gov.cn.mgmyt.cn
http://www.morning.qbfkz.cn.gov.cn.qbfkz.cn
http://www.morning.ltxgk.cn.gov.cn.ltxgk.cn
http://www.morning.cgmzt.cn.gov.cn.cgmzt.cn
http://www.morning.zqdzg.cn.gov.cn.zqdzg.cn
http://www.morning.txzmy.cn.gov.cn.txzmy.cn
http://www.morning.kgmkl.cn.gov.cn.kgmkl.cn
http://www.morning.czqqy.cn.gov.cn.czqqy.cn
http://www.morning.xlmgq.cn.gov.cn.xlmgq.cn
http://www.morning.txtgy.cn.gov.cn.txtgy.cn
http://www.morning.sldrd.cn.gov.cn.sldrd.cn
http://www.morning.xmttd.cn.gov.cn.xmttd.cn
http://www.morning.rhkmn.cn.gov.cn.rhkmn.cn
http://www.morning.mqghs.cn.gov.cn.mqghs.cn
http://www.morning.wspjn.cn.gov.cn.wspjn.cn
http://www.morning.kpbgvaf.cn.gov.cn.kpbgvaf.cn
http://www.morning.mkydt.cn.gov.cn.mkydt.cn
http://www.morning.xkyst.cn.gov.cn.xkyst.cn
http://www.morning.skrh.cn.gov.cn.skrh.cn
http://www.morning.htqrh.cn.gov.cn.htqrh.cn
http://www.morning.lbzgt.cn.gov.cn.lbzgt.cn
http://www.morning.zckhn.cn.gov.cn.zckhn.cn
http://www.morning.qrnbs.cn.gov.cn.qrnbs.cn
http://www.morning.fsfz.cn.gov.cn.fsfz.cn
http://www.morning.ssmhn.cn.gov.cn.ssmhn.cn
http://www.morning.bhpjc.cn.gov.cn.bhpjc.cn
http://www.morning.frqtc.cn.gov.cn.frqtc.cn
http://www.morning.mqfw.cn.gov.cn.mqfw.cn
http://www.morning.gmmyn.cn.gov.cn.gmmyn.cn
http://www.morning.rqxtb.cn.gov.cn.rqxtb.cn
http://www.morning.blfll.cn.gov.cn.blfll.cn
http://www.morning.kjkml.cn.gov.cn.kjkml.cn
http://www.morning.rjcqb.cn.gov.cn.rjcqb.cn
http://www.morning.qkxnw.cn.gov.cn.qkxnw.cn
http://www.morning.srnth.cn.gov.cn.srnth.cn
http://www.morning.hjlwt.cn.gov.cn.hjlwt.cn
http://www.morning.ctwwq.cn.gov.cn.ctwwq.cn
http://www.morning.tcxk.cn.gov.cn.tcxk.cn
http://www.morning.lwmzp.cn.gov.cn.lwmzp.cn
http://www.morning.sfwcb.cn.gov.cn.sfwcb.cn
http://www.morning.lrflh.cn.gov.cn.lrflh.cn
http://www.morning.rfpb.cn.gov.cn.rfpb.cn
http://www.morning.prhfc.cn.gov.cn.prhfc.cn
http://www.morning.dfdhx.cn.gov.cn.dfdhx.cn
http://www.morning.hgwsj.cn.gov.cn.hgwsj.cn
http://www.morning.tslfz.cn.gov.cn.tslfz.cn
http://www.morning.wfmqc.cn.gov.cn.wfmqc.cn
http://www.morning.wxlzr.cn.gov.cn.wxlzr.cn
http://www.morning.dzqyn.cn.gov.cn.dzqyn.cn
http://www.morning.rcgzg.cn.gov.cn.rcgzg.cn
http://www.morning.rbjp.cn.gov.cn.rbjp.cn
http://www.morning.nkqxb.cn.gov.cn.nkqxb.cn
http://www.morning.thrgp.cn.gov.cn.thrgp.cn
http://www.morning.fy974.cn.gov.cn.fy974.cn
http://www.morning.kpbgvaf.cn.gov.cn.kpbgvaf.cn
http://www.morning.kfcz.cn.gov.cn.kfcz.cn
http://www.morning.gjlxn.cn.gov.cn.gjlxn.cn
http://www.morning.rzpkt.cn.gov.cn.rzpkt.cn
http://www.morning.fznj.cn.gov.cn.fznj.cn
http://www.morning.nlqmp.cn.gov.cn.nlqmp.cn
http://www.morning.pjzcp.cn.gov.cn.pjzcp.cn
http://www.morning.rfyk.cn.gov.cn.rfyk.cn
http://www.morning.hqpyt.cn.gov.cn.hqpyt.cn
http://www.morning.ychoise.com.gov.cn.ychoise.com
http://www.morning.rxnxl.cn.gov.cn.rxnxl.cn
http://www.morning.lbxhy.cn.gov.cn.lbxhy.cn
http://www.tj-hxxt.cn/news/267173.html

相关文章:

  • 企业网站建设招标书同ip多域名做同行业网站
  • 网站开发美学新华美玉官方网站在线做
  • 滨州网站建设公司电话ui图标素材网站
  • 高端美食网站建设想做电商怎么入手
  • 摄影旅游网站源码wordpress悬浮刷新
  • 网站的系统建设方式有哪些方面搜索引擎网络排名
  • 手机产品展示网站模板成都装修公司十大排名
  • 挣钱做任务的网站北京网络优化
  • 网站整体形象策划与包装聊城网站建设工作室
  • 多个网站能否统一做等保动态个人网站模板下载
  • 服务器做ssr后还可以做网站吗百度推广登陆入口
  • 做网站开票是多少个点的票哪些网站设计的高大上
  • 科技公司 网站 石家庄成都到西安需要隔离吗
  • 番禺做网站系统郑州那个公司做网站好
  • 网站关键词分隔株洲在线论坛伴你生活每一天
  • 电子商务网站 费用上海公司注册名字查询
  • 如何建设一个双语的网站html企业网站怎么做
  • 网站建设-好发信息网开封+网站建设+网络推广
  • 学校的网站如何建设方案wordpress主题重新激活
  • 展览公司网站建设方案镇江丹阳建设局网站
  • 企业网站模板网 凡建站天津网站制作的公司
  • 网站开发用什么语言最多贵阳网站开发公司推荐
  • 怎样开建网站电商分销主要做什么
  • 阿里云部署一个自己做的网站吗文安做网站
  • 东营wordpress网站建设wordpress仿 模板
  • 网站开发视频播放好做吗软件开发工作内容描述
  • 公司营业执照注册泉州百度seo公司
  • wordpress网页慢网站的seo如何优化
  • 精品网站源码资源程序下载天津实体店网站建设
  • 建设网站找哪个公司动漫网站实现功能