IT自学第四十二天

微服务


0、作业-交易微服务

步骤

  • 复制配置文件,修改文件内的名称
  • 复制依赖路径,
  • 利用代码生成器,生成框架
  • 复制所有代码
  • 修改引用了包
  • 调用其他方法的,改为client调用,把方法抽离出来

0、作业-用户微服务

  • 依赖
  • 配置文件
  • 数据库
  • 启动引导类
  • 复制业务代码

注意:添加nacos注册依赖

XML 复制代码
<!--nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

0、作业-支付微服务

注意:利用client修改单体项目时,调用的其实是另一个项目的controller方法,而之前单体项目调用的是service方法,因此需要改造。


1、网关Gateway-快速入门

网关

用户多系统免密登录。

路由转发、身份效验。

网关:就是网络的关口,负责请求的路由、转发、身份效验。

在SpringCloud中网关的实现包括两种:(Gateway新品)

步骤

创建新模板;引入网关依赖、编写启动类、配置路由规则。

路由配置规则:

引入网关依赖:

XML 复制代码
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

配置文件:

XML 复制代码
server:
  port: 8080
spring:
  application:
    name: hm-gateway
  cloud:
    nacos:
      server-addr: 192.168.45.129:8848
    gateway:
      routes:
        - id: cart
          uri: lb://cart-service
          predicates:
            - Path=/carts/**
        - id: item
          uri: lb://item-service
          predicates:
            - Path=/items/**,/search/**
        - id: user
          uri: lb://user-service
          predicates:
            - Path=/users/**
        - id: trade
          uri: lb://trade-service
          predicates:
            - Path=/orders/**
        - id: pay
          uri: lb://pay-service
          predicates:
            - Path=/pay-orders/**

2、网关路由属性

路由属性

网关路由对应的Java类型是RouteDefinition,其中常见的属性有:

  • id:路由唯一标示
  • uri:路由目标地址
  • predicates:路由断言,判断请求是否符合当前路由;
  • filters:路由过滤器,对请求或响应做特殊处理。

路由断言

Spring提供了12种基本的RoutePredicateFactory实现:(常见method,path)

路由过滤器

网关中提供了33种路由过滤器,每种过滤器都有独特的作用。

添加路由过滤器,去除/api前缀

XML 复制代码
        - id: item
          uri: lb://item-service
          predicates:
            - Path=/api/items/**,/search/**
            - Method=GET,POST
          filters:
            - StripPrefix=1 #  路由到后端的时候要去掉前缀 去掉api

3、网关请求处理流程

网管请求处理流程

网关登录效验

如何在网关转发之前做登录效验?

网关如何将用户信息传递给微服务?

如何在微服务之间传递用户信息?

4、全局过滤器

自定义过滤器

网关过滤器有两种,分别是:

  • GatewayFilter:路由过滤器,作用于任意指定的路由;默认不生效,要配置到路由后生效;
  • GlobalFilter:全局过滤器,作用范围是所有路由,声明后自动生效。

自定义过滤器GlobalFilter

自定义GlobalFilter比较简单,直接实现GlobalFilter接口即可:

代码演示:

java 复制代码
@Component
public class MyGlobalFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //获取请求对象
        ServerHttpRequest request = exchange.getRequest();
        System.out.println("执行了MyGlobalFilter  过滤器  pre...");
        return chain.filter(exchange).then(Mono.fromRunnable(() -> {
            System.out.println("执行了 MyGlobalFilter 过滤器 post...");
        }));
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

5、自定义过滤器

自定义过滤器GatewayFilter

自定义GatewayFilter不是直接实现GatewayFilter,而是实现AbstractGatewayFilterFactory,示例如下:

实现:

代码演示:

java 复制代码
@Component
public class PrintAnyGatewayFilterFactory extends AbstractGatewayFilterFactory<Object> {
    @Override
    public GatewayFilter apply(Object config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                System.out.println("执行了PrintAnyGatewayFilterFactory的gre......");
                return chain.filter(exchange);
            }
        };
    }
}

配置调用:

带参数过滤器:

代码演示:

java 复制代码
@Component
public class PrintAnyGatewayFilterFactory extends AbstractGatewayFilterFactory<PrintAnyGatewayFilterFactory.Config> {
    @Override
    public GatewayFilter apply(Config config) {
        return new OrderedGatewayFilter(new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                //接收来自配置文件中的参数
                String a = config.getA();
                System.out.println("a="+a);
                String b = config.getB();
                System.out.println("b="+ b);
                String c = config.getC();
                System.out.println("c="+c);

                return chain.filter(exchange);
            }
        },100);
    }

    //接收参数的静态内部类
    @Data
    public static class Config{
        private String a;
        private String b;
        private String c;
    }

    //配置接收来自配置文件中参数与上述属性对应的关系
    @Override
    public List<String> shortcutFieldOrder() {
        return List.of("a", "b", "c");
    }
    //将config传递给父类,接收配置文件的参数
    public PrintAnyGatewayFilterFactory(){
        super(Config.class);
    }
}

6、登录效验过滤器分析

案例:实现登录效验

需求:在网关中基于过滤器实现登录效验功能

实现登录效验

处理逻辑

7、登录效验过滤器实现

代码演示:

java 复制代码
@Component
@RequiredArgsConstructor
@EnableConfigurationProperties(AuthProperties.class)
public class AuthGlobalFilter implements GlobalFilter, Ordered {
    private final AuthProperties authProperties;
    private final JwtProperties jwtProperties;
    private final AntPathMatcher antPathMatcher = new AntPathMatcher();
    private final JwtTool jwtTool;
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //1、判断是否要进行登录请求
        ServerHttpRequest request = exchange.getRequest();
        // 不需要登录验证的方法就放行
        if(isExclude(request.getPath().toString())){
            return chain.filter(exchange);
        }
        //2、要登陆,获取请求头的属性authorization的值就是令牌
        String token = request.getHeaders().getFirst("authorization");
        try {
            Long userId = jwtTool.parseToken(token);
            //4、将用户信息传递给后端
            System.out.println("userId:"+userId);
        } catch (Exception e) {
            //效验不通过
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        return chain.filter(exchange);
    }

    private boolean isExclude(String path) {
        for(String excludePath : authProperties.getExcludePaths()){
            if(antPathMatcher.match(excludePath, path)){
                return true;
            }
        }
        return false;
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

登录效验不通过之后,报错401

8、传递用户信息-用户信息写入请求头

网关传递用户

步骤:

相关推荐
java1234_小锋1 小时前
说一下Spring的事务传播行为?
java·数据库·spring
庞轩px1 小时前
第四篇:SpringBoot自动配置——约定大于配置的底层原理
java·spring boot·后端·spring·自动配置·注解开发
不知名的忻1 小时前
Dijkstra算法(朴素版&堆优化版)
java·数据结构·算法··dijkstra算法
苏三说技术1 小时前
美团二面:高并发下如何保证接口幂等性?
java·数据库
兩尛1 小时前
c++知识点5
开发语言·c++
澈2071 小时前
C++内存管理:new/delete与内存泄漏实战
开发语言·c++·内存分区
其实防守也摸鱼1 小时前
VS code怎么使用 Conda 安装预编译包
开发语言·网络·c++·vscode·安全·web安全·conda
默子昂1 小时前
langchain 基本使用
开发语言·python·langchain
yaoxin5211231 小时前
402. Java 文件操作基础 - 读取二进制文件
java·开发语言·python