La position actuelle:Accueil du site>Éléments de base de la validation des haricots - 04

Éléments de base de la validation des haricots - 04

2022-07-23 16:10:52Big buggy Love Buggy


Introduction

Comprendre le contexte du vérificateurValidatorContext,Sachant qu'il peut vérifierValidatorLes cinq principaux composants du noyau sont personnalisés,Quel rôle ces composants de base jouent - ils dans le processus de vérification?,Dans cet article.

En tant qu'élément central,Il est nécessaire d'en savoir plus..Sur cette base,La diffusion, la compréhension et l'utilisation d'autres modules fonctionnels seront comme de l'eau..Mais le processus est vraiment ennuyeux,C'est pour ça qu'il faut insister..

Bean ValidationLes cinq composants de base du vérificateur passent parValidatorContextPeut être défini séparément:Si ce n'est pas réglé(Ounull), Alors revenez à l'utilisation ValidatorFactory Composant par défaut .

Composants prêts ,Adoption uniformeValidatorFactory Exposé à l'accès :

public interface ValidatorFactory extends AutoCloseable {
    
	...
	MessageInterpolator getMessageInterpolator();
	TraversableResolver getTraversableResolver();
	ConstraintValidatorFactory getConstraintValidatorFactory();
	ParameterNameProvider getParameterNameProvider();
	@since 2.0
	ClockProvider getClockProvider();
	...
}

MessageInterpolator

Traduction littérale:Interpolateur de messages. Pas très facile à comprendre littéralement :C'est tout simplement vrai.messageFormatage du contenu,S'il y a un substituant{}OuelExpression${}Effectuer des remplacements et des calculs. Les erreurs grammaticales doivent être tolérées autant que possible .

La vérification d'un modèle de message défaillant lui donne un format de message lisible par l'homme , Il est donc capable de gérer l'internationalisation des messages :MessagekeyC'est le même, Mais selon Locale Afficher différents modèles de message . Enfin en remplacement de / Placeholder dans le modèle technique ~

C'estBean ValidationInterface standard pour,Hibernate ValidatorFournit une mise en œuvre:

Insérer la description de l'image ici
Hibernate ValidationIl utiliseResourceBundleMessageInterpolatorPour supporter à la fois les paramètres,- Oui.ELExpression.

javax.el.ExpressionFactoryC'estAPIPour soutenirELExpression${}De,Comme ça.:must be greater than ${inclusive == true ? 'or equal to ' : ''}{value}Il est capable de calculer dynamiquement${inclusive == true ? 'or equal to ' : ''}La valeur de cette partie.

public interface MessageInterpolator {
    
	String interpolate(String messageTemplate, Context context);
	String interpolate(String messageTemplate, Context context,  Locale locale);
}

Méthode d'interface simple :Selon le contexteContext Remplir le modèle de message messageTemplate. Son flux de travail spécifique est illustré ci - dessous :

Insérer la description de l'image ici

context En général, le contexte a besoin d'être remplacé keyLa valeur de la clé est correcte,Comme le montre la figure ci - dessous:

Insérer la description de l'image ici
HibernateC'est exact.Context L'implémentation de a étendu deux Map(NonJSRCritères), Peut vous donner la priorité sur constraintDescriptorValeur, Je ne peux plus fallback En mode standard ConstraintDescriptorValeur intérieure, C'est la valeur de propriété de l'annotation . Les codes de valeur spécifiques sont les suivants: :

ParameterTermResolver:

	private Object getVariable(Context context, String parameter) {
    
		// Commencez parhibernate Valeur de la méthode étendue 
		if (context instanceof HibernateMessageInterpolatorContext) {
    
			Object variable = ( (HibernateMessageInterpolatorContext) context ).getMessageParameters().get( parameter );
			if ( variable != null ) {
    
				return variable;
			}
		}
		// fallback En mode standard : Valeur de l'attribut annotation 
		return context.getConstraintDescriptor().getAttributes().get( parameter );
	}

Dans la plupart des cas, nous n'obtenons que les valeurs des attributs d'annotation , C'est - à - dire que le message d'erreur peut être utilisé { Annotation nom de l'attribut } Ceci obtient dynamiquement la valeur de l'attribut d'annotation , Donner un message d'erreur amical .

Dans le contexteMessageParamètres etExpression Comment mettre les paramètres ? Dans la section utilisation avancée ultérieure , Sera personnalisé k-vRemplacer les paramètres, Les connaissances avancées en application de cette section seront également utilisées , Voir plus loin .


TraversableResolver

Processeur capable de traverser . Littéralement, c'est très difficile à comprendre. , Dans un langage grossier :Déterminer si une propriété peut êtreValidationProviderAccès à, Chaque fois que vous accédez à un attribut, vous le jugez d'un coup ,Fournir deux méthodes de jugement:

public interface TraversableResolver {
    

	// Si elle est accessible
	boolean isReachable(Object traversableObject,
						Node traversableProperty,
						Class<?> rootBeanType,
						Path pathToTraversableObject,
						ElementType elementType);
						
	// Est cascade(Indique s'il y [email protected]
	boolean isCascadable(Object traversableObject,
						 Node traversableProperty,
						 Class<?> rootBeanType,
						 Path pathToTraversableObject,
						 ElementType elementType);
}

L'interface est principalement jugée en fonction des éléments de configuration,Pas responsable..Pour usage interne, L'appelant n'a pas besoin de s'en soucier. , Il n'y a pas non plus de mécanisme de modification par défaut ,Pour l'instant.


ConstraintValidatorFactory

Usine de contrôle des contraintes .ConstraintValidator Nous ne devrions pas être étrangers au vérificateur des contraintes : Chaque annotation de contrainte doit spécifier un / Plusieurs validateurs de contraintes ,Comme ça.:

@Constraint(validatedBy = {
     xxx.class }).

ConstraintValidatorFactory C'est l'usine :Peut être basé surClassGénérer une instance objet.

public interface ConstraintValidatorFactory {
    

	// Générer une instance:L'interface ne précise pas comment vous générez
	<T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key);
	// Exemple de libération.Marquer cette instance n'est plus nécessaire,Implémentation généralement vide
	// EtSpringLorsque le conteneur est intégré .destroyBean(instance)Cette méthode est appelée lorsque
	void releaseInstance(ConstraintValidator<?, ?> instance);
}

HibernateFournit une mise en œuvre uniqueConstraintValidatorFactoryImpl:Générer une instance en utilisant un constructeur vide clazz.getConstructor().newInstance();.

Conseils: L'interface n'indique pas comment générer une instance ,Hibernate Validator C'est ce qui s'est passé avec la construction vide ~


ParameterNameProvider

Fournisseur de noms de paramètres.Ce composant etSpringDeParameterNameDiscoverer C'est pareil. :Méthode d'obtention/ Nom du paramètre du constructeur .

public interface ParameterNameProvider {
    
	
	List<String> getParameterNames(Constructor<?> constructor);
	List<String> getParameterNames(Method method);
}

Mise en œuvre fournie:

  • DefaultParameterNameProvider:Basé surJavaRéflexeAPI Executable#getParameters()Réalisation
@Test
public void test9() {
    
    ParameterNameProvider parameterNameProvider = new DefaultParameterNameProvider();

    // Prends ça.Person Structure non paramétrique et structure paramétrique (@[email protected]
    Arrays.stream(Person.class.getConstructors()).forEach(c -> System.out.println(parameterNameProvider.getParameterNames(c)));
}

Exécuter le programme,Produits:

[arg0, arg1, arg2, arg3]
[]

Même chose, Si vous souhaitez imprimer un nom de paramètre explicite , Veuillez ajouter aux paramètres de compilation -parametersParamètres.

  • ReflectionParameterNameProvider:Expiré.Veuillez utiliser ledefaultRemplacer
  • ParanamerParameterNameProvider:Basé surcom.thoughtworks.paranamer.Paranamer Implémenter l'acquisition du nom du paramètre , Les paquets correspondants doivent être importés en plus. .

ClockProvider

Fournisseur d'horloges.Cette interface est simple,Est de fournir unClock,Voilà[email protected]、@FutureFournir une référence pour le jugement de lecture.La seule mise en œuvre estDefaultClockProvider:

public class DefaultClockProvider implements ClockProvider {
    

	public static final DefaultClockProvider INSTANCE = new DefaultClockProvider();

	private DefaultClockProvider() {
    
	}

	// La valeur par défaut est l'horloge système
	@Override
	public Clock getClock() {
    
		return Clock.systemDefaultZone();
	}

}

Par défaut, l'horloge système actuelle est utilisée comme référence . Si votre système a des normes de référence globalement harmonisées , Comme l'horloge unifiée , Cela vous permettra d'implémenter votre propre ClockHorloge, Après tout, le temps de chaque serveur n'est pas garanti d'être exactement le même , C'est un scénario d'application sensible au temps ( Par exemple, appel d'offres )C'est nécessaire.

Ce qui précède est justeValidator Une description des cinq composantes principales du vérificateur , Dans l'ensemble, c'est assez simple. . Dont le premier élément :MessageInterpolator Je pense que l'interpolateur est le plus important , Il faut comprendre . Faire un modèle de message personnalisé plus tard 、 Les messages internationaux sont utiles .


ValueExtractor

Extracteur de valeur.2.0 La version ajoute un composant plus important API,Action:Extraire la valeur du conteneur. Les contenants ici comprennent :Tableau、Ensemble、Map、OptionalAttendez un peu!.

// T:Type de conteneur à extraire
public interface ValueExtractor<T> {
    

	// De la valeur originaleoriginalValueExtrait dereceiver- Oui.
	void extractValues(T originalValue, ValueReceiver receiver);

	// Fournir un ensemble de méthodes,Pour recevoirValueExtractorLa valeur extraite
	interface ValueReceiver {
    
	
		// Recevoir les valeurs extraites de l'objet
		void value(String nodeName, Object object);
		// Recevoir des valeurs itératives,Par exemple:List、Map、IterableAttendez.
		void iterableValue(String nodeName, Object object);
		// Recevoir une valeur indexée,Par exemple:List Array
		// i:Valeur de l'index
		void indexedValue(String nodeName, int i, Object object);
		// Recevoir les valeurs des paires de clés,Par exemple:Map
		void keyedValue(String nodeName, Object key, Object object);
	}
}

Facile à penser,ValueExtractor Il y a beaucoup de classes d'implémentation ( Toutes les classes de mise en œuvre sont intégrées ,NonpublicDe, C'est le type de conteneur supporté par défaut ):

Insérer la description de l'image ici
Exemples de deux implémentations typiques :

// ExtractionListValeur en LIST_ELEMENT_NODE_NAME -> <list element>
class ListValueExtractor implements ValueExtractor<List<@ExtractedValue ?>> {
    

	static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new ListValueExtractor() );

	private ListValueExtractor() {
    
	}

	@Override
	public void extractValues(List<?> originalValue, ValueReceiver receiver) {
    
		for ( int i = 0; i < originalValue.size(); i++ ) {
    
			receiver.indexedValue( NodeImpl.LIST_ELEMENT_NODE_NAME, i, originalValue.get( i ) );
		}
	}
}

// ExtractionOptionalValeur en
@UnwrapByDefault
class OptionalLongValueExtractor implements ValueExtractor<@ExtractedValue(type = Long.class) OptionalLong> {
    

	static final ValueExtractorDescriptor DESCRIPTOR = new ValueExtractorDescriptor( new OptionalLongValueExtractor() );

	@Override
	public void extractValues(OptionalLong originalValue, ValueReceiver receiver) {
    
		receiver.value( null, originalValue.isPresent() ? originalValue.getAsLong() : null );
	}
}

CalibrateurValidator Il permet d'extraire la valeur du conteneur pour participer à la vérification , À partir de là, vous devriez être capable de comprendre Mao de Bean Validation2.0 Commencez par prendre en charge la validation des éléments dans le conteneur ,Comme ça.:List<@NotNull @Valid Person>、Optional<@NotNull @Valid Person>, C'est très pratique. .

Si vous avez un conteneur personnalisé , Exigences à extraire , Alors vous pouvez personnaliser ValueExtractorRéalisation,Et à traversValidatorContext#addValueExtractor()Il suffit de l'ajouter


RÉFÉRENCES

4. ValidatorLes cinq principaux composants du calibrateur,Il n'y en a pas moins

Mentions de copyright
Auteur de cet article [Big buggy Love Buggy],Réimpression s’il vous plaît apporter le lien vers l’original, merci
https://fra.chowdera.com/2022/204/202207231152135559.html

Recommandé au hasard