Function:

The purpose of the Spring Cloud gateway is to provide a simple and efficient way to route apis and provide them with cross-domain concerns such as: security, monitoring/measurement, and resiliency.

Contrast:

The official contrast

Working principle:

The client makes a request to the Spring Cloud gateway. If the gateway handler map determines that the request matches the route, it is sent to the gateway Web handler. The handler runs to send requests through a chain of request-specific filters. The reason why filters are separated by dashed lines is that a filter can execute logic before or after sending a proxy request. Perform all the "pre-filter" logic, then issue the proxy request. After the broker request is issued, the "after" filter logic is executed.Copy the code

Introducing dependencies:

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
Copy the code

The configuration file

server: port: 8711 spring: application: name: gateway-service cloud: gateway: # discovery: # locator: If set to true, you can call the service directly using the application name. True # Routes: routes that consist of a unique ID, destination service address, predicates, and filters. Filters are not required. -id: client1-service = client1-service = client1-service = client1-service http://localhost:8702 # predicates: ## matching Path - Path=/client1/get/** # filters: # -stripprefix =1 # filter (filter: preferIpAddress: true) Gateway_service # registry to the right of the location of display client: serviceUrl: defaultZone: http://localhost:8701/eurekaCopy the code

Ps: other assertions can refer to the official document www.springcloud.cc/spring-clou…

Routing test:

Start the registry, Client1, and Gateway respectively

Custom filter

package org.example.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.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Component public class MyFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {system.out.println (" Enter custom filter "); Object object; String key = exchange.getRequest().getQueryParams().getFirst("id"); System.out.println(" pass: "+key); if(!" 123".equals(key)){ ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.NOT_ACCEPTABLE); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return 0; }}Copy the code

Testing:

Custom route assertion factory

package org.example.predicateFactory; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.apache.commons.lang.StringUtils; import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; /** * @author shock wave 2 * @version 1.0 * @description: TODO custom assertions factory needs to inherit AbstractRoutePredicateFactory rewrite the apply method * @ date 2021/6/30 as * / @ Component public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> { public MyRoutePredicateFactory() { super(Config.class); } @Override public Predicate<ServerWebExchange> apply(Config config) { return new Predicate<ServerWebExchange>() { @Override public boolean test(ServerWebExchange serverWebExchange) { String userName = serverWebExchange.getRequest().getQueryParams().getFirst("userName"); if(StringUtils.isBlank(userName)){ return false; If (userName. Equals (config.getName())){return true; } return false; }}; } @override public List<String> shortcutFieldOrder() {return array.aslist ("name"); } @Data public static class Config { private String name; }}Copy the code

Modify the yML file

server:
  port: 8711
spring:
  application:
    name: gateway-service
  cloud:
    gateway:
#      discovery:
#        locator:
#          # 是否和服务注册与发现组件结合,设置为 true 后可以直接使用应用名称调用服务
#          enabled: true
        # 路由(routes:路由,它由唯一标识(ID)、目标服务地址(uri)、一组断言(predicates)和一组过滤器组成(filters)。filters 不是必需参数。)
        routes:
          # 路由标识(id:标识,具有唯一性)   转发指定地址并传入参数
          - id: CLIENT1-SERVICE
            # 目标服务地址(uri:地址,请求转发后的地址)
            uri: http://localhost:8702
            # 路由条件(predicates:断言,匹配 HTTP 请求内容)
            predicates:
              ## 匹配路径
              - Path=/client1/**
              #可以使用这两种方式
#              - name: My
              #前面为自定义路由断言工厂的前缀(注意:这个地方名字一定要命名正确。。。RoutePredicateFactory)
              - My=shockwave
#            filters:
#              - StripPrefix=1
            # 过滤器(filters:过滤器,过滤规则)
eureka:
  instance:
    preferIpAddress: true
    instance-id: gateway_service #注册中心右边的位置的显示
  client:
    serviceUrl:
      defaultZone: http://localhost:8701/eureka
Copy the code

test

So let’s just pick a random argument

Use normal parameters

Custom local filter factories

code

package org.example.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.stereotype.Component; import java.util.Arrays; import java.util.List; /** * @author shock wave 2 * @version 1.0 * @description: TODO * @date 2021/6/30 17:10 */ @Component @Slf4j public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory < MyGatewayFilterFactory. Config > {/ / constructor is a must, remove the complains, general idea will be prompted to add this, Public MyGatewayFilterFactory() {super(config.class); } @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { String version = exchange.getRequest().getQueryParams().getFirst("version"); if (! Config.getversion ().equals(version)) {log.info(" parameter error "); } return chain.filter(exchange); }; } @Override public List<String> shortcutFieldOrder() { return Arrays.asList("version"); } @Data public static class Config { private String version; }}Copy the code

Yml configuration

server: port: 8711 spring: application: name: gateway-service cloud: gateway: # discovery: # locator: If set to true, you can call the service directly using the application name. True # Routes: routes that consist of a unique ID, destination service address, predicates, and filters. Filters are not required. -id: client1-service = client1-service = client1-service = client1-service http://localhost:8702 # predicates: // client1/** My # is the prefix of the custom route assertion factory (note: this place must be named correctly... RoutePredicateFactory) -my =shockwave filters: -my =sr # filter (filters: preferIpAddress) True instance - id: # gateway_service registry to the right of the location of display client: serviceUrl: defaultZone: http://localhost:8701/eurekaCopy the code

test

The results of