#spring #spring-boot #spring-mvc #spring-webflux
Вопрос:
У меня возникли проблемы с параметрами запроса кодирования WebClient, когда значение одного параметра декодируется из значения JSON в строку.
Одним из значений параметров запроса является :
[ { "var": "report_days", "op": "=", "val": "7" } ]
он декодируется с помощью метода HTTP : ? filter=[{"var":"report_days","op":"=","val":"7"}]
. Таким образом, декодирование MultiMaplt;String, Stringgt;
выполняется правильно, но при uriBuilder
этом возникает исключение.
return webClient.get() .uri(uriBuilder -gt; uriBuilder.path("/nodes/last").queryParams(queryParams).build()) //Problem .header(HttpHeaders.AUTHORIZATION, token) .accept(MediaType.APPLICATION_JSON) .retrieve() .bodyToMono(String.class) .log();
Исключение:
java.lang.IllegalArgumentException: Not enough variable values available to expand '"var"' 2021-11-22T11:17:38.252421700Z at org.springframework.web.util.UriComponents$VarArgsTemplateVariables.getValue(UriComponents.java:370) 2021-11-22T11:17:38.252461800Z Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 2021-11-22T11:17:38.252492300Z Error has been observed at the following site(s): 2021-11-22T11:17:38.252521200Z *__checkpoint ⇢ org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter [DefaultWebFilterChain] 2021-11-22T11:17:38.252586100Z *__checkpoint ⇢ HTTP GET "/nodeNew/all/last_protected?filter=[{"var":"report_days","op":"=","val":"7"}]" [ExceptionHandlingWebHandler] 2021-11-22T11:17:38.252628200Z Stack trace: 2021-11-22T11:17:38.252666300Z at org.springframework.web.util.UriComponents$VarArgsTemplateVariables.getValue(UriComponents.java:370) 2021-11-22T11:17:38.252699800Z at org.springframework.web.util.HierarchicalUriComponents$QueryUriTemplateVariables.getValue(HierarchicalUriComponents.java:1087) 2021-11-22T11:17:38.252723100Z at org.springframework.web.util.UriComponents.expandUriComponent(UriComponents.java:263) 2021-11-22T11:17:38.252738600Z at org.springframework.web.util.HierarchicalUriComponents.lambda$expandQueryParams$5(HierarchicalUriComponents.java:450) 2021-11-22T11:17:38.252754400Z at java.base/java.util.Map.forEach(Map.java:713)
Может быть, есть какая-то конфигурация, чтобы решить эту проблему? В параметрах запросов могут быть другие значения, но не в формате JSON, поэтому я хотел бы избежать этого таким образом (это работает сейчас, но он должен пересылать все параметры запросов, а не только ключ «фильтр»).:
return webClient.get() .uri(uriBuilder -gt; uriBuilder.path("/nodes/last").queryParam(URLEncoder.encode(queryParams.getFirst("filter"), StandardCharsets.UTF_8)).build())
Комментарии:
1. ваша трассировка стека не соответствует коду, который у вас есть в вопросе. «/nodeNew/все/last_protected» — это не «/узлы/последние». Пожалуйста, предоставьте воспроизводимый тестовый пример с кодом, который показывает поведение.
2. Привет, это правильная трассировка стека. Это служба шлюза. Запрос находится на GET «/nodeNew/all/last_protected», затем в функции маршрутизации у меня есть обработчик для этого запроса, который выполняет доступ через веб-клиент к нескольким микросервисам и объединяет ответ от них. Этот веб-клиент выполняет один из запросов от обработчика
Ответ №1:
Недавно я столкнулся с такой же проблемой, и это сделало свое дело:
- Создайте метод, который возвращает копию webclient с пользовательским DefaultUriBuilderFactory
public WebClient getWebclientNoEncoded() { DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(this.baseUrl); //Here comes your base url factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.NONE); return this.webClient.mutate() .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .uriBuilderFactory(factory) .build();
}
А затем в клиентском методе:
apiClient.getWebclientNoEncoded() .get() .uri(uriBuilder -gt; uriBuilder .path("/foo") .queryParam(UriUtils.encodeQueryParam(myJsonString, StandardCharsets.UTF_8.toString())) .build()) .header(HttpHeaders.AUTHORIZATION, bearerToken) .retrieve()
Полиция. Извините за мой плохой английский.