International understanding information
International information is also known as the locale. Java objects are represented by localized java.util.Locale class, it creates a localized objects determined by the "language type" and "country / region." To give an example, such as sending a specific request when a key is provided in the header of: "Accept-Language": "zh", by a value corresponding to the Accept-Language, the server can determine which area used language, find the corresponding resource file, formatting, and then returned to the client.
MessageSource
Spring defines MessageSource interface for accessing international information.
- getMessage(String code, Object[] args, String defaultMessage, Locale locale)
- getMessage(String code, Object[] args, Locale locale)
- getMessage(MessageSourceResolvable resolvable, Locale locale)
MessageSourceAutoConfiguration
springboot provides information on international automatic configuration, configuration, registered in the ResourceBundleMessageSource implementation class.
1 @Configuration 2 @ConditionalOnMissingBean(value = MessageSource.class, search = SearchStrategy.CURRENT) 3 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) 4 @Conditional(ResourceBundleCondition.class) 5 @EnableConfigurationProperties 6 public class MessageSourceAutoConfiguration { 7 8 private static final Resource[] NO_RESOURCES = {}; 9 10 @Bean 11 @ConfigurationProperties(prefix = "spring.messages") 12 public MessageSourceProperties messageSourceProperties() { 13 return new MessageSourceProperties(); 14 } 15 16 @Bean 17 public MessageSource messageSource(MessageSourceProperties properties) { 18 ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); 19 if (StringUtils.hasText(properties.getBasename())) { 20 messageSource.setBasenames(StringUtils.commaDelimitedListToStringArray( 21 StringUtils.trimAllWhitespace(properties.getBasename()))); 22 } 23 if (properties.getEncoding() != null) { 24 messageSource.setDefaultEncoding(properties.getEncoding().name()); 25 } 26 messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale()); 27 Duration cacheDuration = properties.getCacheDuration(); 28 if (cacheDuration != null) { 29 messageSource.setCacheMillis(cacheDuration.toMillis()); 30 } 31 messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat()); 32 messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage()); 33 return messageSource; 34 } 35 36 protected static class ResourceBundleCondition extends SpringBootCondition { 37 38 private static ConcurrentReferenceHashMap<String, ConditionOutcome> cache = new ConcurrentReferenceHashMap<>(); 39 40 @Override 41 public ConditionOutcome getMatchOutcome(ConditionContext context, 42 AnnotatedTypeMetadata metadata) { 43 String basename = context.getEnvironment() 44 .getProperty("spring.messages.basename", "messages"); 45 ConditionOutcome outcome = cache.get(basename); 46 if (outcome == null) { 47 outcome = getMatchOutcomeForBasename(context, basename); 48 cache.put(basename, outcome); 49 } 50 return outcome; 51 } 52 53 private ConditionOutcome getMatchOutcomeForBasename(ConditionContext context, 54 String basename) { 55 ConditionMessage.Builder message = ConditionMessage 56 .forCondition("ResourceBundle"); 57 for (String name : StringUtils.commaDelimitedListToStringArray( 58 StringUtils.trimAllWhitespace(basename))) { 59 for (Resource resource : getResources(context.getClassLoader(), name)) { 60 if (resource.exists()) { 61 return ConditionOutcome 62 .match(message.found("bundle").items(resource)); 63 } 64 } 65 } 66 return ConditionOutcome.noMatch( 67 message.didNotFind("bundle with basename " + basename).atAll()); 68 } 69 70 private Resource[] getResources(ClassLoader classLoader, String name) { 71 String target = name.replace('.', '/'); 72 try { 73 return new PathMatchingResourcePatternResolver(classLoader) 74 .getResources("classpath*:" + target + ".properties"); 75 } 76 catch (Exception ex) { 77 return NO_RESOURCES; 78 } 79 } 80 81 } 82 83 }
First MessageSource configuration takes effect relies on a ResourceBundleCondition condition, read spring.messages.basename corresponding value from the environment variable, the default value is the messages, the value is MessageSource corresponding resource file name, file extension resource is .properties, then PathMatchingResourcePatternResolver from the "classpath *:" reads the corresponding directory resource file, if they can properly read to the resource file, load the configuration class.
springmvc automatic assembly configuration class, a register RequestContextFilter filter.
Each request, LocaleContextHolder will save the locale of the current request.
By MessageSourceAccessor get specific information according to the time code, the default configuration if the object is empty localization, through LocaleContextHolder acquired.
messageSource The figure is the application context object (created for this article is GenericWebApplicationContext example), the messageSource object calls ResourceBundleMessageSource instance get specific information.
ValidationAutoConfiguration
Hibernate-validator calibration parameters are loaded by the automatic assembly come.
1 @Configuration 2 @ConditionalOnClass(ExecutableValidator.class) 3 @ConditionalOnResource(resources = "classpath:META-INF/services/javax.validation.spi.ValidationProvider") 4 @Import(PrimaryDefaultValidatorPostProcessor.class) 5 public class ValidationAutoConfiguration { 6 7 @Bean 8 @Role(BeanDefinition.ROLE_INFRASTRUCTURE) 9 @ConditionalOnMissingBean(Validator.class) 10 public static LocalValidatorFactoryBean defaultValidator() { 11 LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean(); 12 MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory(); 13 factoryBean.setMessageInterpolator(interpolatorFactory.getObject()); 14 return factoryBean; 15 } 16 17 @Bean 18 @ConditionalOnMissingBean 19 public static MethodValidationPostProcessor methodValidationPostProcessor( 20 Environment environment, @Lazy Validator validator) { 21 MethodValidationPostProcessor processor = new MethodValidationPostProcessor(); 22 boolean proxyTargetClass = environment 23 .getProperty("spring.aop.proxy-target-class", Boolean.class, true); 24 processor.setProxyTargetClass(proxyTargetClass); 25 processor.setValidator(validator); 26 return processor; 27 } 28 29 }
MethodValidationPostProcessor The post processing method in a single parameter check annotations (JSR and Hibernate validator can check (i.e. Bean Domain Object's attributes) verify, the individual parameters can not be verified.).
LocalValidatorFactoryBean realized javax.validation.ValidatorFactory and javax.validation.Validator two interfaces, as well as Spring's org.springframework.validation.Validator interfaces, you can use any of these interfaces among injecting a need to call the validation logic in the Bean.
By default, validator LocalValidatorFactoryBean created using PlatformResourceBundleLocator obtain the binding relationship between resources, access to the resource name is: ValidationMessages
User-defined check information on the project classpath directory.
In addition hibernate-validator will check the resource load default file name is: org.hibernate.validator.ValidationMessages. You can see, the default check resource bundle file contains configuration information for different regions.
How LocalValidatorFactoryBean acquired validator is loaded with different resource files check it according to different regions? hibernate-validator exposed a message interpolator (MessageInterpolator), spring is the re-interpolator news agency.
By LocaleContextMessageInterpolator source, you can eventually get to see the current time zone information by LocaleContextHolder.
Can you customize the information resources of an international check it? Of course, yes, we just need to rewrite the process of creating LocalValidatorFactoryBean type of bean, resource information specified by setValidationMessageSource custom method.
MessageSource test
Basis test
建立Resouce bundle messages
Write message source test method, to get the current value from the request in Locale
Write test class Locale specified value of the current request or set value header request header: Accept-Language: zh
Depending on the value of the test class Locale request, the acquired text is different.
Formatting test
建立Resouce bundle messages
Write message source test method, to get the current value from the request in Locale
Write test class Locale specified value of the current request or set value header request header: Accept-Language: zh
Depending on the value of the test class Locale request acquired formatted text is different.
Static test message source
Dynamic registration Message (distinguishable Locale), it can be used to customize the message source.
The method of writing tests, accessed through MessageSourceAccessor.
Write test classes, get a custom message source of information.
Depending on the value of the test class Locale request, the acquired text is different.