gpt4 book ai didi

java - Spring MVC + hibernate : data validation strategies

转载 作者:IT老高 更新时间:2023-10-28 20:51:04 24 4
gpt4 key购买 nike

我们都知道,Spring MVC 通常与 Hibernate Validator 和 JSR-303 集成得很好。但是,正如有人所说,Hibernate Validator 只是 Bean Validation 的东西,这意味着应该将更复杂的验证推到数据层。此类验证的示例:业务 key 唯一性、记录内依赖性(这通常指向数据库设计问题,但我们都生活在一个不完美的世界中)。即使是像字符串字段长度这样的简单验证也可能由一些 DB 值驱动,这使得 Hibernate Validator 无法使用。

所以我的问题是,Spring、Hibernate 或 JSR 是否提供了一些东西来执行如此复杂的验证?在基于 Spring 和 Hibernate 的标准 Controller-Service-Repository 设置中是否有一些已建立模式或技术来执行此类验证?

更新:让我说得更具体一些。例如,有一个表单向 Controller 的 save 方法发送 AJAX 保存请求。如果出现一些验证错误——无论是简单的还是“复杂的”——我们应该用一些 json 指示有问题的字段和相关错误返回浏览器。对于简单的错误,我可以从 BindingResult 中提取字段(如果有)和错误消息。对于“复杂”错误,您会建议什么基础设施(可能是特定的,而不是临时异常(exception)?)?使用异常处理程序对我来说似乎不是一个好主意,因为在 save 方法和 @ExceptionHandler 之间分离单个验证过程会使事情变得复杂。目前我使用一些临时异常(例如,ValidationException):

public @ResponseBody Result save(@Valid Entity entity, BindingResult errors) {
Result r = new Result();
if (errors.hasErrors()) {
r.setStatus(Result.VALIDATION_ERROR);
// ...
} else {
try {
dao.save(entity);
r.setStatus(Result.SUCCESS);
} except (ValidationException e) {
r.setStatus(Result.VALIDATION_ERROR);
r.setText(e.getMessage());
}
}
return r;
}

你能提供一些更优化的方法吗?

最佳答案

是的,Exception throwing 的 Java 模式已经确立了良好的旧模式。
Spring MVC 集成的很好(代码示例可以直接跳到我回答的第二部分)。

您所说的“复杂验证”实际上是异常(exception):业务 key 唯一性错误、低层或数据库错误等。


提醒:Spring MVC 中的验证是什么?

验证应该发生在表示层上。它基本上是关于验证提交的表单字段。

我们可以将它们分为两种:

1) 轻度验证(使用 JSR-303/Hibernate 验证):检查提交的字段是否具有给定的 @Size/@Length,它是 @NotNull@NotEmpty/@NotBlank,检查它是否具有 @Email 格式等。

2) 重度验证或复杂验证更多的是关于字段验证的特定情况,例如跨字段验证:

  • 示例1:表单有fieldAfieldBfieldC。每个字段可以单独为空,但至少有一个字段不能为空。
  • 示例 2:如果 userAge 字段的值小于 18,则 responsibleUser 字段不能为空且 responsibleUser 的年龄必须超过21.

这些验证可以通过 Spring Validator implementations 来实现。 , 或 custom annotations/constraints .

现在我明白了,有了所有这些验证工具,再加上 Spring 完全没有侵入性并且可以让你做任何你想做的事情(无论好坏),人们可能会想使用“验证锤”来任何与错误处理模糊相关的内容。
它会起作用:仅通过验证,您可以检查 validator/注释中的所有可能问题(并且几乎不会在较低层抛出任何异常)。这很糟糕,因为你祈祷你考虑过所有的情况。您不会利用 Java 异常来简化逻辑并通过忘记检查是否有错误来减少出错的机会。

所以在 Spring MVC 世界中,不应该将验证(即 UI 验证)误认为是低层 异常,例如有 Service 异常或 DB 异常(关键唯一性等)。


如何在Spring MVC中轻松处理异常?

有些人认为“天哪,所以在我的 Controller 中,我必须一一检查所有可能的已检查异常,并为每个异常考虑一个消息错误?没办法!”。我是那些人的其中一个。 :-)

在大多数情况下,只需使用一些通用的检查异常类,所有异常都会扩展。然后只需在 Spring MVC Controller 中使用 @ExceptionHandler 处理它和一般错误消息。

代码示例:

public class MyAppTechnicalException extends Exception { ... }

@Controller
public class MyController {

...

@RequestMapping(...)
public void createMyObject(...) throws MyAppTechnicalException {
...
someServiceThanCanThrowMyAppTechnicalException.create(...);
...
}

...

@ExceptionHandler(MyAppTechnicalException.class)
public String handleMyAppTechnicalException(MyAppTechnicalException e, Model model) {

// Compute your generic error message/code with e.
// Or just use a generic error/code, in which case you can remove e from the parameters
String genericErrorMessage = "Some technical exception has occured blah blah blah" ;

// There are many other ways to pass an error to the view, but you get the idea
model.addAttribute("myErrors", genericErrorMessage);

return "myView";
}

}

简单、快速、简单、干净!

当您需要为某些特定异常显示错误消息时,或者由于设计不佳的遗留系统无法修改而无法提供通用顶级异常时,只需添加其他 @ExceptionHandlers.
另一个技巧:对于不太困惑的代码,您可以使用

处理多个异常
@ExceptionHandler({MyException1.class, MyException2.class, ...})
public String yourMethod(Exception e, Model model) {
...
}

底线:何时使用验证?什么时候使用异常?

  • 来自 UI 的错误 = 验证 = 验证工具(JSR-303 注释、自定义注释、Spring validator )
  • 来自较低层的错误 = 异常

当我说“来自 UI 的错误”时,我的意思是“用户在他的表单中输入了错误”。

引用资料:

关于java - Spring MVC + hibernate : data validation strategies,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12660262/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com