下面列出了怎么用javax.validation.Constraint的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
public void check(Field field) throws CodeCheckException {
Annotation[] annotations = field.getAnnotations();
for (Annotation annotation : annotations) {
if (excepts.contains(annotation.annotationType())) {
continue;
}
Constraint constraint = annotation.annotationType().getAnnotation(Constraint.class);
if (constraint != null) {
for (Class<?> klass : getAllSuitableClasses(field.getType(), constraint)) {
if (!isSuitable(field.getType(), klass)) {
throw new CodeCheckException(ReflectUtil.fullName(field), "的类型必须是", klass.getCanonicalName(), "或者其子类");
}
}
}
}
}
@Override
public void check(Method method) throws CodeCheckException {
for (Parameter parameter : method.getParameters()) {
Annotation[] annotations = parameter.getAnnotations();
for (Annotation annotation : annotations) {
if (excepts.contains(annotation.annotationType())) {
continue;
}
Constraint constraint = annotation.annotationType().getAnnotation(Constraint.class);
if (constraint != null) {
for (Class<?> klass : getAllSuitableClasses(parameter.getType(), constraint)) {
if (!isSuitable(parameter.getType(), klass)) {
throw new CodeCheckException("方法", ReflectUtil.fullName(method), "的参数", parameter.getName(), "的类型必须是", klass
.getCanonicalName(), "或者其子类");
}
}
}
}
}
}
/**
* @return true if this is a multi-value constraint class as per JSR 303 requirements (contains a value() method
* which returns an array of Constraints), false otherwise.
*/
private static boolean isMultiValueConstraintClass(Class<? extends Annotation> annotationClass) {
// It must have a value() method.
Method valueMethod;
try {
valueMethod = annotationClass.getDeclaredMethod("value");
}
catch (NoSuchMethodException e) {
return false;
}
// That value field must return a type of "array of Constraint"
//noinspection RedundantIfStatement
if (valueMethod.getReturnType().isArray()
&& valueMethod.getReturnType().getComponentType().getAnnotation(Constraint.class) != null) {
return true;
}
return false;
}
private static boolean hasConstraintParameter(Method method) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations != null && parameterAnnotations.length > 0) {
for (Annotation[] annotations : parameterAnnotations) {
for (Annotation annotation : annotations) {
if (annotation.annotationType().isAnnotationPresent(Constraint.class)) {
return true;
}
}
}
}
return false;
}
private List<Class<?>> getAllSuitableClasses(Class<?> klass, Constraint constraint) {
List<Class<?>> classes = new ArrayList<>();
for (var validator : constraint.validatedBy()) {
Class<?> actualClass = (Class<?>) ((ParameterizedType) validator.getGenericInterfaces()[0]).getActualTypeArguments()[1];
classes.add(actualClass);
}
return classes;
}
private static boolean hasConstraintParameter(Method method) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations != null && parameterAnnotations.length > 0) {
for (Annotation[] annotations : parameterAnnotations) {
for (Annotation annotation : annotations) {
if (annotation.annotationType().isAnnotationPresent(Constraint.class)) {
return true;
}
}
}
}
return false;
}
private static boolean hasConstraintParameter(Method method) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations != null && parameterAnnotations.length > 0) {
for (Annotation[] annotations : parameterAnnotations) {
for (Annotation annotation : annotations) {
if (annotation.annotationType().isAnnotationPresent(Constraint.class)) {
return true;
}
}
}
}
return false;
}
private static boolean hasConstraintParameter(Method method) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations != null && parameterAnnotations.length > 0) {
for (Annotation[] annotations : parameterAnnotations) {
for (Annotation annotation : annotations) {
if (annotation.annotationType().isAnnotationPresent(Constraint.class)) {
return true;
}
}
}
}
return false;
}
private boolean isRequired(Field field) {
if (field.isAnnotationPresent(NotNull.class)) {
return true;
}
Annotation[] annotations = field.getAnnotations();
for (Annotation annotation : annotations) {
Class<? extends Annotation> annotationType = annotation.annotationType();
if (annotationType.isAnnotationPresent(Constraint.class) && annotationType
.isAnnotationPresent(NotNull.class)) {
return true;
}
}
return false;
}
private <U, C extends Annotation> Optional<U> determineConstraints(Class<C> clazz, Field field, Function<C, U> callback) {
C constraint = field.getAnnotation(clazz);
if (constraint != null) {
return Optional.of(callback.apply(constraint));
}
for (Annotation annotation : field.getAnnotations()) {
Class<? extends Annotation> annotationType = annotation.annotationType();
if (annotationType.isAnnotationPresent(Constraint.class) && annotationType.isAnnotationPresent(clazz)) {
return Optional.of(callback.apply(annotationType.getAnnotation(clazz)));
}
}
return Optional.empty();
}
private static boolean hasConstraintParameter(Method method) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations != null && parameterAnnotations.length > 0) {
for (Annotation[] annotations : parameterAnnotations) {
for (Annotation annotation : annotations) {
if (annotation.annotationType().isAnnotationPresent(Constraint.class)) {
return true;
}
}
}
}
return false;
}
private boolean isValidationAnnotations(final Annotation... annotations) {
boolean matches = false;
for (Annotation ann : annotations) {
final Class<? extends Annotation> annotationType = ann.annotationType();
if (Valid.class.equals(annotationType) || annotationType.isAnnotationPresent(Constraint.class)) {
matches = true;
break;
}
}
return matches;
}
/**
* Initializes the instance based on what is returned by {@link #ignoreAllAnnotationsAssociatedWithTheseProjectClasses()}
* and {@link #specificAnnotationDeclarationExclusionsForProject()}. This is time consuming and should only be done
* once per project if possible - see the usage info in the {@link ReflectionBasedJsr303AnnotationTrollerBase}
* class-level javadocs.
*
* <p>The given set of extra packages for constraint annotation searching will be passed into {@link
* #getFinalPackagesToSearchForConstraintAnnotations(Set)} to generate the final set of packages that are searched.
* If you don't want the {@link #DEFAULT_CONSTRAINT_SEARCH_PACKAGES} default packages to be searched you can
* override {@link #getDefaultPackagesToSearchForConstraintAnnotations()}.
*/
public ReflectionBasedJsr303AnnotationTrollerBase(Set<String> extraPackagesForConstraintAnnotationSearch) {
/*
* Set up the {@link #ignoreAllAnnotationsAssociatedWithTheseClasses} and
* {@link #specificAnnotationDeclarationsExcludedFromStrictMessageRequirement} fields so we know which
* annotations are project-relevant vs. unit-test-only.
*/
ignoreAllAnnotationsAssociatedWithTheseClasses =
new ArrayList<>(setupIgnoreAllAnnotationsAssociatedWithTheseClasses());
specificAnnotationDeclarationsExcludedFromStrictMessageRequirement =
new ArrayList<>(setupSpecificAnnotationDeclarationExclusions());
/*
* Set up the {@link #reflections}, {@link #constraintAnnotationClasses}, and
* {@link #allConstraintAnnotationsMasterList} fields. This is where the crazy reflection magic happens to troll
* the project for the JSR 303 annotation declarations.
*/
// Create the ConfigurationBuilder to search the relevant set of packages.
ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
for (String packageToAdd : getFinalPackagesToSearchForConstraintAnnotations(
extraPackagesForConstraintAnnotationSearch)) {
configurationBuilder.addUrls(ClasspathHelper.forPackage(packageToAdd));
}
// Create the Reflections object so it scans for all validation annotations we care about and all project
// classes that might have annotations on them.
reflections = new Reflections(configurationBuilder.setScanners(
new SubTypesScanner(), new MethodParameterScanner(), new TypeAnnotationsScanner(),
new MethodAnnotationsScanner(), new FieldAnnotationsScanner()
));
// Gather the list of all JSR 303 validation annotations in the project. Per the JSR 303 spec this is any
// annotation class type that is marked with @Constraint.
constraintAnnotationClasses = new ArrayList<>();
for (Class<?> constraintAnnotatedType : reflections.getTypesAnnotatedWith(Constraint.class, true)) {
if (constraintAnnotatedType.isAnnotation()) {
//noinspection unchecked
constraintAnnotationClasses.add((Class<? extends Annotation>) constraintAnnotatedType);
}
}
// We're not done gathering validation annotations though, unfortunately. JSR 303 also says that *any*
// annotation (whether it is a Constraint or not) that has a value field that returns an array of actual
// Constraints is treated as a "multi-value constraint", and the validation processor will run each
// of the Constraints in the array as if they were declared separately on the annotated element. Therefore,
// we have to dig through all the annotations in the project, find any that fall into this "multi-value
// constraint" category, and include them in our calculations.
for (Class<? extends Annotation> annotationClass : reflections.getSubTypesOf(Annotation.class)) {
if (isMultiValueConstraintClass(annotationClass))
constraintAnnotationClasses.add(annotationClass);
}
// Setup the master constraint list
allConstraintAnnotationsMasterList =
new ArrayList<>(setupAllConstraintAnnotationsMasterList(reflections, constraintAnnotationClasses));
/*
* Finally use the info we've gathered/constructed previously to populate the
* {@link #projectRelevantConstraintAnnotationsExcludingUnitTestsList} field, which is the main chunk of data
* that extensions of this class will care about.
*/
projectRelevantConstraintAnnotationsExcludingUnitTestsList = Collections.unmodifiableList(
getSubAnnotationListUsingExclusionFilters(allConstraintAnnotationsMasterList,
ignoreAllAnnotationsAssociatedWithTheseClasses,
specificAnnotationDeclarationsExcludedFromStrictMessageRequirement));
}
private boolean hasConstraintOrValidAnnotation(Annotation annotation) {
return Annotations.on(annotation.annotationType()).includingMetaAnnotations().find(
Constraint.class).isPresent() ||
Valid.class.equals(annotation.annotationType());
}
/**
* Determines whether the given annotation is a 'constraint' or not.
* It just checks if the annotation has the {@link Constraint} annotation on it or if the annotation is the {@link
* Valid} annotation.
*
* @param annotation the annotation to check
* @return {@code true} if the given annotation is a constraint
*/
private static boolean isConstraint(Annotation annotation) {
return annotation.annotationType().isAnnotationPresent(Constraint.class)
|| annotation.annotationType().equals(Valid.class);
}