Java自定义注解
一、Java自定注解
定义注解
package com.cloud.sample.base.annotation;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author: wanglin
* @date: 2023-08-02 周三
* @Version: 1.0
* @Description:
*/
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = {IsNotBlankListValidator.class})
public @interface NotBlankInList {
boolean required() default false;
String message() default "field not can blank";
/**
* 指定约束分组,在某一个分组时才执行此约束验证
*
* @return
*/
Class<?>[] groups() default {};
/**
* payload 指定的payload,会在验证结果中携带此字段,比如:可以用于验证结果的严重等级分类
*
* @return
*/
Class<? extends Payload>[] payload() default {};
}
注解验证工具类
package com.cloud.sample.base.annotation;
import cn.hutool.core.lang.Assert;
import org.springframework.util.CollectionUtils;
import java.lang.reflect.Field;
import java.util.List;
/**
* @author: wanglin
* @date: 2023-08-02 周三
* @Version: 1.0
* @Description:
*/
public class ValidatorUtil {
/**
* 注解验证测试
*
* @param o
*/
public static void notBlank(Object o) {
Field[] declaredFields = o.getClass().getDeclaredFields();
for (Field declaredField : declaredFields) {
boolean annotationPresent = declaredField.isAnnotationPresent(NotBlankInList.class);
if (annotationPresent) {
NotBlankInList annotation = declaredField.getAnnotation(NotBlankInList.class);
declaredField.setAccessible(true);
String name = declaredField.getName();
System.out.println(name);
List<?> fieldValue = null;
try {
Object valueObject = declaredField.get(o);
Assert.isNull(valueObject, name + "不能为空!");
fieldValue = (List<?>) declaredField.get(o);
Assert.isTrue(fieldValue.size() > 0, name + "不能为空!!");
} catch (IllegalAccessException e) {
e.printStackTrace();
}
System.out.println(fieldValue);
fieldValue.stream().forEach(e -> Assert.isTrue(!isEmptyIfStr(e), name + "不能为空!!!"));
}
}
}
/**
* if null,return true
*
* @param valueList
* @return
*/
public static boolean isEmptyInList(List<?> valueList) {
if (CollectionUtils.isEmpty(valueList)) {
return true;
}
return valueList.stream().anyMatch(e -> isEmptyIfStr(e));
}
/**
* <p>如果对象是字符串是否为空串,空的定义如下:</p><br>
* <ol>
* <li>{@code null}</li>
* <li>空字符串:{@code ""}</li>
* </ol>
*
* <p>例:</p>
* <ul>
* <li>{@code StrUtil.isEmptyIfStr(null) // true}</li>
* <li>{@code StrUtil.isEmptyIfStr("") // true}</li>
* <li>{@code StrUtil.isEmptyIfStr(" \t\n") // false}</li>
* <li>{@code StrUtil.isEmptyIfStr("abc") // false}</li>
* </ul>
*
* <p>注意:该方法与 {@link #isBlankIfStr(Object)} 的区别是:该方法不校验空白字符。</p>
*
* @param obj 对象
* @return 如果为字符串是否为空串
*/
public static boolean isEmptyIfStr(Object obj) {
if (null == obj) {
return true;
} else if (obj instanceof CharSequence) {
return 0 == ((CharSequence) obj).length();
}
return false;
}
/**
* <p>如果对象是字符串是否为空白,空白的定义如下:</p>
* <ol>
* <li>{@code null}</li>
* <li>空字符串:{@code ""}</li>
* <li>空格、全角空格、制表符、换行符,等不可见字符</li>
* </ol>
*
* <p>例:</p>
* <ul>
* <li>{@code StrUtil.isBlankIfStr(null) // true}</li>
* <li>{@code StrUtil.isBlankIfStr("") // true}</li>
* <li>{@code StrUtil.isBlankIfStr(" \t\n") // true}</li>
* <li>{@code StrUtil.isBlankIfStr("abc") // false}</li>
* </ul>
*
* <p>注意:该方法与 {@link #isEmptyIfStr(Object)} 的区别是:
* 该方法会校验空白字符,且性能相对于 {@link #isEmptyIfStr(Object)} 略慢。</p>
*
* @param obj 对象
* @return 如果为字符串是否为空串
*/
public static boolean isBlankIfStr(Object obj) {
if (null == obj) {
return true;
} else if (obj instanceof CharSequence) {
return isBlank((CharSequence) obj);
}
return false;
}
public static boolean isNotBlank(CharSequence str) {
return false == isBlank(str);
}
public static boolean isBlank(CharSequence str) {
final int length;
if ((str == null) || ((length = str.length()) == 0)) {
return true;
}
for (int i = 0; i < length; i++) {
// 只要有一个非空字符即为非空字符串
if (false == isBlankChar(str.charAt(i))) {
return false;
}
}
return true;
}
/**
* 是否空白符<br>
* 空白符包括空格、制表符、全角空格和不间断空格<br>
*
* @param c 字符
* @return 是否空白符
* @see Character#isWhitespace(int)
* @see Character#isSpaceChar(int)
*/
public static boolean isBlankChar(char c) {
return isBlankChar((int) c);
}
/**
* 是否空白符<br>
* 空白符包括空格、制表符、全角空格和不间断空格<br>
*
* @param c 字符
* @return 是否空白符
* @see Character#isWhitespace(int)
* @see Character#isSpaceChar(int)
*/
public static boolean isBlankChar(int c) {
return Character.isWhitespace(c)
|| Character.isSpaceChar(c)
|| c == '\ufeff'
|| c == '\u202a'
|| c == '\u0000'
// issue#I5UGSQ,Hangul Filler
|| c == '\u3164'
// Braille Pattern Blank
|| c == '\u2800'
// MONGOLIAN VOWEL SEPARATOR
|| c == '\u180e';
}
}
测试
ValidatorUtil.notBlank(dto);
二、Springboot自定义注解
原注解不变,需要使用 ConstraintValidator 进行校验,groups 和 payload这两个参数是必要的。groups可以指定注解使用的场景,一个实体类可能会在多个场合有使用,如插入,删除等。通过groups可以指定该注解在插入/删除的环境下生效。payload往往对bean进行使用。
校验类
package com.cloud.sample.base.annotation;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.List;
/**
* @author: wanglin
* @date: 2023-08-02 周三
* @Version: 1.0
* @Description:
*/
public class IsNotBlankListValidator implements ConstraintValidator<NotBlankInList, List<?>> {
@Override
public void initialize(NotBlankInList constraintAnnotation) {
ConstraintValidator.super.initialize(constraintAnnotation);
}
/**
* 自定义注解处理程序, 返回true则通过自定义注解的校验, 返回false则是没有通过自定义注解的校验,并返回自定义注解中message的内容
*
* @param objects
* @param constraintValidatorContext
* @return
*/
@Override
public boolean isValid(List<?> objects, ConstraintValidatorContext constraintValidatorContext) {
boolean isBlankFlag = ValidatorUtil.isEmptyInList(objects);
return !isBlankFlag;
}
}
关注林哥,持续更新哦!!!★,°:.☆( ̄▽ ̄)/$:.°★ 。