是的,有一个古老的 Java 模式异常抛出.
Spring MVC 集成得很好(对于代码示例,您可以直接跳到我答案的第二部分)。
您所谓的“复杂验证”实际上是例外:业务密钥唯一性错误、低层或数据库错误等。
提醒:Spring MVC 中的验证是什么?
验证应该在表示层上进行。它基本上是关于验证提交的表单字段。
我们可以将它们分为两类:
1) 光验证(使用 JSR-303/Hibernate 验证):检查提交的字段是否具有给定的@Size
/@Length
, 这是@NotNull
or @NotEmpty
/@NotBlank
,检查它是否有@Email
格式等
2)大量验证,或复杂验证更多关于字段验证的特定情况,例如跨字段验证:
- 示例 1:表格有
fieldA
, fieldB
and fieldC
。单独而言,每个字段可以为空,但至少其中一个字段不能为空。
- 示例 2:如果
userAge
字段的值小于 18,responsibleUser
字段不得为空并且responsibleUser
的年龄必须超过 21 岁。
这些验证可以通过以下方式实现Spring 验证器实现 https://stackoverflow.com/a/12149331/400545, or 自定义注释/约束 https://stackoverflow.com/questions/1972933/cross-field-validation-with-hibernate-validator-jsr-303.
现在我明白,有了所有这些验证工具,再加上 Spring 根本不具有侵入性,并且可以让您做任何您想做的事情(无论好坏),人们可能会忍不住将“验证锤”用于任何模糊相关的事情到错误处理。
它会起作用:仅通过验证,您可以检查验证器/注释中的每个可能的问题(并且几乎不会在较低层中抛出任何异常)。这很糟糕,因为你祈祷你考虑了所有的情况。您不会利用 Java 异常来简化逻辑并减少因忘记检查某些内容是否有错误而出错的机会。
因此,在 Spring MVC 世界中,人们不应该错误验证(也就是说,用户界面验证) 对于下层例外情况,例如有服务异常或数据库异常(关键唯一性等)。
如何方便地处理Spring MVC中的异常?
有些人认为“天哪,所以在我的控制器中,我必须一一检查所有可能的检查异常,并为每个异常考虑一个消息错误?不可能!”。我是那些人的其中一个。 :-)
对于大多数情况,只需使用所有异常都会扩展的通用检查异常类。然后只需在 Spring MVC 控制器中处理它@ExceptionHandler http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-exceptionhandlers和一般错误消息。
代码示例:
public class MyAppTechnicalException extends Exception { ... }
and
@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";
}
}
简单、快速、方便、干净!
当您需要显示某些特定异常的错误消息时,或者由于无法修改设计不良的遗留系统而无法拥有通用顶级异常时,只需添加其他异常即可@ExceptionHandler
s.
另一个技巧:为了减少混乱的代码,您可以使用以下方法处理多个异常
@ExceptionHandler({MyException1.class, MyException2.class, ...})
public String yourMethod(Exception e, Model model) {
...
}
底线:何时使用验证?何时使用异常?
- 来自 UI 的错误 = 验证 = 验证工具(JSR-303 注释、自定义注释、Spring 验证器)
- 来自较低层的错误 = 异常
当我说“用户界面错误”时,我的意思是“用户在表单中输入了错误的内容”。
参考 :
- 将错误从服务层传递回视图 https://stackoverflow.com/questions/3224749/passing-errors-back-to-the-view-from-the-service-layer
- 关于 Bean 验证的内容非常丰富的博客文章 http://blog.orange11.nl/2009/08/04/bean-validation-integrating-jsr-303-with-spring/