泽西制作媒体类型冲突

我现在正在尝试Jersey,按照此链接在netbeans中设置一个Web服务。 我有我的实体类和我的REST类。 它适用于从javafx2客户端添加,编辑,删除,请求对象(在本例中为Users对象)。

但是,现在我尝试向我的webservice添加一个新方法,以进行一些简单的身份validation。 首先,我在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()发生冲突? 第一个有2个String参数并给出一个Users对象,第二个有2个整数参数并返回一个List对象? 有没有办法解决这个问题,因为我需要一些自定义查询添加到我的webservice …

完成:

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

超类中的代码(AbstractFacade.java)

 public List 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(); } 

问题是,两种方法都使用匹配相同URI的路径模板。 "{a}/{b}"相当于"{c}/{d}" – 就像"{username}/{password}"相当于"{from}/{to}" 。 并且因为两种方法也使用相同的媒体类型,所以存在歧义。 您可以通过在路径模板中使用正则表达式来解决此问题,以使其更具体。 即,因为"{from}/{to}"应始终为数字,您可以通过更改它来消除歧义: "{from: [0-9]+}/{to: [0-9]+}"

无论如何,你确定没有用户会从用户名和密码中选择普通数字吗? 看起来在你的情况下,为两个资源中的每一个使用不同的URI“子空间”会好得多。 例如: login/{username}/{password}ranges/{from}/{to}

但是,设计上几点:

  1. 将密码放在URI中是一个非常糟糕的主意。 从来没有做过! 看看一些现有的经过validation的认证方案 – 不要试图重新发明轮子。
  2. 考虑使用查询参数指定范围 – 例如,如果您有一些收集资源(如“myapp.com/calendar/events”),您可以使用查询参数对范围进行建模 – 例如“myapp.com/calendar/events?from=xxx&to=yyy 。