shikeying
2024-01-11 3b67e947e36133e2a40eb2737b15ea375e157ea0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package com.walker.infrastructure.arguments;
 
import com.walker.infrastructure.core.NestedRuntimeException;
import com.walker.infrastructure.utils.FileCopyUtils;
import com.walker.infrastructure.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.core.io.ClassPathResource;
 
import java.io.File;
import java.io.IOException;
 
/**
 * 可以通过各种方式(XML配置文件、数据库)等来生成系统配置选项管理对象。</br>
 * 目前仅使用XML配置文件,可扩展。
 * @author shikeying
 * @date 2014-5-27
 *
 */
public class ArgumentsManagerFactoryBean implements FactoryBean<ArgumentsManager> {
 
    private final Logger logger = LoggerFactory.getLogger(getClass());
    
    public static final String DEFAULT_CONFIG_FILENAME = "app_variables";
    
    private ArgumentsManager defaultArgumentManager;
    
    // 暂时未使用
    private String filename;
    
    private String suffix = StringUtils.EMPTY_STRING;
    
    /* 是否启动配置文件,在classpath中查找,默认启动,如果不启动则配置文件会拷贝到临时目录中 */
    private boolean openClasspath = true;
    
    public void setOpenClasspath(boolean openClasspath) {
        this.openClasspath = openClasspath;
    }
 
    /**
     * 设置app_variable.xml后缀名,防止多个相同项目部署出现配置不一致问题
     * @param suffix
     */
    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }
 
    @Override
    public ArgumentsManager getObject() throws Exception {
        if(defaultArgumentManager != null){
            return defaultArgumentManager;
        }
        
        if(StringUtils.isNotEmpty(filename)){
            defaultArgumentManager = ArgumentsManagerFactory.createXmlArgumentsManager(filename, false);
        } else {
            if(!openClasspath){
                // 默认都使用绝对文件路径,因为tomcat等容器会检测到文件发生变化时重启服务,所以放在容器之外就可以了。
                String absoluteFilename = System.getProperty("java.io.tmpdir") + DEFAULT_CONFIG_FILENAME + suffix + ".xml";
                logger.info("------------- ArgumentsManager配置文件: " + absoluteFilename);
                doCheckExist(absoluteFilename);
                defaultArgumentManager = ArgumentsManagerFactory.createXmlArgumentsManager(absoluteFilename, false);
            } else {
                String classpathFile = DEFAULT_CONFIG_FILENAME + ".xml";
                logger.info("------------- ArgumentsManager配置文件在classpath中: " + classpathFile);
                defaultArgumentManager = ArgumentsManagerFactory.createXmlArgumentsManager(classpathFile, true);
            }
        }
        return defaultArgumentManager;
    }
    
    /**
     * 判断variable.xml配置文件,在临时文件夹中是否存在。</br>
     * 如果已存在检查更新,如果原始文件更新过就覆盖,确保临时文件最新。</br>
     * 如果不存在就拷贝到临时文件夹。
     * @param filepath
     */
    private void doCheckExist(String filepath){
        File file = new File(filepath);
        org.springframework.core.io.ClassPathResource defaultVariableSource = new ClassPathResource(DEFAULT_CONFIG_FILENAME + ".xml");
        if(!file.exists()){
            // 不存在需要把默认variable.xml文件拷贝到目的路径中。
            try {
                file.createNewFile();
                FileCopyUtils.copy(defaultVariableSource.getFile(), file);
                logger.debug("创建variable配置文件成功: " + filepath);
            } catch (IOException e) {
                logger.error("创建可变参数配置文件出现错误", e);
                throw new NestedRuntimeException(filepath);
            }
        } else {
            // 如果存在文件,比较时间戳,看是否存在变化
            long destFileModified = file.lastModified();
            long srcFileModified = 0;
            try {
                srcFileModified = defaultVariableSource.getFile().lastModified();
                logger.debug("variable文件原始时间: " + srcFileModified + ", 目的文件修改时间: " + destFileModified);
                if(srcFileModified > destFileModified){
                    logger.debug("原始配置文件变化,重新覆盖目的文件");
                    FileCopyUtils.copy(defaultVariableSource.getFile(), file);
                }
            } catch (IOException e) {
                throw new NestedRuntimeException(e.getMessage());
            }
        }
    }
 
    @Override
    public Class<?> getObjectType() {
        return ArgumentsManager.class;
    }
 
    @Override
    public boolean isSingleton() {
        return true;
    }
 
    /**
     * 对于使用xml文件作为存储配置信息时,可以设置classpath下面的文件名,</br>
     * 应用配置参数会被持久到此文件中。
     * @param filename
     */
    public void setFilename(String filename){
        this.filename = filename;
    }
}