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

酒类网站建佛山市住房与城乡建设局网站

酒类网站建,佛山市住房与城乡建设局网站,手机微信一体网站建设,建网站业务员我们将黑马商城拆分为5个微服务#xff1a; 用户服务 商品服务 购物车服务 交易服务 支付服务 由于每个微服务都有不同的地址或端口#xff0c;相信大家在与前端联调的时候发现了一些问题#xff1a; 请求不同数据时要访问不同的入口#xff0c;需要维护多个入口地址…我们将黑马商城拆分为5个微服务 用户服务 商品服务 购物车服务 交易服务 支付服务 由于每个微服务都有不同的地址或端口相信大家在与前端联调的时候发现了一些问题 请求不同数据时要访问不同的入口需要维护多个入口地址麻烦 前端无法调用nacos无法实时更新服务列表 单体架构时我们只需要完成一次用户登录、身份校验就可以在所有业务中获取到用户信息。而微服务拆分后每个微服务都独立部署这就存在一些问题 每个微服务都需要编写登录校验、用户信息获取的功能吗 当微服务之间调用时该如何传递用户信息 接下来我们会通过网关技术解决上述问题。今天的内容会分为3章 第一章网关路由解决前端请求入口的问题。 第二章网关鉴权解决统一登录校验和用户信息获取的问题。 第三章统一配置管理解决微服务的配置文件重复和配置热更新问题。 通过今天的学习你将掌握下列能力 会利用微服务网关做请求路由 会利用微服务网关做登录身份校验 会利用Nacos实现统一配置管理 会利用Nacos实现配置热更新 好了接下来我们就一起进入今天的学习吧。 1.网关路由 1.1.认识网关 网关网关就是网络的关口负责请求的路由、请求的转发、身份校验。 更通俗的来讲网关就像是以前园区传达室的大爷。 外面的人要想进入园区必须经过大爷的认可如果你是不怀好意的人肯定被直接拦截。 外面的人要传话或送信要找大爷。大爷帮你带给目标人。 微服务网关起到同样的作用前端请求不能直接访问微服务而是要请求网关 网关可以做登录身份校验校验通过才放行 通过认证后网关再根据请求去判断访问哪个微服务将请求转发过去 网关其实也是一个微服务它启动之后可以去注册中拉去所有的微服务地址将来微服务地址有变更也会推送回给网关 前端所有的请求都去请求网关然后网关 根据前端发来的请求 判断 这个请求要转发给哪个微服务处理请求的路由然后网关就会把请求转发给具体的微服务请求的转发网关在做请求转发之前还需要对请求的用户进行身份校验身份校验身份校验通过后解析jwt得到用户的信息然后再把用户的信息传给下游微服务 在SpringCloud中提供了两种网关的实现方案 Netflix Zuul早期实现目前已经淘汰 SpringCloudGateway基于Spring的WebFlux技术完全支持响应式编程吞吐能力更强 课堂中我们以SpringCloudGateway为例来讲解官方网站 Spring Cloud GatewayLevel up your Java code and explore what Spring can do for you.https://spring.io/projects/spring-cloud-gateway#learn 1.2.快速入门 接下来我们先看下如何利用网关实现请求路由。由于网关本身也是一个独立的微服务但没有业务逻辑所以也要创建一个模块开发功能。大概步骤如下 创建网关微服务 引入SpringCloudGateway、NacosDiscovery依赖 编写启动类 配置网关路由 1.2.1.创建项目 首先我们要在hmall下创建一个新的module命名为hm-gateway作为网关微服务 1.2.2.引入依赖 在hm-gateway模块的pom.xml文件中引入依赖 ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdparentartifactIdhmall/artifactIdgroupIdcom.heima/groupIdversion1.0.0/version/parentmodelVersion4.0.0/modelVersionartifactIdhm-gateway/artifactIdpropertiesmaven.compiler.source11/maven.compiler.sourcemaven.compiler.target11/maven.compiler.target/propertiesdependencies!--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 /project 1.2.3.启动类 在hm-gateway模块的com.hmall.gateway包下新建一个启动类 代码如下 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);} }1.2.4.配置路由 接下来在hm-gateway模块的resources目录新建一个application.yaml文件内容如下 server: port: 8080 # 网关服务的端口号 spring:application:name: gateway # 网关服务的名称cloud:nacos:server-addr: 192.168.150.101:8848 # 配置nacos服务的地址gateway:routes: # 在routes属性下配置路由规则可以配置多个路由规则- id: item # 路由规则的id(唯一标识)建议和要路由的微服务名一致uri: lb://item-service # 要路由到的目标服务lb代表负载均衡会从注册中心拉取服务列表然后负载均衡挑一个实例predicates: # 路由断言判断请求是否符合这个路由断言符合则按此条路由规则走- Path/items/**,/search/** # 这里是以请求路径作为判断规则等号前面是路由断言的名字右边是规则有多个规则就用逗号隔开- id: carturi: lb://cart-servicepredicates:- Path/carts/**- id: useruri: lb://user-servicepredicates:- Path/users/**,/addresses/**- id: tradeuri: lb://trade-servicepredicates:- Path/orders/**- id: payuri: lb://pay-servicepredicates:- Path/pay-orders/**例如下图 前端发来请求请求路径是/items/list然后就符合了由路断言然后就会按此条路由规则走路由到到uri后面的微服务 1.2.5.测试 启动GatewayApplication以 http://localhost:8080 拼接微服务接口路径来测试。例如 http://localhost:8080/items/page?pageNo1pageSize1 此时启动UserApplication、CartApplication然后打开前端页面发现相关功能都可以正常访问了 1.3.路由过滤 先复习下路由规则的定义语法 spring:cloud:gateway:routes:- id: itemuri: lb://item-servicepredicates:- Path/items/**,/search/** 其中routes对应的Java类型如下 是一个集合也就是说可以定义很多路由规则。集合中的RouteDefinition就是路由规则定义其中常见的属性如下 四个属性含义如下 id路由的唯一标示 predicates路由断言其实就是匹配条件是一个集合可以配置多个 filters路由过滤规则是一个集合可以配置多个 uri路由目标地址lb://代表负载均衡从注册中心获取目标微服务的实例列表并且负载均衡选择一个访问。 这里我们重点关注predicates也就是路由断言。SpringCloudGateway中提供的断言类型有很多 名称 说明 示例 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 权重处理 2.网关做登录校验 单体架构时我们只需要完成一次用户登录、身份校验就可以在所有业务中获取到用户信息。而微服务拆分后每个微服务都独立部署不再共享数据。也就意味着每个微服务都需要做登录校验这显然不可取。 2.1.鉴权思路分析 我们的登录是基于JWT来实现的校验JWT的算法复杂而且需要用到秘钥。如果每个微服务都去做登录校验这就存在着两大问题 每个微服务都需要知道JWT的秘钥不安全 每个微服务重复编写登录校验代码、权限校验代码麻烦 因为网关是所有微服务的入口一切请求都需要先经过网关。所以可以把登录校验放到网关去做这样之前说的问题就解决了 只需要在网关和用户服务保存秘钥 只需要在网关开发登录校验功能 此时登录校验的流程如图 不过这里存在几个问题 网关路由是配置的请求转发是Gateway内部代码我们如何在转发之前做登录校验 网关校验JWT之后如何将用户信息传递给微服务 如何在微服务之间传递用户信息 这些问题将在接下来几节一一解决。 2.2.网关过滤器 登录校验必须在请求转发到微服务之前做否则就失去了意义。而网关的请求转发是Gateway内部代码实现的要想在请求转发之前做登录校验就必须了解Gateway内部工作的基本原理。 如图所示 客户端请求进入网关后由HandlerMapping对发送请求做判断基于路由断言找到与当前请求匹配的路由规则Route然后将请求交给WebHandler去处理。 WebHandler会加载当前路由下需要执行的过滤器链Filter chain然后按照顺序逐一执行后面称为Filter。 NettyRoutingFilter过滤器负责将请求转发到微服务当微服务返回结果后存入上下文然后依次返回给其他过滤器最终返回给用户 最终请求转发是由NettyRoutingFilter的过滤器来执行的这个过滤器是整个过滤器链中最后一个所以只要定义一个过滤器并在其中实现登录校验的逻辑并且将过滤器的执行顺序定义到NettyRoutingFilter之前这样网关就可以在转发请求之前去做登录校验了 图中Filter被虚线分为左右两部分是因为Filter内部的逻辑分为pre和post两部分分别会在请求路由到微服务之前和之后被执行。 只有所有Filter的pre逻辑都依次顺序执行通过后请求才会被路由到微服务。 微服务返回结果后再倒序执行Filter的post逻辑。 最终把响应结果返回。 那么该如何实现一个网关过滤器呢 网关过滤器链中的过滤器有两种 GatewayFilter路由过滤器作用范围比较灵活可以是任意指定的路由Route. 在yml文件中用filters属性配置的那种就是路由过滤器SpringCloudGateway已经提供好的默认不生效要配置到路由后才生效 GlobalFilter全局过滤器作用范围是所有路由声明后自动生效。 其实GatewayFilter和GlobalFilter这两种过滤器的方法签名完全一致 /*** 处理请求并将其传递给下一个过滤器* param exchange 当前请求的上下文其中包含request、response等各种数据* param chain 过滤器链基于它向下传递请求* return 根据返回值标记当前请求是否被完成或拦截chain.filter(exchange)就放行了。*/ MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain); ServerWebExchange网关内部的上下文对象可以保存网关内部的共享数据如request、response、session、或自定义的共享属性。将来在网关的整个过滤器链中都可以从它里面读取数据或存数据chain过滤器链当过滤器执行完后调用过滤器链中的下一个过滤器 FilteringWebHandler在处理请求时会将GlobalFilter装饰为GatewayFilter然后放到同一个过滤器链中排序以后依次执行。 Gateway中内置了很多的GatewayFilter详情可以参考官方文档 Docshttps://b11et3un53m.feishu.cn/wiki/UMgpwmmQKisWBIkaABbcwAPonVf#CbiqdfAlNoTXFCxAJeDcyiwenucGateway内置的GatewayFilter过滤器使用起来非常简单无需编码只需在yaml文件中简单配置即可。而且其作用范围也很灵活配置在哪个Route下就作用于哪个Route. GatewayFilter过滤器的使用有一个过滤器叫做AddRequestHeaderGatewayFilterFacotry顾明思议就是添加请求头的过滤器可以给请求添加一个请求头并传递到下游微服务。 使用的使用只需要在application.yaml中这样配置 spring:cloud:gateway:routes:- id: test_routeuri: lb://test-servicepredicates:-Path/test/**filters:- AddRequestHeaderkey, value # 逗号之前是请求头的key逗号之后是请求头的value 如果想要让过滤器作用于所有的路由则可以这样配置 spring:cloud:gateway:default-filters: - AddRequestHeaderkey, valueroutes:- id: test_routeuri: lb://test-servicepredicates:-Path/test/** 2.3.自定义过滤器 无论是GatewayFilter还是GlobalFilter都支持自定义只不过编码方式、使用方式略有差别。 2.3.1.自定义GatewayFilter先跳过 自定义GatewayFilter不是直接实现GatewayFilter接口而是实现AbstractGatewayFilterFactory。最简单的方式是这样的 Component public class PrintAnyGatewayFilterFactory extends AbstractGatewayFilterFactoryObject {Overridepublic GatewayFilter apply(Object config) {return new GatewayFilter() {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 获取请求ServerHttpRequest request exchange.getRequest();// 编写过滤器逻辑System.out.println(过滤器执行了);// 放行return chain.filter(exchange);}};} } 注意该类的名称一定要以GatewayFilterFactory为后缀 然后在yaml配置中这样使用 spring:cloud:gateway:default-filters:- PrintAny # 此处直接以自定义的GatewayFilterFactory类名称前缀类声明过滤器 另外这种过滤器还可以支持动态配置参数不过实现起来比较复杂示例 Component public class PrintAnyGatewayFilterFactory // 父类泛型是内部类的Config类型extends AbstractGatewayFilterFactoryPrintAnyGatewayFilterFactory.Config {Overridepublic GatewayFilter apply(Config config) {// OrderedGatewayFilter是GatewayFilter的子类包含两个参数// - GatewayFilter过滤器// - int order值值越小过滤器执行优先级越高return new OrderedGatewayFilter(new GatewayFilter() {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 获取config值String a config.getA();String b config.getB();String c config.getC();// 编写过滤器逻辑System.out.println(a a);System.out.println(b b);System.out.println(c c);// 放行return chain.filter(exchange);}}, 100);}// 自定义配置属性成员变量名称很重要下面会用到Datastatic class Config{private String a;private String b;private String c;}// 将变量名称依次返回顺序很重要将来读取参数时需要按顺序获取Overridepublic ListString shortcutFieldOrder() {return List.of(a, b, c);}// 返回当前配置类的类型也就是内部的ConfigOverridepublic ClassConfig getConfigClass() {return Config.class;}} 然后在yaml文件中使用 spring:cloud:gateway:default-filters:- PrintAny1,2,3 # 注意这里多个参数以,隔开将来会按照shortcutFieldOrder()方法返回的参数顺序依次复制 上面这种配置方式参数必须严格按照shortcutFieldOrder()方法的返回参数名顺序来赋值。 还有一种用法无需按照这个顺序就是手动指定参数名 spring:cloud:gateway:default-filters:- name: PrintAnyargs: # 手动指定参数名无需按照参数顺序a: 1b: 2c: 3 2.3.2.自定义GlobalFilter 自定义GlobalFilter过滤器很简单直接实现GlobalFilter接口即可而且也无法设置动态参数 同时实现Ordered接口并重写其中的getOrder方法是为了将这个自定义过滤器的执行顺序放在NettyRoutingFilter之前 Component public class PrintAnyGlobalFilter implements GlobalFilter, Ordered {Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {//获取http请求信息ServerHttpRequest request exchange.getRequest();// 编写过滤器逻辑System.out.println(过滤逻辑模拟);// 放行return chain.filter(exchange);}Overridepublic int getOrder() {// 过滤器执行顺序值越小优先级越高return 0;} } 2.4.登录校验 接下来我们就利用自定义GlobalFilter来完成登录校验。 2.4.1.JWT工具 登录校验需要用到JWT而且JWT的加密需要秘钥和加密工具。这些在hm-service中已经有了我们直接拷贝过来 具体作用如下 AuthProperties类读取yaml文件中配置的登录校验需要拦截的路径从application.yaml文件中获取因为不是所有的路径都需要登录才能访问 JwtProperties定义与JWT工具有关的属性比如秘钥文件位置 SecurityConfig工具的自动装配 JwtToolJWT工具其中包含了校验和解析token的功能 hmall.jks秘钥文件 其中AuthProperties和JwtProperties所需的属性要在application.yaml中配置 hm:jwt:location: classpath:hmall.jks # 秘钥地址alias: hmall # 秘钥别名password: hmall123 # 秘钥文件密码tokenTTL: 30m # 登录有效期auth:excludePaths: # 无需登录校验的路径碰到哪些路径就直接放行- /search/**- /users/login- /items/** 2.4.2.编写登录校验的过滤器 接下来我们定义一个登录校验的过滤器 代码如下 package com.hmall.gateway.filter;import com.hmall.common.exception.UnauthorizedException; import com.hmall.common.utils.CollUtils; import com.hmall.gateway.config.AuthProperties; import com.hmall.gateway.util.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.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 RequiredArgsConstructor EnableConfigurationProperties(AuthProperties.class) public class AuthGlobalFilter implements GlobalFilter, Ordered {private final JwtTool jwtTool;private final AuthProperties authProperties;//spring提供的AntPathMatcher类一个匹配器private final AntPathMatcher antPathMatcher new AntPathMatcher();Overridepublic MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) {// 1.获取RequestServerHttpRequest request exchange.getRequest();// 2.判断 发过来的请求 是否需要做登录拦截if(isExclude(request.getPath().toString())){// 无需拦截直接放行return chain.filter(exchange);}// 3.获取请求头中的tokenString token null;ListString headers request.getHeaders().get(authorization);if (!CollUtils.isEmpty(headers)) {token headers.get(0);}// 4.使用工具类校验并解析tokenLong userId null;try {userId jwtTool.parseToken(token);} catch (UnauthorizedException e) {// 如果无效拦截ServerHttpResponse response exchange.getResponse();response.setRawStatusCode(401);return response.setComplete(); //调用这个方法后后面所有的过滤器就不会执行了}// TODO 5.如果有效传递用户信息System.out.println(userId userId);// 6.放行return chain.filter(exchange);}private boolean isExclude(String antPath) {for (String pathPattern : authProperties.getExcludePaths()) {//判断指定的路径和路径的通配符是否匹配if(antPathMatcher.match(pathPattern, antPath)){return true;}}return false;}Overridepublic int getOrder() {return 0;} } 重启测试会发现访问/items开头的路径未登录状态下不会被拦截 访问其他路径则未登录状态下请求会被拦截并且返回401状态码 2.5.微服务获取用户 现在网关已经可以完成登录校验并获取到登录用户的信息。但是网关将请求转发到微服务时微服务如何获取到用户信息呢 由于网关发送请求到微服务依然采用的是Http请求因此我们可以将用户信息以请求头的方式传递到下游微服务。然后微服务可以从请求头中获取登录用户信息。考虑到微服务内部可能很多地方都需要用到登录用户信息因此我们可以利用SpringMVC的拦截器来实现登录用户信息获取并存入ThreadLocal方便后续使用。 据图流程图如下 因此接下来我们要做的事情有 改造网关过滤器在获取用户信息后保存到请求头转发到下游微服务 编写微服务拦截器拦截请求获取用户信息保存到ThreadLocal后放行 2.5.1.保存用户信息到请求头 首先我们修改登录校验过滤器的处理逻辑保存用户信息到请求头中 .mutate()对下游的请求做改变.request()对请求做处理.build()构造出新的ServerWebExchange对象 到这里可以在controller获取信息 2.5.2.拦截器获取用户 在hm-common中已经有一个用于保存登录用户的ThreadLocal工具 其中已经提供了保存和获取用户的方法 接下来我们只需要编写拦截器获取用户信息并保存到UserContext然后放行即可。 由于每个微服务都有获取登录用户的需求因此拦截器我们直接写在hm-common中并写好自动装配。这样微服务只需要引入hm-common就可以直接具备拦截器功能无需重复编写。 我们在hm-common模块下定义一个拦截器 具体代码如下 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 {Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 1.获取请求头中的用户信息String userInfo request.getHeader(user-info);// 2.判断是否为空if (StrUtil.isNotBlank(userInfo)) {// 不为空保存到ThreadLocalUserContext.setUser(Long.valueOf(userInfo));}// 3.放行return true;}Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {// 移除用户UserContext.removeUser();} } 接着在hm-common模块下编写SpringMVC的配置类配置登录拦截器 具体代码如下 package com.hmall.common.config;import com.hmall.common.interceptors.UserInfoInterceptor; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 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;Configuration ConditionalOnClass(DispatcherServlet.class) public class MvcConfig implements WebMvcConfigurer {Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new UserInfoInterceptor());} } 不过需要注意的是这个配置类默认是不会生效的因为它所在的包是com.hmall.common.config与其它微服务的扫描包不一致无法被扫描到因此无法生效。 基于SpringBoot的自动装配原理我们要将其添加到resources目录下的META-INF/spring.factories文件中 内容如下 org.springframework.boot.autoconfigure.EnableAutoConfiguration\com.hmall.common.config.MyBatisConfig,\com.hmall.common.config.MvcConfig 2.5.3.恢复购物车代码 之前我们无法获取登录用户所以把购物车服务的登录用户写死了现在需要恢复到原来的样子。 找到cart-service模块的com.hmall.cart.service.impl.CartServiceImpl 修改其中的queryMyCarts方法 2.6.OpenFeign传递用户信息 前端发起的请求都会经过网关再到微服务由于我们之前编写的过滤器和拦截器功能微服务可以获取到登录用户的信息。 但有些业务是比较复杂的请求到达微服务后还需要调用其它多个微服务。比如下单业务流程如下 下单的过程中需要调用商品服务扣减库存调用购物车服务清理用户购物车。而清理购物车时必须知道当前登录的用户身份。但是订单服务调用购物车时并没有传递用户信息购物车服务无法知道当前用户是谁 由于微服务获取用户信息是通过拦截器在请求头中读取因此想要实现微服务之间的用户信息传递就必须在微服务 发起调用时 把用户信息存入请求头。 微服务之间调用是基于OpenFeign来实现的并不是我们自己发送的请求。我们如何才能让每一个由OpenFeign发起的请求自动携带登录用户信息呢 OpenFeign中提供了一个拦截器接口feign.RequestInterceptor用于在Feign调用发起前对请求进行处理在所有的OpenFeign发起请求前都会先调用这个拦截器中的apply方法来处理请求。 public interface RequestInterceptor {/*** Called for every request. * Add data using methods on the supplied {link RequestTemplate}.*/void apply(RequestTemplate template); }我们只需要实现这个接口然后实现其apply方法再利用RequestTemplate对象来添加请求头将用户信息保存到请求头中之后每次OpenFeign发起请求时都会调用该方法传递用户信息。 其中RequestTemplate类中提供了一些方法可以修改请求头具体自行查阅 更多的用法参考使用OpenFeing远程调用时为请求添加请求头_openfeign添加请求头-CSDN博客 因为FeignClient全部都是在hm-api模块因此我们在hm-api模块的com.hmall.api.config.DefaultFeignConfig中编写这个拦截器然后任何引入了hm-api模块的微服务在发起远程调用的时候都会生效 在com.hmall.api.config.DefaultFeignConfig配置类中添加一个Bean Bean public 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调用时也会传递登录用户信息了。 3.配置管理 到目前为止我们已经解决了微服务相关的几个问题 微服务远程调用 微服务注册、发现 微服务请求路由、负载均衡 微服务登录用户信息传递 不过现在依然还有几个问题需要解决学习此部分更加方便开发微服务 网关路由在配置文件中写死了如果变更必须重启微服务 某些业务配置在配置文件中写死了每次修改都要重启服务 每个微服务都有很多重复的配置维护成本高yml文件中有很多重复的配置 这些问题可以通过统一的配置管理器服务解决。而Nacos不仅仅具备注册中心功能还具备配置管理的功能 所以微服务共享的配置可以统一交给Nacos保存和管理在Nacos控制台修改配置后Nacos会将配置变更 推送 给相关的微服务而且无需重启即可生效实现配置的热更新。 网关的路由同样是配置因此同样可以基于这个功能实现动态路由功能无需重启网关即可修改路由配置。 3.1.配置共享 把微服务共享的配置抽取到Nacos中统一管理这样就不需要每个微服务都重复配置了。分为两步 在Nacos中添加共享配置 微服务拉取配置 3.1.1.配置管理中添加共享配置 分析重复的配置 以cart-service为例我们看看有哪些配置是重复的可以抽取的 首先是jdbc相关配置 然后是日志配置 然后是swagger以及OpenFeign的配置 我们在nacos控制台分别添加这些配置。 jdbc相关配置 首先是jdbc相关配置在配置管理-配置列表中点击新建一个配置 在弹出的表单中填写信息 其中详细的配置如下 spring:datasource:url: jdbc:mysql://${hm.db.host:192.168.150.101}:${hm.db.port:3306}/${hm.db.database}?useUnicodetruecharacterEncodingUTF-8autoReconnecttrueserverTimezoneAsia/Shanghaidriver-class-name: com.mysql.cj.jdbc.Driverusername: ${hm.db.un:root}password: ${hm.db.pw:123} mybatis-plus:configuration:default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandlerglobal-config:db-config:update-strategy: not_nullid-type: auto 注意这里的jdbc的相关参数并没有写死例如 数据库ip通过${hm.db.host:192.168.150.101}配置了默认值为192.168.150.101同时允许通过${hm.db.host}来覆盖默认值 数据库端口通过${hm.db.port:3306}配置了默认值为3306同时允许通过${hm.db.port}来覆盖默认值 数据库database可以通过${hm.db.database}来设定无默认值 日志配置 然后是统一的日志配置命名为shared-log.yaml配置内容如下 logging:level:com.hmall: debugpattern:dateformat: HH:mm:ss:SSSfile:path: logs/${spring.application.name} swagger配置 然后是统一的swagger配置命名为shared-swagger.yaml配置内容如下 knife4j:enable: trueopenapi:title: ${hm.swagger.title:黑马商城接口文档}description: ${hm.swagger.description:黑马商城接口文档}email: ${hm.swagger.email:zhanghuyiitcast.cn}concat: ${hm.swagger.concat:虎哥}url: https://www.itcast.cnversion: v1.0.0group:default:group-name: defaultapi-rule: packageapi-rule-resources:- ${hm.swagger.package} 注意这里的swagger相关配置我们没有写死例如 title接口文档标题我们用了${hm.swagger.title}来代替将来可以有用户手动指定 email联系人邮箱我们用了${hm.swagger.email:zhanghuyiitcast.cn}默认值是zhanghuyiitcast.cn同时允许用户利用${hm.swagger.email}来覆盖。 3.1.2.拉取共享配置 接下来我们要在微服务拉取共享配置将其与本地的application.yaml配置合并完成项目上下文的初始化。 不过需要注意的是读取Nacos配置是在SpringCloud上下文ApplicationContext初始化时处理的发生在项目的引导阶段。然后才会初始化SpringBoot上下文去读取application.yaml。 也就是说引导阶段application.yaml文件尚未读取根本不知道nacos 地址该如何去加载nacos中的配置文件呢 SpringCloud在初始化上下文的时候会先读取一个名为bootstrap.yaml(或者bootstrap.properties)的文件如果我们将nacos地址配置到bootstrap.yaml中那么在项目引导阶段就可以读取nacos中的配置了。 拉去共享配置的流程如下 其中 拉去Nacos配置拉去Nacos中的共享配置文件初始化ApplicationContext基于从Nacos拉去到的配置完成SpringCloud上下文的初始化之后加载SpringBoot配置文件以及上下文初始化 因此微服务整合Nacos配置管理的步骤如下 1引入依赖 在cart-service模块引入依赖 !--nacos配置管理做配置管理的依赖帮助我们去完成拉去配置的操作--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-nacos-config/artifactId/dependency!--作用读取bootstrap.yaml文件知道nacos的地址后才能去拉取共享配置文件--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-bootstrap/artifactId/dependency 2新建bootstrap.yaml 在cart-service中的resources目录新建一个bootstrap.yaml文件 内容如下 spring:application:name: cart-service # 服务名称profiles:active: devcloud:nacos:server-addr: 192.168.150.101 # nacos地址config:file-extension: yaml # 文件后缀名shared-configs: # 共享配置- dataId: shared-jdbc.yaml # 共享mybatis配置- dataId: shared-log.yaml # 共享日志配置- dataId: shared-swagger.yaml # 共享日志配置 3修改application.yaml 由于一些配置挪到了bootstrap.yaml因此application.yaml需要修改为 server:port: 8082 feign:okhttp:enabled: true # 开启OKHttp连接池支持 hm:swagger:title: 购物车服务接口文档package: com.hmall.cart.controllerdb:database: hm-cart 重启服务发现所有配置都生效了。 3.2.配置热更新到这
文章转载自:
http://www.morning.dgfpp.cn.gov.cn.dgfpp.cn
http://www.morning.zckhn.cn.gov.cn.zckhn.cn
http://www.morning.ysjjr.cn.gov.cn.ysjjr.cn
http://www.morning.lnyds.cn.gov.cn.lnyds.cn
http://www.morning.xcszl.cn.gov.cn.xcszl.cn
http://www.morning.bfhfb.cn.gov.cn.bfhfb.cn
http://www.morning.gsjfn.cn.gov.cn.gsjfn.cn
http://www.morning.ygqjn.cn.gov.cn.ygqjn.cn
http://www.morning.xbdrc.cn.gov.cn.xbdrc.cn
http://www.morning.sflnx.cn.gov.cn.sflnx.cn
http://www.morning.wrkcw.cn.gov.cn.wrkcw.cn
http://www.morning.npqps.cn.gov.cn.npqps.cn
http://www.morning.mlpmf.cn.gov.cn.mlpmf.cn
http://www.morning.tfei69.cn.gov.cn.tfei69.cn
http://www.morning.gsjfn.cn.gov.cn.gsjfn.cn
http://www.morning.qpsdq.cn.gov.cn.qpsdq.cn
http://www.morning.sfdky.cn.gov.cn.sfdky.cn
http://www.morning.prhqn.cn.gov.cn.prhqn.cn
http://www.morning.wflsk.cn.gov.cn.wflsk.cn
http://www.morning.mbmh.cn.gov.cn.mbmh.cn
http://www.morning.lxqyf.cn.gov.cn.lxqyf.cn
http://www.morning.jllnh.cn.gov.cn.jllnh.cn
http://www.morning.ndcjq.cn.gov.cn.ndcjq.cn
http://www.morning.xoaz.cn.gov.cn.xoaz.cn
http://www.morning.ghrlx.cn.gov.cn.ghrlx.cn
http://www.morning.xdpjf.cn.gov.cn.xdpjf.cn
http://www.morning.nlmm.cn.gov.cn.nlmm.cn
http://www.morning.qrqcr.cn.gov.cn.qrqcr.cn
http://www.morning.jxlnr.cn.gov.cn.jxlnr.cn
http://www.morning.bxbnf.cn.gov.cn.bxbnf.cn
http://www.morning.dwzwm.cn.gov.cn.dwzwm.cn
http://www.morning.byjwl.cn.gov.cn.byjwl.cn
http://www.morning.ctrkh.cn.gov.cn.ctrkh.cn
http://www.morning.rqnhf.cn.gov.cn.rqnhf.cn
http://www.morning.pabxcp.com.gov.cn.pabxcp.com
http://www.morning.fewhope.com.gov.cn.fewhope.com
http://www.morning.nkwgy.cn.gov.cn.nkwgy.cn
http://www.morning.jtjmz.cn.gov.cn.jtjmz.cn
http://www.morning.smygl.cn.gov.cn.smygl.cn
http://www.morning.xqndf.cn.gov.cn.xqndf.cn
http://www.morning.nrqnj.cn.gov.cn.nrqnj.cn
http://www.morning.nzmhk.cn.gov.cn.nzmhk.cn
http://www.morning.qdmdp.cn.gov.cn.qdmdp.cn
http://www.morning.qhln.cn.gov.cn.qhln.cn
http://www.morning.dbbcq.cn.gov.cn.dbbcq.cn
http://www.morning.jsljr.cn.gov.cn.jsljr.cn
http://www.morning.csnch.cn.gov.cn.csnch.cn
http://www.morning.mypxm.com.gov.cn.mypxm.com
http://www.morning.mqbzk.cn.gov.cn.mqbzk.cn
http://www.morning.ngqty.cn.gov.cn.ngqty.cn
http://www.morning.mrfbp.cn.gov.cn.mrfbp.cn
http://www.morning.hqrr.cn.gov.cn.hqrr.cn
http://www.morning.dxpzt.cn.gov.cn.dxpzt.cn
http://www.morning.dqpnd.cn.gov.cn.dqpnd.cn
http://www.morning.wcyr.cn.gov.cn.wcyr.cn
http://www.morning.ttshf.cn.gov.cn.ttshf.cn
http://www.morning.yrqb.cn.gov.cn.yrqb.cn
http://www.morning.gbxxh.cn.gov.cn.gbxxh.cn
http://www.morning.wpsfc.cn.gov.cn.wpsfc.cn
http://www.morning.sqqds.cn.gov.cn.sqqds.cn
http://www.morning.rpzth.cn.gov.cn.rpzth.cn
http://www.morning.smfbw.cn.gov.cn.smfbw.cn
http://www.morning.qrhh.cn.gov.cn.qrhh.cn
http://www.morning.bwqcx.cn.gov.cn.bwqcx.cn
http://www.morning.jhswp.cn.gov.cn.jhswp.cn
http://www.morning.gkdhf.cn.gov.cn.gkdhf.cn
http://www.morning.rgsgk.cn.gov.cn.rgsgk.cn
http://www.morning.jrlxz.cn.gov.cn.jrlxz.cn
http://www.morning.wcjgg.cn.gov.cn.wcjgg.cn
http://www.morning.smrty.cn.gov.cn.smrty.cn
http://www.morning.wphfl.cn.gov.cn.wphfl.cn
http://www.morning.kclkb.cn.gov.cn.kclkb.cn
http://www.morning.pqkgb.cn.gov.cn.pqkgb.cn
http://www.morning.sjwzl.cn.gov.cn.sjwzl.cn
http://www.morning.jcjgh.cn.gov.cn.jcjgh.cn
http://www.morning.lxlfr.cn.gov.cn.lxlfr.cn
http://www.morning.rcbdn.cn.gov.cn.rcbdn.cn
http://www.morning.rqkk.cn.gov.cn.rqkk.cn
http://www.morning.drhnj.cn.gov.cn.drhnj.cn
http://www.morning.cnqdn.cn.gov.cn.cnqdn.cn
http://www.tj-hxxt.cn/news/269254.html

相关文章:

  • 石狮网站开发云虚机安装wordpress教程
  • 建设银行网站会员用户名格式seo网站设计点击软件
  • 品牌展示设计网站苏州工业园区做政务网站的公司
  • 电子商务网站建设 臧良运 好不好phpcms 视频网站模板
  • 咸阳网站建设费用wordpress给图片加链接
  • 网站建设赣icp不良网站进入窗口软件下载7
  • 外贸网站定制公司域名注册查询 万网
  • 网站翻页模板选择响应式网站
  • 网站上线之前怎么做推广电子商务网站的主要评价指标有
  • 海口h5建站模板wordpress心情
  • 免费做网站有哪些家屏蔽wordpress自带编辑器
  • 西部数据网站管理助手WordPress好看的博客主题有哪些
  • 网站建设教程搭建厦门怎么没有 网站备案
  • 移动端手机网站建设深圳龙华外国语学校
  • 网站建设规划任务书wordpress登录地址修改密码
  • 院感质控中心网站建设 申请食品电子商务网站建设方案
  • 个人业务网站带后台如何做网络网站推广
  • minecraft做图网站wordpress 外链背景图
  • 中小企业网站设计与开发目的坂田做网站的公司
  • 宁晋网站建设设计网站建设logo显示怎么设置
  • 北京网站设计公司哪儿济南兴田德润简介网站logo的作用
  • 网站的话术少儿编程课是学什么的
  • 深圳网络推广网站著名wordpress个人博客
  • 大淘客做的网站打不开网站开发模块化开发
  • 做网站 不是计算机专业药品网站模板
  • 皮具网站建设服装网站微信小程序服务器费用
  • 有哪些网站可以免费的实时在线街景地图
  • 织梦做的网站前面有不安全文登建设局官方网站
  • 哪个公司做的网站好个人网页设计作品论文
  • 怎么做一个网站出来如何制作公司网页百度发布