gpt4 book ai didi

java - 我怎样才能实现这个 REST API 并保持 DRY?

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:30:34 24 4
gpt4 key购买 nike

我正在构建一个 REST API 来对数据库执行 CRUD 操作。我暂定的堆栈是 Jersey、Spring、Spring Data、JPA 和 Hibernate。我还使用 jersey-spring 来提供资源类的实例,以便 Spring 可以 Autowiring 它们。

该 API 将支持对数十个表进行 CRUD 操作,并伴随有由 Spring Data 存储库支持的 JPA 实体和 DAO。 DAO 接口(interface)系列和相关的 DTO 看起来像这样:

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

public class PersistedObject { /* ... */ }
public class Person extends PersistedObject { /* ... */ }

这是 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();
}
}

问题是几十个资源类的其余部分看起来几乎相同,唯一的区别是它们在不同的 PersistedObject 子类及其相应的 DAO 上运行。我想通过拥有一个可以支持所有实体类型的 CRUD 操作的资源类来保持 DRY,大概是通过多态和 DAO 的巧妙注入(inject)。它可能看起来像这样:

@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 如何知道如何序列化/反序列化?路径参数中的 resourceType 变量指示用户请求的具体类型,但我不知道如何利用它来获得任何优势。
  • 当 Spring 提供资源类实例时,它如何知道要注入(inject)哪个 DAO?

总的来说,我不确定自己是否走在正确的道路上。是否有可能以通用方式实现它?

最佳答案

我自己也遇到过几次这个问题。您可以创建一个通用端点和一个 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() 抽象为一个子类,以避免在我需要做更多事情时强制转换代码比增删改查。但我通常只承担端点上样板的成本,这样我就可以使用 Enunciate 生成 REST 文档,并且它为我提供了一个类,以便在未来需要时采用其他方法。

关于java - 我怎样才能实现这个 REST API 并保持 DRY?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15262425/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com