我正在使用Spring Framework 4.0.7,以及MVC和Rest
我可以和平地工作:
@Controller
ResponseEntity<T>
例如:
@Controller
@RequestMapping("/person")
@Profile("responseentity")
public class PersonRestResponseEntityController {
使用方法(仅创建)
@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 {
使用方法(仅创建)
@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;
}
我的问题是:
答案 0 :(得分:171)
ResponseEntity
用于表示整个HTTP响应。您可以控制进入它的任何内容:状态代码,标题和正文。
@ResponseBody
是HTTP响应正文的标记,@ResponseStatus
声明HTTP响应的状态代码。
@ResponseStatus
不是非常灵活。它标记整个方法,因此您必须确保您的处理程序方法始终以相同的方式运行。你仍然无法设置标题。您需要HttpServletResponse
或HttpHeaders
参数。
基本上,ResponseEntity
可以让您做得更多。
答案 1 :(得分:46)
完成Sotorios Delimanolis的答案。
ResponseEntity
为您提供了更大的灵活性,但在大多数情况下您不会需要它,并且您最终会在控制器中到处都是这些ResponseEntity
因此难以阅读和理解。
如果要处理错误(未找到,冲突等)等特殊情况,可以在Spring配置中添加HandlerExceptionResolver
。因此,在您的代码中,您只抛出一个特定的异常(例如NotFoundException
)并决定在Handler中做什么(将HTTP状态设置为404),使Controller代码更清晰。
答案 2 :(得分:38)
根据官方文件:Plunker
@RestController是一个结合@ResponseBody的构造型注释 和@Controller。 更重要的是,它为您提供了更多的意义 控制器,也可能在将来的版本中携带额外的语义 框架。
为了清晰起见,似乎最好使用@RestController
,但您也可以将与ResponseEntity
结合使用,以便在需要时提供灵活性({{3} }和Creating REST Controllers with the @RestController annotation以及According to official tutorial)。
例如:
@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);
答案 3 :(得分:7)
适当的REST API应该具有以下组件作为响应
ResponseEntity的主要目的是提供选项3,如果没有ResponseEntity,其余选项就可以实现。
因此,如果您想提供资源的位置,则最好使用ResponseEntity,否则可以避免。
考虑一个示例,其中修改了API以提供所有提到的选项
// Step 1 - Without any options provided
@RequestMapping(value="/{id}", method=RequestMethod.GET)
public @ResponseBody Spittle spittleById(@PathVariable long id) {
return spittleRepository.findOne(id);
}
// Step 2- We need to handle exception scenarios, as step 1 only caters happy path.
@ExceptionHandler(SpittleNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public Error spittleNotFound(SpittleNotFoundException e) {
long spittleId = e.getSpittleId();
return new Error(4, "Spittle [" + spittleId + "] not found");
}
// Step 3 - Now we will alter the service method, **if you want to provide location**
@RequestMapping(
method=RequestMethod.POST
consumes="application/json")
public ResponseEntity<Spittle> saveSpittle(
@RequestBody Spittle spittle,
UriComponentsBuilder ucb) {
Spittle spittle = spittleRepository.save(spittle);
HttpHeaders headers = new HttpHeaders();
URI locationUri =
ucb.path("/spittles/")
.path(String.valueOf(spittle.getId()))
.build()
.toUri();
headers.setLocation(locationUri);
ResponseEntity<Spittle> responseEntity =
new ResponseEntity<Spittle>(
spittle, headers, HttpStatus.CREATED)
return responseEntity;
}
// Step4 - If you are not interested to provide the url location, you can omit ResponseEntity and go with
@RequestMapping(
method=RequestMethod.POST
consumes="application/json")
@ResponseStatus(HttpStatus.CREATED)
public Spittle saveSpittle(@RequestBody Spittle spittle) {
return spittleRepository.save(spittle);
}
来源-行动中的春天