Spring Cloud Gateway新一代网关(下篇)
1.Predicate的使用
1.1是什么
启动网关服务,查看控制台
1.2Route Predicate Factories这个是什么
1.3常用的Route Predicate
1.3.1After Route Predicate
根据配置时间来匹配路由
以下配置为,请求时间在指定时间点之后可以用
上面yaml中配置的时间戳,是默认时区时间戳。
public static void main(String[] args) {
ZonedDateTime now = ZonedDateTime.now();
System.out.println(now);//2020-09-02T19:46:53.590+08:00[Asia/Shanghai]
}
- After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
1.3.2Before Route Predicate
以下配置为,请求时间在指定时间点之前可用
Before=2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
1.3.3.Between Route Predicate
以下配置为,请求时间在指定时间之间可用
- Between=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] , 2020-03-08T10:59:34.102+08:00[Asia/Shanghai]
1.3.4.Cookie Route Predicate
- Cookie==chocolate,mic
以上配置的意思是,当前请求需要携带一个name=chocolate,并且value需要正则表达式匹配mic,才能路由到指定的uri上。
1.3.5. Header Route Predicate
无Header请求:
### 查询
GET http://localhost:8084/payment/get/2
Accept: application/json
响应404:
{
"timestamp": "2020-09-03T01:43:53.306+0000",
"path": "/payment/get/2",
"status": 404,
"error": "Not Found",
"message": null,
"requestId": "692024c2"
}
加上Header请求:
### 查询
GET http://localhost:8084/payment/get/2
Accept: application/json
X-Request-ID: 112334
响应:
{
"code": 200,
"message": "查询成功,serverPort: 8086",
"data": {
"id": 2,
"serial": "22222"
}
}
1.3.6.Host Route Predicate
HTTP请求会携带一个Host字段,这个字段表示请求的服务器网址
无Host请求:
### 查询
GET http://localhost:8084/payment/get/2
Accept: application/json
响应404:
{
"timestamp": "2020-09-03T03:19:30.783+0000",
"path": "/payment/get/2",
"status": 404,
"error": "Not Found",
"message": null,
"requestId": "29a76d7b"
}
加上Host请求
### 查询
GET http://localhost:8084/payment/get/2
Accept: application/json
Host: 11.aa.com
响应:
{
"code": 200,
"message": "查询成功,serverPort: 8086",
"data": {
"id": 2,
"serial": "22222"
}
}
加上错误的Host,响应也是404
1.3.7 Method Route Predicate
根据HTTP请求的Method属性来匹配以实现路由
以上配置表示,如果HTTP请求的方法是GET或POST,都会路由到指定的uri上。
1.3.8.Path Route Predicate
请求路径匹配路由时比较常见的路由匹配规则
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Path=/foo/{ segment},/bar/{ segment}
如果请求路径为例如/foo/1或/foo/bar或/bar/baz,则此路由将匹配。
${segment}是比较特殊的占位符,/*表示单层路径匹配,/***表示多层路径匹配。
1.3.99. Query Route Predicate
Query=username, \d+ #要有参数名称并且是正整数才能路由
1.4小总结
说白了,Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理
2.Filter的使用
2.1是什么
2.2Spring Cloud Gateway的Filter
2.2.1生命周期
只有两种
pre:在业务逻辑之前
post:在业务逻辑之后
2.2.2种类
只有两种
单一:GatewayFilter
全局:GlobalFilter
路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。 路由过滤器适用于特定路由。 Spring Cloud Gateway包括许多内置的GatewayFilter工厂。
AddRequestHeader GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Request-Foo, Bar
这会将X-Request-Foo:Bar标头添加到所有匹配请求的下游请求标头中。
AddRequestHeader知道用于匹配路径或主机的URI变量。 URI变量可用于该值,并将在运行时扩展。
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
predicates:
- Path=/foo/{ segment}
filters:
- AddRequestHeader=X-Request-Foo, Bar-{ segment}
AddRequestParameter GatewayFilter Factory
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
filters:
- AddRequestParameter=foo, bar
这会将foo = bar添加到所有匹配请求的下游请求的查询字符串中。
配置
下游controller
@RequestMapping(value = "/v2/payment/test")
public CommonResult<Payment> getPaymentTestById(@RequestHeader("XRequestID") Integer XRequestID,String queryParams) {
return new CommonResult(200, "查询成功,serverPort: " + serverPort, XRequestID+":"+queryParams);
}
测试:
### 查询
GET http://localhost:8084/v2/payment/test
Accept: application/json
结果:
{
"code": 200,
"message": "查询成功,serverPort: 8086",
"data": "1234:sasaas"
}
AddResponseHeader GatewayFilter Factory
这会将X-Response-Foo:Bar标头添加到所有匹配请求的下游响应标头中。
2.3自定义过滤器,自定义全局GlobalFilter
2.3.1两个主要接口介绍
impiemerts GlobalFilter ,Ordered
2.3.2能干什么
- 全局日志记录
- 统一网关鉴权
- 等等
2.3.3代码案例
当请求进入(并与路由匹配时,过滤Web处理程序会将GlobalFilter的所有实例和GatewayFilter的所有特定于路由的实例添加到过滤器链中。 该组合的过滤器链由org.springframework.core.Ordered接口排序,可以通过实现getOrder()方法进行设置。
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
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.HttpHeaders;
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.Flux;
import reactor.core.publisher.Mono;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;
/** * @author Created by niugang on 2020-09-04 10:15 */
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("*********come in MyLogGateWayFilter: " + LocalDateTime.now());
HttpHeaders headers = exchange.getRequest().getHeaders();
log.info("All headers:{}", headers);
List<String> ticket = headers.get("ticket");
if (ticket == null || ticket.isEmpty()) {
log.info("*****用户名为Null 非法用户,(┬_┬)");
//给人家一个回应
ServerHttpResponse originalResponse = exchange.getResponse();
originalResponse.getHeaders().set("Content-Type","application/json;charset=UTF-8");
originalResponse.setStatusCode(HttpStatus.UNAUTHORIZED);
JSONObject jsonObject = new JSONObject();
jsonObject.put("timestamp",System.currentTimeMillis());
jsonObject.put("status",HttpStatus.UNAUTHORIZED.value());
jsonObject.put("reason","未授权,请先登陆");
DataBuffer buffer = originalResponse.bufferFactory().wrap(jsonObject.toJSONString().getBytes(StandardCharsets.UTF_8));
return exchange.getResponse().writeWith(Flux.just(buffer));
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
访问:
### 查询
GET http://localhost:8084/v2/payment/test
Accept: application/json
响应:
增加ticket:
### 查询
GET http://localhost:8084/v2/payment/test
Accept: application/json
ticket: 1234445
还没有评论,来说两句吧...