服务或控制器中的 Spring DTO 验证?
Posted
技术标签:
【中文标题】服务或控制器中的 Spring DTO 验证?【英文标题】:Spring DTO validation in Service or Controller? 【发布时间】:2013-10-06 16:13:45 【问题描述】:我正在使用 Spring 构建一个简单的 AJAX/JSON Web 服务。常见的数据流是:
some DTO from browser
v
Spring @Controller method
v
Spring @Service method
我正在寻找处理数据验证的最简单方法。
我知道@Valid
注释在 @Controller
方法中运行良好。
为什么@Valid
不能在@Service
方法中工作?
我的意思是:任何其他服务和控制器都可以使用服务方法。那么在@Service
级别进行验证不是更有意义吗?
让我们举个简单的例子:
MyDTO.java:
public class MyDTO
@NotNull
public String required
@Min(18)
public int age;
MyServiceImpl.java:
public MyDomainObject foo(MyDTO myDTO)
// persist myDTO
// and return created domain object
MyController.java:
@Autowired
MyService myService;
@Autowired // some simple bean mapper like Dozer or Orika
Mapper mapper; // for converting domain objects to DTO
@RequestMapping(...)
public MyDomainObjectDTO doSomething(@RequestBody MyDTO myDTO)
mapper.map(myService.foo(myDTO), MyDomainObjectDTO.class);
服务方法接收 DTO 是常见的做法吗?
如果yes
:在服务方法中验证 DTO 的最佳做法是什么?
如果no
:控制器是否应该操作域对象并让服务保存该对象? (这对我来说似乎毫无用处)
在我看来,服务应该只负责数据一致性。
你是怎么解决这个问题的?
【问题讨论】:
Check preconditions in Controller or Service layer 的可能重复项 【参考方案1】:我的回答?两者都有。
服务必须检查自己的合同的有效性。
控制器是 UI 的一部分。它应该验证和绑定以获得更好的用户体验,但服务不应该依赖它。
服务无法知道它是如何被调用的。如果将其包装为 REST 服务会怎样?
该服务还以任何 UI 都无法了解的方式了解业务逻辑违规。它需要验证以确保用例得到适当的满足。
双袋吧;两者都做。
【讨论】:
但是为什么服务不允许@Valid
注释呢? ...我明白了,服务和控制器可以在他们的类中使用(例如)不同的字段。在我的应用程序中,它总是一样的。因此,我只是通过 DTO 进入服务。
因为验证和防御性编程/错误处理之间存在差异。话虽如此,我确实将验证用于防御性编程。我会尽快发布答案。【参考方案2】:
查看我的另一个答案:Check preconditions in Controller or Service layer
如果您真的想在 Service 层中进行类似于 Spring MVC 的错误处理之类的验证,您可以使用 javax.validation
和 AspectJ(建议验证方法),这就是我所做的,因为我喜欢让反射完成这项工作和声明式编程(注解)。
Spring MVC 不需要执行 AspectJ/AOP 来进行错误处理,因为方法是通过反射(url 路由/调度)调用的。
最后,对于您的 MVC 代码,您应该知道 @Valid
在某种程度上已被非正式弃用。请考虑使用@Validated
,它将利用更多javax.validation
功能。
【讨论】:
我现在在服务层使用@Validated
,非常棒。只需注册 Spring 的 MethodValidationPostProcessor
,然后在 Service 接口本身上放置一个 @Validated
注释,最后但并非最不重要的是,在 Service 接口中定义的方法签名上放置一些 @Valid
或 @NotNull
注释。 ServiceImpl 保持干净。这非常有效!唯一的“问题”是,抛出的ConstraintViolationException
中的propertyPath
以整个调用层次结构为前缀,即controllerMethod.serviceMethod.dtoProperty
。我必须以某种方式摆脱它。
你所说的“某种非官方弃用”是什么意思?以上是关于服务或控制器中的 Spring DTO 验证?的主要内容,如果未能解决你的问题,请参考以下文章