栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

springboot+validation实现业务校验初尝试

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

springboot+validation实现业务校验初尝试

在springboot工程开发中,会对入参进行校验,以保证接口的安全稳定。参数校验通常引入validation校验框架,在实体类中的属性上加上校验注解(@Null、@Blank等),具体使用方式可看大佬相关文章。
在对入参校验之后,通常会有业务规则的校验需求,通常通过 if 批判,然后 throw 异常的方式处理。
典型场景,新增用户时,需要校验其唯一性,用户的唯一性标识不能存在;编辑用户时,需要校验其冲突性,用户的唯一性标识不能与存在的用户重复,只能与自己的重复。
通常在service层处理,代码逻辑如下:

public void add(User user) {
    User result = ***query***;
    if (result != null) {
        throw new ***Exception("用户已存在,请重新输入");
    }
}

那有没有更优雅的方式呢?减少校验对业务代码的入侵?
借鉴参数校验的方式,通过自定义注解完成业务校验。

实例
1、pom

		
            org.springframework.boot
            spring-boot-starter-validation
        
        
            org.springframework.boot
            spring-boot-starter-web
        

2、自定义注解
新增时:表示一个用户是唯一的,唯一性包含:用户名,手机号码、邮箱

@documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})
@Constraint(validatedBy = UserValidator.UniqueUserValidator.class)
public @interface Unique {

    String message() default "用户名、邮箱、手机号码不允许与现存用户重复";

    Class[] groups() default {};

    Class[] payload() default {};
}

修改时:表示一个用户的信息是无冲突的,无冲突是指该用户的敏感信息与其他用户不重合

@documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE})
@Constraint(validatedBy = UserValidator.NotConflictUserValidator.class)
public @interface NotConflict {

    String message() default "用户名、邮箱、手机号码与现存用户产生重复";

    Class[] groups() default {};

    Class[] payload() default {};
}

3、业务规则校验
想让自定义验证注解生效,需要实现 ConstraintValidator 接口。ConstraintValidator 接口的实现类无需添加 @Component 它在启动的时候就已经被加载到容器中了。

public class UserValidator implements ConstraintValidator {

    protected Predicate predicate = c -> true;

    @Override
    public boolean isValid(User user, ConstraintValidatorContext constraintValidatorContext) {
        return predicate.test(user);
    }

    
    public static class UniqueUserValidator extends UserValidator {
        @Override
        public void initialize(Unique unique) {
            predicate = c -> {
                // 持久层查询是否存在
                return false;
            };
        }
    }

    
    public static class NotConflictUserValidator extends UserValidator {
        @Override
        public void initialize(NotConflict notConflict) {
            predicate = c -> {
                Collection collection = null;
                // 持久层查询是否冲突
                return false;
            };
        }
    }

}

4、测试

@RestController
@Validated
public class UserController {

    @PostMapping("add")
    public User addUser(@Unique @Valid User user){
        System.out.printf("save user id is %s", user.getId());
        return user;
    }

    @PostMapping("update")
    public User updateUser(@NotConflict @Valid User user){
        System.out.printf("update user is %s", user.getId());
        return user;
    }
}

结果

{
    "status": false,
    "code": 400,
    "message": "addUser.user: 用户名、邮箱、手机号码不允许与现存用户重复",
    "data": null
}

使用方式和入参校验一样,只需要在方法上加上自定义注解即可,service层不需要添加业务校验的代码了。
可见,业务校验和业务逻辑解耦了,在需要校验时用@Validated注解自动触发即可。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/760099.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号