<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.yzm</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>gateway-filter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>gateway-filter</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
@EnableEurekaClient
@SpringBootApplication
public class GatewayFilterApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayFilterApplication.class, args);
}
}
server:
port: 8025
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8088/eureka/
spring:
application:
name: gateway-filter
cloud:
gateway:
discovery:
locator:
enabled: true
lowerCaseServiceId: true
spring:
cloud:
gateway:
routes:
- id: addrh_test
uri: http://httpbin.org:80
predicates:
- Path=/get
filters:
- AddRequestHeader=X-Request-Foo, Req
请求:localhost:8025/get,经网关后会额外添加X-Request-Foo:Req键值对的请求头信息再转发到下游服务器
filters:
- AddRequestHeader=X-Request-Foo, Req
- RemoveRequestHeader=User-Agent
filters:
- SetRequestHeader=X-Request-Foo, Req
- SetRequestHeader=X-Forwarded-Host, location:test
filters:
- AddRequestParameter=age, 22
filters:
- RemoveRequestParameter=age
filters:
- AddRequestHeader=X-Request-Foo, Req
- AddResponseHeader=X-Response-Foo, Res
filters:
- RemoveResponseHeader=X-Response-Foo, Res
filters:
- SetResponseHeader=X-Response-Foo, Res
filters:
- SetStatus=401
routes:
- id: strp_test
uri: http://httpbin.org:80
predicates:
- Path=/a/b/get
filters:
- StripPrefix=2
routes:
- id: prep_test
uri: http://httpbin.org:80
predicates:
- Path=/utf8
filters:
- PrefixPath=/encoding
routes:
- id: redirect_test
uri: http://httpbin.org:80
filters:
- RedirectTo=302, https://www.baidu.com
第一个参数是status,必须是300系列的重定向 HTTP 代码
第二个参数是url,跳转地址,会放在响应的Location的header中
routes:
- id: rewp_test
uri: http://httpbin.org:80
predicates:
- Path=/yzm/**
filters:
- RewritePath=/yzm/?(?.*), /$\{segment}
routes:
- id: setp_test
uri: http://httpbin.org:80
predicates:
- Path=/y/zm/{segment}
filters:
- SetPath=/{segment}
routes:
- id: request_size_route
uri: http://localhost:8080/upload
predicates:
- Path=/upload
filters:
- name: RequestSize
args:
maxSize: 5000000
maxSize是一种DataSize类型,因此可以将值定义为一个数字,后跟一个可选的DataUnit后缀,例如“KB”或“MB”。字节的默认值为“B”,大小为 5 MB。
自定义过滤器需要实现 GatewayFilter 和 Ordered 接口。
该过滤器:计算请求过程消耗的时间
@Slf4j
public class MyGatewayFilter implements GatewayFilter, Ordered {
private static final String TIME_BEGIN = "timeBegin";
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//请求执行前
exchange.getAttributes().put(TIME_BEGIN, System.currentTimeMillis());
//请求执行后
return chain.filter(exchange).then(
Mono.fromRunnable(() -> {
Long startTime = exchange.getAttribute(TIME_BEGIN);
if (startTime != null) {
log.info(exchange.getRequest().getURI().getRawPath() + ": "
+ (System.currentTimeMillis() - startTime) + "ms");
}
})
);
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}
通过java代码制定路由规则
@Configuration
public class RouteConfig {
@Bean
public RouteLocator customerRouteLocator(RouteLocatorBuilder builder) {
return builder.routes()
.route(r -> r
.path("/get")
.filters(f -> f
.filter(new MyGatewayFilter())
.addRequestHeader("addRequest", "yzm")
.addResponseHeader("addResponse", "yzm"))
.uri("http://httpbin.org:80")
.id("myFilterTest")
)
.build();
}
}
package com.yzm.gatewayfilter.filter;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.core.style.ToStringCreator;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
/**
* 自定义过滤器工厂
*/
@Slf4j
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.NameConfig> {
private static final String TIME_BEGIN = "timeBegin";
private static final String KEY = "withParams";
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(KEY);
}
public MyGatewayFilterFactory() {
super(NameConfig.class);
}
@Override
public GatewayFilter apply(NameConfig config) {
return (exchange, chain) -> {
exchange.getAttributes().put(TIME_BEGIN, System.currentTimeMillis());
return chain.filter(exchange).then(
Mono.fromRunnable(() -> {
Long startTime = exchange.getAttribute(TIME_BEGIN);
if (startTime != null) {
StringBuilder sb = new StringBuilder(exchange.getRequest().getURI().getRawPath())
.append(": ")
.append(System.currentTimeMillis() - startTime)
.append("ms");
if (config.isWithParams()) {
sb.append(" params:").append(exchange.getRequest().getQueryParams());
}
log.info(sb.toString());
}
})
);
};
}
@Data
static class NameConfig {
private boolean withParams;
boolean isWithParams() {
return withParams;
}
}
public static class NameValueConfig {
private String name;
private String value;
public NameValueConfig() {
}
public String getName() {
return this.name;
}
public MyGatewayFilterFactory.NameValueConfig setName(String name) {
this.name = name;
return this;
}
public String getValue() {
return this.value;
}
public MyGatewayFilterFactory.NameValueConfig setValue(String value) {
this.value = value;
return this;
}
public String toString() {
return (new ToStringCreator(this)).append("name", this.name).append("value", this.value).toString();
}
}
}
spring:
application:
name: gateway-filter
cloud:
gateway:
discovery:
locator:
enabled: true
lowerCaseServiceId: true
routes:
- id: myFactory_test
uri: http://httpbin.org:80
predicates:
- Path=/factory/get
filters:
- StripPrefix=1
- AddRequestHeader=X-Request, Yzm
# MyGatewayFilterFactory 过滤器工厂不需要写全名,前缀即可
- My=false
上面的配置方式是对单一路由规则起效,下面的配置可以对所有路由有效
spring:
application:
name: gateway-filter
cloud:
gateway:
discovery:
locator:
enabled: true
lowerCaseServiceId: true
default-filters:
- My=false
routes:
- id: myFactory_test
uri: http://httpbin.org:80
predicates:
- Path=/factory/get
filters:
- StripPrefix=1
- AddRequestHeader=X-Request, Yzm
# - My=false
全局过滤器需要实现GlobalFilter接口。
该过滤器:要求访问必须携带请求参数token
package com.yzm.gatewayfilter.filter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* 自定义全局过滤器
* 测试:请求接口时需要带有 token 参数
*/
@Component
public class MyTokenFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getQueryParams().getFirst("token");
if (token == null || token.isEmpty()) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -100;
}
}
spring:
application:
name: gateway-filter
cloud:
gateway:
discovery:
locator:
enabled: true
lowerCaseServiceId: true
default-filters:
- My=true
routes:
- id: myFactory_test
uri: http://httpbin.org:80
predicates:
- Path=/factory/get
filters:
- StripPrefix=1
- AddRequestHeader=X-Request, Yzm
# - My=false
首页
上一篇:Gateway路由、断言
下一篇:Gateway熔断、限流