Java 指定HTTP的首选方式是什么;地点“;Spring MVC 3中的响应头?
在SpringMVC3中,指定HTTP“Location”响应头的首选方法是什么 据我所知,Spring将只提供一个“位置”来响应重定向(“redirect:xyz”或RedirectView),但是在某些情况下,位置应该与实体体一起发送(例如,作为“201 Created”的结果) 恐怕我唯一的选择是手动指定它:Java 指定HTTP的首选方式是什么;地点“;Spring MVC 3中的响应头?,java,rest,spring-mvc,Java,Rest,Spring Mvc,在SpringMVC3中,指定HTTP“Location”响应头的首选方法是什么 据我所知,Spring将只提供一个“位置”来响应重定向(“redirect:xyz”或RedirectView),但是在某些情况下,位置应该与实体体一起发送(例如,作为“201 Created”的结果) 恐怕我唯一的选择是手动指定它: httpServletResponse.setHeader("Location", "/x/y/z"); 这是正确的吗?有没有更好的方法来解决这个问题?根据: 应使用绝对URI:
httpServletResponse.setHeader("Location", "/x/y/z");
这是正确的吗?有没有更好的方法来解决这个问题?根据:
应使用绝对URI:
Location = "Location" ":" absoluteURI
并且应该正确转义URI:
您的方法看起来不错,但是为了保持干净,您可以将代码放在自定义的
HandlerInterceptor
中,例如,只有在有HTTP 201时才会触发
有关更多信息,请参阅。关键是使用
UriComponentsBuilder
。
有几种方法可以获得它的实例
MvcUriComponentsBuilder
UriComponentsBuilder
作为参数注入方法MvcUriComponentsBuilder
通过这种方式,您可以获得配置为生成指向某些具有预定义参数的控制器方法的UriComponentsBuilder
以下是forMvcUriComponentsBuilder
的示例:
例如,给定此控制器:
@RequestMapping("/people/{id}/addresses")
class AddressController {
@RequestMapping("/{country}")
public HttpEntity<Void> getAddressesForCountry(@PathVariable String country) { ... }
@RequestMapping(value="/", method=RequestMethod.POST)
public void addAddress(Address address) { ... }
}
A UriComponentsBuilder can be created:
// Inline style with static import of "MvcUriComponentsBuilder.on"
MvcUriComponentsBuilder.fromMethodCall(
on(AddressController.class).getAddressesForCountry("US")).buildAndExpand(1);
UriComponentsBuilder
作为参数注入方法
从spring 3.1开始,可以使用UriComponentBuilder
参数创建位置
,并将其设置为返回的响应属性
<代码>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);
}
@RequestMapping(method=RequestMethod.POST)
公共响应创建客户(UriComponentsBuilder b){
UriComponents UriComponents=
b、 路径(“/customers/{id}”).buildAndExpand(id);
HttpHeaders=新的HttpHeaders();
headers.setLocation(uriComponents.toUri());
返回新的ResponseEntity(标题,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();
}
@RequestMapping(method=RequestMethod.POST)
公共响应创建客户(UriComponentsBuilder b){
UriComponents UriComponents=
b、 路径(“/customers/{id}”).buildAndExpand(id);
返回ResponseEntity.created(uriComponents.toUri()).build();
}
感谢Dieter Hubau指出这一点。这是一个老问题,但如果您想让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
}
@RestController
@请求映射(“/api/v1”)
类作业控制器{
@后映射(“/jobs”)
fun createJob(@RequestParam(“使用gpu”)useGPU:Boolean?):ResponseEntity{
val headers=HttpHeaders()
val jobId=“待定id”
标题.位置=
MVC组件生成器
.fromMethodName(作业控制器::class.java,“getJob”,作业ID)
.buildAndExpand(作业ID)
.toUri()
返回响应属性(标题,HttpStatus.CREATED)
}
@GetMapping(“/job/{jobId}”)
fun getJob(@PathVariable jobId:String)=……//获取作业
}
在这个示例中(用Kotlin编写,但与java类似),基本URI是
/api/v1
(定义在类的顶部)。使用MvcUriComponentsBuilder.fromMethodName
调用可以让Spring计算出正确的完整URI。(MvcUriComponentsBuilder
是在4.0中添加的)。以下示例来自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());
}
这种方法有什么问题?这是一种很好的方法,它符合。headers.setLocation行上有一个语法错误。还有一个额外的结束语,并且“id”不存在。我只是想向其他遇到这个答案的人指出,这不是一个可以编译的完整方法。但是谢谢你的回答,这很有帮助。回答很好,现在你甚至可以把它缩短一点:
returnresponseEntity.created(uriComponents.toUri()).build()代码>是否正在注入UriComponentsBuilder
?可以是@Autowire
d吗?组件没有在应答中添加端口。我总是认为你提到的文件是过时的,而不是过时的。被取代的最终结果表明,该值可以是相对的。
@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());
}
ServletUriComponentsBuilder
.fromCurrentRequest().path("/{id}")