2014-10-24 2 views
81

я работаю с Spring Framework 4.0.7, вместе с MVC и RESTПри использовании ResponseEntity <T> и @RestController для Spring RESTful приложений

я могу спокойно работать с:

  • @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. когда для солидного причине или конкретный сценарий один вариант должен использоваться в обязательном порядке по сравнению с другими
  2. Если (1) не имеет значения, какой подход является предложил и почему.

ответ

117

ResponseEntity предназначен для представления всего ответа HTTP. Вы можете контролировать все, что входит в это: код состояния, заголовки и тело.

@ResponseBody является маркером тела ответа HTTP, а @ResponseStatus объявляет код состояния ответа HTTP.

@ResponseStatus не очень гибкий. Он отмечает весь метод, поэтому вы должны быть уверены, что ваш метод обработчика всегда будет вести себя одинаково. И вы все еще не можете установить заголовки. Вам понадобится параметр HttpServletResponse или HttpHeaders.

В принципе, ResponseEntity позволяет вам делать больше.

+4

Хороший вопрос о третьем наблюдении. Спасибо ... и я так же думал об 'ResponseEntity', он более гибкий. Просто я сомневался в '@ RestController'. Спасибо –

35

Чтобы выполнить ответ от Sotorios Delimanolis.

Это правда, что ResponseEntity дает вам большую гибкость, но в большинстве случаев вам это не понадобится, и вы получите все эти ResponseEntity во всем своем контроллере, что затрудняет чтение и понимание.

Если вы хотите обрабатывать особые случаи, такие как ошибки (не найдено, конфликт и т. Д.), Вы можете добавить HandlerExceptionResolver в конфигурацию Spring. Таким образом, в вашем коде вы просто бросаете конкретное исключение (например, NotFoundException) и решаете, что делать в вашем обработчике (настройка статуса HTTP на 404), что делает код контроллера более понятным.

+3

Ваша точка зрения действительно работает с (@) ExceptionHandler. Дело в том, что если вы хотите, чтобы все обрабатывалось одним методом (Try/Catch), HttpEntity подходит хорошо, если вы хотите использовать обработку исключений для повторного использования (@) ExceptionHandler для многих (@) RequestMapping. Мне нравится HttpEntity, потому что я тоже могу работать с HttpHeaders. –

19

Согласно официальной документации: Creating REST Controllers with the @RestController annotation

@RestController стереотип аннотаций, который сочетает в себе @ResponseBody и @Controller. Более того, это дает больше значения вашему контроллеру , а также может содержать дополнительную семантику в будущих версиях .

кажется, что лучше использовать @RestController для ясности, но вы также можете комбинировать его ResponseEntity гибкость при необходимости (According to official tutorial и the code here и my question to confirm that).

Например:

@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.

Update

Вы можете использовать это:

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

Что делать, если мы добавили @ResponseStatus (HttpStatus.OK) в метод, но метод возвращает return new ResponseEntity <> (user, responseHeaders, HttpStatus.NOT_FOUND); Я просто думаю, что если @ResponseStatus будет далее изменять код ответа. –

+2

@Hemant кажется, что '@ResponseStatus (HttpStatus.OK)' игнорируется при возврате 'ResponseEntity <> (user, responseHeaders, HttpStatus.NOT_FOUND)'. Ответ HTTP - 404 – Danail

Смежные вопросы