При использовании ResponseEntity <T> и @RestController для Spring приложений RESTful
Я работаю с 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;
}
Мои вопросы:
- когда по твердой причине или конкретному сценарию один параметр должен обязательно использоваться над другим
- Если (1) не имеет значения, какой подход предлагается и почему.
Ответы
Ответ 1
ResponseEntity
предназначен для представления всего HTTP-ответа. Вы можете контролировать все, что входит в это: код состояния, заголовки и тело.
@ResponseBody
является маркером для тела ответа HTTP, а @ResponseStatus
объявляет код состояния ответа HTTP.
@ResponseStatus
не очень гибкий. Он отмечает весь метод, поэтому вы должны быть уверены, что ваш метод обработчика всегда будет вести себя одинаково. И вы все еще не можете установить заголовки. Вам понадобится параметр HttpServletResponse
или HttpHeaders
.
В принципе, ResponseEntity
позволяет вам делать больше.
Ответ 2
Чтобы выполнить ответ от Sotorios Delimanolis.
Верно, что ResponseEntity
дает вам большую гибкость, но в большинстве случаев вам это не понадобится, и вы получите все эти ResponseEntity
везде в своем контроллере, что затруднит чтение и понимание.
Если вы хотите обрабатывать особые случаи, такие как ошибки (Not Found, Conflict и т.д.), вы можете добавить HandlerExceptionResolver
к своему Spring. Поэтому в вашем коде вы просто бросаете конкретное исключение (например, NotFoundException
) и решаете, что делать в вашем обработчике (настройка статуса HTTP на 404), что делает код контроллера более понятным.
Ответ 3
Согласно официальной документации: Создание контроллеров REST с аннотацией @RestController
@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);