【问题标题】:Spring data REST advanced resourcesSpring Data REST进阶资源
【发布时间】:2017-07-12 19:56:46
【问题描述】:

我只是为我的应用实现 REST 端点,我不确定哪种方式是最佳实践。

我以这种方式获取所有实体

@GetMapping("/offers")
    @Timed
    public ResponseEntity<List<Offer>> getAllOffers(@ApiParam Pageable pageable)
        throws URISyntaxException {
        log.debug("REST request to get a page of Offers");
        Page<Offer> page = offerService.findAll(pageable);
        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/offers");
        return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
    }

但是我应该怎么做,例如,如果我只想要某些特定 projectId 的报价。

@Query("FROM Offer o WHERE o.project.id = :projectId")
List<Offer> findAllByProject(@Param("projectId") Long projectId);

Q1 这个存储库调用的 REST 方法应该是什么样的?什么是正确的映射路径或参数插入。

Q2如果我想创建更复杂的查询怎么办?例如,根据地点、薪水等获取报价?

我知道我可以做到这一点,但我正在寻找一种干净的代码方式。我想保持我的代码干净、可扩展和可持续。而且主要是我想遵循 REST 的规则

【问题讨论】:

  • Spring Data REST 提供内置的feature 来执行此操作。更多info.

标签: java spring rest spring-data spring-data-rest


【解决方案1】:
  1. 您可以注入您的存储库类型的 bean。 Spring 生成一个完全配置的代理实例并在上下文中定位它。如果已导出,您可以指定存储库中定义的操作的路径:

    @RepositoryRestResource(exported = true, path = "path-to-repository")
    

    要设置操作的路径,可以在方法上放置@RestResource 注释:

    @RestResource(exported = true, path = "operation")
    

    默认情况下,path-to-repository/search/operation 可以使用它。

  2. 使用@Query 和 JPQ 语言编写自定义查询,或者使用原生 SQL 进行更详细的控制:

    @Query(value = "...", nativeQuery = true)
    

实际上,由于存储库的复杂性,某些操作很难由存储库实现。它可能会产生太大的默认方法,这些方法会处理一些存储库方法来产生所需的输出。

解决方案是创建一对控制器和服务,它们将“复制”并补充存储库的操作。幸运的是,Spring 提供了一些方法来制作投影/排序/分页和其他存储库开箱即用的东西。

【讨论】:

    【解决方案2】:

    我看到您正在使用我从未使用过的 swagger 注释 (@ApiParam),但在 Spring 中,如果您还没有这样做,请使用 @RestController 标记您的控制器。

    @RestController
    public class OfferRestController {
    .....
    

    你可以像这样定义你的端点 - 如果你使用 Spring boot,并且在你的类路径中有 jackson,它将为你处理序列化;

    @GetMapping(value="/offers")
    public List<Offer> getAllOffers() {
        return offerService.findAll(pageable);
    }
    
    @GetMapping(value="/offers/{location})
    public List<Offer> getAllOffers(@PathVariable("location") String location) {
        return offerService.findByLocation(location);
    }
    

    很高兴您了解 JPA 存储库,您遇到过 Spring RestRepositories 吗?它们会自动通过 REST 公开您的查询

    interface OfferRepository extends CrudRepository<Offer,Long> {
        List<Offer> findByLocation (final String location)
    }
    

    会像这样暴露一个端点;

    http://localhost:8080/offers/search/findByLocation?location=London
    

    您将需要 spring-boot 启动器、spring-boot-starter-data-jpa、spring-boot-starter-data-rest 和 spring-data-rest-hal-browser 将允许您在 REST 存储库中导航浏览器 (Spring starter guide)。

    我不敢提供示例(!),但要构建更高级的查询,您可以通过查询 Specification 提供自定义实现

    [编辑]

    主要是我想遵循 REST 的规则。

    您还有@PostMapping、@DeleteMapping、@PutMapping,它们的工作方式与@GetMapping 类似,并映射到相应的HTTP 动词;你会这样发帖;

    @PostMapping ("/offers")
    public void postSomething (@RequestBody Offer offer) {
        offerService.save (offer);
    }
    

    【讨论】:

      【解决方案3】:

      使用 spring data jpa,您可以使用查询方法来编写相当复杂的查询。参考here

      【讨论】:

      • 那不是我的问题的答案。我知道查询方法。我不知道如何创建它们的资源/端点。
      猜你喜欢
      • 1970-01-01
      • 2015-08-30
      • 2015-07-28
      • 2014-09-06
      • 2017-03-18
      • 2021-05-12
      • 1970-01-01
      • 2017-06-21
      • 2018-09-04
      相关资源
      最近更新 更多