目录
[微服务 02-01. 什么是网关](#微服务 02-01. 什么是网关)
[微服务 02-02. 网关路由 - 快速入门](#微服务 02-02. 网关路由 - 快速入门)
[微服务 02-03. 网关路由 - 路由属性](#微服务 02-03. 网关路由 - 路由属性)
[微服务 02-04. 网关登录校验 - 思路分析](#微服务 02-04. 网关登录校验 - 思路分析)
[微服务 02-05. 网关登录校验 - 自定义 GlobalFilter](#微服务 02-05. 网关登录校验 - 自定义 GlobalFilter)
[微服务 02-06. 网关登录校验 - 自定义 GatewayFilter](#微服务 02-06. 网关登录校验 - 自定义 GatewayFilter)
问题:gatewayFilter和globalFilter有什么区别?
[微服务 02-07. 网关登录校验 - 实现登录校验](#微服务 02-07. 网关登录校验 - 实现登录校验)
[问题@EnableConfigurationProperties(AuthProperties.class) 为什么要加AuthProperties.class?](#问题@EnableConfigurationProperties(AuthProperties.class) 为什么要加AuthProperties.class?)
[问题:ServerWebExchange exchange这个是什么](#问题:ServerWebExchange exchange这个是什么)
[微服务 02-08. 网关登录校验 - 网关传递用户到微服务](#微服务 02-08. 网关登录校验 - 网关传递用户到微服务)
问题:@ConditionalOnClass(DispatcherServlet.class)这个注解的作用?
问题:@Configuration和@component区别?
问题:怎么让某个配置类只在springmvc生效而不在gateway生效?
[微服务 02-09. 网关登录校验 - OpenFeign 传递用户信息](#微服务 02-09. 网关登录校验 - OpenFeign 传递用户信息)
[微服务 02-10. 配置管理 - 什么是配置管理](#微服务 02-10. 配置管理 - 什么是配置管理)
[微服务 02-11. 配置管理 - 共享配置](#微服务 02-11. 配置管理 - 共享配置)
[微服务 02-12. 配置管理 - 配置热更新](#微服务 02-12. 配置管理 - 配置热更新)
[微服务 02-13. 配置管理 - 动态路由 (拓展)](#微服务 02-13. 配置管理 - 动态路由 (拓展))
微服务 02-01. 什么是网关


微服务 02-02. 网关路由 - 快速入门


微服务 02-03. 网关路由 - 路由属性



问题:路由断言和路由过滤器有什么区别?
特性 路由断言(Route Predicate) 路由过滤器(Route Filter) 核心作用 路由匹配判断:决定「请求是否走这条路由」 请求 / 响应增强:决定「请求怎么转发、怎么处理」 本质 Java 8 Predicate<ServerWebExchange>函数式接口,返回true/falseGatewayFilter/GlobalFilter链式处理器,无返回值执行时机 路由匹配阶段(请求进入网关后,转发前的第一步) 路由匹配成功后 ,分 pre(转发前)和post(响应返回后)两个阶段执行核心目标 精准匹配请求,将请求路由到正确的后端服务 对请求 / 响应做修改、增强、管控,实现通用逻辑复用
微服务 02-04. 网关登录校验 - 思路分析




微服务 02-05. 网关登录校验 - 自定义 GlobalFilter



问题:为什么要将这个过滤器优先级设置为最高(0)?
只要保证比
NettyRoutingFilter的过滤器优先级(2147483647)高即可,因为这个是最终请求转发是有一个名为
NettyRoutingFilter的过滤器来执行的,而且这个过滤器是整个过滤器链中顺序最靠后的一个。如果我们能够定义一个过滤器,在其中实现登录校验逻辑,并且将过滤器执行顺序定义到NettyRoutingFilter之前,这就符合我们的需求了!
微服务 02-06. 网关登录校验 - 自定义 GatewayFilter



问题:gatewayFilter和globalFilter有什么区别?
- GlobalFilter = 全局门禁,所有请求都要过
- GatewayFilter = 专属门禁,只给指定路由用
微服务 02-07. 网关登录校验 - 实现登录校验
网关登录校验代码:
javapackage 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 Mono<Void> 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; List<String> 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; } }
问题:解释下面代码?
javajava 运行 // 判断当前路径是否在【放行列表】里 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 List<String> 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是什么?以及注解@RefreshScope?
profile就是使用的环境变量是dev还是local

微服务 02-13. 配置管理 - 动态路由 (拓展)
问题:
网关的路由配置全部是在项目启动时由org.springframework.cloud.gateway.route.CompositeRouteDefinitionLocator在项目启动的时候加载,并且一经加载就会缓存到内存中的路由表内(一个Map),不会改变。也不会监听路由变更,所以,我们无法利用上节课学习的配置热更新来实现路由更新。
因此,我们必须监听Nacos的配置变更,然后手动把最新的路由更新到路由表中。这里有两个难点:
如何监听Nacos配置变更?
如何把路由信息更新到路由表?


问题:@PostConstruct注解的作用?
@PostConstruct是 Spring Bean 生命周期的初始化回调注解,用于在 Bean 完成依赖注入后、正式投入使用前,执行自定义的初始化逻辑,仅执行一次,常用于配置加载、缓存预热等场景,解决了构造方法中依赖未注入的空指针问题。
java@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/protected(Spring 会通过反射调用)- 只执行 1 次(Bean 单例默认,多例则每次创建 Bean 执行 1 次)
问题:为什么要使用getConfigAndSignListener
// 1.注册监听器并首次拉取配置 String configInfo = nacosConfigManager.getConfigService() .getConfigAndSignListener(dataId, group, 5000, new Listener() {**
getConfigAndSignListener= 一次性做两件事:
- 首次立刻拉取配置(马上拿到值)
- 注册监听器(以后 Nacos 改配置,自动通知更新)**
为什么首次要立刻拉去配置?


问题:解释下图用法?
末尾页
详情请看day04-微服务02 - 飞书云文档










