SpringCloud_day04

张开发
2026/4/4 23:01:42 15 分钟阅读

分享文章

SpringCloud_day04
目录微服务 02-01. 什么是网关微服务 02-02. 网关路由 - 快速入门微服务 02-03. 网关路由 - 路由属性问题:路由断言和路由过滤器有什么区别微服务 02-04. 网关登录校验 - 思路分析微服务 02-05. 网关登录校验 - 自定义 GlobalFilter问题:为什么要将这个过滤器优先级设置为最高(0)?微服务 02-06. 网关登录校验 - 自定义 GatewayFilter问题:gatewayFilter和globalFilter有什么区别?微服务 02-07. 网关登录校验 - 实现登录校验问题:解释下面代码问题EnableConfigurationProperties(AuthProperties.class) 为什么要加AuthProperties.class问题:Mono是什么类型问题:ServerWebExchange exchange这个是什么微服务 02-08. 网关登录校验 - 网关传递用户到微服务问题:ConditionalOnClass(DispatcherServlet.class)这个注解的作用?问题:Configuration和component区别?问题:怎么让某个配置类只在springmvc生效而不在gateway生效微服务 02-09. 网关登录校验 - OpenFeign 传递用户信息微服务 02-10. 配置管理 - 什么是配置管理微服务 02-11. 配置管理 - 共享配置微服务 02-12. 配置管理 - 配置热更新微服务 02-13. 配置管理 - 动态路由 (拓展)末尾页微服务 02-01. 什么是网关微服务 02-02. 网关路由 - 快速入门微服务 02-03. 网关路由 - 路由属性问题:路由断言和路由过滤器有什么区别特性路由断言Route Predicate路由过滤器Route Filter核心作用路由匹配判断决定「请求是否走这条路由」请求 / 响应增强决定「请求怎么转发、怎么处理」本质Java 8PredicateServerWebExchange函数式接口返回true/falseGatewayFilter/GlobalFilter链式处理器无返回值执行时机路由匹配阶段请求进入网关后转发前的第一步路由匹配成功后分pre转发前和post响应返回后两个阶段执行核心目标精准匹配请求将请求路由到正确的后端服务对请求 / 响应做修改、增强、管控实现通用逻辑复用微服务 02-04. 网关登录校验 - 思路分析微服务 02-05. 网关登录校验 - 自定义 GlobalFilter问题:为什么要将这个过滤器优先级设置为最高(0)?只要保证比NettyRoutingFilter的过滤器优先级(2147483647)高即可,因为这个是最终请求转发是有一个名为NettyRoutingFilter的过滤器来执行的而且这个过滤器是整个过滤器链中顺序最靠后的一个。如果我们能够定义一个过滤器在其中实现登录校验逻辑并且将过滤器执行顺序定义到NettyRoutingFilter之前这就符合我们的需求了微服务 02-06. 网关登录校验 - 自定义 GatewayFilter问题:gatewayFilter和globalFilter有什么区别?GlobalFilter 全局门禁所有请求都要过GatewayFilter 专属门禁只给指定路由用微服务 02-07. 网关登录校验 - 实现登录校验网关登录校验代码package com.hmall.gateway.filters; import com.hmall.common.exception.UnauthorizedException; import com.hmall.common.utils.CollUtils; 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.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; private final AntPathMatcher antPathMatcher new AntPathMatcher(); Override public MonoVoid filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 1.获取Request ServerHttpRequest request exchange.getRequest(); // 2.判断是否不需要拦截 if(isExclude(request.getPath().toString())){ // 无需拦截直接放行 return chain.filter(exchange); } // 3.获取请求头中的token String token null; ListString headers request.getHeaders().get(authorization); if (!CollUtils.isEmpty(headers)) { token headers.get(0); } // 4.校验并解析token Long 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; } Override public int getOrder() { return 0; } }问题:解释下面代码java 运行 // 判断当前路径是否在【放行列表】里 private boolean isExclude(String antPath) { // 遍历配置文件里的所有“放行路径”比如/login、/register for (String pathPattern : authProperties.getExcludePaths()) { // 关键Spring提供的路径匹配工具 // 支持: /** 、 /* 、 /user/* 这种通配符 if(antPathMatcher.match(pathPattern, antPath)){ // 匹配上了 → 说明是放行路径 → return true return true; } } // 遍历完所有路径都没匹配上 → 不是放行路径 → return false return false; } 解释这个代码antPathMatcher.match(模板, 真实路径)这是 Spring 专门用来匹配 URL 的工具。例子/**表示匹配任意子路径/*表示匹配一层路径表格模板 (pathPattern)真实路径 (antPath)结果/user/login/user/logintrue/user/**/user/infotrue/user/**/cart/listfalse/item/*/item/100true问题EnableConfigurationProperties(AuthProperties.class) 为什么要加AuthProperties.class加 AuthProperties.class就是告诉 Spring把我写的配置类 AuthProperties 加载进来、交给容器管理让我能自动注入使用。1. AuthProperties 是什么它是你用来接收application.yml配置的类大概长这样java运行ConfigurationProperties(prefix hm.auth) public class AuthProperties { private ListString excludePaths; // getter、setter }它自己不会自动被 Spring 识别并生效。2. 不加 EnableConfigurationProperties (AuthProperties.class) 会怎样AuthProperties 不会被注册成 Bean你在过滤器里写java运行Autowired private AuthProperties authProperties;直接报错找不到这个 Bean注入失败3. 加了之后发生什么Spring 会做三件事扫描并实例化 AuthProperties从 yml 读取hm.auth.xxx配置自动绑定到字段把它放进 Spring 容器变成一个 Bean→ 你就能Autowired注入使用了类比理解ConfigurationProperties“我是配置类”EnableConfigurationProperties(xxx.class)“启用这个配置类交给 Spring 管”就像你写了一个UserService但没加Service别人想Autowired就会报错必须让 Spring 知道它的存在面试标准答案EnableConfigurationProperties的作用是启用指定的配置属性类使其生效并注册为 Spring Bean从而支持 ConfigurationProperties 配置绑定与自动注入。小补充你可能会遇到如果在 AuthProperties 上直接加Component那也可以不用写EnableConfigurationProperties。问题:Mono是什么类型问题:ServerWebExchange exchange这个是什么微服务 02-08. 网关登录校验 - 网关传递用户到微服务问题:ConditionalOnClass(DispatcherServlet.class)这个注解的作用?问题:Configuration和component区别?问题:怎么让某个配置类只在springmvc生效而不在gateway生效ConditionalOnClass(DispatcherServlet.class)另一个是在网关生效的是ConditionalOnClass(ServerWebExchange.class)微服务 02-09. 网关登录校验 - OpenFeign 传递用户信息微服务 02-10. 配置管理 - 什么是配置管理微服务 02-11. 配置管理 - 共享配置问题:${hm.db.host:192.168.150.101}什么意思通过${hm.db.host:192.168.150.101}配置了默认值为192.168.150.101同时允许通过${hm.db.host}来覆盖默认值微服务 02-12. 配置管理 - 配置热更新问题:项目profile是什么?以及注解RefreshScopeprofile就是使用的环境变量是dev还是local微服务 02-13. 配置管理 - 动态路由 (拓展)问题:网关的路由配置全部是在项目启动时由org.springframework.cloud.gateway.route.CompositeRouteDefinitionLocator在项目启动的时候加载并且一经加载就会缓存到内存中的路由表内一个Map不会改变。也不会监听路由变更所以我们无法利用上节课学习的配置热更新来实现路由更新。因此我们必须监听Nacos的配置变更然后手动把最新的路由更新到路由表中。这里有两个难点如何监听Nacos配置变更如何把路由信息更新到路由表问题:PostConstruct注解的作用PostConstruct是 Spring Bean 生命周期的初始化回调注解用于在 Bean 完成依赖注入后、正式投入使用前执行自定义的初始化逻辑仅执行一次常用于配置加载、缓存预热等场景解决了构造方法中依赖未注入的空指针问题。Component public class AuthProperties { Autowired private JwtProperties jwtProperties; // 依赖注入 private String secret; // 构造方法执行时jwtProperties 还没注入不能用 public AuthProperties() { // System.out.println(jwtProperties.getSecret()); ❌ 空指针 } // PostConstruct 方法依赖注入完成后执行安全 PostConstruct public void init() { this.secret jwtProperties.getSecret(); // ✅ 正常获取不会空指针 System.out.println(AuthProperties 初始化完成密钥 secret); } }2. 方法要求必须是非静态方法必须无参数可以是private/public/protectedSpring 会通过反射调用只执行1 次Bean 单例默认多例则每次创建 Bean 执行 1 次问题:为什么要使用getConfigAndSignListener// 1.注册监听器并首次拉取配置 String configInfo nacosConfigManager.getConfigService() .getConfigAndSignListener(dataId, group, 5000, new Listener() {**getConfigAndSignListener 一次性做两件事首次立刻拉取配置马上拿到值注册监听器以后 Nacos 改配置自动通知更新**为什么首次要立刻拉去配置问题:解释下图用法末尾页详情请看⁠‌​​​​​​‬​​‌‌​‍​​​​‍‬​⁠​​​​⁠​‌‌​‬‍​​⁠​​‍​​‍​​​day04-微服务02 - 飞书云文档

更多文章