このような動作を達成する方法はたくさんあります。次のことが可能です。
- ...あなたはレトロフィット・サービス(ユーザー入力フォームなど)を起動する前に、
POST
EDになるように、あなたのオブジェクトを検証し、それが高速に失敗してみましょう。
- ...(あなたがいずれかを持っている場合)あなたのデータ転送は、彼らがされた後、集中管理、オブジェクトをオブジェクト検証...レトロフィット要求コンバータでの集中ごドメインオブジェクトを、検証し、連鎖コンバータ
- を使用ドメインオブジェクトから変換されて送信されるように準備されました
- ...サーバーAPIの実装に依存しています。クライアント側での検証は不要です。サーバーロジックを随時複製する必要はありません。サーバーAPIの検証では、より多くのコードを書くなど、これは私がそのコメントであなたに示唆していたものです。
それらが送信される前に、あなた本当にがリクエストボディを検証する必要がある場合は、最初のオプションで行く必要があります。検証を完全に集中化したい場合は、カスタムRetrofitコンバータを実装して、事前検証を実行できます。 (以下のコードでは、Java 8とGoogle Guava、Retrofit 2、Gsonを少し使用していますが、別のコンポーネントで簡単に再作成できます)。
は、これらを考慮してください。
interface IService {
@POST("/")
Call<String> post(
@Body User user
);
}
final class User {
final String name;
final String group;
User(final String name, final String group) {
this.name = name;
this.group = group;
}
}
今、私たちはレトロフィット-ものを実装することができます。次のmockOkHttpClient
は任意の要求を消費し、HTTP 200 OK
と"OK"
と応答するモックOkHttpClient
です。
private static final OkHttpClient mockOkHttpClient = new OkHttpClient.Builder()
.addInterceptor(chain -> new Response.Builder()
.request(chain.request())
.protocol(HTTP_1_0)
.code(HTTP_OK)
.body(ResponseBody.create(MediaType.parse("application/json"), "\"OK\""))
.build()
)
.build();
それでは、簡単なテストを作成してみましょう:
final Iterable<Retrofit> retrofits = ImmutableList.of(
getAsIsRetrofit(),
getValidatedDomainObjectsRetrofit(),
getValidatedDataTransferObjectsRetrofit()
);
final User user = new User("user", "group");
for (final Retrofit retrofit : retrofits) {
final IService service = retrofit.create(IService.class);
final String message = service.post(user).execute().body();
System.out.println(message);
}
あなたが見ることができるように、それらのそれぞれを実証するための異なる構成でインスタンス化されている3つのレトロフィットインスタンスがあります。
以下のRetrofit
インスタンスは、検証そのものを気にしません。そしてこれは私があなたに行くことをお勧めする別の時です:単にあなたが得たものを投稿して、サーバーAPI実装がそれ自体を処理させるようにします。 HTTP 400 Bad Request
などのような素晴らしい応答を返すAPI実装を考えてみましょう。
private static Retrofit getAsIsRetrofit() {
return new Retrofit.Builder()
.client(mockOkHttpClient)
.baseUrl("http://whatever")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
次Retrofit
インスタンスを検証し、それがGsonやさしい表現に変換(あなたがアプリケーション内のデータ転送オブジェクト変換からドメインオブジェクトがある場合に依存)です前User
オブジェクトを指定:
をprivate static Retrofit getValidatedDomainObjectsRetrofit() {
return new Retrofit.Builder()
.client(mockOkHttpClient)
.baseUrl("http://whatever")
.addConverterFactory(new Converter.Factory() {
@Override
public Converter<?, RequestBody> requestBodyConverter(final Type type, final Annotation[] parameterAnnotations,
final Annotation[] methodAnnotations, final Retrofit retrofit) {
if (type != User.class) {
return null;
}
final Converter<Object, RequestBody> nextConverter = retrofit.nextRequestBodyConverter(this, type, parameterAnnotations, methodAnnotations);
return (Converter<Object, RequestBody>) value -> {
if (value instanceof User) {
final User user = (User) value;
requireNonNull(user.name, "name must not be null");
requireNonNull(user.group, "group must not be null");
}
return nextConverter.convert(value);
};
}
})
.addConverterFactory(GsonConverterFactory.create())
.build();
}
そして、次に出力ストリームに書き込まれる前にデータ転送オブジェクトが検証されます。おそらく最も低レベルのインスタンスです。 requireNonNull
はJDK 8の方法で、あなたが@NotNull
のような何かをしたい場合は、あなたがあなた自身の注釈プロセッサを実装する、または私の実装のアイデアは無用検討し、インターネットでのこのような実装を見つけることができることを
private static Retrofit getValidatedDataTransferObjectsRetrofit() {
final Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new TypeAdapterFactory() {
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
if (typeToken.getRawType() != User.class) {
return null;
}
final TypeAdapter<T> delegateTypeAdapter = gson.getDelegateAdapter(this, typeToken);
return new TypeAdapter<T>() {
@Override
public void write(final JsonWriter out, final T value)
throws IOException {
if (value instanceof User) {
final User user = (User) value;
requireNonNull(user.name, "name must not be null");
requireNonNull(user.group, "group must not be null");
}
delegateTypeAdapter.write(out, value);
}
@Override
public T read(final JsonReader in)
throws IOException {
return delegateTypeAdapter.read(in);
}
};
}
})
.create();
return new Retrofit.Builder()
.client(mockOkHttpClient)
.baseUrl("http://whatever")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
注意。 :)しかし、私は、現状のアプローチが最も好きだと思います。
あなたはそれを必要としていないようです。リクエスト本体が有効かどうかをサーバーに決定させます。 –
@LyubomyrShaydarivしたがって、手動で検証するのが最善の方法です。私はクエリパラメータが持っている検証に似たもっと直感的な方法、例えば 'javax.validation.constraints @ NotNull'を望んでいました。 – OskarD90
私はリクエストをそのまま送信し、サーバがそれを受け入れるか拒否することを意味します。あるいは、あなたがクライアント側でそれを行う必要がある理由がありますか? –