在Spring MVC 3中指定HTTP“位置”响应头的首选方法是什么?
在Spring MVC 3中指定HTTP“位置”响应头的首选方法是什么?
据我所知,Spring只会提供一个“位置”来响应重定向(“redirect:xyz”或RedirectView),但是有些情况下应该将位置与实体主体一起发送(例如, “201 Created”的结果。
我担心我唯一的选择是手动指定它:
httpServletResponse.setHeader("Location", "/x/y/z");
它是否正确? 有没有更好的方法来解决这个问题?
从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(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应该正确转义:
您的方法看起来很好,但为了保持清洁,您可以将代码置于自定义HandlerInterceptor
,该HandlerInterceptor
仅在存在HTTP 201时触发。
有关更多信息,请参见此处