【发布时间】:2011-06-16 01:01:25
【问题描述】:
如果我有一个 Web 应用程序,假设我正在使用 Spring MVC,并在我的表单和控制器中添加验证。如果客户端以其他方式(通过 REST 服务等)访问我的应用程序,我可能还会在我的服务层中进行验证。在这种情况下,我可能在多个地方都有验证逻辑/代码。
是否有建议的方法来保持验证部分干燥?
【问题讨论】:
标签: java validation spring-mvc
如果我有一个 Web 应用程序,假设我正在使用 Spring MVC,并在我的表单和控制器中添加验证。如果客户端以其他方式(通过 REST 服务等)访问我的应用程序,我可能还会在我的服务层中进行验证。在这种情况下,我可能在多个地方都有验证逻辑/代码。
是否有建议的方法来保持验证部分干燥?
【问题讨论】:
标签: java validation spring-mvc
我建议这些是不同类型的验证。
客户端/控制器验证检查以确保存在所需的值、遵守格式等。
将 HTTP 请求参数绑定到要传递给服务层的对象中是控制器的专属职责。
服务层将执行与客户端相同的验证,但也会加入与用例相关的“业务验证”。控制器无法知道这些。
避免重复的一种方法是在客户端和服务器端执行相同的 JavaScript 函数。服务器端使用 JavaScript 引擎执行客户端验证以及与业务验证相关的其他验证。
【讨论】:
首先,业务/功能级别验证应始终在服务层中进行。如果您说您正在重复在 MVC 层上完成的验证,那么在服务层上会重复,这听起来令人震惊。例如,在视图中,您可以验证电话号码格式、信用卡格式等内容。您不得在您的服务层中重复这些内容。
同时,您可能必须重复验证,例如“空”检查,从设计的角度来看,这些都是可以的。
【讨论】:
很多人会告诉你如何做到这一点。我将回答为什么你可能不想。
在 N 层系统中,所有层都是半自治的。但这并不意味着他们可以——或者应该——依赖另一层来保证数据的一致性和有效性。
有两个主要原因。首先,N 层系统是可扩展的。例如,在一个 web 系统中,一个新的前端可能会利用现有的 web 层来做一些在原始设计中从未想过的事情。因此,您通过允许在层的某个中间点出现新的东西来对您的系统进行设计校对。
其次,验证通常越靠近用户越有效。如果我在基于浏览器的解决方案中,并且在双输入验证字段中输入了错误的密码,我希望浏览器立即指出这一点。等待往返需要时间并且让用户感到沮丧。
现在举同样的例子,把它移到逻辑层。逻辑层不完全确定是谁在向它发送数据,希望确定它正在接收两个匹配的密码。所以它也会检查,如果它们不匹配则返回错误。这可以保护数据免受不良更改。
这只是一种哲学,但过去对我来说效果很好。
【讨论】:
Spring 使用validator 接口这是一种方式。我不知道为什么您也不能在服务层中使用它。或者,您可以使用 AOP 并根据需要在任何层中定义切入点。
【讨论】:
可能值得一看 JSR-303 bean 验证。如果您对不同的接口使用相同的 JavaBean,则可以避免重复的验证逻辑。
Hibernate 实现提供了最好的参考文档:
http://hibernate.org/subprojects/validator
Spring 参考文档告诉您如何集成它。
【讨论】: