package org.springframework.learning.resource;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.support.AbstractMessageSource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.util.StringUtils;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.nio.file.*;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
`import java.util.concurrent.Executors;
/**
\* @author
\* @date 2020/10/15 9:15 下午
*
\* 动态监听配置文件的变动,实现动态MessageSource
\* 1. 定位资源位置
\* 2. 初始化properties
\* 3. 实现resolveCode方法
\* 4. 文件监听 @see WatchService
*/
public class DynamicMessageSourceDemoextends AbstractMessageSourceimplements ResourceLoaderAware {
private static final StringFILE_NAME ="messages.properties";
private static final StringRESOURCE_PATH ="/META-INF/i18n/" +FILE_NAME;
private static final StringENCODE ="UTF-8";
private ResourceLoaderresourceLoader;
private final Propertiesproperties;
private final ResourcemessagePropertiesResource;
private final ExecutorServiceexecutorService = Executors.newSingleThreadExecutor();
public DynamicMessageSourceDemo() {
this.messagePropertiesResource = getMessagePropertiesSource();
this.properties = loadProperties();
onMessagePropertiesChanged();
}
private void onMessagePropertiesChanged() {
try {
FilemessagePropertiesSourceFile =messagePropertiesResource.getFile();
PathmessagePropertiesSourcePath =messagePropertiesSourceFile.toPath();
FileSystemfileSystem = FileSystems.getDefault();
WatchServicewatchService =fileSystem.newWatchService();
Pathdir =messagePropertiesSourcePath.getParent();
dir.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
executorService.submit(()->{
processMessagePropertiesChanged(watchService);
});
}catch (IOExceptione) {
throw new RuntimeException();
}
}
private void processMessagePropertiesChanged(WatchServicewatchService) {
while (true){
WatchKey watchKey =null;
try {
watchKey =watchService.take();
if(watchKey.isValid()){
Pathdir = (Path) watchKey.watchable();
for (WatchEventevent : watchKey.pollEvents()) {
PathabsolutePath =dir.resolve((Path)event.context());
if("messages.properties".equals(absolutePath.getFileName().toString())){
System.out.println("文件变化" +absolutePath.toString());
Filefile =absolutePath.toFile();
PropertiesnewProperties = loadProperties(new FileReader(file));
synchronized (properties){
properties.clear();
properties.putAll(newProperties);
}
}
}
}
}catch (Exceptione) {
throw new RuntimeException(e);
}finally {
if(null!=watchKey){
watchKey.reset();
}
}
}
}
private PropertiesloadProperties() {
EncodedResourceencodedResource =new EncodedResource(messagePropertiesResource, ENCODE);
try {
return loadProperties(encodedResource.getReader());
}catch (IOExceptione) {
throw new RuntimeException(e);
}
}
private ResourcegetMessagePropertiesSource() {
return getResourceLoader().getResource(RESOURCE_PATH);
}
private PropertiesloadProperties(Readerreader) {
Propertiesproperties =new Properties();
try {
properties.load(reader);
}catch (IOExceptione) {
throw new RuntimeException(e);
}finally {
try {
reader.close();
}catch (IOExceptione) {
throw new RuntimeException(e);
}
}
return properties;
}
@Override
protected MessageFormatresolveCode(Stringcode, Localelocale) {
StringmessageFormatPattern =properties.getProperty(code);
if (StringUtils.hasText(messageFormatPattern)) {
return new MessageFormat(messageFormatPattern, locale);
}
return null;
}
@Override
public void setResourceLoader(ResourceLoaderresourceLoader) {
this.resourceLoader =resourceLoader;
}
public ResourceLoadergetResourceLoader() {
return this.resourceLoader !=null ?this.resourceLoader :new DefaultResourceLoader();
}
public static void main(String[]args)throws InterruptedException {
DynamicMessageSourceDemodemo =new DynamicMessageSourceDemo();
for(int i=0;i<10000;i++){
Stringmessage =demo.getMessage("name", null, Locale.getDefault());
System.out.println(message);
Thread.sleep(1000);
}
}
}