次のように定義されたサービスがあります。
public String getData(@QueryParam("date") Date date)
私はクライアントからJava.util.Date
を渡そうとしています(これは一般的なHTTPクライアントやブラウザではなく、CXFのjaxrs:clientです)。
私のサービスは、HTTP URLでThu Mar 01 22:33:10 IST 2012
として日付を受け取ります。 CXFはこの文字列を使用してDate
オブジェクトを作成できないため、クライアントは404エラーを受け取ります。サービス側でParameterHandler
を使用しようとしましたが、特定の形式の日付を期待していないため、正常に解析できません。
この投稿 のように、Date
を渡すことはそのままで動作するはずですが、基本的なケースを動作させることはできません。クライアントからサービスにDateオブジェクトを正常に渡すために何かする必要がありますか?ヘルプを感謝します。
ありがとう
問題は、JAX-RSがパラメーターのアンバンドリングを次の2つの方法のいずれかで行うことを指示していることです。
valueOf(String)
メソッドがあります。あなたの場合、Dateは、クライアントが送信している入力形式を処理できないDate(String)
コンストラクターによってアンバンドルされています。これを改善するためのオプションがいくつかあります。
オプション1
クライアントに送信する前に日付の形式を変更するよう依頼してください。これは理想ですが、おそらく達成するのが最も難しいでしょう!
オプション2
クレイジーな日付形式を処理します。これのオプションは次のとおりです。
文字列を受け入れるようにメソッドシグネチャを変更します。それからDateオブジェクトを作成し、それが失敗した場合は、独自のカスタムSimpleDateFormatクラスを使用して解析します。
_static final DateFormat CRAZY_FORMAT = new SimpleDateFormat("");
public String getData(@QueryParam("date") String dateString) {
final Date date;
try {
date = new Date(dateString); // yes, I know this is a deprecated method
} catch(Exception e) {
date = CRAZY_FORMAT.parse(dateString);
}
}
_
上記のロジックを実行する独自のパラメータークラスを定義します。ロジックを起動する文字列コンストラクターまたは静的valueOf(String)
メソッドを指定します。すべてのことを言って完了した日付を取得します。
_public class DateParameter implements Serializable {
public static DateParameter valueOf(String dateString) {
try {
date = new Date(dateString); // yes, I know this is a deprecated method
} catch(Exception e) {
date = CRAZY_FORMAT.parse(dateString);
}
}
private Date date;
// Constructor, Getters, Setters
}
public String getData(@QueryParam("date") DateParameter dateParam) {
final Date date = dateParam.getDate();
}
_
または、最後に、日付のパラメーターハンドラーを登録できます。そのロジックは、上記の他のオプションで説明したものと単純に同じです。少なくともCXFを使用する必要があることに注意してください2.5.3デフォルトのアンバンドリングロジックを試行する前にパラメーターハンドラーを評価するため
_public class DateHandler implements ParameterHandler<Date> {
public Map fromString(String s) {
final Date date;
try {
date = new Date(dateString); // yes, I know this is a deprecated method
} catch(Exception e) {
date = CRAZY_FORMAT.parse(dateString);
}
}
}
_
Percepitonの答え は非常に便利でしたが、ParameterHandler
はApache-cxf 3.0で非推奨になりました。 Apache-cxf 3.0移行ガイド を参照してください。
CXF JAX-RS ParameterHandlerは削除されました。JAX-RS2.0 ParamConverterProviderを使用してください。
ParamConverterProvider
を使用して例を追加します。
public class DateParameterConverterProvider implements ParamConverterProvider {
@Override
public <T> ParamConverter<T> getConverter(Class<T> type, Type type1, Annotation[] antns) {
if (Date.class.equals(type)) {
@SuppressWarnings("unchecked")
ParamConverter<T> paramConverter = (ParamConverter<T>) new DateParameterConverter();
return paramConverter;
}
return null;
}
}
public class DateParameterConverter implements ParamConverter<Date> {
public static final String format = "yyyy-MM-dd"; // set the format to whatever you need
@Override
public Date fromString(String string) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
try {
return simpleDateFormat.parse(string);
} catch (ParseException ex) {
throw new WebApplicationException(ex);
}
}
@Override
public String toString(Date t) {
return new SimpleDateFormat(format).format(t);
}
}
@SuppressWarnings
は、コンパイル中の「未チェックまたは安全でない操作」の警告を抑制するために必要です。詳細については、「 未チェックのキャスト警告に対処する方法 」を参照してください。
ParamConverterProvider
はプロバイダーとして登録できます。ここに私がそれをした方法があります:
<jaxrs:server id="myService" address="/rest">
<jaxrs:serviceBeans>
...
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="dateParameterConverterProvider" />
</jaxrs:providers>
</jaxrs:server>
<bean id="dateParameterConverterProvider" class="myPackage.DateParameterConverterProvider"/>
詳細については、 Apache-cxf JAX-RS:Services Configuration を参照してください。
カスタムDateParamクラスを使用するのが最も安全なオプションのようです。次に、そのメソッドシグネチャを基にして、valueOf()メソッドまたはクラスコンストラクター内にい変換ロジックを実装できます。また、プレーンな文字列を使用するよりも自己文書化されています
@Perception
は、オプション2で、日付を処理できることを示唆しています。ただし、次を使用する必要があります。
private Date getDateFromString(String dateString) {
try {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date date = df.parse(dateString);
return date;
} catch (ParseException e) {
//WebApplicationException ...("Date format should be yyyy-MM-dd'T'HH:mm:ss", Status.BAD_REQUEST);
}
}
リソース内から次のように呼び出します
Date date = getDateFromString(dateString);//dateString is query param.