16

私は現在、Jersey を試しています。このリンクに従って、netbeans で Web サービスをセットアップしました。エンティティ クラスと REST クラスがあります。これは、javafx2 クライアントからオブジェクト (この場合は Users オブジェクト) を追加、編集、削除、要求するために機能します。

ただし、簡単な認証のために Web サービスに新しいメソッドを追加しようとしています。まず、Users.java ファイルに新しい名前付きクエリ (Users.login) を追加しました。

@NamedQueries({
    @NamedQuery(name = "Users.findAll", query = "SELECT u FROM Users u"),
    @NamedQuery(name = "Users.login", query = "SELECT u FROM Users u WHERE u.username = :username AND u.password = :password"),
    @NamedQuery(name = "Users.findById", query = "SELECT u FROM Users u WHERE u.id = :id"),
    @NamedQuery(name = "Users.findByUserlevel", query = "SELECT u FROM Users u WHERE u.userlevel = :userlevel"),
    @NamedQuery(name = "Users.findByDisabled", query = "SELECT u FROM Users u WHERE u.disabled = :disabled")
})

その後、UsersFacadeREST.java ファイル (Netbeans 7.2 で生成) に次のコードを追加しました。

@GET
@Path("{username}/{password}")
@Produces({"application/xml", "application/json"})
public Users login(@PathParam("username") String username, @PathParam("password") String password) {
    return em.createNamedQuery("login", Users.class)
            .setParameter("username", username)
            .setParameter("password", password)
            .getSingleResult();
}

ただし、Web サービスをデプロイしようとすると、次のエラーが表示されます。

SEVERE: Producing media type conflict. The resource methods public entities.Users service.UsersFacadeREST.login(java.lang.String,java.lang.String) and public java.util.List service.UsersFacadeREST.findRange(java.lang.Integer,java.lang.Integer) can produce the same media type

私はこれに慣れていないので、login() メソッドが findRange() と競合する理由がわかりません。1 つ目は 2 つの文字列パラメーターを持ち、Users オブジェクトを提供し、2 つ目は 2 つの整数パラメーターを持ち、List オブジェクトを返しますか? Web サービスにいくつかのカスタム クエリを追加する必要があるため、この問題を解決する方法はありますか...

完了するには:

@GET
@Path("{from}/{to}")
@Produces({"application/xml", "application/json"})
public List<Users> findRange(@PathParam("from") Integer from, @PathParam("to") Integer to) {
    return super.findRange(new int[]{from, to});
}

スーパークラスのコード (AbstractFacade.java)

public List<T> findRange(int[] range) {
    javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
    cq.select(cq.from(entityClass));
    javax.persistence.Query q = getEntityManager().createQuery(cq);
    q.setMaxResults(range[1] - range[0]);
    q.setFirstResult(range[0]);
    return q.getResultList();
}
4

1 に答える 1

28

問題は、両方の方法が同じ URI に一致するパス テンプレートを使用していることです。"{a}/{b}""{c}/{d}"-と同等であり、同様に"{username}/{password}"は と同等"{from}/{to}"です。また、どちらの方法も同じメディア タイプを使用するため、あいまいさが生じます。これは、パス テンプレートで正規表現を使用してより具体的にすることで修正できます。つまり、"{from}/{to}"常に数値である必要があるため、次のように変更することで曖昧さをなくすことができます"{from: [0-9]+}/{to: [0-9]+}"

とにかく、ユーザー名とパスワードから単純な数字を選ぶユーザーはいないと思いますか? あなたの場合、2つのリソースのそれぞれに異なるURI「サブスペース」を使用する方がはるかに良いようです。例:login/{username}/{password}ranges/{from}/{to}.

しかし、設計上のいくつかのポイント:

  1. URI にパスワードを入れるのは非常に悪い考えです。絶対にしないでください!既存の実績のある認証方式をいくつか見てください。車輪の再発明を試みないでください。
  2. 範囲を指定するためにクエリ パラメーターを使用することを検討してください。たとえば、コレクション リソース ("myapp.com/calendar/events" など) がある場合は、クエリ パラメーターを使用して範囲をモデル化できます。たとえば、"myapp.com/calendar/events?from=xxx&to=yyy .
于 2012-10-14T19:50:07.077 に答える