微服务
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、传递用户信息-用户信息写入请求头
网关传递用户

步骤: