当前位置:网站首页>Bean validation core components - 04
Bean validation core components - 04
2022-07-23 16:11:00 【Big flicker love flicker】
Bean Validation Core components ----04
introduction
Understand the verifier context again ValidatorContext, Know that it can check the calibrator Validator The five core components of are customized , So what role do these core components play in the verification process , In this paper, the author tries to find out .
As a core component , It is necessary to explore more . On this basis , Further spread, understanding and using other functional modules will be like a fish in water . But it's true that the process is boring , So we need to stick to it .
Bean Validation The five core components of the calibrator passed ValidatorContext It can be set separately : If not set ( Or for null), Then go back to using ValidatorFactory Default component .
Ready components , To pass through ValidatorFactory Expose it and visit it :
public interface ValidatorFactory extends AutoCloseable {
...
MessageInterpolator getMessageInterpolator();
TraversableResolver getTraversableResolver();
ConstraintValidatorFactory getConstraintValidatorFactory();
ParameterNameProvider getParameterNameProvider();
@since 2.0
ClockProvider getClockProvider();
...
}
MessageInterpolator
Literal translation : Message interpolator . It's not easy to understand literally : Simply put, yes message Format the content , If there are placeholders {} perhaps el expression ${} Just perform the substitution and calculation . Grammatical errors should be tolerated as much as possible .
The message template that fails the verification is handed over to it for processing, which becomes a message format that people can understand , So it can handle the internationalization of messages : News key Is the same , But according to different Locale Show different message templates . Finally, replace / The placeholder in the technical template is enough ~
This is a Bean Validation Standard interface for ,Hibernate Validator Provides implementation :

Hibernate Validation It uses ResourceBundleMessageInterpolator To support both parameters , Also support EL expression .
javax.el.ExpressionFactory This API To support EL expression ${} Of , It's like this :must be greater than ${inclusive == true ? 'or equal to ' : ''}{value} It can dynamically calculate ${inclusive == true ? 'or equal to ' : ''} The value of this part .
public interface MessageInterpolator {
String interpolate(String messageTemplate, Context context);
String interpolate(String messageTemplate, Context context, Locale locale);
}
The interface method is straightforward : According to context Context Fill in the message template messageTemplate. Its specific workflow is shown below :

context In the context, there is usually something that needs to be replaced key The key value of , As shown in the figure below :

Hibernate Yes Context As shown in the figure, two Map( Not JSR standard ), Can give you priority over constraintDescriptor Value , No more fallback To the standard mode ConstraintDescriptor Value in , That is, the attribute value of the annotation . The specific value code is as follows :
ParameterTermResolver:
private Object getVariable(Context context, String parameter) {
// First from hibernate The extended method takes values
if (context instanceof HibernateMessageInterpolatorContext) {
Object variable = ( (HibernateMessageInterpolatorContext) context ).getMessageParameters().get( parameter );
if ( variable != null ) {
return variable;
}
}
// fallback To standard mode : Take value from annotation attribute
return context.getConstraintDescriptor().getAttributes().get( parameter );
}
In most cases, we only get the value in the annotation attribute , That is, you can use { Annotation attribute name } In this way, the annotation attribute value is dynamically obtained , Give friendly error tips .
In the context of Message Parameters and Expression How to put parameters ? In the following advanced use section , Can customize k-v Replace parameters , You will also use the advanced application knowledge in this part , See you later .
TraversableResolver
Spanning processors . It's very difficult to understand literally , Explain it in rude language as : Determine whether a property can be ValidationProvider visit , When you access a property, you will use it to judge , There are two ways to judge :
public interface TraversableResolver {
// Whether it's accessible
boolean isReachable(Object traversableObject,
Node traversableProperty,
Class<?> rootBeanType,
Path pathToTraversableObject,
ElementType elementType);
// Whether it is cascadable ( Whether it is marked with @Valid annotation )
boolean isCascadable(Object traversableObject,
Node traversableProperty,
Class<?> rootBeanType,
Path pathToTraversableObject,
ElementType elementType);
}
This interface mainly judges based on configuration items , Not responsible . For internal use , The caller basically doesn't need to care , Nor is it possible to change its default mechanism , Let's skip .
ConstraintValidatorFactory
Constraint verifier factory .ConstraintValidator We should not be unfamiliar with constraint validators : Each constraint annotation must specify a / Multiple constraint validators , It's like this :
@Constraint(validatedBy = {
xxx.class }).
ConstraintValidatorFactory It's a factory : According to Class Generate object instance .
public interface ConstraintValidatorFactory {
// Build instance : Interfaces don't dictate how you generate
<T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key);
// Release instance . Marking this instance no longer requires , Generally empty implementation
// and Spring Container integration .destroyBean(instance) Will call this method
void releaseInstance(ConstraintValidator<?, ?> instance);
}
Hibernate Provides a unique implementation ConstraintValidatorFactoryImpl: Generate an instance using an empty constructor clazz.getConstructor().newInstance();.
Tips: : The interface does not specify how you generate instances ,Hibernate Validator It is implemented by using empty constructs ~
ParameterNameProvider
Parameter name provider . This component and Spring Of ParameterNameDiscoverer The effect is the same : Access method / Constructor parameter name .
public interface ParameterNameProvider {
List<String> getParameterNames(Constructor<?> constructor);
List<String> getParameterNames(Method method);
}
The implementation provided :
- DefaultParameterNameProvider: be based on Java Reflection API Executable#getParameters() Realization
@Test
public void test9() {
ParameterNameProvider parameterNameProvider = new DefaultParameterNameProvider();
// Get Person Nonparametric structure and parametric structure of (@NoArgsConstructor and @AllArgsConstructor)
Arrays.stream(Person.class.getConstructors()).forEach(c -> System.out.println(parameterNameProvider.getParameterNames(c)));
}
Run the program , Output :
[arg0, arg1, arg2, arg3]
[]
Same , If you want to print out explicit parameter names , Please add -parameters Parameters .
- ReflectionParameterNameProvider: Has expired . Please use the above default Instead of
- ParanamerParameterNameProvider: be based on com.thoughtworks.paranamer.Paranamer Get the parameter name , You need to import the corresponding package additionally .
ClockProvider
Clock provider . The interface is simple , Is to provide a Clock, to @Past、@Future And so on . The only implementation is DefaultClockProvider:
public class DefaultClockProvider implements ClockProvider {
public static final DefaultClockProvider INSTANCE = new DefaultClockProvider();
private DefaultClockProvider() {
}
// The default is the system clock
@Override
public Clock getClock() {
return Clock.systemDefaultZone();
}
}
By default, the current system clock is used as a reference . If your system has a globally unified reference standard , For example, unified clock , Then you can realize your own Clock The clock , After all, the time of each server is not guaranteed to be exactly the same , This is for time sensitive application scenarios ( Such as bidding ) It needs to be done .
That's right Validator A description of the five core components of the verifier , On the whole, it is relatively simple . The first component :MessageInterpolator I think interpolator is the most important , It needs to be understood . Customize the message template for the following 、 International news is useful .
ValueExtractor
Value extractor .2.0 The version adds a more important component API, effect : Extract the value from the container . The containers here include : Array 、 aggregate 、Map、Optional wait .
// T: Type of container to be extracted
public interface ValueExtractor<T> {
// From the original value originalValue Extract to receiver in
void extractValues(T originalValue, ValueReceiver receiver);
// Provide a set of methods , Used to receive ValueExtractor Extracted values
interface ValueReceiver {
// Receive the value extracted from the object
void value(String nodeName, Object object);
// Receive values that can be iterated , Such as List、Map、Iterable etc.
void iterableValue(String nodeName, Object object);
// Receive indexed values , Such as List Array
// i: Index value
void indexedValue(String nodeName, int i, Object object);
// Receive the value of a key value pair , Such as Map
void keyedValue(String nodeName, Object key, Object object);
}
}
Easy to think of ,ValueExtractor There are many implementation classes ( All implementation classes are built-in , Not public Of , This is the container type supported by default ):

Two typical implementations are illustrated :
// extract List In the value of the 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 ) );
}
}
}
// extract Optional In the value of the
@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 );
}
}
validators Validator Through it, the value is extracted from the container to participate in the verification , From this you should be able to understand Mao Cong Bean Validation2.0 It supports the verification of elements in containers from the beginning , It's like this :List<@NotNull @Valid Person>、Optional<@NotNull @Valid Person>, It can be said that it is greatly convenient to use .
If you have custom containers , Requirements that need to be extracted , Then you can customize one ValueExtractor Realization , And then through ValidatorContext#addValueExtractor() Just add in
Reference resources
4. Validator The five core components of the calibrator , Not one less
边栏推荐
猜你喜欢

Chapter 4 event handling of quick mastering QML

【攻防世界WEB】难度三星9分入门题(上):simple_js、mfw

W3C introduces decentralized identifier as web standard

云服务器ECS远程监控

Ultra detailed MP4 format analysis

24 道几乎必问的 JVM 面试题,我只会 7 道,你能答出几道?

FPGA-HLS-乘法器(流水线对比普通仿真)

lc marathon 7.23

Software testing weekly (No. 81): what can resist negativity is not positivity, but concentration; What can resist anxiety is not comfort, but concrete.
![[untitled]](/img/cb/eb8edb5b15a8e87560a63355f35a9c.png)
[untitled]
随机推荐
【论文学习】《Source Mixing and Separation Robust Audio Steganography》
A quietly rising domestic software is too strong!
Without Huawei, Qualcomm will raise prices at will, and domestic mobile phones that lack core technology can only be slaughtered
后缀表达式(暑假每日一题 4)
後綴錶達式(暑假每日一題 4)
SOC的第一个Hello_World实验
Éléments de base de la validation des haricots - 04
“1+1>10”:无代码/低代码与RPA技术的潜在结合
Redis installation
JS filter / replace sensitive characters
Harbor image warehouse
After Effects 教程,如何在 After Effects 中创建动画?
Bean Validation核心组件篇----04
lc marathon 7.23
ICML 2022 | 稀疏双下降:网络剪枝也能加剧模型过拟合?
数字化转型时代的企业数据新基建 | 爱分析报告
Pydensecrf installation
The difference between deadlock, hunger and dead cycle
bug修改
ORA-01654错误:表空间满了,插入失败