【问题标题】:Best use of Optionals in RestAPI Spring application在 Rest API Spring 应用程序中最好地使用 Optionals
【发布时间】:2021-10-28 16:12:08
【问题描述】:

我对在我的 RestAPI Spring 应用程序中使用 Optionals 来设计存储库 -> 服务 -> 控制器通信的方式有点困惑。 例如,客户想通过 id 查找电影,但电影不存在并且存储库返回空 Optional。我有两种处理方式:

  1. Service 方法返回 Optional 值或抛出异常,可以在 Controller 中使用 ControllerAdvice 处理。

  2. Service 返回 Optional,Controller 处理它(返回值,如果存在或处理异常,或者只是做其他事情)。

我知道在这种简单的情况下使用异常并不是最佳实践,您可能会建议其他方法让客户知道 id 是错误的。

目前 RestController 中的方法:

@GetMapping("/{id}")
public FilmGetDto getFilm(@PathVariable int id) {
    return filmService.getFilm(id);
}

【问题讨论】:

    标签: java spring rest optional


    【解决方案1】:

    我遵循或看到的大多数遵循的做法是您应该在服务中处理它并使用包装类进行响应。通过这种方式,您将实现两件事,即您将拥有一个可以在所有应用程序中使用的常量 Response 对象,并且您可以非常轻松地使用异常等。您应该始终按照 MVC 状态处理服务层中寻求的任何业务逻辑。我在这里发布一个示例,以便您更好地理解我在这里要说的内容。

    控制器:

    @GetMapping("/{id}")
    public Response getFilm(@PathVariable int id) {
        return filmService.getFilm(id);
    }
    

    服务:

    public Response getFilm(int id){
      Optional<Film> film = repo.findById(id);
      return film.map(f -> Response.builder().status(200).data(f).message("request  successful"))
                 .orElseGet(() -> Response.builder().status(422).data(null).message("Film with given id not found");
    
    }
    

    和响应类与@Adrash 所建议的一样

    class Response {
      private int status;
      private Object data;
      private String message;
       
      //you can use lombok or IDE  generate getter setters to generate getters setters
     }
    

    注意:我使用lombok builder方法在服务层创建响应对象。

    【讨论】:

    • 你好。您如何使用包装器处理 HTTP 代码?返回带有状态码和数据的 ResponseEntity 还是?
    • 嗨@Tovarisch,对不起,如果我没有理解你的问题,但我想你想问的是我如何在我的响应对象中使用http代码。因此,对此的回答是您可以将响应类中的属性“状态”用作 HTTP 代码。当然 Response 是你的类,你可以按照你想要的方式修改它
    • 如果你想添加完整的 ResponseEntity 对象而不仅仅是代码,你也可以使用它而不是“private int status”。或者我认为您想要做的是代替私有 int 状态,您可以使用“私有 HttpStatus statusCode”。希望这会有所帮助
    • 我认为返回显然与 HTTP 耦合的 Response 对象并不是最佳实践。服务应该更可重用且与技术无关
    【解决方案2】:

    如果您想向客户端发送有关此类 id 不存在的消息,您必须处理此类边缘情况。 如果 optional.isPresent() 返回 false,可能您可以使用 Optional 并处理,您可以发送自定义消息并让您的客户知道不存在具有此类 id 的数据。

    您可以使用包装类来实现这一点。

    class ErrorResponse {
      private String status;
      private int statusCode;
      private String message;
    
      public ErrorResponse(String status, int statusCode, String message){
          this.status = status;
          -----
          -----
       }
    }
    

    设置这个字段并返回这个类对象作为响应。

    【讨论】:

      【解决方案3】:

      你必须遵循标准,所以你不应该在控制器中编写代码,而是应该在服务中编写代码,而且你可以将你的响应包装在一个类中,为它提供一个适当的自定义消息,以便它有意义给客户。正如@Adarsh 上面提到的 Wrapper 类,您可以创建完全相同的类,它可以解决您的问题。并遵循@Danish 提到的标准。

      【讨论】:

        猜你喜欢
        • 2014-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-17
        • 1970-01-01
        • 2021-04-24
        • 1970-01-01
        相关资源
        最近更新 更多