Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to implement spring cloud version 2.x Gateway Custom filter

2025-03-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article focuses on "how to implement the spring cloud 2.x version of Gateway custom filter", interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn "how to implement spring cloud 2.x Gateway custom filter"!

The preface of this paper is 2.1.8 RELEASE version Greenwich.SR3 using Spring cloud.

[toc]

This article is based on the implementation of eureka-server, eureka-client, eureka-ribbon, eureka-feign and spring-gataway in the previous two articles. Referenc

Eureka-server

Eureka-client

Eureka-ribbon

Eureka-feign

Spring-gateway

General skill

Spring Cloud Gateway has provided a lot of filters such as filter,Hystrix Gateway Filter, Prefix PathGateway Filter, and so on. Interested partners can directly read the relevant documents on the Spring Cloud Gateway official website or read the source code directly. But in many cases, the self-built filter can not meet our needs, so it is very important to customize the filter. This paper mainly introduces global filter (Global Filter) and local filter (Gateway Filter).

Gateway Filter

Custom filters need to implement GatewayFilter and Ordered. GatewayFilter is mainly used to implement the specific logic of customization, and the getOrder () method in Ordered is used to set the priority of the filter. The higher the value, the lower the priority.

1.1 create Filterpackage spring.cloud.demo.spring.gateway.filter;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.cloud.gateway.filter.GatewayFilter;import org.springframework.cloud.gateway.filter.GatewayFilterChain;import org.springframework.core.Ordered;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Mono;public class MyGatewayFilter implements GatewayFilter, Ordered {private static final Log log = LogFactory.getLog (MyGatewayFilter.class); private static final String TIME = "Time" @ Override public Mono filter (ServerWebExchange exchange, GatewayFilterChain chain) {exchange.getAttributes () .put (TIME, System.currentTimeMillis ()); return chain.filter (exchange) .then (Mono.fromRunnable (()-> {Long start = exchange.getAttribute (TIME)) If (start! = null) {log.info ("exchange request uri:" + exchange.getRequest () .getURI () + ", Time:" + (System.currentTimeMillis ()-start) + "ms");}}));} @ Override public int getOrder () {return Ordered.LOWEST_PRECEDENCE;}}

When the request arrives, we put an attribute TIME in the ServerWebExchange. The value of the attribute is the number of milliseconds of the current time. Then, after the request ends, we will compare the requested time with the current time to get the elapsed time.

How to distinguish between "pre" and "post"?

Pre is the chain.filter (exchange) part.

Post is the then () part.

1.2 add Filter to Chainpackage spring.cloud.demo.spring.gateway.config;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;import spring.cloud.demo.spring.gateway.filter.MyGatewayFilter / * * @ auther: fujie.feng * @ DateT: 2019-10-12 * / @ Configurationpublic class RoutesConfig {@ Bean public RouteLocator routeLocator (RouteLocatorBuilder routeLocatorBuilder) {return routeLocatorBuilder.routes () .route (r-> r.path ("/ ribbon/**") .filter (f-> f.stripPrefix (1) .filter (new MyGatewayFilter ()) / / add custom filter .addRequestHeader ("X-Response-Default-Foo" "Default-Bar") .uri ("lb://EUREKA-RIBBON") .order (0) .id ("ribbon-route")) .build () }} 1.2 start related services

Start the services related to eureka-server, eureka-client, eureka-ribbon and spring-gateway, and visit the http://localhost:8100/ribbon/sayHello address. The page displays the result as follows:

When I open the console, I can see that the log output is:

2.1 create GlobalFilterpackage spring.cloud.demo.spring.gateway.filter;import org.apache.commons.lang.StringUtils;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.web.server.ServerWebExchange;import reactor.core.publisher.Mono;/** * global filter * verify token * / public class MyGlobalFilter implements GlobalFilter, Ordered {private static final String TOKEN = "token" @ Override public Mono filter (ServerWebExchange exchange, GatewayFilterChain chain) {String parm = exchange.getRequest () .getQueryParams () .getFirst (TOKEN); if (StringUtils.isBlank (parm)) {exchange.getResponse () .setStatusCode (HttpStatus.UNAUTHORIZED); return exchange.getResponse () .setComplete ();} return chain.filter (exchange);} @ Override public int getOrder () {return 1 }} 2.2 add Bean

Add MyGlobalFilter to Bean

Package spring.cloud.demo.spring.gateway.filter;import org.apache.commons.lang.StringUtils;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.web.server.ServerWebExchange;import reactor.core.publisher.Mono;/** * Global filter * check token * / public class MyGlobalFilter implements GlobalFilter, Ordered {private static final String TOKEN = "token" @ Override public Mono filter (ServerWebExchange exchange, GatewayFilterChain chain) {String parm = exchange.getRequest () .getQueryParams () .getFirst (TOKEN); if (StringUtils.isBlank (parm)) {exchange.getResponse () .setStatusCode (HttpStatus.UNAUTHORIZED); return exchange.getResponse () .setComplete ();} return chain.filter (exchange);} @ Override public int getOrder () {return 1 }}

Here is just a simple simulation, if interested partners can try to take out all the parameters and parse (you can use reflection to achieve).

2.3 start the service

Restart the service, visit http://localhost:8100/ribbon/sayHello, and display as follows: I can see that the access is not valid. We add token=xxx to the request as shown below: this is to see the normal return. Log input / output:

2019-10-21 16 INFO 20 Flipping property 00.478 INFO 15322-[ctor-http-nio-2] c.netflix.config.ChainedDynamicProperty: Flipping property: EUREKA-RIBBON.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 21474836472019-10-21 16 Swiss 20 c.netflix.config.ChainedDynamicProperty 00.480 INFO 15322-[ctor-http-nio-2] c.n.l.DynamicServerListLoadBalancer: DynamicServerListLoadBalancer for client EUREKA-RIBBON initialized: DynamicServerListLoadBalancer: {NFLoadBalancer:name=EUREKA-RIBBON,current list of Servers= [eureka1.server.com:8901] Load balancer stats=Zone stats: {defaultzone= [Zone:defaultzone Instance count:1; Active connections count: 0; Circuit breaker tripped count: 0; Active connections per server: 0;]}, Server stats: [Server:eureka1.server.com:8901; Zone:defaultZone; Total Requests:0; Successive connection failure:0; Total blackout seconds:0; Last connection made:Thu Jan 01 08:00:00 CST 1970; First connection made:Thu Jan 01 08:00:00 CST 1970; Active Connections:0 Total failure count in last (1000) msecs:0; average resp time:0.0; 90 percentile resp time:0.0; 95 percentile resp time:0.0; min resp time:0.0; max resp time:0.0 [stddev resp time:0.0]]} ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@405859762019-10-21 16 INFO 20 ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@405859762019 01.293 INFO 15322-[ctor-http-nio-8] s.c.d.s.gateway.filter.MyGatewayFilter: exchange request uri: http://localhost:8100/sayHello?token=xxx, Time:23ms2019-10-21 16 c.netflix.config.ChainedDynamicProperty 20 erListUpdater-0 01.467 INFO 15322-[erListUpdater-0] c.netflix.config.ChainedDynamicProperty: Flipping property: EUREKA-RIBBON.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647

To quote the original article on the official website: The GlobalFilter interface has the same signature as GatewayFilter. These are special filters that are conditionally applied to all routes. (This interface and usage are subject to change in future milestones). It shows that there will be some changes in GlobalFilter in future versions.

Summary

At this point, the two ways to customize filter are simply implemented. Tests can be done in feign in the same way.

Colored egg

In the previous article, there was a configuration in the configuration file:

Filters:-StripPrefix=1-AddResponseHeader=X-Response-Default-Foo, Default-Bar

The configurations of StripPrefix and AddResponseHeader are actually two Filter filter factories (GatewayFilterFactory). The next step is to introduce the use of filter factories, which is relatively more flexible.

1.1 create a custom filter factory package spring.cloud.demo.spring.gateway.factory;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.cloud.gateway.filter.GatewayFilter;import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;import reactor.core.publisher.Mono;import java.util.Arrays;import java.util.List / * Custom filter Factory * / public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory {private static final Log log = LogFactory.getLog (MyGatewayFilterFactory.class); private static final String PARAMS = "myParams"; private static final String START_TIME = "startTime"; public MyGatewayFilterFactory () {super (Config.class);} @ Override public List shortcutFieldOrder () {return Arrays.asList (PARAMS) } @ Override public GatewayFilter apply (Config config) {return ((exchange, chain)-> {exchange.getAttributes () .put (START_TIME, System.currentTimeMillis ()); return chain.filter (exchange) .then (Mono.fromRunnable (()-> {Long startTime = exchange.getAttribute (START_TIME)) If (startTime = = null) {return;} StringBuilder sb = new StringBuilder (); sb.append ("exchange request uri:" + exchange.getRequest (). GetURI () + ",") Sb.append ("Time:" + (System.currentTimeMillis ()-startTime) + "ms."); if (config.isMyParams ()) {sb.append ("params:" + exchange.getRequest (). GetQueryParams ());} log.info (sb.toString ()) }));});} / * * configuration parameter class * / public static class Config {private boolean myParams; public boolean isMyParams () {return myParams;} public void setMyParams (boolean myParams) {this.myParams = myParams;}

Note: when we inherit AbstractGatewayFilterFactory, we want to pass the custom Config class to the parent class, otherwise an error will be reported.

1.2 add a custom factory Beanpackage spring.cloud.demo.spring.gateway.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import spring.cloud.demo.spring.gateway.factory.MyGatewayFilterFactory;@Configurationpublic class FilterFactory {@ Bean public MyGatewayFilterFactory myGatewayFilterFactory () {return new MyGatewayFilterFactory () }} 1.3 modify application.ymlserver: port: 8100spring: application: name: spring-gateway cloud: gateway: discovery: locator: enabled: true # enable the function of automatically creating routes based on serviceId through the service center default-filters:-My=true routes:-id: ribbon-route uri: lb: / / EUREKA-RIBBON order: 0 predicates:-Path=/ribbon/** filters:-StripPrefix=1 # remove the prefix For more information, please see StripPrefixGatewayFilterFactory-AddResponseHeader=X-Response-Default-Foo, Default-Bar-id: feign-route uri: lb://EUREKA-FEIGN order: 0 predicates:-Path=/feign/** filters:-StripPrefix=1-AddResponseHeader=X-Response-Default-Foo Default-Bareureka: instance: hostname: eureka1.server.com lease-renewal-interval-in-seconds: 5 lease-expiration-duration-in-seconds: 10 client: service-url: defaultZone: http://eureka1.server.com:8701/eureka/,http://eureka2.server.com:8702/eureka/,http://eureka3.server.com:8703/eureka/

Default-filters:- My=true mainly adds this configuration.

1.4 start the service

Access http://localhost:8100/ribbon/sayHello?token=xxx to display if: log output result:

2019-10-21 17 INFO 4020.191 INFO 18059-[ctor-http-nio-2] c.netflix.config.ChainedDynamicProperty: Flipping property: EUREKA-RIBBON.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 21474836472019-10-21 17 c.netflix.config.ChainedDynamicProperty 4020. 192 INFO 18059-[ctor-http-nio-2] c.n.l.DynamicServerListLoadBalancer: DynamicServerListLoadBalancer for client EUREKA-RIBBON initialized: DynamicServerListLoadBalancer: {NFLoadBalancer:name=EUREKA-RIBBON,current list of Servers= [eureka1.server.com:8901] Load balancer stats=Zone stats: {defaultzone= [Zone:defaultzone Instance count:1; Active connections count: 0; Circuit breaker tripped count: 0; Active connections per server: 0;]}, Server stats: [Server:eureka1.server.com:8901; Zone:defaultZone; Total Requests:0; Successive connection failure:0; Total blackout seconds:0; Last connection made:Thu Jan 01 08:00:00 CST 1970; First connection made:Thu Jan 01 08:00:00 CST 1970; Active Connections:0 Total failure count in last (1000) msecs:0; average resp time:0.0; 90 percentile resp time:0.0; 95 percentile resp time:0.0; min resp time:0.0; max resp time:0.0 Stddev resp time:0.0]} ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@46c172ce2019-10-21 17 ServerList:org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList@46c172ce2019 40 INFO 20.583 INFO 18059-[ctor-http-nio-7] s.c.d.s.g.f.MyGatewayFilterFactory: exchange request uri: http://localhost:8100/ribbon/sayHello?token=xxx, Time:582ms.params: {token= [xxx]} 2019-10-21 17 INFO 21.181 INFO 18059-[erListUpdater-0] c.netflix.config.ChainedDynamicProperty: Flipping property: EUREKA-RIBBON.ribbon.ActiveConnectionsLimit to use NEXT property: niws.loadbalancer.availabilityFilteringRule.activeConnectionsLimit = 2147483647 Summary

The top-level interface of the filter factory is GatewayFilterFactory, and we can directly inherit their two abstract classes, AbstractGatewayFilterFactory and AbstractNameValueGatewayFilterFactory, to simplify development. The difference is that AbstractGatewayFilterFactory accepts one parameter and AbstractNameValueGatewayFilterFactory receives two parameters, such as-AddResponseHeader=X-Response-Default-Foo and Default-Bar

At this point, I believe you have a deeper understanding of "how to implement spring cloud 2.x version Gateway custom filter". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report