Spring数据REST高级资源

时间:2017-07-12 19:56:47

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

我只是为我的应用程序实现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的规则

3 个答案:

答案 0 :(得分:1)

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

@RestController
public class OfferRestController {
.....

您可以像这样定义端点 - 如果您正在使用Spring启动,并且在类路径上安装了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-starter-data-jpa,spring-boot-starter-data-rest和spring-data-rest-hal-browser将允许你导航你的REST存储库浏览器(http://maven.apache.org/pom.html#The_Super_POM)。

我没有勇气提供示例(!),但是为了构建更高级的查询,您可以通过查询提供自定义实现Spring starter guide

[编辑]

  

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

你也有@ PostMapping,@ DeleteMapping,@ PopMapping,它像@GetMapping一样工作并映射到相应的HTTP谓词;你会像这样发帖;

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

答案 1 :(得分: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)
    
  3. 实际上,由于存储库的复杂性,某些操作几乎无法通过存储库实现。它可能会产生过大的默认方法,这些方法会处理一些存储库方法以产生所需的输出。

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

答案 2 :(得分:0)

使用spring数据jpa,您可以使用查询方法来构成相当复杂的查询。参考here