java後端做正則驗證

前言

在項目中,前端要對特殊字段做正則驗證,後端也要對特殊的字段做正則驗證和非空判斷,在做正則的時候遇到了很多坑,今天就和大家分享。主要有以下幾種方式:

環境

springboot1.5.x
jpa
java8

1.結合註解來正則來校驗

正則表達式

package com.test.util;

/**
 * 描述:正則表達式格式
 */
public class RegexpProperties {
    public static final String MOBILE_PATTERN = "^$|0?(13|14|15|18|17)[0-9]{9}$";//手機號
    public static final String EMAIL_PATTERN = "^$|(\\w)+(\\.\\w+)*@(\\w)+((\\.\\w+)+)$";//郵箱
    public static final String FAX_PATTERN = "^$|(\\d{3,4}-)?\\d{7,8}$";//傳值
    public static final String CREDIT_CODE_PATTERN = "^$|[a-zA-Z0-9]{18}$";//社會信用代碼
}

實體類

package com.test.entity;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.DynamicInsert;
import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.*;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Date;

@Table(name = "company")
@Entity
@Getter
@Setter
@DynamicInsert//新增時空字段不去插入values
@DynamicUpdate//只跟新變化的字段,結合merge方法使用
@JsonInclude(JsonInclude.Include.NON_NULL)
@EntityListeners({AuditingEntityListener.class})
@JsonIgnoreProperties({"createDate", "modifyDate"})
public class Company implements BaseEntity{
    //BaseEntity 是實現序列化的,這個類我就不放進來了

    @Id
    @GeneratedValue
    private Integer id;
    @NotBlank(message = "企業名稱不能爲空")
    private String name;
    @NotBlank(message = "社會信用代碼不能爲空")
    @Pattern(regexp = RegexpProperties.CREDIT_CODE_PATTERN, message = "社會信用代碼格式有誤")
    private String creditCode;
    private String contactName;
    @Pattern(regexp = RegexpProperties.MOBILE_PATTERN, message = "電話格式有誤")
    private String contactPhone;
    @Length(min = 0, max = 50, message = "企業法人長度不得超過50個字符")
    private String corporation;
    @Pattern(regexp = RegexpProperties.EMAIL_PATTERN, message = "郵箱格式有誤")
    private String email;
    @Pattern(regexp = RegexpProperties.FAX_PATTERN, message = "傳真格式有誤")
    private String fax;
    private String address;
    @Min(value = 0, message = "佔地面積不能小於0")
    private Double floorArea;
    private Integer attentionLevel;
    private Integer industryId;
    private String industryName;
    private Timestamp establishedDate;
    @Min(value = 0, message = "請輸入正確的員工人數")
    private Integer staffNum;
    private Boolean isDeleted = false;
    
    @CreatedDate
    private Date createDate;
    @LastModifiedBy
    private Integer modifier;
    @LastModifiedDate
    private Date modifyDate;
}

該方法在新增或者修改的時使用, 在controller層中,
在@RequestBody 前面加上@Validated 這種方能起作用.

1.2正則驗證手機號的另外一種方式

package com.test.util;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.Pattern;

/**
 * 請求參數驗證器
 */
@Getter
public class Validator {
    public static final int SUCCESS = 0;
    public static final int ARGUMENT_NULL = 101;
    public static final int ARGUMENT_ERROR = 102;
    private static final Pattern EMAIL_PATTERN = Pattern.compile("^(\\w)+(\\.\\w+)*@(\\w)+((\\.\\w+)+)$");
    private static final Pattern MOBILE_PATTERN = Pattern.compile("1\\d{10}");
    public static final Pattern FAX_PATTERN = Pattern.compile("^(\\d{3,4}-)?\\d{7,8}$");
    private static final Pattern TEL_PATTERN = Pattern.compile("^((0\\d{2,3})-)(\\d{7,8})(-(\\d{3,}))?$");
    private static final Pattern SPACE_PATTERN = Pattern.compile("\\s*|\t|\r|\n", Pattern.CASE_INSENSITIVE);
    private static final Pattern DATE_PATTERN =
            Pattern.compile("^\\d{4}[./-]\\d{1,2}[./-]\\d{1,2}[\\d\\.\\:\\+ZT ]+$", Pattern.CASE_INSENSITIVE);
    private static final Pattern EMOJI_PATTERN =
            Pattern.compile("[\\uD800-\\uDBFF\\uDC00-\\uDFFF\\u2600-\\u27ff]",
                    Pattern.UNICODE_CASE | Pattern.CASE_INSENSITIVE);
    private static final Pattern IP_PATTERN =
            Pattern.compile("\\b((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])"
                    + "\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])"
                    + "\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])"
                    + "\\.((?!\\d\\d\\d)\\d+|1\\d\\d|2[0-4]\\d|25[0-5])\\b");
    private static final Pattern ID_CARD_NO_PATTERN =
            Pattern.compile("^(^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$)|(^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[Xx])$)$");
    private final List<Valid> expressions = new ArrayList<>();
    private int code;
    private String message;

    public static Validator create() {
        return new Validator();
    }

    public static Validator create(String appId) {
        return Validator.create().appId(appId);
    }

    public static boolean isNullOrEmpty(String string) {
        return string == null || string.length() == 0;
    }

    public static boolean isPhone(String phone) {
        return !isNullOrEmpty(phone) && (TEL_PATTERN.matcher(phone).matches() || isMobile(phone));
    }

    public static boolean isMobile(String mobile) {
        return hasMobile(mobile) && mobile.length() == 11;
    }

    public static boolean hasMobile(String content) {
        return !isNullOrEmpty(content) && MOBILE_PATTERN.matcher(content).find();
    }

    public static boolean hasFax(String content) {
        return !isNullOrEmpty(content) && FAX_PATTERN.matcher(content).find();
    }

    public static boolean isFax(String fax) {
        return hasFax(fax) && fax.length() >= 7;
    }

    public static boolean isEmail(String email) {
        return hasEmail(email) && email.length() > 4;
    }

    public static boolean hasEmail(String content) {
        return !isNullOrEmpty(content) && EMAIL_PATTERN.matcher(content).find();
    }

    public static boolean isIp(String ip) {
        return !isNullOrEmpty(ip) && IP_PATTERN.matcher(ip).matches();
    }

    public static boolean hasEmoji(String text) {
        return !isNullOrEmpty(text) && EMOJI_PATTERN.matcher(text).matches();
    }

    /**
     * 是否身份證號
     */
    public static boolean isIdCardNO(String text) {
        return !isNullOrEmpty(text)
                && text.length() >= 15
                && ID_CARD_NO_PATTERN.matcher(text).matches();
    }
    
    public boolean valid() {
        for (Valid valid : expressions) {
            if (!valid.getExpression().get()) {
                this.code = valid.getCode();
                this.message = valid.getAlter();
                return false;
            }
        }
        return true;
    }

    public <T> T convert(Function<Validator, T> function) {
        return function.apply(this);
    }

    public Validator valid(int code, String alter, Supplier<Boolean> expression) {
        Valid valid = new Valid(code, alter, expression);
        this.expressions.add(valid);
        return this;
    }

    public Validator validNull(String name, Supplier<Boolean> valid) {
        String alert = "缺少必要的請求參數:" + name;
        return valid(ARGUMENT_NULL, alert, valid);
    }

    public Validator validError(String name, Supplier<Boolean> valid) {
        String alert = "請求參數格式錯誤:" + name;
        return valid(ARGUMENT_ERROR, alert, valid);
    }

    public Validator appId(String appId) {
        return valid(ARGUMENT_NULL, "缺少參數 _appId", () -> !isNullOrEmpty(appId));
    }

    public Validator notNull(String name, Object value) {
        return validNull(name, () -> value != null);
    }

    public Validator notEmpty(String name, String value) {
        return validNull(name, () -> !isNullOrEmpty(value));
    }

    public Validator notEmpty(String name, Collection value) {
        return validNull(name, () -> value != null && value.size() > 0);
    }

    public Validator greaterThanZero(String name, Number value) {
        return greaterThan(name, value, 0);
    }

    public Validator greaterThan(String name, Number value, Number min) {
        String alert = String.format("%s 值必須大於 %s", name, min);
        return valid(ARGUMENT_ERROR, alert, () -> value != null && value.doubleValue() > min.doubleValue());
    }

    public Validator greaterThanOrEqual(String name, Number value, Number min) {
        String alert = String.format("%s 值必須大於等於 %s", name, min);
        return valid(ARGUMENT_ERROR, alert, () -> value != null && value.doubleValue() >= min.doubleValue());
    }

    public Validator lessThan(String name, Number value, Number max) {
        String alert = String.format("%s值必須小於 %s", name, max);
        return valid(ARGUMENT_ERROR, alert, () -> value != null && value.doubleValue() < max.doubleValue());
    }

    public Validator lessThanOrEqual(String name, Number value, Number max) {
        String alert = String.format("%s 值必須小於等於 %s", name, max);
        return valid(ARGUMENT_ERROR, alert, () -> value != null && value.doubleValue() <= max.doubleValue());
    }

    public Validator range(String name, Number value, Number min, Number max) {
        String alert = String.format("%s值必須在 [%s~%s] 之間", name, min, max);
        return valid(ARGUMENT_ERROR, alert, () -> value.doubleValue() >= min.doubleValue()
                && value.doubleValue() <= max.doubleValue());
    }

    public Validator regexMatches(String name, String value, String pattern) {
        String alert = String.format("%s必須滿足格式:%s", name, pattern);
        return valid(ARGUMENT_ERROR, alert, () -> Pattern.matches(pattern, value));
    }

    public Validator phone(String phone) {
        String alert = String.format("電話號碼格式不正確,tel:[%s]", phone);
        return valid(ARGUMENT_ERROR, alert, () -> isPhone(phone));
    }

    public Validator mobile(String mobile) {
        String alert = String.format("手機號碼格式不正確,mobile:[%s]", mobile);
        return valid(ARGUMENT_ERROR, alert, () -> isMobile(mobile));
    }

    public Validator email(String email) {
        String alert = String.format("郵箱格式不正確,email:[%s]", email);
        return valid(ARGUMENT_ERROR, alert, () -> isEmail(email));
    }

    public Validator idCardNo(String idCardNo) {
        String alert = String.format("身份證號格式不正確,number:[%s]", idCardNo);
        return valid(ARGUMENT_ERROR, alert, () -> isIdCardNO(idCardNo));
    }

    public Validator ip(String ip) {
        String alert = "ip地址格式不正確";
        return valid(ARGUMENT_ERROR, alert, () -> isIp(ip));
    }

    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    private class Valid {
        private int code;
        private String alter;
        private Supplier<Boolean> expression;
    }
}
 /**
     * 驗證手機號
     *
     * @param str 手機號
     * @return
     */
    public static boolean isMobile(String str) {
        boolean b = false;
        String s2 = "^$|0?(13|14|15|18|17)[0-9]{9}$";// 驗證手機號
        if (Helpers.isNotNullAndEmpty(str)) {
            Pattern p = Pattern.compile(s2);
            Matcher m = p.matcher(str);
            b = m.matches();
        }
        return b;
    }

/**
     * 驗證不爲空
     *
     *
     */
  Validator validator = Validator.create()
                    .notEmpty("用戶名", user.getUserName())
                    .notEmpty("密碼", user.getPassword())
                    .notEmpty("驗證碼", user.getCode())
                    .mobile(user.getMobile());


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章