今天,我与我们的一位团队成员就Controller
和Service
层中的RESTful API输入的验证进行了广泛的讨论,我觉得这是提出更大论点的糟糕日子。因此,我们有一个具有分层体系结构的Spring Boot微服务应用程序
Controller --> Service --> Repository
该参数是在每一层进行验证还是仅在Controller
层进行验证,例如,我们有Controller
的{{1}}请求并使用JSR-380验证输入请求正文
控制器:
POST
配置:请求正文
@PostMapping(value = "/", consumes = {"application/json"}, produces = {"application/json"})
public ResponseEntity<Detail> createConfig(
@NotNull(message = "{error.message.config_detail}")
@RequestBody @Validated Config config) {
return new ResponseEntity<>(configService.create(config.getConfigId(), config.getTaskId()), HttpStatus.CREATED);
}
如果验证成功,则使用public class Config {
@ApiModelProperty(name = "config_id", example = "1", required = true)
@NotNull(message = "{error.message.config_id}")
private Long configId;
@ApiModelProperty(name = "task_id", example = "11", required = true)
@NotNull(message = "{error.message.task_id}")
@Min(value = 0, message = "{error.message.task_id}")
@Max(value = 9999, message = "{error.message.task_id}")
private Integer taskId;
// bunch of addition fields with validations
}
的某些属性调用Service
方法
服务:
Config
因此,如果我们看到上述代码,则在public Detail create(@Valid @NotNull Long configId, @NotNull Integer taskId) {
// some business logic to convert to entity and saving to database
return repository.save(entity));
}
和Controller
处进行相同的验证,因此我认为无需在Service
层进行验证,请在以下位置进行验证控制器层,如果输入错误,则向用户抛出Service
或400
。 但是团队中的另一个人也建议在每个块中对块中使用的内容进行验证,以确保每段代码都是安全的(专注于单元而不是集成路径)。
我知道在这种情况下我可能是错的,但是仍然无法理解每一层的验证(我同意无效检查),因此建议在每个级别进行验证的方法
500
但是我认为首选的验证方式是什么??如果Controller --> validation call service
Service ---> validation and call business
Business ---> validation and call repository
Repository --> save
输入是有效的,请致电Controller
并执行业务逻辑并致电Service
。如果我错了,请纠正我,以便我可以遵循推荐的模式
答案 0 :(得分:0)
您是对的:如果可能的话,验证应该放在控制器中。在我看来,验证数据超过1次是没有意义的。 另请参阅DRY原理https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
答案 1 :(得分:0)
这是情境。一些验证需要在服务层中执行。说,您将需要更改对象的状态,但前提是要满足某些条件等。 一部分,根据经验,我遵循以下准则: 如果您的服务通过RMI公开提供给其他服务,则服务层验证是强制性的,如果不与控制器级别验证一起使用的话。
答案 2 :(得分:0)
除非您也将服务和/或存储库用作其他项目中的库,否则多次进行验证是没有意义的。 如果控制器是访问附加层的唯一类,则无需进行其他验证,因为您和您的控制器是访问Spring Bean的唯一类。您和控制器将控制使用有效参数访问服务。
进行几次验证的缺点是编写更复杂的服务-包括单元测试。 慢一点 更改验证将需要更长的时间,因为必须更改多个层(包括单元测试)。 在几层上的验证可以并且将在时间上有所不同。
首选方法是在控制器中(甚至在控制器之前)进行一次验证,并编写集成测试以确保其功能。