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

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

据我所知,Spring只会提供一个“位置”来响应重定向(“redirect:xyz”或RedirectView),但是也有一些场景应该和实体一起发送(例如,作为“201创建”的结果)。

恐怕我唯一的选择是手动指定它:

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<Void>(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指出这一点。

下面的例子是从春季教程:

 @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}") 

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

应该使用绝对URI:

 Location = "Location" ":" absoluteURI 

URI应该正确地转义:

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

你的方法看起来很好,但为了保持干净,你可以把代码放到一个自定义的HandlerInterceptor ,例如只有当有一个HTTP 201的时候才会触发。

在这里看到更多的信息。

这是一个古老的问题,但是如果你想让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) = mapOf("id" to jobId) } 

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

这是做这件事的好方法,它符合http规范 。