Maison  >  Article  >  Java  >  Introduction aux filtres globaux de Spring Cloud Gateway

Introduction aux filtres globaux de Spring Cloud Gateway

不言
不言avant
2019-03-06 15:51:312821parcourir

Cet article vous présente le filtre global Spring Cloud Gateway. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Les filtres globaux s'appliquent à toutes les routes et n'ont pas besoin d'être configurés séparément. Nous pouvons les utiliser pour répondre à de nombreuses exigences commerciales de traitement unifié, telles que l'authentification des autorités, les restrictions d'accès IP, etc.

Classe de définition d'interface : org.springframework.cloud.gateway.filter.GlobalFilter

public interface GlobalFilter {
    Mono<void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}</void>

Il existe de nombreuses classes d'implémentation GlobalFilter fournies avec la passerelle, comme indiqué ci-dessous :

Introduction aux filtres globaux de Spring Cloud Gateway

Il existe des GlobalFilters liés au transfert, au routage, au chargement, etc. Si vous êtes intéressé, vous pouvez consulter le code source pour en savoir plus.

Comment définissons-nous GlobalFilter pour mettre en œuvre notre propre logique métier ?

Donnez un exemple tiré du document officiel :

@Configuration
public class ExampleConfiguration {
    private Logger log = LoggerFactory.getLogger(ExampleConfiguration.class);

    @Bean
    @Order(-1)
    public GlobalFilter a() {
        return (exchange, chain) -> {
            log.info("first pre filter");
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                log.info("third post filter");
            }));
        };
    }

    @Bean
    @Order(0)
    public GlobalFilter b() {
        return (exchange, chain) -> {
            log.info("second pre filter");
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                log.info("second post filter");
            }));
        };
    }

    @Bean
    @Order(1)
    public GlobalFilter c() {
        return (exchange, chain) -> {
            log.info("third pre filter");
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                log.info("first post filter");
            }));
        };
    }
}

Trois GlobalFilters sont définis ci-dessus, et l'ordre d'exécution est spécifié via @Order. Plus le nombre est petit, plus la priorité est élevée. Voici le journal de sortie. Vous pouvez voir l'ordre d'exécution à partir du journal :

2018-10-14 12:08:52.406  INFO 55062 --- [ioEventLoop-4-1] c.c.gateway.config.ExampleConfiguration  : first pre filter
2018-10-14 12:08:52.406  INFO 55062 --- [ioEventLoop-4-1] c.c.gateway.config.ExampleConfiguration  : second pre filter
2018-10-14 12:08:52.407  INFO 55062 --- [ioEventLoop-4-1] c.c.gateway.config.ExampleConfiguration  : third pre filter
2018-10-14 12:08:52.437  INFO 55062 --- [ctor-http-nio-7] c.c.gateway.config.ExampleConfiguration  : first post filter
2018-10-14 12:08:52.438  INFO 55062 --- [ctor-http-nio-7] c.c.gateway.config.ExampleConfiguration  : second post filter
2018-10-14 12:08:52.438  INFO 55062 --- [ctor-http-nio-7] c.c.gateway.config.ExampleConfiguration  : third post filter

Lorsque le GlobalFilter a beaucoup de logique, je vous recommande toujours d'écrire un GlobalFilter séparé pour le gérer. Par exemple, si nous souhaitons implémenter des restrictions d'accès IP, les requêtes qui ne figurent pas dans la liste blanche IP ne seront pas autorisées à être appelées.

Pour une définition séparée, il vous suffit d'implémenter les deux interfaces GlobalFilter et Ordered.

@Component
public class IPCheckFilter implements GlobalFilter, Ordered {

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public Mono<void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        HttpHeaders headers = exchange.getRequest().getHeaders();
        // 此处写死了,演示用,实际中需要采取配置的方式
        if (getIp(headers).equals("127.0.0.1")) {
            ServerHttpResponse response = exchange.getResponse();
            ResponseData data = new ResponseData();
            data.setCode(401);
            data.setMessage("非法请求");
            byte[] datas = JsonUtils.toJson(data).getBytes(StandardCharsets.UTF_8);
            DataBuffer buffer = response.bufferFactory().wrap(datas);
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
            return response.writeWith(Mono.just(buffer));
        }
        return chain.filter(exchange);
    }

    // 这边从请求头中获取用户的实际IP,根据Nginx转发的请求头获取
    private String getIp(HttpHeaders headers) {
        return "127.0.0.1";
    }

}</void>

Il n'y a rien à dire sur l'utilisation du filtrage. C'est relativement simple, mais il est très efficace et peut répondre à de nombreux besoins. L'interception d'authentification IP mentionnée ci-dessus n'est que la pointe de l'iceberg. Plus de fonctions doivent être basées sur le filtrage nous-mêmes du périphérique à mettre en œuvre.

Par exemple, si je veux faire des tests a/b, je dois alors travailler au niveau du routage et du transfert. Nous avons publié une image plus tôt. Il y a de nombreux filtres globaux par défaut dans l'image, parmi lesquels. est un LoadBalancerClientFilter qui est responsable de la sélection des routes. Le filtre de charge du service sélectionnera le service de transfert via LoadBalancer, puis le transmettra au filtre NettyRoutingFilter de routage suivant pour l'exécution, nous pourrons ensuite l'implémenter sur la base de ce mécanisme.

La méthode suivante est utilisée pour transmettre les données du Filtre au Filtre suivant :

exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);

L'acquéreur les obtient directement :

URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);

Si je souhaite modifier le routage, vous pouvez faire ceci :

@Component
public class DebugFilter implements GlobalFilter, Ordered {

    @Override
    public int getOrder() {
        return 10101;
    }

    @Override
    public Mono<void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        try {
            exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, new URI("http://192.168.31.245:8081/house/hello2"));
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return chain.filter(exchange);
    }

}</void>

L'ordre de LoadBalancerClientFilter est 10100, soit 1 de plus qu'ici, afin que l'adresse à acheminer puisse être remplacée après son exécution.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer