关键词:
【中文标题】Spring MVC + Hibernate:数据验证策略【英文标题】:Spring MVC + Hibernate: data validation strategies 【发布时间】:2012-09-21 12:49:04 【问题描述】:我们都知道,Spring MVC 通常与 Hibernate Validator 和 JSR-303 集成得很好。但是正如有人所说,Hibernate Validator 只是 Bean Validation 的东西,这意味着更复杂的验证应该被推送到数据层。此类验证的示例:业务密钥唯一性、记录内依赖性(这通常指向数据库设计问题,但我们都生活在一个不完美的世界中)。即使是像字符串字段长度这样的简单验证也可能由一些 DB 值驱动,这使得 Hibernate Validator 无法使用。
所以我的问题是,Spring、Hibernate 或 JSR 是否提供了一些东西来执行如此复杂的验证?在基于 Spring 和 Hibernate 的标准 Controller-Service-Repository 设置中是否有一些已建立 模式或技术来执行此类验证?
更新:让我说得更具体一些。例如,有一个表单向控制器的save
方法发送AJAX 保存请求。如果出现一些验证错误——无论是简单的还是“复杂的”——我们应该用一些 json 指示有问题的字段和相关错误返回浏览器。对于简单的错误,我可以从BindingResult
中提取字段(如果有)和错误消息。对于“复杂”错误,您会建议什么基础设施(可能是特定的,而不是临时例外?)?使用异常处理程序对我来说似乎不是一个好主意,因为在 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;
你能提供一些更优化的方法吗?
【问题讨论】:
【参考方案1】:是的,Exception throwing 的 Java 模式已经确立了良好的旧模式。 Spring MVC 集成的很好(代码示例可以直接跳到我回答的第二部分)。
您所说的“复杂验证”实际上是例外:业务密钥唯一性错误、低层或数据库错误等。
提醒:Spring MVC 中的验证是什么?
验证应该发生在表示层上。它基本上是关于验证提交的表单字段。
我们可以将它们分为两种:
1) 轻度验证(使用 JSR-303/Hibernate 验证):检查提交的字段是否具有给定的 @Size
/@Length
,它是 @NotNull
或 @NotEmpty
/@NotBlank
,检查它是否具有@Email
格式等。
2) 重度验证或复杂验证更多的是关于字段验证的特定情况,例如跨字段验证:
示例 1:表单有fieldA
、fieldB
和 fieldC
。每个字段可以单独为空,但至少其中一个不能为空。
示例 2:如果 userAge
字段的值小于 18,则responsibleUser
字段不能为空且responsibleUser
的年龄必须大于 21。
可以使用Spring Validator implementations 或custom annotations/constraints 来实现这些验证。
现在我明白了,有了所有这些验证工具,再加上 Spring 完全没有侵入性并且可以让你做任何你想做的事情(无论好坏),人们可能会想使用“验证锤”来任何与错误处理模糊相关的内容。 它会起作用:仅通过验证,您可以检查验证器/注释中的所有可能问题(并且几乎不会在较低层抛出任何异常)。这很糟糕,因为你祈祷你考虑过所有的情况。您不会利用 Java 异常来简化逻辑并通过忘记检查是否有错误来减少出错的机会。
所以在 Spring MVC 世界中,不应该将验证(即 UI 验证)误认为是低层 异常,例如有 Service 异常或 DB 异常(关键唯一性等)。
如何在Spring MVC中轻松处理异常?
有些人认为“天哪,所以在我的控制器中,我必须一一检查所有可能的已检查异常,并为每个异常考虑一个消息错误?没办法!”。我是那些人的其中一个。 :-)
在大多数情况下,只需使用一些通用的检查异常类,所有异常都会扩展。然后只需在 Spring MVC 控制器中使用 @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";
简单、快速、简单、干净!
当您需要为某些特定异常显示错误消息时,或者由于无法修改的旧系统设计不佳而无法提供通用***异常时,只需添加其他 @ExceptionHandler
s。
另一个技巧:对于不那么混乱的代码,您可以使用
@ExceptionHandler(MyException1.class, MyException2.class, ...)
public String yourMethod(Exception e, Model model)
...
底线:何时使用验证?什么时候使用异常?
来自 UI 的错误 = 验证 = 验证工具(JSR-303 注释、自定义注释、Spring 验证器) 来自较低层的错误 = 异常当我说“来自 UI 的错误”时,我的意思是“用户在他的表单中输入了错误”。
参考资料:
Passing errors back to the view from the service layer Very informative blog post about bean validation【讨论】:
杰罗姆,感谢您抽出宝贵时间。请查看更新的问题,我添加了一些细节。您能对此发表意见吗? 我已阅读您的更新,它不会改变我回答的基本内容。使用@ExceptionHandler,您不会分离验证过程,因为异常处理不是验证。在一个好的应用程序中,我认为你应该处理验证和异常:它们在技术上是两个不同的东西。所以没有分离,事情也不复杂。现在,如果您碰巧在验证处理和异常处理中进行了相同的处理,我建议您编写一个方法,例如“processError(...)”,这两个部分都会调用。希望这会有所帮助,我想我不能说更多 不过,如果它们以相同的结尾(向用户显示验证消息)和来自相同的开头(用户输入无效数据),我无法理解它们在“技术上是两个不同的东西” )?假设我没有一个方法,但是有 两个 方法可以抛出这个 ValidationException (一个是保存,另一个 - 删除,删除可能由于非系统错误而失败)并且它们都返回不同的结构JSON。我如何辨别在@ExceptionHandler 中返回哪个视图? 它们是两个不同的东西,因为它们不是验证:数据库错误,因为基础已满,数据库中不存在要更新的元素,您的控制器所依赖的 Web 服务离线或有问题,服务无法创建文件,因为文件夹上的权限已被更改,以及我现在没有想到的任何其他异常:对于大多数情况,您想警告用户“发生了一些意外错误” .至于您的示例,您可以使用 SaveException 和 DeleteException 来实现差异,您可以使用两个不同的 @ExceptionHandler 来处理它们。 简单示例——业务密钥唯一性检查,不是“base is full”之类的系统错误,但与@NotNull
check still大致相同,它需要复杂像 DB 一样处理。你会把这张支票放在哪里?如果在@ExceptionHandler
中,那么我无法理解为什么将其与BindingResult
支票分开。开发人员希望找到组合(或至少链接)在一起的所有验证步骤。如果控制器很大,将它们放入单独的方法中需要额外的脑力劳动(例如,“验证消息来自哪里?!不是来自 BindingResult!”)。在spring mvc中选择spring hibernate中的查询
】在springmvc中选择springhibernate中的查询【英文标题】:Selectqueryinspringhibernateinspringmvc【发布时间】:2014-07-1109:36:27【问题描述】:嗨,我正在编写一个springmvc,使用mysql数据库、hibernate注释和jsp的员工应用程序。该数据库包含一... 查看详情
使用 Spring Boot + Hibernate + MySql 运行 MVC 应用程序
】使用SpringBoot+Hibernate+MySql运行MVC应用程序【英文标题】:RunningaMVCappusingSpringBoot+Hibernate+MySql【发布时间】:2014-08-2207:00:11【问题描述】:我是Spring环境的新手。我试图使用SpringBoot和Hibernate作为ORM和MYSQL作为数据库来开发一个基... 查看详情
Spring Mvc Hibernate Encoding/多行导入sql
】SpringMvcHibernateEncoding/多行导入sql【英文标题】:SpringMvcHibernateEncoding/Multi-lineimportsql【发布时间】:2015-10-0516:10:11【问题描述】:我正在研究SpringMVC,在项目启动时,我已将database设置为导入默认sql使用休眠配置hibernate.hbm2ddl.imp... 查看详情
Hibernate - Spring Security - Spring MVC 版本
】Hibernate-SpringSecurity-SpringMVC版本【英文标题】:Hibernate-SpringSecurity-SpringMVCVersions【发布时间】:2018-04-0514:34:09【问题描述】:我正在尝试使用SpringSecurity、SpringMVC和Hibernate实现一个Web应用程序。经过对互联网的一些研究,我面临... 查看详情
spring 4 mvc + Hibernate + Annotations 配置堆内存问题
】spring4mvc+Hibernate+Annotations配置堆内存问题【英文标题】:spring4mvc+Hibernate+AnnotationsconfigurationHeapmemoryissue【发布时间】:2017-06-2806:42:37【问题描述】:环境细节是。IntellijIDESpring4Hibernatewithsimpleschemaof30tablesElasticsearchclientMys 查看详情
当数据正确显示时,为啥我在这个 Spring MVC Web 应用程序中得到一个 Hibernate LazyInitializationException?
...正确显示时,为啥我在这个SpringMVCWeb应用程序中得到一个HibernateLazyInitializationException?【英文标题】:WhyamIgettingaHibernateLazyInitializationExceptioninthisSpringMVCwebapplicationwhenthedatadisplayscorrectly?当数据正确显示时,为什么我在这个SpringMVC... 查看详情
如何提高 Spring MVC - Hibernate - JSP - AngularJS v1.6 的性能? [关闭]
】如何提高SpringMVC-Hibernate-JSP-AngularJSv1.6的性能?[关闭]【英文标题】:HowtoincreaseperformanceinSpringMVC-Hibernate-JSP-AngularJSv1.6?[closed]【发布时间】:2018-05-0603:45:48【问题描述】:给我一些想法/建议/解决方案,以更快地检索数据和... 查看详情
我们如何使用hibernate作为orm单独的数据库和模式来构建一个spring mvc多租户应用程序
】我们如何使用hibernate作为orm单独的数据库和模式来构建一个springmvc多租户应用程序【英文标题】:howcanwebuildaspringmvcmultitenantapplicationusinghibernateasormseparatedatabaseandschema【发布时间】:2019-12-3008:17:51【问题描述】:你从springio转... 查看详情
从 Migrate 迁移到 Spring MVC 4 + Hibernate5
】从Migrate迁移到SpringMVC4+Hibernate5【英文标题】:MigratingfromMigratetoSpringMVC4+Hibernate5【发布时间】:2017-08-0322:39:51【问题描述】:我正在将应用程序从Jersey1.18、Spring3、Hibernate3.6、Maven迁移到全新的架构:Spring4.3(通过SpringBoot)、Hi... 查看详情
Spring MVC + Hibernate 4 + Spring Security
】SpringMVC+Hibernate4+SpringSecurity【英文标题】:【发布时间】:2012-12-0504:06:23【问题描述】:从现在开始,我一直在努力完成所有这些工作,不知道该怎么办。我相信我在SO上浏览了关于该主题的每一篇文章,并浏览了数十个教程..... 查看详情
集成magnolia和spring mvc,hibernate
】集成magnolia和springmvc,hibernate【英文标题】:integratingmagnoliaandspringmvc,hibernate【发布时间】:2015-03-1814:02:50【问题描述】:我们正在使用开花插件将SpringMVC集成到Magnolia中。以下是我们集成的步骤。-创建bloom项目,然后添加一些... 查看详情
请解释spring MVC,hibernate和Spring security
】请解释springMVC,hibernate和Springsecurity【英文标题】:PleaseExplainspringMVC,hibernateandSpringsecurity【发布时间】:2017-01-0323:44:24【问题描述】:在很多指南的帮助下,我刚刚使用Spring安全性和休眠创建了我的第一个登录页面。我遇到的... 查看详情
带有 Spring、Spring MVC、Hibernate、JPA 的项目的 Maven 3 原型
】带有Spring、SpringMVC、Hibernate、JPA的项目的Maven3原型【英文标题】:Maven3ArchetypeforProjectWithSpring,SpringMVC,Hibernate,JPA【发布时间】:2013-01-1316:42:33【问题描述】:我正在尝试使用Maven3创建一个使用Spring3、SpringMVC、Hibernate4和JPA的项... 查看详情
Spring boot、mvc、hibernate 和 mysql 配置 - sessionFactory 错误
】Springboot、mvc、hibernate和mysql配置-sessionFactory错误【英文标题】:Springboot,mvc,hibernateandmysqlconfiguration-sessionFactoryerror【发布时间】:2017-02-1005:29:33【问题描述】:我是春季靴子的新手。我想用mysql、hibernate、jpa和jsp配置springboot。... 查看详情
Spring 框架 MVC - Hibernate 异常是 java.lang.NoSuchMethodError
】Spring框架MVC-Hibernate异常是java.lang.NoSuchMethodError【英文标题】:SpringframeworkMVC-Hibernateexceptionisjava.lang.NoSuchMethodError【发布时间】:2016-02-1506:41:00【问题描述】:我发布这个问题是关于我在JavaSpringFrameworkMVC-Hibernate中的一个项目。... 查看详情
确保 AUTHENTICATED 用户被授权访问资源的最佳实践 - Spring mvc、Spring Security、Hibernate
...TED用户被授权访问资源的最佳实践-Springmvc、SpringSecurity、Hibernate【英文标题】:BestpracticetomakesureanAUTHENTICATEDuserisAUTHORISEDtoaccessaresource-Springmvc,SpringSecurity,Hibernate【发布时间】:2016-06-1808:52:10【问题描述】:我们有一个spring 查看详情
Spring MVC“org.hibernate.PropertyAccessException”中的休眠注释映射异常
】SpringMVC“org.hibernate.PropertyAccessException”中的休眠注释映射异常【英文标题】:HibernateAnnotationMappingExceptioninSpringMVC"org.hibernate.PropertyAccessException"【发布时间】:2015-01-2017:13:18【问题描述】:我是SpringMVC和Hibernate的新手。... 查看详情
Spring MVC + Hibernate DAO:无法连接 bean
】SpringMVC+HibernateDAO:无法连接bean【英文标题】:SpringMVC+HibernateDAOs:unabletowirebeans【发布时间】:2012-06-0120:49:28【问题描述】:我目前正在开发一个集成了Hibernate的SpringMVC项目。纯SpringMVC部分(DispatcherServlet+请求映射)工作正常... 查看详情