Gateway 自定義過濾器

點(diǎn)擊上方「藍(lán)字」關(guān)注我們

Spring Cloud Gateway雖然自帶有許多實(shí)用的GatewayFilter Factory、Gateway Filter、Global Filter,但是在很多業(yè)務(wù)情景下仍然需要自定義過濾器。實(shí)現(xiàn)一些自定義操作,滿足業(yè)務(wù)需求。所以自定義過濾器就顯得非常有必要。本文分表介紹自定義Gateway Filter、自定義Global Filter、自定義Gateway Filter Factory。
實(shí)現(xiàn)自定義過濾器,其實(shí)可以去查看Spring Cloud Gateway自帶過濾器源碼是如何實(shí)現(xiàn)的。
自定義Gateway Filter
實(shí)現(xiàn)自定義的Gateway Filter,需要GatewayFilter、Ordered兩個接口
/**
?*?此過濾器功能為計(jì)算請求完成時間
?*/
public?class?MyFilter?implements?GatewayFilter,?Ordered?{
????private?static?final?String?ELAPSED_TIME_BEGIN?=?"elapsedTimeBegin";
????@Override
????public?Mono?filter(ServerWebExchange?exchange,?GatewayFilterChain?chain)? {
????????exchange.getAttributes().put(ELAPSED_TIME_BEGIN,?System.currentTimeMillis());
????????return?chain.filter(exchange).then(
????????????????Mono.fromRunnable(()?->?{
????????????????????Long?startTime?=?exchange.getAttribute(ELAPSED_TIME_BEGIN);
????????????????????if?(startTime?!=?null)?{
????????????????????????System.out.println(exchange.getRequest().getURI().getRawPath()?+?":?"?+?(System.currentTimeMillis()?-?startTime)?+?"ms");
????????????????????}
????????????????})
????????);
????}
????/*
????*過濾器存在優(yōu)先級,order越大,優(yōu)先級越低
????*/
????@Override
????public?int?getOrder()?{
????????return?Ordered.LOWEST_PRECEDENCE;
????}
}
定義好MyFilter以后,其需要跟Route綁定使用,不能在application.yml文件中配置使用
@Bean
public?RouteLocator?routeLocator(RouteLocatorBuilder?builder)?{
?????return?builder.routes().route(r?->
?????????????r.path("/aa")
?????????????????????//轉(zhuǎn)發(fā)路由
??????????????????? .uri("http://localhost:8080/provider/test")
?????????????????????//注冊自定義過濾器
?????????????????????.filters(new?MyFilter())
????????????????????//給定id
????????????????????.id("user-service"))
???????????????? .build();
}
測試結(jié)果:可以在控制臺看到請求響應(yīng)時間。
自定義Gateway Filter Factory
很多時候更希望在配置文件中配置Gateway Filter,所以可以自定義過濾器工廠實(shí)現(xiàn)。
自定義過濾器工廠需要繼承AbstractGatewayFilterFactory
@Component
public?class?AuthorizeGatewayFilterFactory?extends?AbstractGatewayFilterFactory<AuthorizeGatewayFilterFactory.Config>?{
????private?static?final?Log?logger?=?LogFactory.getLog(AuthorizeGatewayFilterFactory.class);
????private?static?final?String?AUTHORIZE_TOKEN?=?"token";
????private?static?final?String?AUTHORIZE_UID?=?"uid";
????@Autowired
????private?StringRedisTemplate?stringRedisTemplate;
????public?AuthorizeGatewayFilterFactory()?{
????????super(Config.class);
????????logger.info("Loaded?GatewayFilterFactory?[Authorize]");
????}
????@Override
????public?List?shortcutFieldOrder()? {
????????return?Arrays.asList("enabled");
????}
????@Override
????public?GatewayFilter?apply(AuthorizeGatewayFilterFactory.Config?config)?{
????????return?(exchange,?chain)?->?{
????????????if?(!config.isEnabled())?{
????????????????return?chain.filter(exchange);
????????????}
????????????ServerHttpRequest?request?=?exchange.getRequest();
????????????HttpHeaders?headers?=?request.getHeaders();
????????????String?token?=?headers.getFirst(AUTHORIZE_TOKEN);
????????????String?uid?=?headers.getFirst(AUTHORIZE_UID);
????????????if?(token?==?null)?{
????????????????token?=?request.getQueryParams().getFirst(AUTHORIZE_TOKEN);
????????????}
????????????if?(uid?==?null)?{
????????????????uid?=?request.getQueryParams().getFirst(AUTHORIZE_UID);
????????????}
????????????ServerHttpResponse?response?=?exchange.getResponse();
????????????if?(StringUtils.isEmpty(token)?||?StringUtils.isEmpty(uid))?{
????????????????response.setStatusCode(HttpStatus.UNAUTHORIZED);
????????????????return?response.setComplete();
????????????}
????????????String?authToken?=?stringRedisTemplate.opsForValue().get(uid);
????????????if?(authToken?==?null?||?!authToken.equals(token))?{
????????????????response.setStatusCode(HttpStatus.UNAUTHORIZED);
????????????????return?response.setComplete();
????????????}
????????????return?chain.filter(exchange);
????????};
????}
????public?static?class?Config?{
????????//?控制是否開啟認(rèn)證
????????private?boolean?enabled;
????????public?Config()?{ }
????????public?boolean?isEnabled()?{
????????????return?enabled;
????????}
????????public?void?setEnabled(boolean?enabled)?{
????????????this.enabled?=?enabled;
????????}
????}
}
在application.yml配置使用
#?網(wǎng)關(guān)路由配置
spring:
??cloud:
????gateway:
??????routes:
??????-?id:?user-center-service
????????uri:?http://localhost:8080/api/user/list
????????predicates:
????????-?Path=/user/list
????????filters:
????????#?關(guān)鍵在下面一句,值為true則開啟認(rèn)證,false則不開啟
????????#?這種配置方式和spring?cloud?gateway內(nèi)置的GatewayFilterFactory一致
????????-?Authorize=true
自定義Global Filter
實(shí)現(xiàn)自定義全局過濾器需要繼承GlobalFilter和Ordered
@Component
public?class?MyGloablFilter?implements?GlobalFilter,?Ordered?{
????@Override
????public?Mono?filter(ServerWebExchange?exchange,?GatewayFilterChain?chain)? {
????????System.out.println("MyGloablFilter>>>");
????????return?chain.filter(exchange);
????}
????@Override
????public?int?getOrder()?{
????????return?0;
????}
}
使用它只需要加上@Component注解。

掃碼二維碼
獲取更多精彩
Java樂園

評論
圖片
表情
