我需要在http servlet中运行时热加载或重新加载业务配置/对象。
通过在servletConfig
期间读取文件来生成 init()
对象。我需要在更改/更新文件时重新加载此对象。
public void init() {
Config config = initializeConfigFile();
}
任务1 将是一个线程定期监视文件内容,如果更改,则从更改的文件重新创建配置对象..我认为这可以通过在文件内容上使用md5之类的哈希来实现..检查新哈希是否改变..
public void run() {
// Read file
// Generate hash of file contents
// Compare with previous hash
// If different set a flag to hold threads
// configFileChanged = true;
}
任务2 保留请求线程,直到创建新的配置对象。由于这在运行时发生,可能有请求线程已经访问旧的配置对象,我不能只是交换配置对象,因为这可能会产生意外的行为。所以我需要等到已经访问旧配置的所有线程完成。
所以我需要有关任务2的建议..我没有探索过很多基于java高级线程和基于队列的API' s 现在考虑一些持有请求线程的队列。
public void doGet(HttpServletRequest req, HttpServletResponse resp) {
if (configFileChanged) {
synchronized (ActionServlet.class) {
while (configFileChanged) {
if (queue.isEmpty) {
config = initializeConfigFile();
configFileChanged = false;
} else {
sleep(2000);
}
}
}
}
queue.insert(Thread.currentThread());
// perform task using config object
queue.remove();
}
同时建议任务1的即兴创作,如果有的话......
谢谢..
答案 0 :(得分:0)
这两项任务都很糟糕:
对于任务1:
检查文件常规不是一个逻辑过程,而您可以有一个观察者/监视器,换句话说,一旦文件被更改,检查新配置(文件监视器使用java.nio.file
)
对于任务2:
如果且未配置/覆盖容器以为每个请求创建新实例。 - >默认/ std行为是拥有Servlet的一个对象,并通过一个线程为每个请求调用实例,因此synchronized void reload()
方法会有所帮助。
在reload()
方法运行期间,因为它锁定了Servlet对象,所有新请求将一直保持到reload()
完成它的工作。
public void doGet(HttpServletRequest req, HttpServletResponse resp) {
//servlet business
}
//the reload is called by the file monitor
//The synchronized method will hold all new requests
synchronized void reload(){/*applying new configs*/}
除了让文件(外部)观察者看起来不安全和合乎逻辑之外,我建议有一个外部应用程序监视文件并通过调用servlet(可能是/friends/reload_config
)通知web上下文,其中有一个servlet映射到/friends/reload_config
,将调用reload()
方法。
您可以在/friends/reload_config
servlet中检查请求ip,以确保请求是由本地应用程序生成的(而不是来自网络)