使用ResponseEntity时<;T>;和@RestController,用于Spring RESTful应用程序

使用ResponseEntity时<;T>;和@RestController,用于Spring RESTful应用程序,spring,spring-mvc,spring-3,spring-4,Spring,Spring Mvc,Spring 3,Spring 4,我正在使用SpringFramework4.0.7,以及MVC和Rest 我可以与以下人员和平相处: @控制器 响应性 例如: @Controller @RequestMapping("/person") @Profile("responseentity") public class PersonRestResponseEntityController { @RestController @RequestMapping("/person") @Profile("restcontroller

我正在使用SpringFramework4.0.7,以及MVC和Rest

我可以与以下人员和平相处:

  • @控制器
  • 响应性
例如:

@Controller
@RequestMapping("/person")
@Profile("responseentity")
public class PersonRestResponseEntityController {
@RestController
@RequestMapping("/person")
@Profile("restcontroller")
public class PersonRestController {
@RestController
public class MyController {

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

        return user;
    }

}
使用方法(仅用于创建)

使用方法(仅用于创建)

归还某物

@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);
}
@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)不重要,建议采用什么方法以及原因

  • ResponseEntity
    表示整个HTTP响应。您可以控制其中的任何内容:状态代码、标题和正文

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

    @ResponseStatus
    不是很灵活。它标记整个方法,因此您必须确保处理程序方法始终以相同的方式运行。您仍然无法设置标题。您需要
    HttpServletResponse
    HttpHeaders
    参数


    基本上,
    ResponseEntity
    可以让你做得更多。

    完成索托里奥斯·德里马诺利斯的回答

    诚然,
    ResponseEntity
    为您提供了更大的灵活性,但在大多数情况下,您并不需要它,最终您的控制器中到处都会出现这些
    ResponseEntity
    ,因此难以阅读和理解


    如果您想处理诸如错误(未找到、冲突等)之类的特殊情况,可以向Spring配置中添加一个。因此,在代码中,您只需抛出一个特定的异常(
    NotFoundException
    ),并决定在处理程序中执行什么操作(将HTTP状态设置为404),使控制器代码更加清晰。

    根据官方文档:

    @RestController是一个结合@ResponseBody的原型注释 和@Controller更重要的是,它赋予您的 控制器,也可能在将来的版本中带有附加语义 框架的一部分。

    为了清晰起见,最好使用
    @RestController
    ,但您也可以将它与
    响应性
    结合起来,以便在需要时灵活使用(和)

    例如:

    @Controller
    @RequestMapping("/person")
    @Profile("responseentity")
    public class PersonRestResponseEntityController {
    
    @RestController
    @RequestMapping("/person")
    @Profile("restcontroller")
    public class PersonRestController {
    
    @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);
        }
    
    }
    

    一个合适的RESTAPI应该有以下组件作为响应

  • 状态码
  • 响应体
  • 更改的资源的位置(例如,如果创建了一个资源,客户端将有兴趣知道该位置的url)
  • 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);
    }
    
    //步骤1-不提供任何选项
    @RequestMapping(value=“/{id}”,method=RequestMethod.GET)
    public@ResponseBody Spittle spittleById(@PathVariable long id){
    返回spittleRepository.findOne(id);
    }
    //第2步-我们需要处理异常情况,因为第1步只提供了一条快乐的道路。
    @ExceptionHandler(SpitleNotFoundException.class)
    @ResponseStatus(未找到HttpStatus.NOT_)
    公共错误SpitleNotFound(SpitleNotFound异常){
    long spittleId=e.getSpittleId();
    返回新错误(4,“未找到Spitle[“+SpitleId+”);
    }
    //步骤3-现在我们将更改服务方法,**如果您想提供位置**
    @请求映射(
    method=RequestMethod.POST
    consumes=“application/json”)
    公共责任节约唾沫(
    @身体上的唾沫,
    UriComponentsBuilder(ucb){
    Spittle Spittle=spittleRepository.save(Spittle);
    HttpHeaders=新的HttpHeaders();
    URI位置URI=
    ucb.path(“/spittles/”)
    .path(String.valueOf(spittle.getId()))
    .build()
    .toUri();
    headers.setLocation(locationUri);
    响应响应响应响应响应响应=
    新反应(
    Spitle、标头、HttpStatus.CREATED)
    返回响应性;
    }
    //第4步-如果您对提供url位置不感兴趣,可以省略ResponseEntity并使用
    @请求映射(
    method=RequestMethod.POST
    consumes=“application/json”)
    @ResponseStatus(HttpStatus.CREATED)
    公共唾沫节约唾沫(@RequestBody唾沫){
    返回spittle存储库。保存(spittle);
    }
    
    关于第三个观察的观点很好。谢谢你……我对
    响应性也有同样的想法,它更灵活。只是我对
    @RestController
    有点怀疑。谢谢您您的观点在使用(@)ExceptionHandler时是有效的。要点是:如果希望在一个方法(Try/Catch)中处理所有请求,那么HttpEntity很适合,如果希望重用异常处理(@)ExceptionHandler处理多个(@)请求,那么映射很适合。我喜欢HttpEntity,因为我也可以使用HttpHeaders。如果我们在方法上添加了@ResponseStatus(HttpStatus.OK),但方法返回新的ResponseEntity(user,responseHeaders,HttpStatus.NOT_FOUND);我只是在想@ResponseStatus是否会进一步修改响应代码。@Hemant似乎在返回
    ResponseEntity(用户、响应负责人、HttpStatus.NOT_FOUND)
    时忽略了
    @ResponseStatus(HttpStatus.OK)
    。HTTP响应是来自ResponseStatus的JavaDocs的
    404
    。当调用处理程序方法时,状态代码将应用于HTTP响应,并通过其他方式覆盖状态信息集,如{@code ResponseEntity}或{@code“redirect:”}。