SpringCloud gateway
一、服务搭建
1.1 Eureka-server
新建Eureka-service模块
引入依赖、添加配置
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--为服务注册中心引入 Eureka Server 的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--devtools 和 lombok 均为开发辅助模块,根据需求适当选择-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
server:
port: 9000 #该 Module 的端口号
eureka:
instance:
hostname: localhost #eureka服务端的实例名称,
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #单机版服务注册中心
启动成功后访问http://localhost:9000/eureka/
1.2 gateway-server
新建gateway-server模块
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
将gateway服务注册到Eureka
server:
port: 8080
spring:
application:
name: space-gateway
eureka:
instance:
prefer-ip-address: true #是否使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #ip:port
client:
service-url:
defaultZone: http://localhost:9000/eureka/
二、服务路由
只记录了两种路由方式
2.1 ip路由
修改yml文件
spring:
application:
name: space-gateway
cloud:
gateway:
routes:
- id: space-uploadfile # 路由ID 唯一
uri: http://localhost:8081/ # 目标URI,路由到微服务的地址
#路由规则
predicates: # 断言(判断条件)
- Path=/uploadFile/** #匹配对应URL的请求,将匹配到的请求追加到目标URL之后
#- Query=token, gzs. #匹配请求参数中包含token,并且其参数值满足gzs. 的请求
#- Method=GET #匹配任意GET请求
#- After=2022-05-14T20:00:00.000+08:00[Asia/Shanghai] #匹配中国上海地区2022-05-14 20:00:00之后的请求
#- RemoteAddr=xx.xx.xx.xx/0 #只能xx.xx.xx.xx的ip才可以请求,/0是子网掩码
#- Header=token, \d+ #表示匹配请求头中的token,/d+ 是正则表达式,表示匹配数字
- id: space-auth
uri: http://localhost:8082/
predicates:
- Path=/auth/**
2.2 动态路由
这种方式的好处就是不用跟着ip的修改来变动,将服务注册到eureka,根据服务名称到eureka获取服务的ip:port,微服务的ip端口再怎么变化,我们也无需更改,只要服务名称对的上
修改yml文件
spring:
application:
name: space-gateway
cloud:
gateway:
routes:
- id: space-uploadfile
uri: lb://space-uploadfile #根据服务名称从注册中心获取服务请求地址
predicates:
- Path=/uploadFile/**
- id: space-auth
uri: lb://space-auth
predicates:
- Path=/auth/**
以上两种选择一种即可
配置完成之后访问只需请求gateway服务即可,会根据路由规则- Path=/auth/**,将/auth/匹配追加到uri: http://localhost:8082/之后
三、过滤器
package com.gzs.space.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* @author GZS
* @date 2022年05月14日
* 权限验证过滤器
*/
@Component
public class AccessFilter implements GlobalFilter, Ordered {
private Logger log = LoggerFactory.getLogger(AccessFilter.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//获取请求头中的token
//getFirst()并不是获取第一个,不管是第几个都用getFirst()
String token = exchange.getRequest().getHeaders().getFirst("token");
if (token == null){
log.warn("token is null...");
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().add("Content-Type","application/json;charset=utf-8");
response.setStatusCode(HttpStatus.UNAUTHORIZED);
String message = "{\"message\":\"" + HttpStatus.UNAUTHORIZED.getReasonPhrase() + "\"}";
DataBuffer buffer = response.bufferFactory().wrap(message.getBytes());
//返回错误信息
return response.writeWith(Mono.just(buffer));
}
log.info("token is ok...");
//通过放行
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}