Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何实现这个RESTAPI并保持干爽?_Java_Spring_Jersey_Jax Rs_Spring Data - Fatal编程技术网

Java 如何实现这个RESTAPI并保持干爽?

Java 如何实现这个RESTAPI并保持干爽?,java,spring,jersey,jax-rs,spring-data,Java,Spring,Jersey,Jax Rs,Spring Data,我正在构建一个RESTAPI,用于在数据库上执行CRUD操作。我的暂定堆栈是Jersey、Spring、Spring数据、JPA和Hibernate。我还使用jersey spring提供资源类的实例,以便spring可以自动连接它们 该API将支持几十个表上的CRUD操作,并伴随着由Spring数据存储库支持的JPA实体和DAO。DAO接口和相关DTO系列如下所示: public interface CrudService<T extends PersistedObject> {

我正在构建一个RESTAPI,用于在数据库上执行CRUD操作。我的暂定堆栈是Jersey、Spring、Spring数据、JPA和Hibernate。我还使用jersey spring提供资源类的实例,以便spring可以自动连接它们

该API将支持几十个表上的CRUD操作,并伴随着由Spring数据存储库支持的JPA实体和DAO。DAO接口和相关DTO系列如下所示:

public interface CrudService<T extends PersistedObject> { /* ... */  }
public interface PersonService extends CrudService<Person> { /* ... */  }

public class PersistedObject { /* ... */ }
public class Person extends PersistedObject { /* ... */ }
@Component
@Path("/{resourceType}")
public class CrudResource {

    @Autowired
    private CrudService crudService;

    @Path("/{id}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public PersistedObject get(@PathParam("id") String id) {
        return crudService.findOne(Long.valueOf(id));
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response post(PersistedObject entity) {
        crudService.save(entity);
        return Response.created().build();
    }
}
问题是几十个资源类中的其余部分看起来几乎相同,唯一的区别是它们在不同的PersistedObject子类及其对应的DAO上操作。我希望有一个资源类可以支持所有实体类型上的CRUD操作,这可能是通过多元论和DAO的巧妙注入来实现的。它可能看起来像这样:

public interface CrudService<T extends PersistedObject> { /* ... */  }
public interface PersonService extends CrudService<Person> { /* ... */  }

public class PersistedObject { /* ... */ }
public class Person extends PersistedObject { /* ... */ }
@Component
@Path("/{resourceType}")
public class CrudResource {

    @Autowired
    private CrudService crudService;

    @Path("/{id}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public PersistedObject get(@PathParam("id") String id) {
        return crudService.findOne(Long.valueOf(id));
    }

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response post(PersistedObject entity) {
        crudService.save(entity);
        return Response.created().build();
    }
}
我需要解决的问题是:

  • 如果资源方法接受并返回PersistedObject,Jersey/Jackson如何知道如何序列化/反序列化?path参数中的
    resourceType
    变量表示用户请求的具体类型,但我不知道如何利用这一点
  • 当Spring提供资源类实例时,它如何知道要注入哪个DAO

总的来说,我不确定我是否走上了正确的道路。有没有可能以一种通用的方式实现这一点?

我自己也遇到过几次这个问题。您可以创建一个通用端点和一个PersistedObjectDao,这一切都可以正常工作。在Hibernate中,会话方法(如persist()、merge()和delete())不关心它得到什么,只要它是托管对象或可以成为托管对象(在merge()的情况下)。由于您只通过id进行查找,并且应该在PersistedObject类而不是Person类中进行管理,因此DAO的功能将正常工作

这种方法唯一的问题是,它破坏了诸如Enouncate之类的文档工具,并使资源URL需要全局唯一的ID/xxx/1和/yyy/1不能共存。findOne方法将为两者返回相同的对象。这意味着您必须使用@heritance(strategy=InheritanceType.JOINED)来避免id冲突,并在数据库中的所有持久化实体之间创建一个全局唯一的id列


因此,我通常创建一个AbstractPersistedObjectDAO类,实现persist()、merge()和delete(),并将findOne()抽象为一个子类,以避免在需要执行CRUD以外的操作时需要强制转换代码。但是我通常只需要承担端点上样板文件的成本,这样我就可以使用Enouncate生成REST文档,它给了我一个类,以便将来在需要时使用其他方法。

不确定您是否以任何方式与JAX-RS绑定,但是Spring项目数据系列附带了自动公开的模块由Spring数据存储库以超媒体驱动的方式管理的实体。它基于SpringMVC

因此,您基本上可以免费获得实体上的CRUD操作,透明地公开查询方法,并能够根据您的需要调整和调整所有内容

以下是一些有用的链接,您可能希望浏览这些链接以获取更多信息:

  • -摘自可用的Spring数据手册
  • -一个更高级的示例,展示了如何使用自定义的更复杂的功能扩展导出的实体,以超媒体驱动的方式实现业务流程