服务或控制器中的 Spring DTO 验证?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19100317/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring DTO validation in Service or Controller?
提问by Benjamin M
I'm building a straight forward AJAX / JSON web service with Spring. The common data flow is:
我正在使用 Spring 构建一个直接的 AJAX/JSON Web 服务。常见的数据流是:
some DTO from browser
v
Spring @Controller method
v
Spring @Service method
I'm looking for the most easy way to handle data validation.
我正在寻找处理数据验证的最简单方法。
- I know the
@Validannotation which works pretty well inside@Controllermethods. - Why does
@Validnotwork within@Servicemethods?
- 我知道
@Valid在@Controller方法中运行良好的注释。 - 为什么
@Valid不内工作@Service的方法呢?
I mean: A service method can be used by any other service and controller. So wouldn't it make much more sense to validate at @Servicelevel?
我的意思是:服务方法可以被任何其他服务和控制器使用。那么在@Service级别上进行验证不是更有意义吗?
Let's take this simple example:
让我们以这个简单的例子为例:
MyDTO.java:
我的DTO.java:
public class MyDTO {
@NotNull
public String required
@Min(18)
public int age;
}
MyServiceImpl.java:
MyServiceImpl.java:
public MyDomainObject foo(MyDTO myDTO) {
// persist myDTO
// and return created domain object
}
MyController.java:
我的控制器.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);
}
Is it common practice that the service method receives the DTO?
服务方法接收 DTO 是常见的做法吗?
- If
yes: What's the best practice to validate that DTO inside the service method? - If
no: Should maybe the controller manipulate the Domain object and just let the service save that object? (this seems pretty useless to me)
- 如果
yes:在服务方法中验证 DTO 的最佳实践是什么? - 如果
no:控制器是否应该操作域对象并让服务保存该对象?(这对我来说似乎没什么用)
In my opinion the service should be responsible for only data consistency.
在我看来,服务应该只负责数据一致性。
How do you solve this?
你如何解决这个问题?
回答by duffymo
My answer? Both.
我的答案?两个都。
The service must check its own contract for validity.
服务必须检查自己的合同的有效性。
The controller is part of the UI. It should validate and bind for a better user experience, but the service should not rely on it.
控制器是 UI 的一部分。它应该验证和绑定以获得更好的用户体验,但服务不应该依赖它。
The service cannot know how it's being called. What if you wrap it as a REST service?
该服务无法知道它是如何被调用的。如果将其包装为 REST 服务会怎样?
The service also knows about business logic violations in a way that no UI can. It needs to validate to make sure that the use case is fulfilled appropriately.
该服务还以 UI 无法做到的方式了解业务逻辑违规。它需要验证以确保用例得到适当的满足。
Double bag it; do both.
双袋它; 两者都做。
回答by Adam Gent
See my other answer: Check preconditions in Controller or Service layer
请参阅我的其他答案:检查控制器或服务层中的前提条件
If you really want to do validation like error handling in your Service layer similar to Spring MVC you can use javax.validationand AspectJ (to advice the methods to validate) which is what I do because I like making reflection do the work and declarative programming (annotations).
如果您真的想在类似于 Spring MVC 的服务层中进行诸如错误处理之类的验证,您可以使用javax.validationAspectJ(建议验证方法),这就是我所做的,因为我喜欢让反射完成工作和声明式编程(注释) .
Spring MVC doesn't need to do AspectJ/AOP to do the error handling because the methods are being called through reflection (url routing/dispatching).
Spring MVC 不需要执行 AspectJ/AOP 来进行错误处理,因为这些方法是通过反射(url 路由/调度)调用的。
Finally for you MVC code you should know that @Validis sort of unofficially deprecated. Instead consider @Validatedwhich will leverage more of the javax.validationfeatures.
最后,对于您的 MVC 代码,您应该知道这@Valid是非官方弃用的。而是考虑@Validated哪个将利用更多的javax.validation功能。

