SpringCloud_day04

目录

[微服务 02-01. 什么是网关](#微服务 02-01. 什么是网关)

[微服务 02-02. 网关路由 - 快速入门](#微服务 02-02. 网关路由 - 快速入门)

[微服务 02-03. 网关路由 - 路由属性](#微服务 02-03. 网关路由 - 路由属性)

问题:路由断言和路由过滤器有什么区别?

[微服务 02-04. 网关登录校验 - 思路分析](#微服务 02-04. 网关登录校验 - 思路分析)

[微服务 02-05. 网关登录校验 - 自定义 GlobalFilter](#微服务 02-05. 网关登录校验 - 自定义 GlobalFilter)

问题:为什么要将这个过滤器优先级设置为最高(0)?

[微服务 02-06. 网关登录校验 - 自定义 GatewayFilter](#微服务 02-06. 网关登录校验 - 自定义 GatewayFilter)

问题:gatewayFilter和globalFilter有什么区别?

[微服务 02-07. 网关登录校验 - 实现登录校验](#微服务 02-07. 网关登录校验 - 实现登录校验)

问题:解释下面代码?

[问题@EnableConfigurationProperties(AuthProperties.class) 为什么要加AuthProperties.class?](#问题@EnableConfigurationProperties(AuthProperties.class) 为什么要加AuthProperties.class?)

问题:Mono是什么类型

[问题: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/false GatewayFilter / GlobalFilter 链式处理器,无返回值
执行时机 路由匹配阶段(请求进入网关后,转发前的第一步) 路由匹配成功后 ,分 pre(转发前)和 post(响应返回后)两个阶段执行
核心目标 精准匹配请求,将请求路由到正确的后端服务 对请求 / 响应做修改、增强、管控,实现通用逻辑复用

微服务 02-04. 网关登录校验 - 思路分析

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

问题:为什么要将这个过滤器优先级设置为最高(0)?

只要保证比NettyRoutingFilter的过滤器优先级(2147483647)高即可,因为这个是

最终请求转发是有一个名为NettyRoutingFilter的过滤器来执行的,而且这个过滤器是整个过滤器链中顺序最靠后的一个。如果我们能够定义一个过滤器,在其中实现登录校验逻辑,并且将过滤器执行顺序定义到 NettyRoutingFilter 之前,这就符合我们的需求了!

微服务 02-06. 网关登录校验 - 自定义 GatewayFilter

问题:gatewayFilter和globalFilter有什么区别?

  • GlobalFilter = 全局门禁,所有请求都要过
  • GatewayFilter = 专属门禁,只给指定路由用

微服务 02-07. 网关登录校验 - 实现登录校验

网关登录校验代码:

java 复制代码
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 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;
    }
}

问题:解释下面代码?

java 复制代码
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/login true
/user/** /user/info true
/user/** /cart/list false
/item/* /item/100 true

问题@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 会做三件事:

  1. 扫描并实例化 AuthProperties
  2. 从 yml 读取 hm.auth.xxx 配置,自动绑定到字段
  3. 把它放进 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 = 一次性做两件事:

  1. 首次立刻拉取配置(马上拿到值)
  2. 注册监听器(以后 Nacos 改配置,自动通知更新)**

为什么首次要立刻拉去配置?

问题:解释下图用法?

末尾页

详情请看⁠‌​​​​​​‬​​‌‌​‍​​​​‍‬​⁠​​​​⁠​‌‌​‬‍​​⁠​​‍​​‍​​​day04-微服务02 - 飞书云文档

相关推荐
Ken_11152 小时前
SpringCloud系列(58)--将服务消费者注册进Nacos
spring cloud
chools2 小时前
Java后端拥抱AI开发之个人学习路线 - - Spring AI【第三期】(向量数据库 + RAG检索增强生成)
java·人工智能·学习·spring·ai
小信丶3 小时前
Spring MVC @SessionAttributes 注解详解:用法、场景与实战示例
java·spring boot·后端·spring·mvc
盐城吊霸天3 小时前
Spring AI + Flux/FluxSink + SSE 实战技术笔记
人工智能·笔记·spring
爱丽_4 小时前
Redis 持久化与高可用:RDB/AOF、主从复制、哨兵与一致性取舍
java·后端·spring
盐水冰4 小时前
【烘焙坊项目】补充完善(1)- SpringAI大模型接入
java·后端·大模型
softshow10264 小时前
SpringCloud Redis与分布式
redis·分布式·spring cloud
yuanlaile4 小时前
Go语言(Golang)2026年3月整理经典面试常见问题面试题汇总,建议收藏
后端·golang·go语言面试题·golang后端开发·2026golang面试
蜜獾云4 小时前
Spring Cloud微服务如何设计异常处理机制
spring·spring cloud·微服务