如何避免Web层和服务层中的重复验证?

时间:2011-01-26 18:09:39

标签: java validation spring-mvc

如果我有一个Web应用程序,说我正在使用Spring MVC,并且我在表单和控制器中添加了验证。如果客户端以其他方式访问我的应用程序(通过REST服务等),我可能也会在我的服务层中进行验证。在这种情况下,我可能在多个地方都有验证逻辑/代码。

是否有建议的方法来保持验证部分DRY?

5 个答案:

答案 0 :(得分:6)

很多人会告诉你如何做到这一点。我将回答你可能不想要的原因。

在N层系统中,所有层都是半自动运行的。但这并不意味着他们可以 - 或者应该 - 依赖另一层来保证数据的一致性和有效性。

主要有两个原因。首先,N层系统是可扩展的。例如,在Web系统中,新的前端可能利用现有的Web层来执行原始设计中从未想到的事情。因此,您可以通过允许在层中的某个中间点获得新的东西来设计校对系统。

其次,验证通常最有效,越接近用户。如果我在基于浏览器的解决方案中并且在双输入验证字段中输入了错误的密码,我希望浏览器立即指出这一点。等待往返需要花费时间并使用户感到沮丧。

现在采用相同的示例并将其移至逻辑层。逻辑层,不确定谁发送数据,想要确定它正在接收两个匹配的密码。所以它也检查,如果它们不匹配则返回错误。这可以保护数据免受不良变化的影响。

这只是一种哲学,但过去它对我来说效果很好。

答案 1 :(得分:2)

看看JSR-303 bean验证可能是值得的。如果对不同的接口使用相同的JavaBeans,则可以避免重复的验证逻辑。

Hibernate实现提供了最佳参考文档:

http://hibernate.org/subprojects/validator

Spring参考文档告诉您如何集成它。

http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/validation.html#validation-beanvalidation-overview

答案 2 :(得分:2)

我建议这些是不同类型的验证。

客户端/控制器验证检查以确保存在所需的值,遵循格式等。

将HTTP请求参数绑定到要传递给服务层的对象是控制器的专有责任。

服务层将执行与客户端相同的验证,但也会引入与用例相关的“业务验证”。控制器无法知道这些。

避免重复的一种方法是在客户端和服务器端执行相同的JavaScript功能。服务器端使用JavaScript引擎执行客户端验证以及与业务验证相关的其他验证。

答案 3 :(得分:0)

Spring使用validator接口这是一种方式。我不知道为什么你也不能在服务层中使用它。或者,您可以使用AOP并根据需要在任何层中定义切入点。

答案 4 :(得分:0)

首先,业务/功能级别验证应始终位于服务层。如果你说你复制的验证是在你的MVC层上完成的,那么在服务层复制这听起来很惊人。例如,在视图中,您可以验证电话号码格式,信用卡格式等内容。您不得在服务层中复制这些内容。

与此同时,您可能需要复制验证,例如“空”检查,从设计的角度来看,这些都是正常的。