21

我正在使用 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:控制器是否应该操纵域对象并让服务保存该对象?(这对我来说似乎毫无用处)

在我看来,该服务应该只负责数据一致性。

你如何解决这个问题?

4

2 回答 2

25

我的答案?两个都。

服务必须检查自己的合同的有效性。

控制器是 UI 的一部分。它应该验证和绑定以获得更好的用户体验,但服务不应该依赖它。

该服务无法知道它是如何被调用的。如果将其包装为 REST 服务会怎样?

该服务还以任何 UI 都无法了解的方式了解业务逻辑违规。它需要验证以确保用例得到适当的满足。

双层包装;两者都做。

于 2013-09-30T17:37:42.530 回答
6

查看我的其他答案:检查控制器或服务层中的先决条件

如果您真的想在类似于 Spring MVC 的服务层中进行错误处理等验证,您可以使用javax.validationAspectJ(建议验证方法),这就是我所做的,因为我喜欢让反射完成工作和声明式编程(注释) .

Spring MVC 不需要执行 AspectJ/AOP 来进行错误处理,因为这些方法是通过反射(url 路由/调度)调用的。

最后,对于您的 MVC 代码,您应该知道这@Valid是一种非正式弃用的代码。而是考虑@Validated哪个会利用更多的javax.validation功能。

于 2013-09-30T18:24:23.480 回答