【问题标题】:Spring how to resolve entity uri in @RepositoryRestControllerSpring如何在@RepositoryRestController中解析实体uri
【发布时间】:2017-11-27 21:05:33
【问题描述】:

我正在使用 Spring Boot 1.5.3、Spring Data REST、Spring HATEOAS。 Spring Data REST 非常棒,做得很完美,但有时它需要自定义业务逻辑,因此我需要创建一个自定义控制器。

我将使用 @RepositoryRestController 来利用 Spring Data REST 功能 (http://docs.spring.io/spring-data/rest/docs/current/reference/html/#customizing-sdr.overriding-sdr-response-handlers)。

因为 Spring Data REST 默认使用 HATEOAS,所以我正在使用它。我需要这样的控制器:

@RepositoryRestController
@RequestMapping(path = "/api/v1/workSessions")
public class WorkSessionController {

    @Autowired
    private EntityLinks entityLinks;

    @Autowired
    private WorkSessionRepository workSessionRepository;

    @Autowired
    private UserRepository userRepository;

    @PreAuthorize("isAuthenticated()")
    @RequestMapping(method = RequestMethod.POST, path = "/start")
    public ResponseEntity<?> start(@RequestBody(required = true) CheckPoint checkPoint) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

        if (checkPoint == null) {
            throw new RuntimeException("Checkpoint cannot be empty");
        }

        if (workSessionRepository.findByAgentUsernameAndEndDateIsNull(auth.getName()).size() > 0) {
            // TODO return exception
            throw new RuntimeException("Exist a open work session for the user {0}");
        }

        // ...otherwise it's opened a new work session
        WorkSession workSession = new WorkSession();
        workSession.setAgent(userRepository.findByUsername(auth.getName()));
        workSession.setCheckPoint(checkPoint);
        workSession = workSessionRepository.save(workSession);

        Resource<WorkSession> resource = new Resource<>(workSession); 
        resource.add(entityLinks.linkFor(WorkSession.class).slash(workSession.getId()).withSelfRel());
        return ResponseEntity.ok(resource);
    }
}

因为参数 CheckPoint 必须是一个存在的资源,我希望客户端发送资源的链接(就像你可以在 Spring Data REST POST 方法中做的那样)。 不幸的是,当我尝试这样做时,服务器端我收到了一个空的 CheckPoint 对象。

我已经读过Resolving entity URI in custom controller (Spring HATEOAS)converting URI to entity with custom controller in spring data rest? 尤其是Accepting a Spring Data REST URI in custom controller

我想知道是否有最佳实践来避免将 id 暴露给客户端,遵循 HATEOAS 原则。

【问题讨论】:

标签: spring spring-mvc spring-data-rest


【解决方案1】:

尝试像这样改变你的控制器:

@RepositoryRestController
@RequestMapping(path = "/checkPoints")
public class CheckPointController {

    //...

    @Transactional
    @PostMapping("/{id}/start")
    public ResponseEntity<?> startWorkSession(@PathVariable("id") CheckPoint checkPoint) {

        //...           
    }
}

这意味着:“对于具有给定 ID 的 CheckPoint 启动新的 WorkSession”。 您的 POST 请求将类似于:localhost:8080/api/v1/checkPoints/1/start

【讨论】:

  • 我无法遵循第一个解决方案,因为它不符合 HATEOAS 标准。我没有资源的 id,而只是完整的 ui(例如localhost:8080/api/v1/checkPoints/1)。由于杰克逊反序列化器异常,使用“容器”的第二个想法不起作用。我正在寻找可以遵循的 Spring 最佳实践。
  • 对不起,可能我表达的方式不对。我正在尝试一种方法来解析@RepositoryRestController 中的实体uri,就像我在标题中写的那样。您的建议适用于特定情况,但如果我需要更多参数(实体)怎么办?关键是:有办法转换 uri -> 实体。谢谢
  • 我也有同样的问题。是的,我还阅读了路径参数中带有 ID 的建议。但我同意@drenda 客户不知道 ID(号码)。客户端只知道完整的 URI(即 spring-hateoas 中的 ID)。
  • 这也不起作用。因为请求由框架的内部控制器 RepositoryPropertyReferenceController 处理,该控制器检查资源的属性,如果斜线后的片段不是其余资源上的属性,则抛出 404
猜你喜欢
  • 1970-01-01
  • 2016-10-27
  • 2018-12-14
  • 1970-01-01
  • 2016-02-25
  • 2012-10-04
  • 2022-01-26
  • 2018-06-14
  • 1970-01-01
相关资源
最近更新 更多