在Spring MVC 3中指定HTTP"位置"响应头的首选方法是什么?

Bri*_*ent 32 java rest spring-mvc

在Spring MVC 3中指定HTTP"位置"响应头的首选方法是什么?

据我所知,Spring只会提供一个"位置"来响应重定向("redirect:xyz"或RedirectView),但有些场景应该与实体主体一起发送(例如,作为"201 Created"的结果.

我担心我唯一的选择是手动指定它:

httpServletResponse.setHeader("Location", "/x/y/z");
Run Code Online (Sandbox Code Playgroud)

它是否正确?有没有更好的方法来解决这个问题?

Rom*_*val 77

从3.1版开始,制作Location的最佳方法是使用UriComponentBuilder参数并将其设置为返回ResponseEntity.UriComponentBuilder了解上下文并使用相对路径进行操作:

@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<?> createCustomer(UriComponentsBuilder b) {

    UriComponents uriComponents = 
        b.path("/customers/{id}").buildAndExpand(id);

    HttpHeaders headers = new HttpHeaders();
    headers.setLocation(uriComponents.toUri());
    return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
Run Code Online (Sandbox Code Playgroud)

从版本4.1开始,您可以缩短版本

@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<?> createCustomer(UriComponentsBuilder b) {

    UriComponents uriComponents = 
        b.path("/customers/{id}").buildAndExpand(id);

    return ResponseEntity.created(uriComponents.toUri()).build();
}
Run Code Online (Sandbox Code Playgroud)

感谢Dieter Hubau指出这一点.

  • 很好的答案,你现在甚至可以缩短它:`return ResponseEntity.created(uriComponents.toUri()).build();` (7认同)
  • headers.setLocation行有语法错误.有一个额外的关闭parens和"id"不存在.只是想指出遇到这个答案的其他人,这不是一个可以编译的完整方法.但是感谢答案,这很有帮助. (2认同)

Agu*_*hez 22

以下示例来自spring教程:

@RequestMapping(method = RequestMethod.POST)
ResponseEntity<?> add(@PathVariable String userId, @RequestBody Bookmark input) {
    this.validateUser(userId);

    return this.accountRepository
            .findByUsername(userId)
            .map(account -> {
                Bookmark result = bookmarkRepository.save(new Bookmark(account,
                        input.uri, input.description));

                URI location = ServletUriComponentsBuilder
                    .fromCurrentRequest().path("/{id}")
                    .buildAndExpand(result.getId()).toUri();

                return ResponseEntity.created(location).build();
            })
            .orElse(ResponseEntity.noContent().build());

}
Run Code Online (Sandbox Code Playgroud)

请注意,以下内容将计算上下文路径(URI),以避免代码重复并使您的应用程序更具可移植性:

ServletUriComponentsBuilder
                    .fromCurrentRequest().path("/{id}")
Run Code Online (Sandbox Code Playgroud)


yan*_*yan 6

这是一个老问题,但如果您想让 Spring 真正为您构建 URI,您可以做些什么。

@RestController
@RequestMapping("/api/v1")
class JobsController {

  @PostMapping("/jobs")
  fun createJob(@RequestParam("use-gpu") useGPU: Boolean?): ResponseEntity<Unit> {

    val headers = HttpHeaders()

    val jobId = "TBD id"

    headers.location =
            MvcUriComponentsBuilder
                    .fromMethodName(JobsController::class.java, "getJob", jobId)
                    .buildAndExpand(jobId)
                    .toUri()

    return ResponseEntity(headers, HttpStatus.CREATED)
  }

  @GetMapping("/job/{jobId}")
  fun getJob(@PathVariable jobId: String) = ... // fetch job
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中(它是用 Kotlin 编写的,但类似于 java),基本 URI 是/api/v1(在类的顶部定义)。使用MvcUriComponentsBuilder.fromMethodNamecall 让 Spring 找出正确的完整 URI。(MvcUriComponentsBuilder在 4.0 中添加)。