技术博客
SpringBoot中 Validator 与自定义注解的手机号码校验实践

SpringBoot中 Validator 与自定义注解的手机号码校验实践

作者: 万维易源
2024-11-10
csdn
SpringBootValidator自定义校验注解

摘要

在SpringBoot框架中,Validator组件结合自定义约束注解是一种实现手机号码校验和密码格式限制的有效方法。具体来说,@IsMobile注解用于校验手机号码,而密码格式限制则通过自定义校验规则实现。Java Bean Validation框架提供了@Constraint注解,它允许开发者定义自己的校验规则。通过将@Constraint注解应用于自定义注解上,并指定一个实现了ConstraintValidator接口的验证器类,可以确保注解标记的字段或参数满足特定的校验条件。

关键词

SpringBoot, Validator, 自定义, 校验, 注解

一、手机号码校验的需求与挑战

1.1 手机号码校验在应用程序中的重要性

在现代应用程序开发中,手机号码校验是一个不可或缺的环节。无论是用户注册、登录验证还是信息推送,手机号码作为用户身份的重要标识,其准确性和有效性直接影响到应用的安全性和用户体验。首先,手机号码的正确性可以确保用户能够及时接收到重要的通知和消息,例如验证码、订单确认等。其次,有效的手机号码校验可以防止恶意用户利用虚假信息进行欺诈活动,保护平台和用户的利益。此外,手机号码的唯一性还可以帮助开发者更好地管理和维护用户数据,提高数据的可靠性和一致性。

1.2 现有手机号码校验方法的局限性

尽管手机号码校验的重要性不言而喻,但现有的校验方法仍存在一些局限性。传统的校验方法通常依赖于正则表达式或简单的字符串匹配,这些方法虽然简单易用,但在复杂场景下往往显得力不从心。例如,不同国家和地区的手机号码格式各不相同,仅靠简单的正则表达式难以覆盖所有情况。此外,正则表达式的编写和维护成本较高,容易出错,且难以扩展。另外,现有的校验方法通常只能在表单提交时进行校验,无法实现实时校验,这在用户体验上存在一定的不足。因此,开发一种更加灵活、高效且易于维护的手机号码校验方法显得尤为重要。

通过引入SpringBoot框架中的Validator组件和自定义约束注解,可以有效解决上述问题。@IsMobile注解不仅能够灵活应对不同国家和地区的手机号码格式,还能实现实时校验,提升用户体验。同时,自定义校验规则的实现也使得开发者可以根据具体需求进行扩展和优化,确保校验逻辑的准确性和可靠性。

二、SpringBoot框架与Validator组件的介绍

2.1 SpringBoot框架的优势

SpringBoot框架自推出以来,凭借其简洁、高效的特点,迅速成为了企业级应用开发的首选框架之一。它不仅简化了Spring应用的初始搭建和开发过程,还提供了一系列强大的功能和工具,使得开发者能够更加专注于业务逻辑的实现。以下是SpringBoot框架的几个主要优势:

  1. 快速启动和配置:SpringBoot通过自动配置机制,大大减少了项目初始化和配置的工作量。开发者只需添加相应的依赖,框架会自动配置好所需的组件和服务,使得项目能够快速启动并运行。
  2. 内置嵌入式服务器:SpringBoot内置了Tomcat、Jetty等嵌入式服务器,无需单独部署,直接运行即可。这不仅简化了开发环境的搭建,还提高了开发效率,使得开发者能够更快速地进行测试和调试。
  3. 丰富的starter依赖:SpringBoot提供了一整套的starter依赖,涵盖了数据库访问、安全认证、缓存、消息队列等多个方面。开发者只需在pom.xml文件中添加相应的starter依赖,即可轻松集成所需的功能模块,极大地提升了开发的便捷性和灵活性。
  4. 强大的社区支持:SpringBoot拥有庞大的开发者社区和丰富的文档资源,无论是遇到技术难题还是需要最佳实践,都可以在社区中找到解决方案。这为开发者提供了强有力的技术支持,有助于项目的顺利推进。
  5. 微服务架构支持:随着微服务架构的兴起,SpringBoot凭借其轻量级、模块化的特点,成为了构建微服务应用的理想选择。它提供了诸如Spring Cloud等工具,帮助开发者轻松实现服务发现、负载均衡、断路器等功能,使得微服务架构的构建变得更加简单和高效。

2.2 Validator组件在SpringBoot中的角色

在SpringBoot框架中,Validator组件扮演着至关重要的角色。它不仅提供了强大的数据校验功能,还通过与自定义约束注解的结合,使得数据校验变得更加灵活和高效。以下是Validator组件在SpringBoot中的几个主要作用:

  1. 统一的数据校验机制:SpringBoot集成了Java Bean Validation框架,提供了一套统一的数据校验机制。开发者可以通过在实体类的属性上添加注解,如@NotNull@Size等,来定义校验规则。这些注解会在数据绑定时自动生效,确保输入数据的合法性和完整性。
  2. 自定义校验注解的支持:除了内置的校验注解外,SpringBoot还支持自定义校验注解。通过使用@Constraint注解,开发者可以定义自己的校验规则,并指定一个实现了ConstraintValidator接口的验证器类。例如,@IsMobile注解可以用于校验手机号码的格式,而密码格式限制则可以通过自定义校验规则实现。这种灵活的校验方式使得开发者能够根据具体需求进行扩展和优化,确保校验逻辑的准确性和可靠性。
  3. 实时校验和反馈:SpringBoot的Validator组件不仅支持在表单提交时进行校验,还支持实现实时校验。通过结合前端框架(如React、Vue等),可以在用户输入数据时立即进行校验,并给出实时反馈。这不仅提升了用户体验,还减少了无效数据的提交,提高了系统的整体性能。
  4. 集成测试的支持:SpringBoot提供了丰富的测试支持,使得开发者可以方便地对Validator组件进行单元测试和集成测试。通过使用@Valid@Validated注解,可以在测试用例中模拟数据校验的过程,确保校验逻辑的正确性和稳定性。

综上所述,SpringBoot框架中的Validator组件不仅提供了强大的数据校验功能,还通过与自定义约束注解的结合,使得数据校验变得更加灵活和高效。这不仅提升了开发者的开发效率,还确保了应用的安全性和用户体验。

三、自定义注解与@IsMobile的实现

3.1 自定义注解的概念

在现代软件开发中,注解(Annotation)已经成为一种非常强大的工具,用于在代码中添加元数据信息。这些元数据信息可以被编译器、运行时环境或其他工具解析和处理,从而实现各种功能,如依赖注入、事务管理、数据校验等。SpringBoot框架充分利用了注解的这一特性,通过自定义注解,开发者可以更加灵活地实现特定的业务需求。

自定义注解的核心在于@Constraint注解。@Constraint注解允许开发者定义自己的校验规则,并将其应用于实体类的属性或方法参数上。通过这种方式,开发者可以确保标记了该注解的字段或参数满足特定的校验条件。例如,在手机号码校验中,我们可以定义一个@IsMobile注解,用于校验手机号码的格式是否正确。

自定义注解的创建步骤如下:

  1. 定义注解:使用@Constraint注解定义一个新的注解,并指定其校验器类。
  2. 实现校验器:创建一个实现了ConstraintValidator接口的类,并在其中实现具体的校验逻辑。
  3. 应用注解:在需要校验的字段或方法参数上使用自定义注解。

通过这种方式,开发者可以轻松地扩展和定制数据校验规则,确保应用的健壮性和安全性。

3.2 @IsMobile注解的创建与使用

3.2.1 定义@IsMobile注解

首先,我们需要定义一个@IsMobile注解。这个注解将用于校验手机号码的格式是否符合要求。我们可以通过以下代码来定义@IsMobile注解:

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Documented
@Constraint(validatedBy = IsMobileValidator.class)
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface IsMobile {
    String message() default "手机号码格式不正确";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

在这个定义中,@Constraint注解指定了IsMobileValidator类作为校验器类。@Target注解指定了该注解可以应用于方法、字段、注解类型和参数。@Retention注解指定了该注解的保留策略为运行时,这意味着该注解在运行时仍然可用。

3.2.2 实现IsMobileValidator校验器

接下来,我们需要实现IsMobileValidator类,该类将包含具体的校验逻辑。我们可以通过以下代码来实现IsMobileValidator类:

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class IsMobileValidator implements ConstraintValidator<IsMobile, String> {

    private static final String MOBILE_PATTERN = "^1[3-9]\\d{9}$";

    @Override
    public void initialize(IsMobile constraintAnnotation) {
        // 初始化方法,可以在这里进行一些准备工作
    }

    @Override
    public boolean isValid(String mobile, ConstraintValidatorContext context) {
        if (mobile == null || mobile.isEmpty()) {
            return false;
        }
        return mobile.matches(MOBILE_PATTERN);
    }
}

在这个实现中,MOBILE_PATTERN定义了一个正则表达式,用于匹配中国大陆的手机号码格式。isValid方法用于校验传入的手机号码是否符合该正则表达式。如果手机号码为空或不符合格式,则返回false,否则返回true

3.2.3 应用@IsMobile注解

最后,我们可以在需要校验的字段上使用@IsMobile注解。例如,假设我们有一个用户注册的实体类User,我们可以在手机号码字段上使用@IsMobile注解:

import javax.validation.constraints.NotNull;

public class User {

    @NotNull(message = "用户名不能为空")
    private String username;

    @IsMobile
    private String mobile;

    // 其他字段和方法
}

通过这种方式,当用户提交注册信息时,系统会自动校验手机号码的格式是否正确。如果手机号码格式不正确,系统将返回相应的错误信息,提示用户进行修正。

总之,通过自定义注解@IsMobile,开发者可以轻松实现手机号码的校验,确保用户输入的数据符合预期,从而提升应用的安全性和用户体验。

四、密码格式限制的自定义校验规则

4.1 定义密码复杂度的需求

在现代网络安全环境中,密码复杂度的校验是保障用户账户安全的重要手段。随着网络攻击手段的不断进化,简单的密码已经无法有效抵御恶意攻击。因此,定义和实现密码复杂度的需求变得尤为关键。密码复杂度的校验不仅能够提高用户账户的安全性,还能增强用户对应用的信任感。

首先,密码复杂度的需求通常包括以下几个方面:

  1. 长度要求:密码的长度应至少为8个字符,以增加破解难度。
  2. 字符多样性:密码应包含大小写字母、数字和特殊字符,以提高复杂度。
  3. 禁止常见密码:禁止使用常见的弱密码,如“123456”、“password”等。
  4. 定期更换:建议用户定期更换密码,以减少长期使用同一密码带来的风险。

这些要求不仅能够有效提升密码的安全性,还能帮助用户养成良好的密码管理习惯。通过在应用中实现这些密码复杂度的校验规则,开发者可以显著降低因弱密码导致的安全风险,保护用户数据的安全。

4.2 实现自定义密码校验规则的步骤

为了实现上述密码复杂度的需求,开发者可以利用SpringBoot框架中的自定义注解和Validator组件。具体步骤如下:

4.2.1 定义自定义注解

首先,我们需要定义一个自定义注解@PasswordComplexity,用于校验密码的复杂度。通过以下代码可以定义该注解:

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Documented
@Constraint(validatedBy = PasswordComplexityValidator.class)
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface PasswordComplexity {
    String message() default "密码复杂度不满足要求";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}

在这个定义中,@Constraint注解指定了PasswordComplexityValidator类作为校验器类。@Target注解指定了该注解可以应用于方法、字段、注解类型和参数。@Retention注解指定了该注解的保留策略为运行时,这意味着该注解在运行时仍然可用。

4.2.2 实现PasswordComplexityValidator校验器

接下来,我们需要实现PasswordComplexityValidator类,该类将包含具体的校验逻辑。我们可以通过以下代码来实现PasswordComplexityValidator类:

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class PasswordComplexityValidator implements ConstraintValidator<PasswordComplexity, String> {

    private static final int MIN_LENGTH = 8;
    private static final String SPECIAL_CHARACTERS = "!@#$%^&*()-_=+[]{}|;:,.<>?";

    @Override
    public void initialize(PasswordComplexity constraintAnnotation) {
        // 初始化方法,可以在这里进行一些准备工作
    }

    @Override
    public boolean isValid(String password, ConstraintValidatorContext context) {
        if (password == null || password.length() < MIN_LENGTH) {
            return false;
        }

        boolean hasUpperCase = !password.equals(password.toLowerCase());
        boolean hasLowerCase = !password.equals(password.toUpperCase());
        boolean hasDigit = password.matches(".*\\d.*");
        boolean hasSpecialChar = password.chars().anyMatch(c -> SPECIAL_CHARACTERS.indexOf(c) >= 0);

        return hasUpperCase && hasLowerCase && hasDigit && hasSpecialChar;
    }
}

在这个实现中,MIN_LENGTH定义了密码的最小长度要求。SPECIAL_CHARACTERS定义了允许的特殊字符集合。isValid方法用于校验传入的密码是否满足以下条件:

  • 密码长度至少为8个字符。
  • 密码包含大写字母、小写字母、数字和特殊字符。

如果密码不满足上述任何一条条件,则返回false,否则返回true

4.2.3 应用@PasswordComplexity注解

最后,我们可以在需要校验的字段上使用@PasswordComplexity注解。例如,假设我们有一个用户注册的实体类User,我们可以在密码字段上使用@PasswordComplexity注解:

import javax.validation.constraints.NotNull;

public class User {

    @NotNull(message = "用户名不能为空")
    private String username;

    @IsMobile
    private String mobile;

    @PasswordComplexity
    private String password;

    // 其他字段和方法
}

通过这种方式,当用户提交注册信息时,系统会自动校验密码的复杂度是否符合要求。如果密码复杂度不满足要求,系统将返回相应的错误信息,提示用户进行修正。

总之,通过自定义注解@PasswordComplexity,开发者可以轻松实现密码复杂度的校验,确保用户输入的密码符合安全要求,从而提升应用的整体安全性。

五、Validator组件的集成与测试

5.1 在SpringBoot项目中集成Validator组件

在SpringBoot项目中集成Validator组件,不仅可以提升数据校验的效率和准确性,还能显著改善用户体验。以下是具体步骤,帮助开发者轻松实现这一目标。

5.1.1 添加依赖

首先,需要在项目的pom.xml文件中添加Spring Boot Validation的依赖。这一步骤非常简单,只需在dependencies标签内添加以下内容:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

通过添加这个依赖,SpringBoot会自动配置好Bean Validation框架,使得开发者可以立即开始使用内置和自定义的校验注解。

5.1.2 配置Validator

在SpringBoot中,Validator组件的配置非常简便。默认情况下,SpringBoot会自动配置一个LocalValidatorFactoryBean,开发者可以直接在控制器或服务层中注入并使用它。例如:

import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ValidatorConfig {

    @Bean
    public Validator validator() {
        return new LocalValidatorFactoryBean();
    }
}

通过这种方式,开发者可以确保在整个项目中都能方便地使用Validator组件。

5.1.3 使用Validator进行数据校验

在实际应用中,开发者可以在控制器的方法参数上使用@Valid@Validated注解,结合自定义注解(如@IsMobile@PasswordComplexity),实现数据的自动校验。例如:

import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @PostMapping("/register")
    public ResponseEntity<String> register(@Valid @RequestBody User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResponseEntity.badRequest().body(bindingResult.getAllErrors().toString());
        }
        // 处理用户注册逻辑
        return ResponseEntity.ok("注册成功");
    }
}

在这个示例中,@Valid注解用于标记需要校验的User对象,BindingResult用于捕获校验结果。如果校验失败,系统会返回包含错误信息的HTTP响应,提示用户进行修正。

5.2 测试自定义注解的有效性

为了确保自定义注解(如@IsMobile@PasswordComplexity)的有效性,开发者需要进行充分的测试。以下是一些常用的测试方法和技巧。

5.2.1 单元测试

单元测试是验证自定义注解有效性的最直接方法。开发者可以使用JUnit等测试框架,编写针对自定义注解和校验器的单元测试。例如:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertTrue;

@SpringBootTest
public class CustomAnnotationTest {

    @Autowired
    private Validator validator;

    @Test
    public void testIsMobileAnnotation() {
        User user = new User();
        user.setMobile("12345678901");

        Set<ConstraintViolation<User>> violations = validator.validate(user);
        assertTrue(violations.isEmpty(), "手机号码格式不正确");
    }

    @Test
    public void testPasswordComplexityAnnotation() {
        User user = new User();
        user.setPassword("WeakPass");

        Set<ConstraintViolation<User>> violations = validator.validate(user);
        assertTrue(!violations.isEmpty(), "密码复杂度不满足要求");
    }
}

在这个示例中,testIsMobileAnnotation方法测试了@IsMobile注解的有效性,testPasswordComplexityAnnotation方法测试了@PasswordComplexity注解的有效性。通过这些测试,开发者可以确保自定义注解在实际应用中的表现符合预期。

5.2.2 集成测试

除了单元测试,集成测试也是验证自定义注解有效性的关键步骤。开发者可以使用Spring Boot的测试支持,编写针对整个应用的集成测试。例如:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerIntegrationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testRegisterWithInvalidMobile() throws Exception {
        User user = new User();
        user.setUsername("testUser");
        user.setMobile("1234567890"); // 无效的手机号码

        mockMvc.perform(post("/register")
                .contentType("application/json")
                .content(objectMapper.writeValueAsString(user)))
                .andExpect(status().isBadRequest());
    }

    @Test
    public void testRegisterWithInvalidPassword() throws Exception {
        User user = new User();
        user.setUsername("testUser");
        user.setMobile("13800138000");
        user.setPassword("weak"); // 无效的密码

        mockMvc.perform(post("/register")
                .contentType("application/json")
                .content(objectMapper.writeValueAsString(user)))
                .andExpect(status().isBadRequest());
    }
}

在这个示例中,testRegisterWithInvalidMobile方法测试了无效手机号码的注册请求,testRegisterWithInvalidPassword方法测试了无效密码的注册请求。通过这些集成测试,开发者可以确保自定义注解在实际应用中的表现符合预期,从而提升应用的稳定性和可靠性。

总之,通过在SpringBoot项目中集成Validator组件并进行充分的测试,开发者可以确保自定义注解的有效性和可靠性,从而提升应用的安全性和用户体验。

六、最佳实践与性能优化

6.1 校验过程中的性能考量

在现代Web应用中,数据校验是确保数据完整性和安全性的重要环节。然而,随着应用规模的不断扩大,校验过程中的性能问题逐渐凸显。如何在保证校验准确性的前提下,提升校验性能,成为开发者需要关注的重点。在SpringBoot框架中,通过合理的设计和优化,可以有效解决这一问题。

首先,异步校验是一种常见的性能优化手段。在用户提交表单时,可以采用异步的方式进行数据校验,避免阻塞主线程,从而提升用户体验。例如,可以使用JavaScript在前端进行初步校验,再通过AJAX请求将数据发送到后端进行进一步校验。这样不仅可以减少不必要的请求,还能提高系统的响应速度。

其次,缓存校验结果也是一种有效的性能优化方法。对于一些频繁使用的校验规则,可以将校验结果缓存起来,避免每次请求都重新执行相同的校验逻辑。例如,可以使用Redis等缓存工具,将已校验过的手机号码或密码存储在缓存中,下次遇到相同的输入时直接返回缓存结果,从而减少计算开销。

此外,分批校验也是提升性能的一种策略。在处理大量数据时,可以将数据分成多个批次进行校验,每个批次独立处理,避免一次性加载过多数据导致内存溢出或性能下降。例如,在批量导入用户数据时,可以将数据分成多个小批次,逐个进行校验和处理。

最后,优化校验逻辑本身也是提升性能的关键。开发者应尽量减少不必要的校验步骤,简化校验逻辑,提高代码的执行效率。例如,可以使用更高效的正则表达式,或者通过预编译等方式优化校验规则的执行速度。

6.2 维护与优化校验逻辑的经验分享

在实际开发过程中,维护和优化校验逻辑是一项持续的工作。随着业务需求的变化和技术的发展,原有的校验规则可能不再适用,需要不断地进行调整和优化。以下是一些维护和优化校验逻辑的经验分享。

首先,文档化校验规则是非常重要的。开发者应详细记录每一条校验规则的用途、实现方式和注意事项,以便其他团队成员理解和维护。文档应包括校验规则的定义、校验器的实现逻辑、以及常见的错误案例和解决方案。这样可以减少沟通成本,提高团队协作效率。

其次,单元测试和集成测试是确保校验逻辑正确性的关键。通过编写全面的测试用例,可以验证校验规则在各种情况下的表现,及时发现和修复潜在的问题。例如,可以编写针对不同国家和地区手机号码格式的测试用例,确保@IsMobile注解在不同场景下的准确性。同时,集成测试可以帮助开发者验证校验逻辑在整个应用中的表现,确保各个模块之间的协同工作。

此外,**持续集成和持续交付(CI/CD)**也是维护校验逻辑的重要手段。通过自动化构建和测试流程,可以及时发现和修复代码中的问题,确保校验逻辑的稳定性和可靠性。例如,可以在每次代码提交时自动运行单元测试和集成测试,确保新添加的校验规则不会引入新的问题。

最后,社区和开源工具是优化校验逻辑的重要资源。开发者可以积极参与社区讨论,借鉴其他开发者的经验和最佳实践,不断改进自己的校验逻辑。同时,可以利用开源工具和库,如Hibernate Validator等,简化校验逻辑的实现,提高开发效率。

总之,通过合理的性能优化和持续的维护,开发者可以确保校验逻辑的高效性和可靠性,从而提升应用的整体质量和用户体验。

七、总结

本文详细介绍了在SpringBoot框架中,通过Validator组件结合自定义约束注解实现手机号码校验和密码格式限制的方法。首先,我们探讨了手机号码校验在应用程序中的重要性及其现有方法的局限性,引出了使用@IsMobile注解的必要性。接着,我们介绍了SpringBoot框架的优势和Validator组件的作用,强调了其在数据校验中的重要地位。随后,我们详细讲解了如何创建和使用自定义注解@IsMobile,并通过具体的代码示例展示了其实现过程。此外,我们还讨论了密码复杂度的需求,并实现了自定义注解@PasswordComplexity,确保密码的安全性。最后,我们介绍了如何在SpringBoot项目中集成Validator组件,并进行了单元测试和集成测试,确保自定义注解的有效性和可靠性。通过这些方法,开发者可以显著提升应用的安全性和用户体验,同时优化校验过程的性能。