Java控制器和服务验证

时间:2018-05-14 10:27:39

标签: java spring

我们得到了这个设计: 休息控制器 - >呼叫服务 - >调用JPA DAO

让我们说救员工。我们有要求验证员工姓名。

IEmployeeService.saveEmployee(Employee emp) EmployeeController.saveEmployee(Employee emp)

选项1:我可以在Employee上注入JSR303注释,让Rest Rest Controller将其作为自动验证的一部分进行验证。

选项2:我在服务方法中验证并引发异常,让控制器返回该异常的正确JSON。

似乎服务应该进行验证...但是在JSR303注释控制器存在的情况下,控制器正在做所有事情,因此如果服务也进行了这些检查,那么似乎存在重复逻辑。

你怎么接近?欢迎大家的评论,我们将不胜感激。

由于 巴巴尔

3 个答案:

答案 0 :(得分:0)

恕我直言,标准方法是使用选项1和选项2。

但是,你必须定义每层中要验证的内容。

这是我最喜欢的方法:

  1. 验证Controller中的字段约束。这包括:日期格式,字符串长度,最小值,最大值,空值...验证
  2. 在Service中验证业务逻辑约束。包括:独特的,存在的检查,从日期<迄今为止,每组实体的最大项目......
  3. 一方面注意:实体永远不应该暴露在外面。我们应该有某种转换器逻辑将实体转换为输出JSON / model

答案 1 :(得分:0)

理想情况下,面向Web的部分应该实现验证逻辑。服务层应该纯粹用于项目的业务部分。在达到您的服务层代码之前,它也是安全性最佳实践。如今人们会混淆层,想要在同一层做所有事情。 jsr-303注释是bean级别验证。所以通常它应用于模型进入画面的地方。

所以你可以在

那样做
  1. 控制器层:验证您的输入和其他最小/最大范围和基本验证。
  2. 服务层:通过自动装配javax.validation.Validator在服务层进行任何特定验证。

答案 2 :(得分:0)

我会做两件事。

在您的示例中,您似乎有两个方法都引用Employee,这在非常简单的场景中可能是可能的,但在实际情况下,这不是。

您更有可能拥有一个{J}属性映射到Java对象字段的EmployeeDTO。您甚至可能具有针对特定员工操作的更具体的DTO(例如更改密码),具体取决于您的UI所公开的形式。这将由您的控制器接收,并且JSR303可以帮助执行语法验证,例如检查字符串不为空,名称不包含数字等。 DTO不应该渗透到服务中,但是它的数据应该转换为服务期望的任何内容,这应该与控制器的输入分离。

您的服务将收到Employee。如果它是有意义的,则可以是JPA实体,或者与正在执行的操作相关的一些其他中间域对象。理想情况下,Employee的创建应该已经强制执行一些简单的检查(例如非空检查),以确保在构造之后对象是一致的。然后,服务本身应该验证它接收的内容,而不管控制器验证的内容。该服务可以由其他控制器使用,或者将来由其他服务调用,因此您应该始终以防御性方式进行编程。该服务还可以进行更多逻辑检查(例如,是否存在具有相同ID但存在不同详细信息的另一名员工?等等)这将进行业务逻辑验证,从而强制执行更强大的功能。

如果您在DTO和实体或中间对象之间看到很多公共代码,那么还有mapper实用程序库可以帮助您避免重复,例如MapStruct。