gateway介绍
This project provides an API Gateway built on top of the Spring Ecosystem, including: Spring 5, Spring Boot 2 and Project Reactor. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.
Spring Cloud Gateway 基于Spring Boot 2.x、Spring WebFlux和Project Reactor构建。因此,当您使用 Spring Cloud Gateway 时,您所知道的许多熟悉的同步库(例如 Spring Data 和 Spring Security)和模式可能不适用。如果您不熟悉这些项目,我们建议您在使用 Spring Cloud Gateway 之前先阅读他们的文档以熟悉一些新概念。
Spring Cloud Gateway requires the Netty runtime provided by Spring Boot and Spring Webflux. It does not work in a traditional Servlet Container or when built as a WAR.
gateway项目搭建
pom.xml
<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>
启动类添加@EnableEurekaClient注解
yaml文件
spring:
cloud:
gateway:
routes:
- id: payment-service_route
uri: lb://PAYMENT-SERVICE
predicates:
- Path=/payment/**
- After=2021-06-11T21:12:31.512+08:00[Asia/Shanghai]
discovery:
locator:
enabled: true
启动类添加@EnableEurekaClient注解
自定义过滤器
需要实现GlobalFilter,Ordered接口,order是过滤器优先级,在filter方法中可以通过ServerWebExchange对象获取request、response等。
@Component
@Slf4j
public class GatewayLogFilter implements GlobalFilter,Ordered {
/**
* 过滤器优先级,越小的优先级越高
* @return
*/
@Override
public int getOrder() {
return 0;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("************进入过滤器GatewayLogFilter,时间:{}", new Date());
List<String> uname = exchange.getRequest().getQueryParams().get("uname");
if (uname == null || uname.size() == 0){
log.info("************用户名为null,非法用户");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
}
需要注意的知识点
开启路由规则需要设置spring.cloud.gateway.discovery.locator.enabled=true
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#configuring-predicates-and-filters-for-discoveryclient-routes
官网关于predicates如何配置描述文档:
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-before-route-predicate-factory
文档中提到的ZonedDateTime使用方式如下(将输出的字符串替换样例里的时间即可):
@Test
public void getDate(){
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now);
}
官网filters介绍
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#global-filters
学习过程中遇到的问题
报错一
Description:
Binding to target [Bindable@77a86528 type = java.util.List<org.springframework.cloud.gateway.handler.predicate.PredicateDefinition>, value = 'provided', annotations = array<Annotation>[@javax.validation.constraints.NotEmpty(message={javax.validation.constraints.NotEmpty.message}, groups=[], payload=[]), @javax.validation.Valid()]] failed:
Property: spring.cloud.gateway.routes[0].predicates[0].path
Value: /payment/**
Origin: class path resource [application.yaml]:21:21
Reason: The elements [spring.cloud.gateway.routes[0].predicates[0].path] were left unbound.
Action:
Update your application's configuration
原因是predicates.path的值配置时写的是冒号,这里要用=
报错二
reactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.IllegalArgumentException: Unable to find RoutePredicateFactory with name path
Caused by: java.lang.IllegalArgumentException: Unable to find RoutePredicateFactory with name path
原因是predicates.path中的path首字母需要大写,修改为predicates.Path启动成功