1.**概述**
在本教程中,我们将讨论 Java 应用程序服务层中的 Spring 验证。尽管Spring Boot 支持与自定义验证器的无缝集成,但执行验证的事实上的标准是Hibernate Validator 。
在这里,我们将学习如何将我们的验证逻辑从控制器中移到一个单独的服务层中。此外,我们将在 Spring 应用程序的服务层中实现验证。
2. 应用分层
根据需求,Java 业务应用程序可以采用多种不同的形式和类型。例如,我们必须根据这些标准确定我们的应用程序需要哪些层。除非有特定需求,否则许多应用程序不会从服务或存储库层增加的复杂性和维护成本中受益。
我们可以通过使用多层来解决所有这些问题。这些层是:
消费者层或 Web 层是 Web 应用程序的最顶层。它负责解释用户的输入并提供适当的响应。其他层抛出的异常也必须由 web 层处理。由于 web 层是我们应用程序的入口点,它负责身份验证并作为防止未经授权用户的第一道防线。
web层下面是Service层。它充当事务屏障并容纳应用程序和基础设施服务。此外,服务层的公共 API 由应用服务提供。它们通常作为交易边界并负责授权交易。基础设施服务提供连接到外部工具(包括文件系统、数据库和电子邮件服务器)的“管道代码”。这些方法通常由多个应用程序服务使用。
Web 应用程序的最低层是持久层。换句话说,它负责与用户的数据存储进行交互。
3.**服务层验证**
服務層是應用程序中促進控制器和持久層之間通信的層。此外,業務邏輯存儲在服務層中。它特別包括驗證邏輯。模型狀態用於在控制器和服務層之間進行通信。
將驗證視為業務邏輯有利有弊,Spring 的驗證(和數據綁定)架構也不排除這兩種情況。驗證尤其不應綁定到 Web 層,應易於本地化,並應允許使用任何可用的驗證器。
此外,客戶端輸入數據並不總是通過 REST 控制器進程,如果我們不在服務層進行驗證,不可接受的數據可能會通過,從而導致幾個問題。在這種情況下,我們將使用標準的 Java JSR-303 驗證方案。
服务层是应用程序中促进控制器和持久层之间通信的层。此外,业务逻辑存储在服务层中。它特别包括验证逻辑。模型状态用于在控制器和服务层之间进行通信。
将验证视为业务逻辑有利有弊,Spring 的验证(和数据绑定)架构也不排除这两种情况。验证尤其不应绑定到Web 层,应易于本地化,并应允许使用任何可用的验证器。
此外,客户端输入数据并不总是通过REST 控制器进程,在这种情况下,
4.*例子*
让我们考虑一个使用Spring Boot 开发的简单用户帐户注册表。
4.1.简单域类
首先,我们将只有姓名、年龄、电话和密码属性:
public class UserAccount { @NotNull(message = "Password must be between 4 to 15 characters") @Size(min = 4, max = 15) private String password; @NotBlank(message = "Name must not be blank") private String name; @Min(value = 18, message = "Age should not be less than 18") private int age; @NotBlank(message = "Phone must not be blank") private String phone; // standard constructors / setters / getters / toString }
在这里,在上面的类中,我们使用了四个批注-@NotNull
@Size
@NotBlank
@Min
4.2.在服务层实现验证
有许多验证解决方案可用,Spring 或Hibernate 处理实际验证。另一方面,手动验证是一种可行的替代方法 在将验证集成到我们应用程序的正确部分时,这为我们提供了很大的灵活性。
接下来,让我们在服务类中实现我们的验证:
@Service public class UserAccountService { @Autowired private Validator validator; @Autowired private UserAccountDao dao; public String addUserAccount(UserAccount useraccount) { Set<ConstraintViolation> violations = validator.validate(useraccount); if (!violations.isEmpty()) { StringBuilder sb = new StringBuilder(); for (ConstraintViolation constraintViolation : violations) { sb.append(constraintViolation.getMessage()); } dao.addUserAccount(useraccount); throw new ConstraintViolationException("Error occurred: " + sb.toString(), violations); } return "Account for " + useraccount.getName() + " Added!"; } }
Validator
是Bean Validation API 的一部分,负责验证Java 对象 此外,Spring 自动提供了一个 函数中传递的对象。结果是一Validator
UserAccountService
Validator
validate(..)
Set
ConstraintViolation
如果没有违反验证约束(对像有效),则 否则,我们会抛出Set
ConstraintViolationException
4.3.实现REST 控制器
在此之后,让我们构建Spring REST Controller 类以向客户端或最终用户显示服务并评估应用程序的输入验证:
@RestController public class UserAccountController { @Autowired private UserAccountService service; @PostMapping("/addUserAccount") public Object addUserAccount(@RequestBody UserAccount userAccount) { return service.addUserAccount(userAccount); } }
我们没有在上面的REST 控制器表单中@Valid
4.4.测试REST 控制器
现在,让我们通过运行Spring Boot 应用程序来测试这个方法。之后,使用Postman 或任何其他API 测试工具,我们将JSON 输入发布到localhost:8080/addUserAccount
{ "name":"Baeldung", "age":25, "phone":"1234567890", "password":"test", "useraddress":{ "countryCode":"UK" } }
在确认测试成功运行后,让我们现在检查验证是否按预期工作。下一个合乎逻辑的步骤是使用少量无效输入来测试应用程序。因此,我们将使用无效值更新我们的输入JSON:
{ "name":"", "age":25, "phone":"1234567890", "password":"", "useraddress":{ "countryCode":"UK" } }
控制台现在显示错误消息,因此,
Error occurred: Password must be between 4 to 15 characters, Name must not be blank
5. 优点和缺点
在服务/业务层,这通常是一种成功的验证方法。它不限于方法参数,可以应用于各种对象。例如,我们可以从数据库加载一个对象,更改它,然后在继续之前验证它。
我们也可以使用这个方法进行单元测试,这样我们就可以实际模拟Service 类。为了便于在单元测试中进行真正的验证,我们可以手动生成必要的Validator
这两种情况都不需要在我们的测试中引导Spring 应用程序上下文。
六,结论
在本快速教程中,我们探索了Java 业务应用程序的不同层。我们学习了如何将我们的验证逻辑从控制器中移到一个单独的服务层中。此外,我们实现了一种在Spring 应用程序的服务层中执行验证的方法。
0 评论