Фильтр WebFlux: Redis доступа к потоку, если все в порядке, затем запустить следующий фильтр, но несоответствие - PullRequest
0 голосов
/ 29 сентября 2018

В проекте я проверяю, что app_key действителен, передайте redis.

Я использую ReactiveRedisTemplate для доступа к данным redis ,, и в фильтре я проверяю, что app_key действителен. Если app_key действителен, затем перейдите к следующемуфильтр, иначе выведите клиенту исключение.

На самом деле: если тайм-аут соединения redis , ex должен быть runnig.but, когда redis работает нормально, программа не exec verfiy app_key, это прямой переход к следующему фильтру.

Скажите, пожалуйста, как это сделать, спасибо!

@Resource
private AppKeyProvider appKeyProvider;

public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    try {
        String app_key =exchange.getRequest().getQueryParams().getFirst("app_key"));         
        //app_key verify
        Flux.just(app_key).flatMap(key -> appKeyProvider.getAppKey(key)).subscribe(
                appKey -> {                       
                    if (appKey == null) {
                        //app_key is not valid
                        throw new AppException(ErrorCode.ILLEGAL_APP_KEY);
                    }else{
                            //do... jump to next filter
                    }
                },
                ex -> {
                    throw new AppException(ErrorCode.SERVICE_BASIC_ERROR, ex);
                }
        );
    } catch (AppException ex) {            
        exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
        exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
        String  result = RestHelper.build(ex, exchange).toString();                
        return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(result.getBytes(Charsets.UTF_8))));
    }
    return chain.filter(exchange);
}

AppKeyProvider.java

@Component
public class AppKeyProvider {

@Resource
private ReactiveRedisTemplate reactiveRedisTemplate;

private final static Logger logger = LoggerFactory.getLogger(AppKeyProvider.class);
private final static AppKeyProvider instance = new AppKeyProvider();
private static ConcurrentHashMap<String, Api> apiMap = new ConcurrentHashMap<String, Api>();
private final static Lock lock = new ReentrantLock(true);

/**
 * Get AppKey
 *
 * @param app_key
 * @return
 */
public Mono<AppKey> getAppKey(String app_key) {
    ReactiveValueOperations<String, AppKey> operations = reactiveRedisTemplate.opsForValue();
    Mono<AppKey> appKey = operations.get(RedisKeypPrefix.APP_KEY + app_key);
    return appKey;
}

}

1 Ответ

0 голосов
/ 01 октября 2018

Это происходит потому, что вы вручную подписались на поиск ключей.Это отделяет основную обработку фильтра от этой операции, что означает, что они могут происходить одновременно в разных потоках - поэтому они не могут отслеживать результаты друг друга.

Кроме того, в реактивном программировании ошибки происходят в конвейере и должны бытьимел дело с операторами;блоки try / catch в этом случае не будут работать.

Вот попытка исправить этот фрагмент кода:

public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    String app_key = exchange.getRequest().getQueryParams().getFirst("app_key"));         
    return appKeyProvider.getAppKey(app_key)
              .switchOnEmpty(Mono.error(new AppException(ErrorCode.ILLEGAL_APP_KEY)))
              .flatMap(key -> chain.filter(exchange))
              .onErrorResume(AppException.class, exc -> {
                exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
                exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON);
                String  result = RestHelper.build(ex, exchange).toString();                
                return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(result.getBytes(Charsets.UTF_8))));  
              });
}
...