Gateway网关
1 .创建一个 api-gateway 的模块,导入相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shop-parent</artifactId>
<groupId>cn.wolfcode</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>api-gateway</artifactId>
<dependencies>
<!--gateway网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
2.编写启动类
@SpringBootApplication
@EnableDiscoveryClient
public class ApiGatewayServer {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayServer.class,args);
}
}
3.编写配置文件
server:
port: 9000
spring:
application:
name: api-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
enabled: true # 让gateway可以发现nacos中的微服务
4 .启动测试
http://localhost:9000/product-service/get?id=1
自定义路由规则
spring:
application:
gateway:
routes:
- id: product_route
uri: lb://product-service
predicates:
- Path=/product-serv/**
filters:
- StripPrefix=1
- id: order_route
uri: lb://order-service
predicates:
- Path=/order-serv/**
filters:
- StripPrefix=1
自定义路由测试
http://localhost:9000/product-serv/get?id=1
局部路由过滤器
局部过滤器是针对单个路由的过滤器,在SpringCloud Gateway中内置了很多不同类型的网关路由过滤器,有兴趣同学可以自行了解,这里太多了,我们就不一一讲解,我们主要来讲一下自定义路由过滤器。
需求: 统计订单服务调用耗时.
1.编写Filter类,注意名称是有固定格式xxxGatewayFilterFactory
@Component
public class TimeGatewayFilterFactory extends AbstractGatewayFilterFactory<TimeGatewayFilterFactory.Config>{
private static final String BEGIN_TIME = "beginTime";
//构造函数
public TimeGatewayFilterFactory() {
super(TimeGatewayFilterFactory.Config.class);
}
//读取配置文件中的参数 赋值到 配置类中
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("show");
}
@Override
public GatewayFilter apply(Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if(!config.show){
return chain.filter(exchange);
}
exchange.getAttributes().put(BEGIN_TIME, System.currentTimeMillis());
/**
* pre的逻辑
* chain.filter().then(Mono.fromRunable(()->{
* post的逻辑
* }))
*/
return chain.filter(exchange).then(Mono.fromRunnable(()->{
Long startTime = exchange.getAttribute(BEGIN_TIME);
if (startTime != null) {
System.out.println(exchange.getRequest().getURI() + "请求耗时: " + (System.currentTimeMillis() - startTime) + "ms");
}
}));
}
};
}
@Setter@Getter
static class Config{
private boolean show;
}
}
- 在指定的路由中添加路由规则
server:
port: 9000
spring:
application:
name: api-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
enabled: true
routes:
- id: product_route
uri: lb://product-service
predicates:
- Path=/product-serv/**
filters:
- StripPrefix=1
- id: order_route
uri: lb://order-service
predicates:
- Path=/order-serv/**
filters:
- StripPrefix=1
- Time=true #这里配置局部路由规则
全局路由过滤器
全局过滤器作用于所有路由, 无需配置。通过全局过滤器可以实现对权限的统一校验,安全性验证等功能
SpringCloud Gateway内部也是通过一系列的内置全局过滤器对整个路由转发进行处理如下:
需求: 实现统一鉴权的功能,我们需要在网关判断请求中是否包含token且,如果没有则不转发路由,有则执行正常逻辑。
1编写全局过滤类
@Component
public class AuthGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("前置逻辑");
/**
* 登录鉴权 :判断是否有携带一个token的参数 如果这个参数不为空并且这个参数的值为123
* 那么就表示登录过了,否则就进行拦截操作
*
*
*/
String token = exchange.getRequest().getQueryParams().getFirst("token");
String app = exchange.getRequest().getQueryParams().getFirst("app");
if (StringUtils.isEmpty(token) || !"123".equals(token)){
//进行拦截操作 401
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange).then(Mono.fromRunnable(new Runnable() {
@Override
public void run() {
System.out.println("后置逻辑");
}
}));
}
}
2 .启动测试
http://localhost:9000/product-serv/get?id=1&token=123&app=123