Jer*_*oss 7 java spring jax-rs jersey spring-data
我正在构建一个REST API,用于在数据库上执行CRUD操作.我的暂定堆栈是Jersey,Spring,Spring Data,JPA和Hibernate.我也使用jersey-spring来提供资源类的实例,以便Spring可以自动装配它们.
API将支持数十个表上的CRUD操作,伴随着由Spring Data存储库支持的JPA实体和DAO.DAO接口和相关DTO系列看起来像这样:
public interface CrudService<T extends PersistedObject> { /* ... */ }
public interface PersonService extends CrudService<Person> { /* ... */ }
public class PersistedObject { /* ... */ }
public class Person extends PersistedObject { /* ... */ }
Run Code Online (Sandbox Code Playgroud)
这是JAX-RS资源类的简化版本:
@Component
@Path("/people")
public class PersonResource {
@Autowired
private PersonService personService;
@Path("/{id}")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Person get(@PathParam("id") String id) {
return personService.findOne(Long.valueOf(id));
}
@POST
@Consumes(MediaType.APPLICATION_JSON)
public Response post(Person person) {
personService.save(person);
return Response.created().build();
}
}
Run Code Online (Sandbox Code Playgroud)
问题是几十个资源类的其余部分看起来几乎相同,唯一的区别是它们在不同的PersistedObject子类及其相应的DAO上运行.我想通过拥有一个可以支持所有实体类型的CRUD操作的资源类来保持DRY,可能是通过多态和巧妙注入DAO.它可能看起来像这样:
@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();
}
}
Run Code Online (Sandbox Code Playgroud)
我需要解决的问题:
resourceTypepath参数中的变量指示用户请求的具体类型,但我不知道如何使用它来获得任何优势.总的来说,我不确定我是在正确的道路上.是否有可能以通用方式实现这一点?
我自己也遇到过这个问题好几次。您可以创建一个通用端点和一个 PersistedObjectDao,它应该一切正常。在Hibernate中,session方法如persist()、merge()和delete()并不关心它得到什么,只要它是一个托管对象或者可以成为一个托管对象(在merge()的情况下) 。由于您仅通过 id 进行查找,并且应该在 PersistedObject 类而不是 Person 类中进行管理,因此 DAO 的功能将正常工作。
这种方法的唯一问题是它破坏了 Enunciate 等文档工具,并使资源 URL 需要全局唯一的 id。/xxx/1 和 /yyy/1 不能共存。findOne 方法将为两者返回相同的对象。这意味着您必须使用 @Inheritance(strategy = InheritanceType.JOINED) 来避免 id 冲突,并在数据库中的所有持久实体中创建全局唯一的 id 列。
因此,我通常创建一个 AbstractPersistedObjectDAO 类并实现 persist()、merge() 和 delete(),并将 findOne() 抽象为子类,以避免在我需要执行 CRUD 以外的操作时无需转换代码。但我通常只是消耗端点上样板的成本,以便我可以使用 Enunciate 生成 REST 文档,并且它为我提供了一个类,以便在将来需要时采用其他方法。
| 归档时间: |
|
| 查看次数: |
816 次 |
| 最近记录: |