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


问题内容

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

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

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

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

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


问题答案:

关键是要使用UriComponentsBuilder。有几种方法可以获取它的实例

  1. UriComponentsBuilder从预先配置MvcUriComponentsBuilder
  2. UriComponentsBuilder 作为方法的参数注入

UriComponentsBuilder从预先配置MvcUriComponentsBuilder

通过这种方式,您可以获取UriComponentsBuilder已配置为生成URI指向带有预定义参数的某些控制器方法的指针。

下面是例如,从的javadocMvcUriComponentsBuilder

例如,给定此控制器:

 @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);

有时可能更可取的另一种选择是通过名称指定控制器方法:

UriComponents uriComponents = MvcUriComponentsBuilder.fromMethodName(
    AddressController.class, "getAddressesForCountry", "US").buildAndExpand(1);
URI nextUri = uriComponents.toUri();

UriComponentsBuilder 作为方法的参数注入

从spring 3.1开始,Location可以使用UriComponentBuilder参数制作并将其设置为return
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指出这一点。