分层架构中的 Spring 启动 rest API 验证



今天,我与我们的一位团队成员就Controller层和Service层中 RESTful API 输入的验证进行了一次大讨论,我觉得这是提出更大争论的糟糕一天。所以我们有一个具有分层架构的 Spring 引导微服务应用程序

Controller --> Service --> Repository

参数是在每一层进行验证,或者只是在Controller层进行验证,例如,我们对POST请求进行了Controller,并对输入请求正文使用 JSR-380 验证

控制器:

@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 
}

如果验证成功,则使用Config中的某些属性调用Service方法

服务:

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));
}

所以如果我们看到上面的代码,同样的验证是在ControllerService完成的,所以我认为没有必要在Service层进行验证,在控制器层执行验证,如果输入错误,则抛出400500给用户。但是团队中的另一个人也建议在每个块中对块中使用的任何内容进行验证,以便单个代码段是安全的(专注于单元而不是集成路径(。

我知道在这种情况下我可能是错的,但仍然无法理解每一层的验证,(空检查我同意(,所以建议在每个级别进行验证的方法

Controller --> validation call service
Service ---> validation and call business 
Business ---> validation and call repository
Repository --> save

但是首选的验证方式是什么? 根据我的说法Controller输入是否有效 调用Service并执行业务逻辑并调用Repository. 如果我错了,请纠正我,以便我可以遵循推荐的模式

你是对的:如果可能的话,验证应该放在控制器中。在我看来,验证数据超过 1 次是没有意义的。 另见干原则 https://en.wikipedia.org/wiki/Don%27t_repeat_yourself

这是情境性的。需要在服务层中执行一些验证。比如说,你需要改变对象的状态,但前提是满足某些条件等。 其中的一部分,根据经验,我遵循以下准则: 如果您的服务通过 RMI 公开向其他服务公开,则服务层验证是强制性的,如果不进行控制器级别验证。

除非您也将服务和/或存储库用作其他项目中的库,否则多次进行验证是没有意义的。 如果控制器是唯一访问附加层的类,则无需进行额外的验证,因为您和您的控制器是唯一访问 Spring bean 的类。您和控制器可以控制使用有效参数访问服务。

执行多个验证的缺点是编写更复杂的服务(包括单元测试(。 它更慢。 更改验证将花费更长的时间,因为必须更改多个层 - 包括单元测试。 几个层上的验证可能会而且会在一段时间内有所不同。

首选方法是在控制器中(甚至之前(进行一次验证,并编写集成测试以确保其功能。

最新更新