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

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

据我所知,Spring只会提供一个“位置”来响应重定向(“redirect:xyz”或RedirectView),但是有些情况下应该将位置与实体主体一起发送(例如, “201 Created”的结果。

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

httpServletResponse.setHeader("Location", "/x/y/z"); 

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

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

 @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(headers, HttpStatus.CREATED); } 

从版本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(); } 

感谢Dieter Hubau指出这一点。

以下示例来自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()); } 

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

 ServletUriComponentsBuilder .fromCurrentRequest().path("/{id}") 

这是一个老问题,但如果你想让Spring真正为你构建URI,你可以做的就是这个问题。

 @RestController @RequestMapping("/api/v1") class JobsController { @PostMapping("/jobs") fun createJob(@RequestParam("use-gpu") useGPU: Boolean?): ResponseEntity { 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) = mapOf("id" to jobId) } 

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

根据: http : //www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.30

应使用绝对URI:

 Location = "Location" ":" absoluteURI 

URI应该正确转义:

http://www.ietf.org/rfc/rfc2396.txt

您的方法看起来很好,但为了保持清洁,您可以将代码置于自定义HandlerInterceptor ,该HandlerInterceptor仅在存在HTTP 201时触发。

有关更多信息,请参见此处