【问题标题】:What are the best practices to handler or throw exceptions in a Spring Boot application?在 Spring Boot 应用程序中处理或抛出异常的最佳实践是什么?
【发布时间】:2019-06-21 02:00:52
【问题描述】:

我使用 Spring Boot 开发了一个 rest api。在我的一种服务方法中,我抛出一个ServletException,以防找不到特定用户。我想知道这是否是最好的方法,我的意思是,这是引发异常的正确层吗?

【问题讨论】:

  • 不,你应该处理这种情况,必须返回 404 错误代码,这意味着找不到

标签: java spring-boot exception-handling


【解决方案1】:

创建自定义异常类型比使用ServletException 更好。 为了处理异常,您可以使用@ControllerAdvice。 首先创建自定义异常类型:

public class UserNotFoundException extends RuntimeException {

  public UserNotFoundException(String message) {
    super(message);
  }
}

假设您的控制器和服务看起来或多或少像这样:

@RestController
@RequestMapping("users")
class UserController {

  private final UserService userService;

  UserController(UserService userService) {
    this.userService = userService;
  }

  @GetMapping
  List<String> users() {
    return userService.getUsers();
  }
}

@Service
class UserService {

  List<String> getUsers() {
    // ...
    throw new UserNotFoundException("User not found");
  }
}

你可以用@ControllerAdvice处理你UserNotFoundException

@ControllerAdvice
class CustomExceptionHandler {

  @ExceptionHandler({UserNotFoundException.class})
  public ResponseEntity<Object> handleUserNotFoundException(UserNotFoundException exception) {
    return new ResponseEntity<>(exception.getMessage(), HttpStatus.NOT_FOUND);
  }
}

【讨论】:

    【解决方案2】:

    最好的方法之一或我所做的是,

    1. 检查有效数据的数据/参数(例如,有时使用 if 语句手动检查 Null)。
    2. 检查数据/参数的大小(如文件大小)
    3. 检查有效范围的数据或参数以及数据类型,如果不是有效类型(如字符串、长整型、整数等),请进行类型转换。
    4. 如果数据/参数在系统引发异常之前无效,则引发消息并返回该 API

    【讨论】:

      【解决方案3】:

      我假设您希望捕获应用程序中发生的所有异常。 Spring-Boot 提供了一个全局异常处理程序来优雅地捕获所有异常并根据特定的异常返回响应。 它使您可以灵活地相应地更改状态代码、响应数据和标头。实现此功能的几个有用链接是 -

      1.) Dzone

      2.) Spring Boot Tutorial

      【讨论】:

        【解决方案4】:

        @Service 中抛出异常是可以的。 ServletException 不是很有意义。我的建议是创建自己的扩展 RuntimeException 的异常类并抛出它。

        所以你最终会得到类似的东西:

        只调用服务方法的Controller(最好不要有任何 这里的逻辑)

        @RestController
        @RequestMapping("/users")
        public class UserController {
        
            @Autowired
            private UserService userService;
        
            @GetMapping("/{id}")
            public User getUserById(@PathVariable("id") Long id) {
                return userService.getById(id);
            }
        }
        

        一个调用DAO 类的Service 类(扩展JPARepository

        @Service
        public class UserServiceImpl implements UserService {
        
            @Autowired
            private UserDAO userDAO;
        
            @Override
            public User getById(Long id) {
                return userDAO.findById(id).orElseThrow(() -> new UserNotFoundException("No user with id = " + id + " found."));
            }
        }
        

        道:

        @Repository
        public interface UserDAO extends JpaRepository<User, Long> {
        }
        

        注意:它返回Optional&lt;Object&gt;,非常方便。

        最后是你自己的Exception 类。

        @ResponseStatus(HttpStatus.NOT_FOUND)
        public class UserNotFoundException extends RuntimeException {
            public UserNotFoundException(String message) {
                super(message);
            }
        }
        

        注意:@ResponseStatus - 抛出此异常时将返回 HTTP 状态代码 404。

        恕我直言,这是开发你的 rest api 的一种非常干净和好的方法。

        还可以在这里查看:How to get spesific error instead of Internal Service Error。我回答了一个问题,提供了您可能会觉得有用的信息

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-11-05
          • 1970-01-01
          • 2011-11-16
          • 2021-02-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-13
          相关资源
          最近更新 更多