参数校验

使用自定义方法进行参数校验

为了提升性能,建议在 ControllerService 中使用自定义方法进行参数校验。以下是一个示例,展示了如何实现登录参数的校验逻辑。

import com.jfinal.kit.StrKit;
import com.litongjava.tio.utils.resp.RespBodyVo;

public class LoginValidator {

  public RespBodyVo validateLogin(String username, String password, String verificationCode) {
    RespBodyVo retval = null;

    // 验证用户名是否为空
    if (StrKit.isBlank(username)) {
      retval = RespBodyVo.fail("用户名或密码不能为空");
      return retval;
    }

    // 验证其他字段
    // ...
    // 验证成功返回null,验证不成功返回错误信息
    return retval;
  }
}

在这个示例中,LoginValidator 类负责验证登录参数。具体步骤如下:

  • 使用 StrKit.isBlank 方法检查用户名是否为空,如果为空则返回一个带有错误信息的 RespBodyVo 对象。
  • 其他字段的验证可以按需进行,所有验证通过时返回 null,否则返回错误信息。
import com.litongjava.jfinal.aop.Aop;
import com.litongjava.tio.http.common.HttpResponse;
import com.litongjava.annotation.RequestPath;
import com.litongjava.tio.utils.resp.RespBodyVo;
import com.litongjava.tio.web.hello.validator.LoginValidator;

@AController
@RequestPath("/auth")
public class LoginController {

  public RespBodyVo login(String username, String password, String verificationCode) {
    // 调用 LoginValidator 的验证方法
    RespBodyVo validateResult = Aop.get(LoginValidator.class).validateLogin(username, password, verificationCode);

    // 验证失败时返回错误信息
    if (validateResult != null) return validateResult;

    // 验证成功时返回成功信息
    return RespBodyVo.ok();
  }
}

LoginController 类中,使用 Aop.get(LoginValidator.class) 调用自定义验证器 LoginValidatorvalidateLogin 方法来进行验证。如果验证失败,直接返回错误信息;验证通过则返回登录成功的响应。


校验结果返回对象 ValidateResult

在校验失败时,返回的结果对象通常是 ValidateResult,这是一个内置在 java-model 中的实体类,用于封装校验错误信息。以下是其部分实现代码:

package com.litongjava.model.validate;

import java.util.ArrayList;
import java.util.List;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class ValidateResult {
  private String field; // 校验失败的字段
  private List<String> messages; // 错误消息列表

  public static List<ValidateResult> toList(String field, String message) {
    ValidateResult verifyResult = by(field, message);
    List<ValidateResult> verifyResults = new ArrayList<>();
    verifyResults.add(verifyResult);
    return verifyResults;
  }

  public static ValidateResult by(String field, String message) {
    List<String> messages = new ArrayList<>();
    messages.add(message);
    return by(field, messages);
  }

  public static ValidateResult by(String field, List<String> messages) {
    return new ValidateResult(field, messages);
  }
}

ValidateResult 类具有以下功能:

  • field 表示校验失败的字段。
  • messages 是一个字符串列表,用于存储该字段的校验错误信息。
  • 提供了静态方法 bytoList 来方便创建 ValidateResult 对象。

邮箱与密码校验示例

EmailValidatorPasswordValidatortio-utils 框架中提供的两个校验工具类。以下是一个用户注册服务的实现,包含了对邮箱和密码的校验。

package com.litongjava.open.chat.services.user;

import java.util.ArrayList;
import java.util.List;

import com.litongjava.model.body.RespBodyVo;
import com.litongjava.model.validate.ValidateResult;
import com.litongjava.open.chat.model.UserRegisterVo;
import com.litongjava.tio.utils.validator.EmailValidator;
import com.litongjava.tio.utils.validator.PasswordValidator;

public class UserRegisterService {

  public RespBodyVo register(UserRegisterVo vo) {
    List<ValidateResult> validateResults = new ArrayList<>();
    String email = vo.getEmail();
    String password = vo.getPassword();

    // 校验邮箱格式
    boolean validate = EmailValidator.validate(email);
    boolean ok = true;

    if (!validate) {
      ValidateResult validateResult = ValidateResult.by("email", "邮箱校验失败: " + email);
      validateResults.add(validateResult);
      ok = false;
    }

    // 校验密码格式
    validate = PasswordValidator.validate(password);
    if (!validate) {
      ValidateResult validateResult = ValidateResult.by("password", "密码校验失败: " + password);
      validateResults.add(validateResult);
      ok = false;
    }

    // 校验用户类型
    if (vo.getUser_type() == null) {
      ValidateResult validateResult = ValidateResult.by("user_type", "用户类型不能为空");
      validateResults.add(validateResult);
      ok = false;
    }

    // 校验通过则返回成功结果,校验失败则返回错误信息
    if (ok) {
      return RespBodyVo.ok();
    } else {
      return RespBodyVo.failData(validateResults);
    }
  }
}

此代码展示了如何校验用户注册时的邮箱和密码格式,并返回对应的校验结果:

  • 如果邮箱格式不符合要求,会返回错误信息 邮箱校验失败
  • 如果密码格式不正确,会返回错误信息 密码校验失败
  • 如果用户类型为空,也会返回相应的错误信息。

测试代码示例

下面的单元测试用例展示了如何测试 UserRegisterService 的注册方法:

package com.litongjava.open.chat.services.user;

import org.junit.Test;

import com.litongjava.jfinal.aop.Aop;
import com.litongjava.model.body.RespBodyVo;
import com.litongjava.open.chat.model.UserRegisterVo;
import com.litongjava.tio.utils.json.JsonUtils;

public class UserRegisterServiceTest {

  @Test
  public void test() {
    UserRegisterService userRegisterService = Aop.get(UserRegisterService.class);
    UserRegisterVo userRegisterVo = new UserRegisterVo();
    userRegisterVo.setEmail("1234").setPassword("123456");

    RespBodyVo bodyVo = userRegisterService.register(userRegisterVo);
    System.out.println(JsonUtils.toJson(bodyVo));
  }
}

运行上面的测试时,如果校验失败,输出的 JSON 格式的错误信息如下:

{
  "data": [
    {
      "field": "email",
      "messages": ["邮箱校验失败: 1234"]
    },
    {
      "field": "password",
      "messages": ["密码校验失败: 123456"]
    },
    {
      "field": "user_type",
      "messages": ["用户类型不能为空"]
    }
  ],
  "ok": false,
  "code": 0,
  "msg": null
}

总结

本文档详细描述了如何在 Java 中使用自定义方法进行参数校验,并通过示例展示了对邮箱和密码的校验过程。通过引入 ValidateResult 对象,可以清晰地将校验失败的字段和错误信息返回给前端,提供了一个通用且灵活的参数校验方案。