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

时间:2014-01-28 14:10:16

标签: java spring validation spring-mvc

很长一段时间以来,我试图弄清楚应该在Spring MVC应用程序中进行用户输入的验证。在许多在线博客和教程中,我基本上读到控制器应验证用户输入,如果无效,则通过显示包含错误消息的页面来响应用户。然而,我目前对Spring和Spring MVC分层系统的理解是,Controller是应用程序逻辑(服务层)和“Web世界”之间唯一的浅层接口,允许从Web使用服务层。另外,据我所知,Spring MVC只提供合理的控制器验证工具。

如果现在验证发生在Controller中,如果稍后我想解开来自“web world”的应用程序逻辑,则必须在新环境中重新实现验证逻辑(例如使用Swing的桌面应用程序)。在我看来,决定哪些操作在域对象上“有效”以及这些对象可能具有哪些“有效”状态的能力是服务层的核心部分,而不是应用程序的其他部分的关注(例如控制器)。

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

2 个答案:

答案 0 :(得分:9)

一种常见的方法是在两个地方进行验证。但是如果你在谈论@Valid,根据我的经验,将控制器级别放在更好的位置。

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

@Data
public class MyBean {
    @NotNull private UUID someId;
    @NotEmpty private String someName; 
}

在控制器级别使用@Valid注释此bean是有意义的,因此它甚至无法访问服务。将@Valid放在服务方法上没有任何好处,因为为什么你可以在控制器中立即进一步传播它,以确定它是否有效。

然后是第二种类型的验证:业务逻辑验证。让我们说同一个bean,someId属性是timeUUid,它的时间戳在某个事件发生后最多需要2天,在其他情况下,该服务应该丢弃该bean。

这看起来像是一个业务逻辑验证案例,因为只要查看bean,就无法验证它,除非你对它应用一些逻辑。

由于两种验证方法实际上都验证了不同的东西,因此很明显可以看到每个MVC组件 - 模型,视图和控制器都进行自己的验证,并且在不引入其他依赖性的情况下验证它的验证应该是合理的。组件。

至于向用户显示错误,是的,Errors对象确实打算用于控制器级别的bean验证,但是你可以设计一些过滤器来捕获任何级别的异常,然后是相当格式它为用户。它有很多种方法,而且我不确定Spring是否规定任何方法比其他方法更好

根据不同的解析机制(例如,jstl或jackson或其他内容),可能倾向于以不同的方式处理验证。例如,传统的jstl view resolver可以很好地处理使用错误的装置,而jackson resolver可能会更好地使用@ResponseBody和一些捕获错误并将它们放入的过滤器的组合响应对象的预定义错误部分。

答案 1 :(得分:2)

在我们之前的一个项目中,我们有非常复杂的逻辑形式,这意味着许多验证代码。所以我们使用了第三种解决方案。对于每个控制器,我们都自动启动了一个辅助类。 例如:

myview <-> MyController <- MyService <- MyDAO
                 ^
                 |
               MyHelper

Controllers处理了解析视图 Services处理从dto-s到模型对象的映射,反之亦然,
DAO-s处理了数据库事务,并且 Helpers处理了其他一切,包括验证。

如果现在有人想要将前端从Web更改为其他内容,那么它会更容易,同时,我们也不会过度膨胀服务实现类。