Параметры запроса кодирования WebClient spring

#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()  

Полиция. Извините за мой плохой английский.