URI リンク

このセクションでは、URI を準備するために Spring Framework で使用可能なさまざまなオプションについて説明します。

UriComponents

UriComponentsBuilder は、次の例に示すように、変数を持つ URI テンプレートから URI を作成できます。

  • Java

  • Kotlin

UriComponents uriComponents = UriComponentsBuilder
		.fromUriString("https://example.com/hotels/{hotel}") (1)
		.queryParam("q", "{q}") (2)
		.encode() (3)
		.build(); (4)

URI uri = uriComponents.expand("Westin", "123").toUri(); (5)
1URI テンプレートを使用した静的ファクトリメソッド。
2URI コンポーネントを追加または置換します。
3URI テンプレートと URI 変数をエンコードするようリクエストします。
4UriComponents をビルドします。
5 変数を展開し、URI を取得します。
val uriComponents = UriComponentsBuilder
		.fromUriString("https://example.com/hotels/{hotel}") (1)
		.queryParam("q", "{q}") (2)
		.encode() (3)
		.build() (4)

val uri = uriComponents.expand("Westin", "123").toUri() (5)
1URI テンプレートを使用した静的ファクトリメソッド。
2URI コンポーネントを追加または置換します。
3URI テンプレートと URI 変数をエンコードするようリクエストします。
4UriComponents をビルドします。
5 変数を展開し、URI を取得します。

前述の例は、次の例に示すように、1 つのチェーンに統合し、buildAndExpand で短縮できます。

  • Java

  • Kotlin

URI uri = UriComponentsBuilder
		.fromUriString("https://example.com/hotels/{hotel}")
		.queryParam("q", "{q}")
		.encode()
		.buildAndExpand("Westin", "123")
		.toUri();
val uri = UriComponentsBuilder
		.fromUriString("https://example.com/hotels/{hotel}")
		.queryParam("q", "{q}")
		.encode()
		.buildAndExpand("Westin", "123")
		.toUri()

次の例に示すように、URI に直接移動することで(エンコードを暗示する)、さらに短くすることができます。

  • Java

  • Kotlin

URI uri = UriComponentsBuilder
		.fromUriString("https://example.com/hotels/{hotel}")
		.queryParam("q", "{q}")
		.build("Westin", "123");
val uri = UriComponentsBuilder
		.fromUriString("https://example.com/hotels/{hotel}")
		.queryParam("q", "{q}")
		.build("Westin", "123")

次の例に示すように、完全な URI テンプレートを使用してさらに短縮できます。

  • Java

  • Kotlin

URI uri = UriComponentsBuilder
		.fromUriString("https://example.com/hotels/{hotel}?q={q}")
		.build("Westin", "123");
val uri = UriComponentsBuilder
		.fromUriString("https://example.com/hotels/{hotel}?q={q}")
		.build("Westin", "123")

UriBuilder

Spring MVC および Spring WebFlux

UriComponentsBuilder は UriBuilder を実装しています。UriBuilderFactory を使用して、UriBuilder を作成できます。UriBuilderFactory と UriBuilder は、ベース URL、エンコード設定、その他の詳細などの共有構成に基づいて、URI テンプレートから URI を構築するプラグ可能なメカニズムを提供します。

RestTemplate および WebClient を UriBuilderFactory で構成して、URI の準備をカスタマイズできます。DefaultUriBuilderFactory は、UriComponentsBuilder を内部で使用し、共有構成オプションを公開する UriBuilderFactory のデフォルト実装です。

次の例は、RestTemplate を構成する方法を示しています。

  • Java

  • Kotlin

// import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;

String baseUrl = "https://example.org";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);

RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(factory);
// import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode

val baseUrl = "https://example.org"
val factory = DefaultUriBuilderFactory(baseUrl)
factory.encodingMode = EncodingMode.TEMPLATE_AND_VALUES

val restTemplate = RestTemplate()
restTemplate.uriTemplateHandler = factory

次の例では、WebClient を構成します。

  • Java

  • Kotlin

// import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;

String baseUrl = "https://example.org";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl);
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);

WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
// import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode

val baseUrl = "https://example.org"
val factory = DefaultUriBuilderFactory(baseUrl)
factory.encodingMode = EncodingMode.TEMPLATE_AND_VALUES

val client = WebClient.builder().uriBuilderFactory(factory).build()

さらに、DefaultUriBuilderFactory を直接使用することもできます。UriComponentsBuilder の使用に似ていますが、次の例に示すように、静的ファクトリメソッドの代わりに、構成と設定を保持する実際のインスタンスです。

  • Java

  • Kotlin

String baseUrl = "https://example.com";
DefaultUriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(baseUrl);

URI uri = uriBuilderFactory.uriString("/hotels/{hotel}")
		.queryParam("q", "{q}")
		.build("Westin", "123");
val baseUrl = "https://example.com"
val uriBuilderFactory = DefaultUriBuilderFactory(baseUrl)

val uri = uriBuilderFactory.uriString("/hotels/{hotel}")
		.queryParam("q", "{q}")
		.build("Westin", "123")

URI エンコーディング

Spring MVC および Spring WebFlux

UriComponentsBuilder は、2 つのレベルでエンコードオプションを公開します。

どちらのオプションも、非 ASCII 文字と不正な文字をエスケープされたオクテットに置き換えます。ただし、最初のオプションは、URI 変数に表示される予約された意味で文字を置き換えます。

";" を検討してください。これはパスでは有効ですが、意味は予約されています。最初のオプションは ";" を置き換えます。URI 変数には "%3B" が含まれますが、URI テンプレートには含まれません。対照的に、2 番目のオプションはパス内の正当な文字であるため、";" を置き換えることはありません。

ほとんどの場合、最初のオプションは URI 変数を完全にエンコードされる不透明(OPAQUE)データとして扱うため、期待どおりの結果が得られる可能性があります。2 番目のオプションは、URI 変数に意図的に予約文字が含まれている場合に役立ちます。2 番目のオプションは、URI 変数をまったく展開しない場合にも役立ちます。これは、偶然に URI 変数のように見えるものもエンコードするためです。

次の例では、最初のオプションを使用しています。

  • Java

  • Kotlin

URI uri = UriComponentsBuilder.fromPath("/hotel list/{city}")
		.queryParam("q", "{q}")
		.encode()
		.buildAndExpand("New York", "foo+bar")
		.toUri();

// Result is "/hotel%20list/New%20York?q=foo%2Bbar"
val uri = UriComponentsBuilder.fromPath("/hotel list/{city}")
		.queryParam("q", "{q}")
		.encode()
		.buildAndExpand("New York", "foo+bar")
		.toUri()

// Result is "/hotel%20list/New%20York?q=foo%2Bbar"

次の例に示すように、URI に直接移動することで、前述の例を短縮できます(エンコードを意味します)。

  • Java

  • Kotlin

URI uri = UriComponentsBuilder.fromPath("/hotel list/{city}")
		.queryParam("q", "{q}")
		.build("New York", "foo+bar");
val uri = UriComponentsBuilder.fromPath("/hotel list/{city}")
		.queryParam("q", "{q}")
		.build("New York", "foo+bar")

次の例に示すように、完全な URI テンプレートを使用してさらに短縮できます。

  • Java

  • Kotlin

URI uri = UriComponentsBuilder.fromUriString("/hotel list/{city}?q={q}")
		.build("New York", "foo+bar");
val uri = UriComponentsBuilder.fromUriString("/hotel list/{city}?q={q}")
		.build("New York", "foo+bar")

WebClient と RestTemplate は、UriBuilderFactory 戦略を通じて内部で URI テンプレートを拡張およびエンコードします。次の例に示すように、どちらもカスタム戦略で構成できます。

  • Java

  • Kotlin

String baseUrl = "https://example.com";
DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(baseUrl)
factory.setEncodingMode(EncodingMode.TEMPLATE_AND_VALUES);

// Customize the RestTemplate..
RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(factory);

// Customize the WebClient..
WebClient client = WebClient.builder().uriBuilderFactory(factory).build();
val baseUrl = "https://example.com"
val factory = DefaultUriBuilderFactory(baseUrl).apply {
	encodingMode = EncodingMode.TEMPLATE_AND_VALUES
}

// Customize the RestTemplate..
val restTemplate = RestTemplate().apply {
	uriTemplateHandler = factory
}

// Customize the WebClient..
val client = WebClient.builder().uriBuilderFactory(factory).build()

DefaultUriBuilderFactory 実装は、UriComponentsBuilder を内部的に使用して URI テンプレートを展開およびエンコードします。ファクトリとして、以下のエンコードモードのいずれかに基づいて、エンコードへのアプローチを構成する単一の場所を提供します。

  • TEMPLATE_AND_VALUES: 前のリストの最初のオプションに対応する UriComponentsBuilder#encode() を使用して、URI テンプレートを事前エンコードし、展開時に URI 変数を厳密にエンコードします。

  • VALUES_ONLY: URI テンプレートをエンコードせず、代わりに、UriUtils#encodeUriVariables を使用して URI 変数をテンプレートに展開する前に URI 変数に厳密なエンコードを適用します。

  • URI_COMPONENT: 前のリストの 2 番目のオプションに対応する UriComponents#encode() を使用して、URI 変数が展開された後に URI コンポーネント値をエンコードします。

  • NONE: エンコードは適用されません。

RestTemplate は、歴史的な理由と下位互換性のために EncodingMode.URI_COMPONENT に設定されています。WebClient は、5.0.x の EncodingMode.URI_COMPONENT から 5.1 の EncodingMode.TEMPLATE_AND_VALUES に変更された DefaultUriBuilderFactory のデフォルト値に依存しています。