Какой идиоматический c способ в Spring добавить дополнительные параметры запроса к заданному URL? URL-адрес может уже содержать параметры запроса или фрагмент. Конечно, значения параметров должны быть правильно закодированы.
Idiomati c означает, что я ищу краткий код без импорта каких-либо дополнительных библиотек, кроме обычной установки Spring Boot.
Метод должен иметь следующую подпись:
/** Add additional query parameters to the specified URL. @param url the URL @param params map with additional query parameters (parameter name/value pairs) @return the new URL */ String addQueryParameters(String url, Map<String, String> params);
Учитывая следующие дополнительные параметры:
price: €25 name: Réne e Suzanne config: {"f1":34,"f2":"&?"}
и эти URL:
http://www.app.com/one%20two/ http://www.berry.nz/one/two?return=%7B%22abc%22%3A%22%25%5E%3F%22%7D http://www.soil.au:8080/one/two#section-2
ожидаемый результат должно быть:
http://www.app.com/one%20two/?price=%E2%82%AC25&name=R%C3%A9ne+e+Suzanne&config=%7B%22f1%22%3A34%2C%22f2%22%3A%22%26%3F%22%7D http://www.berry.nz/one/two?return=%7B%22abc%22%3A%22%25%5E%3F%22%7D&price=%E2%82%AC25&name=R%C3%A9ne+e+Suzanne&config=%7B%22f1%22%3A34%2C%22f2%22%3A%22%26%3F%22%7D http://www.soil.au:8080/one/two?price=%E2%82%AC25&name=R%C3%A9ne+e+Suzanne&config=%7B%22f1%22%3A34%2C%22f2%22%3A%22%26%3F%22%7D#section-2
Кстати: это для серьезного программного обеспечения (без домашней работы). Я попытался решить ее с помощью UriComponentsBuilder и не смог ...: - (
UriComponentsBuilder
Обновление
Проблема с UriComponentsBuilder заключается в том, что он не может отменить кодирование процента параметров запроса. Затем я получил смесь закодированных и некодированных параметров с двумя выходами: существующие параметры были неправильно кодированы дважды или дополнительные параметры не были закодированы вообще.
URL-адреса немного сложны для кодирования, так как разные типы кодирования смешаны. Например, пробелы в URL кодируются как %20, а пробелы в параметрах запроса - как +. Поэтому я создал метод encodeUtf8 для отдельного кодирования параметров запроса:
%20
+
encodeUtf8
import org.junit.Test; import org.springframework.web.util.UriComponentsBuilder; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import static org.assertj.core.api.Assertions.assertThat; public class SomeTest { @Test public void test1() throws Exception { String url = UriComponentsBuilder.fromUriString("http://www.app.com/one%20two/") .queryParam("price", encodeUtf8("€25")) .queryParam("name", encodeUtf8("Réne e Suzanne")) .queryParam("config", encodeUtf8("{\"f1\":34,\"f2\":\"&?\"}")) .build() .toUriString(); assertThat(url).isEqualTo("http://www.app.com/one%20two/?price=%E2%82%AC25&name=R%C3%A9ne+e+Suzanne&config=%7B%22f1%22%3A34%2C%22f2%22%3A%22%26%3F%22%7D"); } @Test public void test2() throws Exception { String url = UriComponentsBuilder.fromUriString("http://www.berry.nz/one/two?return=%7B%22abc%22%3A%22%25%5E%3F%22%7D") .queryParam("price", encodeUtf8("€25")) .queryParam("name", encodeUtf8("Réne e Suzanne")) .queryParam("config", encodeUtf8("{\"f1\":34,\"f2\":\"&?\"}")) .build() .toUriString(); assertThat(url).isEqualTo("http://www.berry.nz/one/two?return=%7B%22abc%22%3A%22%25%5E%3F%22%7D&price=%E2%82%AC25&name=R%C3%A9ne+e+Suzanne&config=%7B%22f1%22%3A34%2C%22f2%22%3A%22%26%3F%22%7D"); } @Test public void test3() throws Exception { String url = UriComponentsBuilder.fromUriString("http://www.soil.au:8080/one/two#section-2") .queryParam("price", encodeUtf8("€25")) .queryParam("name", encodeUtf8("Réne e Suzanne")) .queryParam("config", encodeUtf8("{\"f1\":34,\"f2\":\"&?\"}")) .build() .toUriString(); assertThat(url).isEqualTo("http://www.soil.au:8080/one/two?price=%E2%82%AC25&name=R%C3%A9ne+e+Suzanne&config=%7B%22f1%22%3A34%2C%22f2%22%3A%22%26%3F%22%7D#section-2"); } private static String encodeUtf8(String val) throws UnsupportedEncodingException { return URLEncoder.encode(val, "UTF-8"); } }