春天的验证者应该访问数据库吗?

时间:2009-06-25 19:54:48

标签: java validation spring spring-mvc

我不确定根据数据库状态使验证器验证命令是否是一个好的设计决策。例如,如果我需要验证User bean,除了检查电子邮件和用户名是否为空等。如果已经使用过,我还需要拒绝它们。这种逻辑应该放在验证器还是服务对象中?

6 个答案:

答案 0 :(得分:12)

那么你的验证器只是spring bean,所以它们可以注入处理数据访问的服务对象。您可以让验证器从数据库中获取数据,而不会影响设计。

答案 1 :(得分:7)

这在很大程度上取决于您如何定义验证。考虑一下:你正在买东西,然后输入你的信用卡号码。如果校验位不匹配,则验证失败。没有尝试过任何交易。但是,如果它是有效的信用卡号,但它与您的邮政编码(需要DB /第三方交互)不匹配,则表示付款错误。

现在考虑一下:您输入的是您的地址,并输入Mastiffica作为您所在的国家/地区。为什么系统甚至允许你输入它 - 他们应该只将接口限制为有效条目(输入后不需要DB)。

或者您在银行付款屏幕的金额字段中输入“50”。为什么它允许那里的字母 - 验证失败(不需要DB)。但是你在金额字段中输入50,结果证明你的账户里没有50英镑。这是验证错误吗?或者这是一次失败的交易?

现在,请考虑您已通过所有基本条目验证(信用卡校验和,国家/地区,数字,邮政编码),并且交易失败,因为您的信用卡已过期。是验证错误还是失败的交易?

您可以将验证视为用户不会完全输入完整数据的基本保证,或者您可以将验证视为“我可以使用我给出的数据完成此事务”。我个人赞成前者,但同样,这是定义的问题。

然后是第一线验证的一个方面作为安全措施 - 已经被您的顶级UI层接受的野生数据可能存在安全风险(SQL注入,例如)

答案 2 :(得分:3)

不,恕我直言的验证器应该很小并side-effect free,以便它们可以轻松组合。确切地说,验证器应该与持久层解耦

答案 3 :(得分:1)

我检查了我的一个,我正在从验证器调用服务层:

@Service
public final class StartFormValidator {
private FacilityService facilityService;
private AdminService adminService;

/**
 * Verify that they've selected a facility. Verify that they've selected a
 * valid facility. Verify that they've selected a view and that it's a valid
 * view.
 * 
 * @param startForm
 * @param errors
 * @return true if no errors were set
 */
public boolean isValid(final StartForm startForm, final Errors errors) {
    if (startForm.getFacilityId() == 0) {
        errors.rejectValue("facilityId", "facilityIdEmpty",
                "Select a facility.");
    }

    if (!this.facilityService.isFacilWaitlistEnabled(startForm
            .getFacilityId())) {
        errors.rejectValue("facilityId", "facilityInvalid",
                "Invalid facility");
    }

    if (StringUtils.isBlank(startForm.getPassword())) {
        errors.rejectValue("password", "passwordEmpty",
                "Enter the password.");

        return (false);
    }

    if (!this.adminService.validateAdmin(startForm.getPassword()))
        errors.rejectValue("password", "passwordInvalid",
                "Incorrect password");

    return (!errors.hasErrors());
}

/**
 * @param _facilityService
 */
@Autowired
public void setFacilityService(final FacilityService _facilityService) {
    this.facilityService = _facilityService;
}

/**
 * @param _adminService
 */
@Autowired
public void setAdminService(final AdminService _adminService) {
    this.adminService = _adminService;
}

}

答案 4 :(得分:1)

如果您真的相信“MVC”,那么我不这么认为,您希望验证器转到数据库。验证是从业务逻辑的角度来看基本上验证数据的阶段。

数据库不需要知道验证器将如何使用它,验证器也不应该知道数据库是什么样的。这只是不适合MVC模型。明天,如果您有来自多个来源的数据,您是否仍会继续告诉您的验证人员在特定条件下应该访问哪些具体来源。这本身就构成了甚至不需要的逻辑。在申请中。

您正在寻找的验证类型将被视为业务对象的一部分,这将确保在甚至调用服务对象之前;这种组合尚不存在。

服务对象也不应包含业务验证,因此它既不属于验证器也不属于Service对象。但是,是的,如果应用程序足够小,不用担心太多层,那么偏斜的方法就好了,但只要“它始终遵循标准”。

简而言之,我觉得Spring验证器是用于基本验证而不是真正的业务验证。

答案 5 :(得分:0)

我赞成使用数据库验证最终用户可用性。

在提交注册表单时,您要检查用户名是否在语法上正确以及是否已提供此用户名(需要进行数据库访问)。

表单可以立即返回所有错误。它可以向用户显示所有问题。用户可以修复它并再次发送表单。

我知道你可以用ajax等做得更聪明,这不是重点。

我总是检查一切。我检查这个表单是否将由即将进行的交易处理。如果没有,我会因为一些可以轻松处理的并发访问而获得异常。