spring cloud 2. x 버 전 Gateway 사용자 정의 필터 튜 토리 얼
16016 단어 spring
Spring cloud 2.1.8RELEASE,version=Greenwich.SR3
본 고 는 앞의 두 편의 문장 인 eureka - server, eureka - client, eureka - ribbon, eureka - fegn 과 spring - gataway 의 실현 을 바탕 으로 한다.레 퍼 런 스
개략
Spring Cloud Gateway 내부 에는 이미 매우 많은 필터 필터 필터, Hystrix Gateway Filter, Prefix PathGateway Filter 등 이 제공 되 고 있다.관심 있 는 파트너 는 Spring Cloud Gateway 홈 페이지 관련 문 서 를 직접 읽 거나 소스 코드 를 직접 읽 을 수 있다.그러나 자체 필터 가 우리 의 요 구 를 만족 시 키 지 못 하 는 경우 가 많 기 때문에 사용자 정의 필 터 는 매우 중요 하 다.본 고 는 주로 전역 필터 (Global Filter) 와 국부 필터 (Gateway Filter) 를 소개 한다.
Gateway Filter
사용자 정의 필 터 는 Gateway Filter 와 Ordered 를 실현 해 야 합 니 다.그 중에서 Gateway Filter 는 사용자 정의 의 구체 적 인 논 리 를 실현 하 는 데 사 용 됩 니 다. Ordered 의 getOrder () 방법 은 필터 에 우선 순 위 를 설정 하 는 것 입 니 다. 값 이 클 수록 우선 순위 가 낮 습 니 다.
1.1 필터 생 성
package 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;
}
}
저희 가 도착 을 요청 할 때 ServerWebExchange 에 속성 TIME 를 넣 었 습 니 다. 속성의 값 은 현재 시간의 밀리초 입 니 다. 그리고 요청 이 끝 난 후에 요청 한 시간 수 를 꺼 내 서 현재 시간 수 와 차이 가 나 고 시간 이 걸 립 니 다.
어떻게 "pre" 와 "post" 를 구분 합 니까?
package 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;
@Configuration
public class RoutesConfig {
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder routeLocatorBuilder){
return routeLocatorBuilder.routes().route(r -> r.path("/ribbon/**")
.filters(f -> f.stripPrefix(1)
.filter(new MyGatewayFilter()) // filter
.addRequestHeader("X-Response-Default-Foo", "Default-Bar"))
.uri("lb://EUREKA-RIBBON")
.order(0)
.id("ribbon-route")
).build();
}
}
1.2 관련 서비스 시작
eureka - server, eureka - client, eureka - ribbon, spring - gateway 관련 서 비 스 를 시작 하여 방문 합 니 다.http://localhost:8100/ribbon/sayHello주소, 페이지 표시 결 과 는 다음 과 같 습 니 다.
이 때 콘 솔 을 열 면 로그 출력 을 볼 수 있 습 니 다:
2.1 글로벌 필터 만 들 기
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;
/**
*
* 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 빈 추가
MyGlobalFilter 를 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;
/**
*
* 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.3 서비스 시작
서비스 재 시작, 접근http://localhost:8100/ribbon/sayHello다음 과 같이 표 시 됩 니 다. 저 는 디 스 플레이 접근 이 유효 하지 않 음 을 볼 수 있 습 니 다. 저 희 는 요청 에 token = xxx 를 추가 하여 다음 과 같이 표 시 됩 니 다. 이것 은 정상 적 인 귀환 을 볼 수 있 습 니 다.로그 출력 입력:
2019-10-21 16:20: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 = 2147483647
2019-10-21 16:20: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.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@40585976
2019-10-21 16:20: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:23ms
2019-10-21 16:20: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
홈 페이지 원문 참조: The GlobalFilter interface has the same signature as Gateway Filter. These are special filter that are conditionally applied to all routes.
총결산
이로써 사용자 정의 filter 의 두 가지 방식 이 간단하게 이 루어 졌 다.같은 방식 으로 feign 에서 테스트 할 수 있 습 니 다.
달걀
이전 글 에서 설정 파일 에 다음 설정 이 있 습 니 다.
filters:
- StripPrefix=1
- AddResponseHeader=X-Response-Default-Foo, Default-Bar
Strip Prefix 와 AddResponse Header 두 설정 은 사실상 두 필터 공장 (Gateway Filter Factory) 으로 필터 공장 의 사용 을 소개 합 니 다. 상대 적 으로 이런 방식 이 더욱 유연 합 니 다.
1.1 사용자 정의 필터 공장 만 들 기
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;
/**
*
*/
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());
})
);
});
}
/**
*
*/
public static class Config {
private boolean myParams;
public boolean isMyParams() {
return myParams;
}
public void setMyParams(boolean myParams) {
this.myParams = myParams;
}
}
}
메모: AbstractGateway FilterFactory 를 계승 할 때 사용자 정의 Config 클래스 를 부모 클래스 에 전달 해 야 합 니 다. 그렇지 않 으 면 잘못 보고 할 수 있 습 니 다.
1.2 사용자 정의 공장 빈 추가
package 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;
@Configuration
public class FilterFactory {
@Bean
public MyGatewayFilterFactory myGatewayFilterFactory() {
return new MyGatewayFilterFactory();
}
}
1.3 application. yml 수정
server:
port: 8100
spring:
application:
name: spring-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # serviceId
default-filters:
- My=true
routes:
- id: ribbon-route
uri: lb://EUREKA-RIBBON
order: 0
predicates:
- Path=/ribbon/**
filters:
- StripPrefix=1 # , 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-Bar
eureka:
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 - filers: - My = true 는 주로 이 설정 을 추 가 했 습 니 다.
1.4 서비스 시작
방문 하 다.http://localhost:8100/ribbon/sayHello?token=xxx다음: 로그 출력 결과 보이 기:
2019-10-21 17:40:20.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 = 2147483647
2019-10-21 17:40:20.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.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@46c172ce
2019-10-21 17:40: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:40: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
총결산
필터 공장 의 최고급 인 터 페 이 스 는 Gateway FilterFactory 입 니 다. 추상 적 인 두 가지 추상 적 인 추상 적 인 추상 적 인 AbstractGateway FilterFactory 와 AbstractNameValueGateway FilterFactory 를 직접 계승 하여 개발 을 간소화 할 수 있 습 니 다.차이 점 은 AbstractGateway FilterFactory 는 하나의 인 자 를 받 아들 이 는 것 이 고, AbstractNameValueGateway FilterFactory 는 두 개의 인 자 를 받 는 것 이다. 예 를 들 어 - AddResponseHeader = X - Response - Default - Foo, Default - Bar
결어
본 고 는 Gateway Filter, GlobalFilter, Gateway Filter Factory 의 간단 한 사용 방식 을 소개 하 였 으 며, 어린이 들 이 Spring Cloud Gateway 에 대해 간단 한 이 해 를 가지 게 되 었 다 고 믿는다.
코드 주소
gitHub 주소
디 렉 터 리
본 고 는 블 로그 한 글 다발 플랫폼 OpenWrite 에서 발표 합 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
thymeleaf로 HTML 페이지를 동적으로 만듭니다 (spring + gradle)지난번에는 에서 화면에 HTML을 표시했습니다. 이번에는 화면을 동적으로 움직여보고 싶기 때문에 입력한 문자를 화면에 표시시키고 싶습니다. 초보자의 비망록이므로 이상한 점 등 있으면 지적 받을 수 있으면 기쁩니다! ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.