私はMVCとRestと共にSpring Framework 4.0.7で働いています
私は安心して働くことができます:
@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;
}
私の質問は:
ResponseEntity
はHTTPレスポンス全体を表すことを意図しています。ステータスコード、ヘッダ、本文など、管理するものはすべて制御できます。
@ResponseBody
はHTTPレスポンスボディのマーカーで、@ResponseStatus
はHTTPレスポンスのステータスコードを宣言します。
@ResponseStatus
はそれほど柔軟ではありません。メソッド全体をマークするので、ハンドラメソッドが常に同じように動作することを確認する必要があります。それでも、ヘッダを設定することはできません。 HttpServletResponse
またはHttpHeaders
パラメータが必要です。
基本的に、ResponseEntity
はあなたがもっとできるようにします。
Sotorios Delimanolisからの回答を完成させるため。
ResponseEntity
を使用すると柔軟性が増しますが、ほとんどの場合は必要ないため、コントローラのいたるところでこれらのResponseEntity
を使用することになり、読みやすく理解しづらくなります。
エラー(Not Found、Conflictなど)のような特別なケースを処理したい場合は、 HandlerExceptionResolver
をSpringの設定に追加することができます。そのため、コードでは、特定の例外(たとえばNotFoundException
)をスローし、Handlerで何をするか(HTTPステータスを404に設定)を決めるだけで、Controllerコードがより明確になります。
公式文書によると、 @RestControllerアノテーションを使用したRESTコントローラの作成
@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);
適切な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);
}
出典 - 春のアクション