如何在@RestController中仅覆盖1个Http方法(POST),但让Spring使用标准的HATEOAS响应处理所有其他Http方法

时间:2018-02-14 12:14:57

标签: java spring spring-boot spring-restcontroller spring-hateoas

我想在Spring中公开一些REST资源,默认情况下我可以让Spring Boot处理这个问题,这会产生一个很好的HATEOAS响应,我可以获得所有内容' free'。

现在我需要在某个资源被POSTED时执行一些逻辑,所以我实现了自己的@RestController类并覆盖了POST方法,如下所示:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;

import java.net.URI;
import java.security.Principal;

@RestController
@RequestMapping(Constants.PROJECTSPATH)
public class ProjectController {
    @Autowired private ProjectRepository projectRepo;
    @Autowired private ProjectRoleRepository projectRoleRepo;
    @Autowired private AccountRepository accountRepo;

    @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<?> addProject(@RequestBody Project projectFromRequest, Principal principal) {
        Project project = projectRepo.save(projectFromRequest);
        Account currentAccount = accountRepo.findByUsername(principal.getName());
        ProjectRole ownerRole = new ProjectRole(project, currentAccount, ProjectRoleEnum.OWNER);
        projectRoleRepo.save(ownerRole);

        final URI uri =
                MvcUriComponentsBuilder.fromController(getClass())
                        .path("/{id}")
                        .buildAndExpand(project.getId())
                        .toUri();
        return ResponseEntity.created(uri).body(new ProjectResource(project));
    }
}

我使用从ResourceSupport继承的类,在那里我为HATEOAS响应生成所需的链接。到目前为止一切都很好,这不是太多的定制工作。

问题在于,如果我现在只是尝试获取所有项目,我会收到以下消息:

  

{&#34; timestamp&#34;:1518610270403,&#34; status&#34;:405,&#34; error&#34;:&#34; Method Not Not   允许&#34;&#34;例外&#34;:&#34; org.springframework.web.HttpRequestMethodNotSupportedException&#34;&#34;消息&#34;:&#34;请求   方法&#39; GET&#39;不支持&#34;,&#34;路径&#34;:&#34; / projects&#34;}

我真的不想实现其他方法,Spring Boot默认完成。但我现在也被迫实施这些并且每次都更改我的整个HATEOAS响应,我的域对象会更改吗?这是我喜欢的功能,开箱即用&#39;。

1 个答案:

答案 0 :(得分:2)

  

如何在@RestController中仅覆盖1个Http方法(POST),但让Spring使用标准的HATEOAS响应处理所有其他Http方法

你不能用@RestController做到这一点。如Spring Data REST reference中所述:

  

有时您可能希望为特定资源编写自定义处理程序。要利用Spring Data REST的设置,消息转换器,异常处理等,请使用@RepositoryRestController注释而不是标准的Spring MVC @Controller或@RestController

没有明确提及,但使用@RepositoryRestController注释控制器允许您为一个端点定义自定义行为,同时保留Spring自动生成的所有其他端点。但重要的是,在method level only使用@RequestMapping注释。

你的例子变成了:

@RepositoryRestController
public class ProjectController {

    @Autowired private ProjectRepository projectRepo;
    @Autowired private ProjectRoleRepository projectRoleRepo;
    @Autowired private AccountRepository accountRepo;

    @PostMapping(Constants.PROJECTSPATH) // @PostMapping is a shortcut for @RequestMapping(method = RequestMethod.POST)
    public ResponseEntity<?> addProject(@RequestBody Project projectFromRequest, Principal principal) {
        Project project = projectRepo.save(projectFromRequest);
        Account currentAccount = accountRepo.findByUsername(principal.getName());
        ProjectRole ownerRole = new ProjectRole(project, currentAccount, ProjectRoleEnum.OWNER);
        projectRoleRepo.save(ownerRole);

        final URI uri =
                MvcUriComponentsBuilder.fromController(getClass())
                        .path("/{id}")
                        .buildAndExpand(project.getId())
                        .toUri();
        return ResponseEntity.created(uri).body(new ProjectResource(project));
    }
}