当为Spring REST风格的应用程序使用ResponseEntity <T>和@RestController时

我正在使用Spring Framework 4.0.7以及MVC和Rest

我可以和平地工作:

  • @Controller
  • ResponseEntity<T>

例如:

 @Controller @RequestMapping("/person") @Profile("responseentity") public class PersonRestResponseEntityController { 

用这个方法(只是为了创build)

 @RequestMapping(value="/", method=RequestMethod.POST) public ResponseEntity<Void> createPerson(@RequestBody Person person, UriComponentsBuilder ucb){ logger.info("PersonRestResponseEntityController - createPerson"); if(person==null) logger.error("person is null!!!"); else logger.info("{}", person.toString()); personMapRepository.savePerson(person); HttpHeaders headers = new HttpHeaders(); headers.add("1", "uno"); //http://localhost:8080/spring-utility/person/1 headers.setLocation(ucb.path("/person/{id}").buildAndExpand(person.getId()).toUri()); return new ResponseEntity<>(headers, HttpStatus.CREATED); } 

返回一些东西

 @RequestMapping(value="/{id}", method=RequestMethod.GET) public ResponseEntity<Person> getPerson(@PathVariable Integer id){ logger.info("PersonRestResponseEntityController - getPerson - id: {}", id); Person person = personMapRepository.findPerson(id); return new ResponseEntity<>(person, HttpStatus.FOUND); } 

工作正常

我可以这样做

  • @RestController (我知道这是@Controller + @ResponseBody相同)
  • @ResponseStatus

例如:

 @RestController @RequestMapping("/person") @Profile("restcontroller") public class PersonRestController { 

用这个方法(只是为了创build)

 @RequestMapping(value="/", method=RequestMethod.POST) @ResponseStatus(HttpStatus.CREATED) public void createPerson(@RequestBody Person person, HttpServletRequest request, HttpServletResponse response){ logger.info("PersonRestController - createPerson"); if(person==null) logger.error("person is null!!!"); else logger.info("{}", person.toString()); personMapRepository.savePerson(person); response.setHeader("1", "uno"); //http://localhost:8080/spring-utility/person/1 response.setHeader("Location", request.getRequestURL().append(person.getId()).toString()); } 

返回一些东西

 @RequestMapping(value="/{id}", method=RequestMethod.GET) @ResponseStatus(HttpStatus.FOUND) public Person getPerson(@PathVariable Integer id){ logger.info("PersonRestController - getPerson - id: {}", id); Person person = personMapRepository.findPerson(id); return person; } 

我的问题是:

  1. 出于坚实的理由具体情况必须强制使用一个选项
  2. 如果(1)无关紧要,build议采取什么方法,为什么。

ResponseEntity旨在表示整个HTTP响应。 您可以控制进入它的任何内容:状态码,标题和正文。

@ResponseBody是HTTP响应主体的标记, @ResponseStatus声明了HTTP响应的状态码。

@ResponseStatus不是很灵活。 它标记了整个方法,所以你必须确保你的处理器方法总是以相同的方式运行。 而且您仍然无法设置标题。 你需要HttpServletResponseHttpHeaders参数。

基本上, ResponseEntity让你做更多。

从Sotorios Delimanolis完成答案。

的确, ResponseEntity给了你更多的灵活性,但是在大多数情况下你不需要它,你的控制器到处都会有这个ResponseEntity ,所以很难阅读和理解。

如果你想处理像错误(Not Found,Conflict等)的特殊情况,你可以在你的Springconfiguration中添加一个HandlerExceptionResolver 。 因此,在你的代码中,你只需要抛出一个特定的exception(例如NotFoundException ),并决定在你的Handler中做什么(把HTTP状态设置为404),使Controller代码更清晰。

根据官方文档: 使用@RestController注释创buildREST控制器

@RestController是一个结合了@ResponseBody和@Controller的构造型注释。 更重要的是,它给你的控制器带来了更多的意义,也可能在框架的未来版本中带来额外的语义。

看起来最好使用@RestController来清晰起见,但是你也可以在需要的时候它和ResponseEntity 结合起来使用( 根据官方的教程和代码以及我的问题来确认 )。

例如:

 @RestController public class MyController { @GetMapping(path = "/test") @ResponseStatus(HttpStatus.OK) public User test() { User user = new User(); user.setName("Name 1"); return user; } } 

是相同的:

 @RestController public class MyController { @GetMapping(path = "/test") public ResponseEntity<User> test() { User user = new User(); user.setName("Name 1"); HttpHeaders responseHeaders = new HttpHeaders(); // ... return new ResponseEntity<>(user, responseHeaders, HttpStatus.OK); } } 

这样,只有在需要时才可以定义ResponseEntity

更新

你可以使用这个:

  return ResponseEntity.ok().headers(responseHeaders).body(user);