ScriptAssert注解实现参数个性化校验的简单用法

web接口往往需要做参数校验,hibernate-validator包中提供了很多注解,譬如Length、Email、NotBlank、Range等注解为我们提供了特定的校验功能。但是一些个性化的校验以上注解就无能为力了,譬如校验两次输入的密码是否一致。但是ScriptAssert为我们提供了个性化检验参数的能力。

以用户注册为例。在用户注册时我们要校验输入密码与确认密码是否一致,和用户名中是否包含特殊字符

@ScriptAssert(script = "_this.password.equals(_this.rePassword)",lang = "javascript",message = "确认密码与输入密码不一致")

上面是校验对象中password属性与rePassword属性是否相等,equals返回true表示校验通过,返回false表示校验不通过(会返回错误信息)。

_this是默认的对象别名,lang="javascript" 表示用java 执行script中的脚本

script指定特定的静态方法校验用户名是否包含特殊字符

@ScriptAssert(script = "com.wl.account.dto.RegisterUserDto.checkUserName(_this.userName)",lang = "javascript",
                message = "用户名不能包含! @ # $ % & * \\ / ? ?特殊符号")
public class RegisterUserDto {

    private String userName;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
     }

    public static boolean checkUserName(String userName){
        String[] chars = {"!","@","#","$","%","&","*","\\","/","?","?"};
        for(String c : chars){
            if(userName.contains(c)){
                return false;
            }
        }
        return true;
    }

}

注意script中方法是一个静态的方法,且包含完整的调用路径。校验参数时,会调用CheckUserName这个静态方法,方法参数为这个对象的userName属性。

多个ScriptAssert需要使用@ScriptAssert.List

完整的例子如下

校验参数的dto

package com.wl.account.dto;

import com.wl.account.common.model.UserVo;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.ScriptAssert;

/**
 * Created by wl on 2021/4/17.
 */
//@ScriptAssert(script = "_this.password==_this.rePassword",lang = "javascript",message = "确认密码与输入密码不一致")
@ScriptAssert.List({
        @ScriptAssert(script = "com.wl.account.dto.RegisterUserDto.checkUserName(_this.userName)",lang = "javascript",
                message = "用户名不能包含! @ # $ % & * \\ / ? ?特殊符号"),
        @ScriptAssert(script = "_this.password.equals(_this.rePassword)",lang = "javascript",message = "确认密码与输入密码不一致")
})
public class RegisterUserDto {

    @NotBlank(message = "用户名不能为空")
    @Length(message = "用户名长度应在3-12位",max = 12,min = 3)
    private String userName;

    @NotBlank(message = "密码不能为空")
    @Length(message = "密码长度应在6-15位",max = 15,min = 6)
    private String password;

    @NotBlank(message = "确认密码不能为空")
    private String rePassword;

    private String mobile;

    @Email
    private String email;

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }


    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getRePassword() {
        return rePassword;
    }

    public void setRePassword(String rePassword) {
        this.rePassword = rePassword;
    }

    public String getMobile() {
        return mobile;
    }

    public void setMobile(String mobile) {
        this.mobile = mobile;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public static boolean checkUserName(String userName){
        String[] chars = {"!","@","#","$","%","&","*","\\","/","?","?"};
        for(String c : chars){
            if(userName.contains(c)){
                return false;
            }
        }
        return true;
    }

    public UserVo toUserVo(){
        UserVo userVo = new UserVo();
        userVo.setUserName(this.getUserName());
        userVo.setPassword(this.getPassword());
        userVo.setEmail(this.getEmail());
        userVo.setMobile(this.getMobile());
        return userVo;
    }

}

注册接口

    @RequestMapping("sign")
    public Result sign(@Validated RegisterUserDto dto, BindingResult result,HttpServletRequest request){
        if(result.getErrorCount() > 0){
            return Result.fail(result.getAllErrors().get(0).getDefaultMessage());
        }
        //注册逻辑
        return Result.success();
    }

前端注册输入含有特殊字符的用户名

返回响应错误信息

使用ExceptionHandler注解捕获异常,这样代码中就不用声明BindingResult

我的ExceptionHandler如下(可根据自身需求返回特定的错误信息,可以通过ExceptionHandler注解的value值捕获特定的异常)

    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Result handlerException(Throwable t){
        logger.error("throwable:  ",t);
        return Result.fail(getExceptionMsg(t));
    }

    private String getExceptionMsg(Throwable t){
        StringBuilder baseMsg = t.getMessage() != null ? new StringBuilder(t.getMessage()) : new StringBuilder(t.toString());
        if(t.getCause() != null){
            if(t.getCause().getCause() != null) {
                if (t.getCause().getCause().getMessage() != null) {
                    baseMsg.append("\n").append(t.getCause().getCause().getMessage());
                }
            }
        }
        if(t.getStackTrace() != null && t.getStackTrace().length > 0){
            StackTraceElement[] elements = t.getStackTrace();
            for(StackTraceElement element : elements){
                if(element.getClassName().contains("com.wl.account")){
                    baseMsg.append("\n")
                            .append("className:").append(element.getClassName())
                            .append("\n").append("methodName:").append(element.getMethodName())
                            .append("\n").append("lineNumber:").append(element.getLineNumber());
                    break;
                }
            }
        }
        return baseMsg.toString();
    }

将上述代码放入BaseController中,所有继承BaseController的对象都将获得捕获异常的能力

返回错误

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值