Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 控制器或服务层中的Spring MVC验证?_Java_Spring_Validation_Spring Mvc - Fatal编程技术网

Java 控制器或服务层中的Spring MVC验证?

Java 控制器或服务层中的Spring MVC验证?,java,spring,validation,spring-mvc,Java,Spring,Validation,Spring Mvc,在相当长的一段时间里,我试图找出用户输入的验证应该在SpringMVC应用程序中的何处进行。在许多在线博客和教程中,我基本上读到控制器应该验证用户的输入,如果输入无效,则通过显示包含错误消息的页面来响应用户。然而,我目前对Spring和SpringMVC分层系统的理解是,控制器只是应用程序逻辑(服务层)和“web世界”之间的一个肤浅的接口,允许从web使用服务层。而且,据我所见,SpringMVC只为控制器中的验证提供了合理的工具 如果现在验证在控制器中进行,如果稍后我想将应用程序逻辑与“web

在相当长的一段时间里,我试图找出用户输入的验证应该在SpringMVC应用程序中的何处进行。在许多在线博客和教程中,我基本上读到控制器应该验证用户的输入,如果输入无效,则通过显示包含错误消息的页面来响应用户。然而,我目前对Spring和SpringMVC分层系统的理解是,控制器只是应用程序逻辑(服务层)和“web世界”之间的一个肤浅的接口,允许从web使用服务层。而且,据我所见,SpringMVC只为控制器中的验证提供了合理的工具

如果现在验证在控制器中进行,如果稍后我想将应用程序逻辑与“web世界”分离,则必须在新环境中重新实现验证逻辑(例如,使用Swing的桌面应用程序)。在我看来,决定哪些操作对域对象是“有效”的,以及这些对象可能具有什么“有效”状态的能力是服务层的核心部分,而不是应用程序的某些其他部分(例如控制器)所关心的


在这种情况下,为什么将输入验证逻辑放在控制器层而不是服务层是“良好实践”

一种常见的方法是在两个地方进行验证。但如果你说的是@Valid,根据我的经验,最好是在控制器级别

这还取决于我们所讨论的验证逻辑的类型。假设你有一个豆子:

@Data
public class MyBean {
    @NotNull private UUID someId;
    @NotEmpty private String someName; 
}
在控制器级别用
@Valid
注释这个bean是有意义的,这样它甚至不会到达服务。将
@Valid
放在服务方法上没有任何好处,因为当您可以立即在控制器中决定它是否有效时,为什么还要进一步传播它

然后还有第二种验证:业务逻辑验证。假设对于同一个bean,someId属性是timeUUid,其时间戳最多需要在某个事件发生后2天,在另一种情况下,该bean应该被服务丢弃

这看起来像是一个业务逻辑验证案例,因为仅仅通过查看bean,您将无法验证它,除非您对其应用一些逻辑

由于这两种验证方法实际上验证了不同的东西,很明显,您的每个MVC组件(模型、视图和控制器)都会进行各自的验证,并且在不向其他组件引入依赖关系的情况下,验证内容应该是合理的

至于向用户显示错误,是的,该对象确实打算用于控制器级别的bean验证,但是您可以设计一些过滤器来捕获任何级别的异常,然后为用户对其进行漂亮的格式化。有很多方法,我不确定Spring是否规定任何一种都比另一种好


根据不同的解析机制(例如,在jstl或jackson等中),您可能倾向于以不同的方式处理验证。例如,传统的会很好地处理使用错误的装置,而a可能会更好地处理和一些过滤器的组合,这些过滤器捕捉错误并将其放入响应对象的预定义错误部分。

在我们以前的一个项目中,我们有巨大的表单和非常复杂的逻辑,这意味着大量的验证代码。所以我们使用了第三种解决方案。对于每个控制器,我们自动连接了一个helper类。 例如:


myview MyController@xSNRG没有理由在两个验证范围之间进行同步。控制器层应该简要检查它可以验证的任何bean属性,如果所有属性都有效,则传递给服务。然后服务应该自己进行业务验证,并将其传递给模型(模型应该有自己的域约束和验证内容)。如果您不将这些层紧密耦合,那么就不需要在它们之间进行任何同步,而只需要单独维护每个层。您的答案中并不明确,但您是否建议不将javax.validation用于业务逻辑验证?如果你能这样做,根据我目前的理解,如果你所做的两种验证类型如此不同,它们应该是分开的,但它们验证相同的对象/类,那么你可以用两个单独的自定义验证程序来分离关注点。@copyandplaste我在回答中提到了两种类型:“原始正确性“验证类型:数据是否有意义):例如填写必填字段、整数和正数等。然后是业务验证,这可能比简单地检查两个属性是否为空要复杂得多,例如,您是否有订单容量,这甚至可能涉及一个数据库调用,您可以将它从“原始”验证中分离出来,放入验证服务或类似的东西中。javax.*比其他类型更适合“raw”,但它不是100%规则。jeejava.com/spring-service-layer-bean-validation/
myview <-> MyController <- MyService <- MyDAO
                 ^
                 |
               MyHelper