3

我有一个用于密码重置的 Spring MVC 网页。这需要我们执行以下验证工作流程:

  1. 提供用户名或电子邮件
  2. 如果提供了电子邮件,请确保其格式有效(例如:@Email)
  3. 通过以下方式检查用户是否存在:

    3a) 尝试通过用户名从数据库加载用户
    3b) 如果通过用户名加载返回null,尝试通过电子邮件从数据库加载用户

  4. 加载后,检查用户是否被锁定:user.isLocked()

目前我在一个org.springframework.validation.Validator

但是,这需要我的验证器有权访问该UserService对象,以便它可以加载用户。这会导致用户被加载 2 次,一次由我的验证器加载,第二次由我的验证器加载,Controller因此它可以调用.resetPassword(User).


问题:我应该在哪里检查项目#3?

这些验证是否更适合 Controller ?如果我保持原样验证,我可以从验证器返回用户吗(void由于验证器接口它有方法)?

4

3 回答 3

3

在我看来,步骤 3 和 4 根本不属于视图层(特别是控制器执行的验证)。

这些步骤是该场景业务逻辑的重要组成部分,因此它们应该在服务层中实现。

您的服务层应提供一种方法,例如

public void resetPasswordByUsernameOrEmail(String usernameOrEmail) { ... }

并且这些步骤应该发生在这个方法中,以及resetPassword(User).

如果需要,您可以通过抛出异常、返回 aboolean或 an enum(如果您想区分不同的错误条件)使控制器知道此方法的结果。

于 2013-09-12T15:06:29.643 回答
2

按顺序回答您的问题:

  1. 您应该在UserDao中检查用户是否存在。
  2. ,这些验证不应该在控制器中。控制器不应该对验证一无所知,否则它会尝试做太多事情,我们会犯低内聚力
  3. 由于您使用的接口定义了一个返回 void 的方法,因此如果您想返回一个 User ,您必须执行以下操作之一:
    • 在 Validator 实现中创建自己的方法。这样做的缺点是您不能有效地使用多态性,因为您将依赖未在接口中定义的方法。
    • 制作你自己的验证器(可能制作你自己的接口,扩展 Spring 的验证器接口并定义你想要的方法)。这大概是我会选择的。
于 2013-09-12T15:04:54.080 回答
1

也许这是重复的:Spring MVC Bean Validation

另一种解决方案是:

在我工作的一个项目中,我们曾经有一个 SpringBeanUtil 类。它将获取 WebApplicationContext,并通过静态方法获取所需的 bean。这有点丑陋,但有助于解决这些问题。

使用风险自负。

public class SpringBeanUtil implements ApplicationContextAware{

private static ApplicationContext APPLICATION_CONTEXT;

@Override
public void setApplicationContext(ApplicationContext applicationContext)
        throws BeansException {
    APPLICATION_CONTEXT=applicationContext;
}

public static Object getBean(String name){
    return APPLICATION_CONTEXT.getBean(name);
}
public static <T> T getBean(Class<T> type){
    return APPLICATION_CONTEXT.getBean(type);
}
}
于 2013-09-12T15:04:27.467 回答