java - 通过 JAX-RS 实现 REST 服务的可重用性

标签 java web-services rest jax-rs reusability

我有一个简单的类似 REST 的服务,在 JAX-RS 中实现维护 Foo 的。它使用 POST foos 创建 foos,使用 GET foos 列出 foos,并使用 GET foo/42 详细说明给定的 foo(其中 42 是给定的 foo id)。

public class FooService {

  @POST
  @Path("/foos")
  public Foo create(Foo foo){
    entityManager.getTransaction().begin();
    entityManager.persist(foo);
    entityManager.getTransaction().commit();
    return foo;
  }

  @GET
  @Path("/foos")
  public List<Foo> get(){
        List<Foo> foos = //more-or-less generic JPA querying-code
        return foos;
  }

  @GET
  @Path("/foos/{id}")
  public Foo get(@PathParam("id") int id){
        Foo foo = //more-or-less generic JPA querying-code
        return foo;
  }
}

现在,如果我也有类似的服务来维护 Bar,我该如何优雅地避免代码重复呢?

public class BarService {

  @POST
  @Path("/bars")
  public Bar create(Bar bar){
    entityManager.getTransaction().begin();
    entityManager.persist(bar);
    entityManager.getTransaction().commit();
    return bar;
  }

  @GET
  @Path("/bars")
  public List<Bar> get(){
        List<Bar> bars = //more-or-less generic JPA querying-code
        return bars;
  }

  @GET
  @Path("/bars/{id}")
  public Bar get(@PathParam("id") int id){
        Bar bar = //more-or-less generic JPA querying-code
        return bar;
  }
}

唯一的区别是 @Path 注释中指定的 path 值。由于该值应该是静态的(在编译时可见),因此不可能创建如下所示的 AbstracService 类:

public abstract class AbstracService<X> {

  //abstrac static is not possible
  public abstract static final String PATH;

  @POST
  @Path(PATH)
  public X create(X entity){ ... }

  @GET
  @Path(PATH)
  public List<X> get(){ ... }

  @GET
  @Path(PATH + "/{id}")
  public X get(@PathParam("id") int id){ ... }
}


public class FooService extends AbstractService<Foo>{
      //just override the PATH to be "foos"
}    

public class BarService extends AbstractService<Bar>{
      //just override the PATH to be "bars"
}    

我是否需要重写每个服务方法来调整 @Path 并调用 super 的实现?

上面的类 FooServiceBarService 太相似了,无法让我对可重用性的钟声保持沉默。

最佳答案

这种模式在我的资源类中很常见

@Path("foo")
public class FoosResource {
    @GET  // get all `Foo` resources
    ...
    @GET 
    @Path("{id}")  // get `Foo` with this id
    ...
    @POST // create new `Foo` in `foo` collection
    ...
    @PUT 
    @Path("{id}")  // Update `Foo` with this id
}

你明白了。重点是集合的名称位于资源类上,而不是像您那样位于资源方法级别上

@Path("foo/{id}")

无论如何,您都需要一个 @Path 来使该类成为资源类,为什么不为其使用最合适的名称。

我要补充的另一件事是我经常做的事情。我在抽象类中添加了一个 Class 字段,并带有一个可以将 Class 传递给的构造函数参数。然后在具体的类实现中,我super(Foo.class)。这样,JPA 就可以访问该类,从而更容易使用类型查询。

关于java - 通过 JAX-RS 实现 REST 服务的可重用性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29398629/

相关文章:

java - 反序列化 javax.json.JsonObject

java - 使用 java :module scoped resources 使用 EJB 3 和 glassfish 进行 JUnit 测试

java - jstat和JSP配置

c# - 图像转换器: Parameter is not valid for a byte array

xml - 通过 HTTPS 为 REST 服务构建什么样的脚本/应用程序

rest - HTTP 方法 POST 一定是幂等的吗?

java - 奇怪的行为 Datediff java Datediff sql

java - Jackson ObjectMapper 如何将 byte[] 传输到 String 以及如何在没有对象类的情况下翻译它?

web-services - 列出SharePoint网站中的所有警报,而不使用SharePoint API?

java - Jersey 记录过滤器