1、简介
GlobalGilter 全局过滤器接口与 GatewayFilter 网关过滤器接口具有相同的方法定义。全局过滤器是一系列特殊的过滤器,会根据条件应用到所有路由中。网关过滤器是更细粒度的过滤器,作用于指定的路由中。
查看GlobalGilter 的类图如下:
包括路由转发、负载均衡、ws 路由、netty 路由等全局过滤器,如需详细了解每个类需要自行百度。
GlobalGilter的例子:
package com.zoo.gateway.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.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* @Author: xf
* @Date: 2019/8/14 15:25
* @Version 1.0
*/
@Component
public class TokenFilter implements GlobalFilter, Ordered {
private static final boolean enableRateLimit = false;//开关
@Override
public int getOrder() {
// -1 is response write filter, must be called before that
return -2;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (!enableRateLimit) {
return chain.filter(exchange);
}
ServerHttpRequest request = exchange.getRequest();
String token = request.getQueryParams().getFirst("token");
if (token == null || token.isEmpty()) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
}
GatewayFilter的例子:
package com.zoo.gateway.filter;
import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket;
import io.github.bucket4j.Bucket4j;
import io.github.bucket4j.Refill;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @Author: xf
* @Date: 2019/8/14 15:38
* @Version 1.0
*/
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RateLimitByIpGatewayFilter implements GatewayFilter, Ordered {
int capacity;//桶的最大容量,即能装载 Token 的最大数量
int refillTokens;//每次 Token 补充量
Duration refillDuration;//补充 Token 的时间间隔
private static final Map<String, Bucket> CACHE = new ConcurrentHashMap<>();
private static final boolean enableRateLimit = true;//开关
private Bucket createNewBucket() {
Refill refill = Refill.of(refillTokens, refillDuration);
Bandwidth limit = Bandwidth.classic(capacity, refill);
return Bucket4j.builder().addLimit(limit).build();
}
@Override
public int getOrder() {
return -2;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (!enableRateLimit){
return chain.filter(exchange);
}
String ip = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
Bucket bucket = CACHE.computeIfAbsent(ip, k -> createNewBucket());
if (bucket.tryConsume(1)) {
return chain.filter(exchange);
} else {
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
return exchange.getResponse().setComplete();
}
}
// public static void main(String[] args) {
// Bandwidth limit = Bandwidth.simple(10, Duration.ofSeconds(1));
// Bucket bucket = Bucket4j.builder().addLimit(limit).build();
// if(bucket.tryConsume(1)){
// System.out.println("do something");
// }else{
// System.out.println("do nothing");
// }
// }
public static void main(String[] args) {
Bandwidth limit = Bandwidth.simple(1, Duration.ofSeconds(1));
Bucket bucket = Bucket4j.builder().addLimit(limit).build();
while(true){
if(bucket.tryConsume(1)){
System.out.println(new SimpleDateFormat("HH:mm:ss").format(new Date()));
}else{
try{
System.out.println("waiting...");
Thread.sleep(200);
}catch (Exception e){
}
}
}
}
}
。。。。。