SpringCloud:Spring Cloud Gateway中如何定制filter实现自定义路由
Spring Cloud Gateway中定制filter实现动态路由
·
Spring Cloud Gateway中提供的默认filter有时不能满足实际的业务需求,因此很多时候需要使用定制的filter。
在Spring Cloud Gateway中,predicate用于定义请求需要满足什么条件才能对它继续进行处理,filter用于定义对请求进行怎样的处理,uri用于定义处理后的请求要转发到什么地址。
filter执行的顺序是有优先级的,优先级越高则在pre阶段执行顺序越靠前,而在post阶段执行顺序越靠后。在Spring Cloud Gateway中会为每个filter设置一个order值,order值越大则优先级越低,order值起小优先级越高。
Spring Cloud Gateway中有两个非常重要的GlobalFilter:
filter名称 | 作用 | 优先级 |
RouteToRequestUrlFilter | 生成最终转发到的uri | 10000 |
NettyRoutingFilter | 转发报文 | Integer.MAX_VALUE |
例如要实现根据特定标识将请求转发到指定uri的功能,则定制的filter的优先级要在RouteToRequestUrlFilter和NettyRoutingFilter之间,下面提供一个例子:
pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<version>2.4.4</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
application.properties
server.port=8070
spring.application.name=gateway_server
# unit: ms
spring.cloud.gateway.httpclient.connect-timeout=10000
spring.cloud.gateway.httpclient.response-timeout=5s
java代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@SpringBootApplication
@EnableAutoConfiguration(exclude = { ErrorMvcAutoConfiguration.class })
public class SpringCloudGatewayApplication {
@Autowired
private CustomerFilter filter;
public static void main(String[] args) {
SpringApplication.run(SpringCloudGatewayApplication.class, args);
}
@Bean
public RouteLocator myRoutes(RouteLocatorBuilder builder) {
return builder.routes().route(p -> p.path("/**").filters(f -> f.filter(filter)).uri("no://op")).build();
}
}
import reactor.core.publisher.Mono;
@Component
public class CustomerFilter implements GatewayFilter, Ordered {
@Override
public int getOrder() {
return RouteToRequestUrlFilter.ROUTE_TO_URL_FILTER_ORDER + 1;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String newUrl = null;
String serviceName = "";
List<String> serviceHeaderList = exchange.getRequest().getHeaders().getValuesAsList("serviceName");
if (serviceHeaderList.contains("s1")) {
newUrl = "http://127.0.0.1:9090/TestWebApp/testServlet";
serviceName = "s1";
} else if (serviceHeaderList.contains("s2")) {
newUrl = "http://127.0.0.1:9090/TestWebApp/regionServlet?flag=list";
serviceName = "s2";
}
try {
exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, new URI(newUrl));
} catch (URISyntaxException e) {
e.printStackTrace();
}
Mono<Void> ret = chain.filter(exchange);
exchange.getResponse().getHeaders().add("doWork", serviceName + " ok");
return ret;
}
}
以上代码中可以看到,会根据请求头中serviceName对应的值转到不同的uri,同时把order的值设置成比RouteToRequestUrlFilter的order的值大1,这样CustomerFilter在pre阶段就会在RouteToRequestUrlFilter之后执行。
更多推荐
已为社区贡献8条内容
所有评论(0)