System.out.println(
new URI("http", "example.com", "/servlet", "a=x%20y", null));
結果はhttp://example.com/servlet?a=x%2520y
で、クエリ パラメータの値が指定された値と異なります。奇妙ですが、これは Javadoc に従います。
「パーセント文字 ('%') は、これらのコンストラクターによって常に引用されます。」
デコードされた文字列を渡すa=x y
と、妥当な (?) 結果が得られa=x%20y
ます。
しかし、クエリ パラメータの値に「&」文字が含まれている場合はどうなるでしょうか。これは、たとえば、値がクエリ パラメータを含む URL 自体である場合に発生します。この (間違った) クエリ文字列を見てください:
a=b&c
. アンパサンドはここでエスケープする必要があります ( )。そうしないと、これはクエリ パラメーターおよびゴミとa=b%26c
見なされる可能性があります( )。これを URI コンストラクターに渡すと、エンコードされ、間違った URL が返されます。a=b
c
...?a=b%2526c
この問題により、java.util.URI が役に立たなくなるようです。ここで何か不足していますか?
回答のまとめ
java.net.URI は、URI のクエリ部分の存在を認識していますが、スキーマごとに異なる可能性があるクエリ部分の内部構造は理解していません。たとえば、java.net.URI は HTTP クエリ部分の内部構造を理解していません。java.net.URI がクエリを不透明な文字列と見なし、それを変更しなかった場合、これは問題になりません。ただし、HTTP URL を壊す一般的なパーセント エンコーディング アルゴリズムを適用しようとします。
したがって、コンストラクターがあるにもかかわらず、URI クラスを使用して URL をその部分から確実に組み立てることはできません。また、Java 7 の時点で、相対化操作の実装はかなり制限されており、ある URL が別の URL のプレフィックスである場合にのみ機能することにも言及します。私が java.net.URI に興味を持った理由は、これら 2 つの機能 (およびこれらの目的のためのより無駄のないインターフェース) でしたが、どちらも私にとってはうまくいきませんでした。
最後に、解析に java.net.URL を使用し、部分から URL を組み立てて 2 つの URL を相対化するコードを書きました。Apache HttpClient の URIBuilder クラスもチェックしましたが、HTTP クエリ文字列の内部は理解できますが、4.3 の時点で、クエリ部分全体を処理する際に java.net.URI のようなエンコーディングで同じ問題が発生します。