如果我有一个Web应用程序,比如说我正在使用Spring MVC,并且我在表单和控制器中添加了验证。如果客户以其他方式访问我的应用程序(通过REST服务等),我可能还会在服务层进行验证。在这种情况下,我可能会在多个地方有验证逻辑/代码。如何避免Web层和服务层中的重复验证?
是否有建议的方法来保持验证部分干?
如果我有一个Web应用程序,比如说我正在使用Spring MVC,并且我在表单和控制器中添加了验证。如果客户以其他方式访问我的应用程序(通过REST服务等),我可能还会在服务层进行验证。在这种情况下,我可能会在多个地方有验证逻辑/代码。如何避免Web层和服务层中的重复验证?
是否有建议的方法来保持验证部分干?
很多人会告诉你如何做到这一点。我要回答你为什么不想要。
在N层系统中,层级都是半自主操作的。但这并不意味着他们可以 - 或者应该 - 依靠另一层来保证数据的一致性和有效性。
有两个主要原因。首先,N层系统是可扩展的。例如,在网络系统中,新的前端可能会利用现有的网络层来完成原始设计中从未想过的事情。所以你的设计证明你的系统允许在层级的某个中间点出现新的东西。
其次,验证往往是最有效的越接近用户。如果我在基于浏览器的解决方案中,并且在双输入验证字段中输入了错误的密码,我希望浏览器立即指出。等待往返需要时间并使用户感到沮丧。
现在采取相同的例子,并将其移动到逻辑层。逻辑层,不完全确定谁在发送数据,想要确定它正在接收两个匹配的密码。所以它也检查,并且如果它们不匹配则返回一个错误。这可以保护数据免遭不良变化。
这只是一种哲学,但它在过去对我来说效果很好。
这可能是值得看看JSR-303 bean验证。如果为不同的接口使用相同的JavaBean,则可以避免重复的验证逻辑。
Hibernate实现提供了最好的参考文档:
http://hibernate.org/subprojects/validator
和Spring参考文档告诉你如何整合它。
Spring使用validator接口是单向的。我不知道你为什么不能在服务层中使用它的原因。或者,您可以使用AOP并根据需要在任何层中定义切入点。
首先,业务/功能级验证应始终在服务层进行。如果你说你正在复制在你的MVC层完成的验证在服务层复制,听起来令人担忧。例如,您可以在视图上验证电话号码格式,信用卡格式等内容。您不得在服务层中复制这些内容。
与此同时,您可能必须重复验证,例如“空白”检查,并且从设计的角度来看,这些都是可以的。
我会建议这些是不同种类的验证。
客户机/控制器验证检查,以确保所需的值都存在,格式服从等
绑定HTTP请求参数为对象传递到服务层是控制器的全部责任。
服务层将执行与客户端相同的验证,但也会涉及与用例相关的“业务验证”。控制器无法知道这些。
避免重复的一种方法是在客户端和服务器端执行相同的JavaScript函数。服务器端使用JavaScript引擎执行客户端验证以及与业务验证相关的附加服务器验证。
你说得对,验证更接近用户,但通常可以在服务层中使用的域模型中描述验证约束。例如。服务层返回一个错误对象,Web层负责翻译它,另一个服务层用户将按照他们需要的方式处理它。 – Daff 2011-01-26 18:23:53