-
路由:是 Spring Cloud Gateway 中基础的组件,通常由一个 id 标识,目标 URI,以及一系列断言(Predicate)和过滤器组成。 -
断言(Predicate):是 Java 8 函数库的 Predicate 对象,具体类型为 Predicate<ServerWebExchange>
,用于匹配 HTTP 请求上数据信息,如请求头信息,请求体信息。如果对于某个请求的断言为 true,那么它所关联的路由就算匹配成功,然后将请求给这个路由处理。 -
过滤器:用于某一个路由的请求或者响应进行修改的组件,在 Spring Cloud Gateway 都要实现 GatewayFilter 接口,并且需要由基于 GatewayFilterFactory 具体实现类构造。
-
客户端请求首先被 GatewayHandlerMapping 获取,然后根据断言匹配找到对应的路由 -
找到路由后,走完所关联的一组请求过滤器的处理方法,请求到目标 URI 所对应的服务程序,获得服务响应。 -
网关收到响应后,通过关联的响应过滤器的处理方法后,同样由 GatewayHandlerMapping 返回响应给客户端。
如何实现 API 聚合
spring-cloud-gateway-quick-start
,并且为了实现请求的路由,表现网关的效果,再分别新建用户服务应用 demo-userservice
和订单服务应用 demo-orderservice
,各自提供一个可调用 API 接口。// demo-userservice 项目
@RestController
@RequestMapping("/user")
public class UserServiceController {
@RequestMapping("/get")
public User get() {
return User.mock();
}
}
// demo-orderservice 项目
@RestController
@RequestMapping("/order")
public class OrderServiceController {
@RequestMapping("/get")
public Order get() {
return Order.mock();
}
}
@SpringBootApplication
public class DemogatewayApplication {
public static void main(String[] args) {
SpringApplication.run(DemogatewayApplication.class, args);
}
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
return builder.routes().route("user-service", r -> r.path("/user/*").uri("http://localhost:8071"))
.route("order-service", r -> r.path("/order/*").uri("http://localhost:8061"))
.build();
}
}
spring-cloud-gateway-quick-start
项目中,首先来看下利用 Spring Cloud Gateway API 方式的实现:spring-cloud-gateway-quick-start
和其他服务应用,就可以统一通过网关应用访问用户服务和订单服务了:one@192 ~ % curl http://localhost:8080/user/get
{"id":4720186416534735290,"token":"86b6118d-7dc6-4d30-a5f3-3d5fc6348f9a"}
one@192 ~ % curl http://localhost:8080/order/get
{"id":5832646761962425508,"title":"My Order"}
DemogatewayApplication#customRouteLocator
方法中定义了两个 id 分别为 user-service 和 order-service 的路由,并且设置了匹配请求的断言,以及真正目标请求地址。这里路由的断言采用了路径匹配的规则,只要原始请求地址符合对应的规则就算匹配到此路由,但 Spring Cloud Gate 还支持丰富的断言规则,如主机匹配,请求体字段匹配,请求数据匹配等等,足以满足定制路由断言的规则了。spring.cloud.gateway.routes[0].id=order-service
spring.cloud.gateway.routes[0].uri=http://localhost:8061
spring.cloud.gateway.routes[0].predicates[0].name=Path
spring.cloud.gateway.routes[0].predicates[0].args[pattern]=/order/*
spring.cloud.gateway.routes[1].id=user-service
spring.cloud.gateway.routes[1].uri=http://localhost:8071
spring.cloud.gateway.routes[1].predicates[0].name=Path
spring.cloud.gateway.routes[1].predicates[0].args[pattern]=/user/*
如何自定义过滤器
-
ForwardRoutingFilter -
LoadBalancerClientFilter(弃用) -
ReactiveLoadBalancerClientFilter -
WebClientHttpRoutingFilter -
NettyWriteResponseFilter -
RouteToRequestUrlFilter -
WebsocketRoutingFilter -
GatewayMetricsFilter
@Component
public class CustomGlobalFilter implements GlobalFilter, Ordered {
private Logger log = LoggerFactory.getLogger(MyAuthFilterFactory.class);
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("执行自定过滤器");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}
@Component
public class MyAuthGatewayFilterFactory extends AbstractGatewayFilterFactory<MyAuthGatewayFilterFactory.Config> {
private Logger logger = LoggerFactory.getLogger(MyAuthGatewayFilterFactory.class);
public MyAuthGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> queryParams = request.getQueryParams();
String from = queryParams.getFirst(config.getAuthKey());
ServerHttpResponse response = exchange.getResponse();
logger.warn("校验授权开始");
if (config.getAuthValue().equals(from)) {
logger.warn("校验授权成功");
return chain.filter(exchange);
} else {
logger.warn("校验授权失败");
response.setStatusCode(HttpStatus.OK);
response.getHeaders().setContentType(MediaType.valueOf("text/html;charset=utf-8"));
DataBuffer wrap = response.bufferFactory().wrap(config.getAuthFailMsg().getBytes(Charset.forName("UTF-8")));
return response.writeWith(Flux.just(wrap));
}
}
};
}
public static class Config {
private String authKey = "from";
private String authValue = "system";
private String authFailMsg = "授权失败";
public String getAuthKey() {
return authKey;
}
public void setAuthKey(String authKey) {
this.authKey = authKey;
}
public String getAuthValue() {
return authValue;
}
public void setAuthValue(String authValue) {
this.authValue = authValue;
}
public String getAuthFailMsg() {
return authFailMsg;
}
public void setAuthFailMsg(String authFailMsg) {
this.authFailMsg = authFailMsg;
}
}
}
spring.cloud.gateway.routes[1].filters[0].name=MyAuth
java.lang.IllegalArgumentException: Unable to find GatewayFilterFactory with name MyAuth2
http://localhost:8080/user/get?from=system
方式访问才能成功获取到数据,说明定义的授权拦截器已经起了作用。未经允许不得转载:大自然的搬运工 » Spring Cloud Gateway 入门