はじめに
Webアプリケーションインターフェイスからデータを転送する方法はいくつかありますが、おそらく最も一般的なのは、MIMEタイプの
application/x-www-form-urlencoded
フォームを送信することです。 別のオプションは
multipart/form-data
です。
MVCフレームワークのコントローラーは、受信用のサーバーテクノロジーとして使用できます( Spring MVC 、 Java Server Pages 、 Java Server Facesは、主要なJavaテクノロジーから言及する必要があります。しかし、これらのフレームワークは、Javaまたはニーズフレームワークが許可するものから離れたステップ。RESTインターフェースをアプリケーションのバックエンドに公開する場合、フロントエンド開発は単純化されます。 onizatora選択肢が大幅に拡大: Apacheの速度 、 FreeMarkerのトゥルービュー/コントローラに関連付けされ、その後、サーバー側でフォームデータをビーナで書かれているが(Spirng MVCはよく最新に統合することを言及する価値がある)、JSFはまた、遺伝的問題を観察しました。..エンコーディングについては、別の記事のトピックを検討します。
JAX-RSの簡単な紹介は、 前の記事で説明しました 。 また、JAX-RSを介して公開されるインターフェースは、フォームデータを使用して
GET
および
POST
リクエストを受け入れることができます。 この記事では、非
latin-1
を使用する場合のこのアプローチの問題について説明します。
JAX-RSでのフォームデータの取得
フォームからメソッドにパラメーターを注入するためのアノテーションがいくつかあります:
@Form
、
@FormParam
。
POST
要求の場合、
@FormParam
GET
in動作の
@FormParam
同等です。 小さな例外を除いて:utf-8使用時の動作。
GET
メソッドを使用する場合、
urlencoded
から文字列へのデコードは問題なく発生します。
POST
、
Content-Type
で
charset=utf-8
を指定する
POST
も必要です。これにより、
urlencoded
からデコードするとき
urlencoded
、バイトストリームがLatin-1ではなくUTF-8に変換されます(デフォルトの動作)。
ブラウザ
ブラウザ(またはjqueryなど)はエンコーディングを指定しないため、古いUTF-8 CPが含まれている場合、フォームフィールドの値が誤って解釈されます。
Content-Type: application/x-www-form-urlencoded; charset=utf-8
ヘッダーを明示的に指定することにより、jqueryを使用する場合、この問題は回避されます。application
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Content-Type: application/x-www-form-urlencoded; charset=utf-8
。 jsのないフォームの場合、フォームにenctypeを指定して成功しませんでした。
Jboss resteasy
もちろん、疑問が生じます。データが他のアプリケーションから取得される場合は、 Form注釈を使用する必要がありますか? 私たちの場合、その使用はDRYの原則から正当化されます。同じメソッドをクライアントフォームとこのAPIを使用する外部アプリケーションの両方で使用できます。
Resteasyクライアントフレームワークを使用する場合、いくつかのオプションが可能です。 たとえば、必要なメソッドに
@HeaderParam("Content-Type")
を追加できます。
@Path("/") public interface Rest { @POST @Path("test") public String test(@FormParam("q") String query, @HeaderParam("Content-Type") String contentType); }
使用法は次のようになります。
Rest client = ProxyFactory.create(Rest.class, url); client.test(query, "application/x-www-form-urlencode; charset=utf-8");
ただし、
Content-Type: application/x-www-form-urlencoded
ヘッダーに
charset
フィールドを追加するクライアントインターセプターを使用する方がより正確で便利です。 次のように実装されます。
@ClientInterceptor @HeaderDecoratorPrecedence public class RestInterceptor implements ClientExecutionInterceptor { public static final String FORM_CONTENT_TYPE = "application/x-www-form-urlencoded"; public static final String FORM_CONTENT_TYPE_WITH_CHARSET = "application/x-www-form-urlencoded; charset=utf-8"; @Override public ClientResponse execute(ClientExecutionContext context) throws Exception { String contentType = context.getRequest().getHeaders().getFirst(HttpHeaders.CONTENT_TYPE); if (formWithoutCharset(contentType)) { context.getRequest().header(HttpHeaders.CONTENT_TYPE, FORM_CONTENT_TYPE_WITH_CHARSET); } return context.proceed(); } private boolean formWithoutCharset(String contentType) { return contentType != null && contentType.contains(FORM_CONTENT_TYPE) && ! contentType.contains("charset"); } }
もちろん、インターセプターのこのバリアントは理想的ではありません。
latin-1
フォームを送信したい可能性があります...しかし、これはクライアントコードを簡素化する最初のステップです。
有効にするには、フレームワークの初期化手順をわずかに修正する必要があります。
public static void initResteasy() { ResteasyProviderFactory factory = ResteasyProviderFactory.getInstance(); RegisterBuiltin.register(factory); InterceptorRegistry<ClientExecutionInterceptor> registry = factory.getClientExecutionInterceptorRegistry(); registry.register(new RestInterceptor()); }
その後、
ClientRequest
を使用するとき、およびリクエストの送信プロセスでプロキシオブジェクトを使用するとき、
application/x-www-form-urlencoded
で
Content-Type
ヘッダーがあり、
charset
がない場合、それを含むヘッダーが付加されます。