文件监听之WatchService浅析

简介

WatchService是jdk7之后nio包中的新功能。可以看作是文件监控器,通过操作系统原生文件系统来运行。 针对单点多appkey的情况,可以注册开启多个监控器。 每个监控器可看作是后台线程,通过监控文件发出的信号来实现监控。

应用场景

1、感知系统配置文件的变化,修改配置文件内容即时生效,无需重启服务器 2、监控磁盘中的文件变化

用watchservice修改配置文件方式仅适合于比较小的项目,例如只有一两台服务器,而且配置文件是可以直接修改的。例如 Spring mvc 以 war 包的形式部署,可以直接修改resources 中的配置文件。如果是 Spring boot 项目,还想用这种方式的话,就要引用一个外部可以编辑的文件,比如一个固定的目录,因为 spring boot 大多数以 jar 包部署,打到包里的配置文件没办法直接修改。如果是比较大的项目,最好还是用配置中心,例如携程的 Apollo、Consul 等。

动态修改配置即时生效实现方法

1、WatchService 实例化

watchService = FileSystems.getDefault().newWatchService();

2、使用 Path 来指定要监控的目录

String filePath = new ClassPathResource(configName).getFile().getParent();
Path path = Paths.get(filePath);

3、将 Path 注册到 WatchService

使用Path.register() 方法注册要监控指定目录的那些事件(创建、修改、删除)

StandardWatchEventKinds.ENTRYCREATE //创建 StandardWatchEventKinds.ENTRYMODIFY //修改 StandardWatchEventKinds.ENTRY_DELETE //删除

path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_CREATE);

4、创建监听配置文件守护线程

使用WatchService监听配置文件所在目录内容的变化,包括修改、删除事件。通过后台线程实现阻塞等待内容变化事件,一旦发现有变更,则重新装载配置文件

核心代码块:

private void pollingMonitor() {
        while (true) {
            try {
                // 尝试获取监控池的变化,如果没有则一直等待
                WatchKey watchKey = watchService.take();
                for (WatchEvent<?> event : watchKey.pollEvents()) {
                    if (PropsUtil.CONFIG_NAME.equals(event.context().toString())) {
                        logger.info("监控到{}发生{}操作,将重新加载", event.context(), event.kind());
                        PropsUtil.getInstance().loadProperties(event.context().toString());
                        break;
                    }
                }
                // 完成一次监控就需要重置监控器一次
                watchKey.reset();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

5、注册关闭钩子,当JVM停止时关闭WatchService。

public class WatcherHookThead implements Runnable {
    private static Logger logger = LoggerFactory.getLogger(WatcherHookThead.class);

    private WatchService watchService;

    public WatcherHookThead(WatchService watchService) {
        super();
        this.watchService = watchService;
    }

    @Override
    public void run() {

        try {
            watchService.close();
            logger.info("watcher close success...");
        } catch (IOException e) {
            logger.error("watcher close fail:" + e.getMessage(), e);
        }
    }

}
public void shutDownWatcher() {
        Thread shutDownThread = new Thread(new WatcherHookThead(watchService));
        shutDownThread.setName("shutDownThread");
        Runtime.getRuntime().addShutdownHook(shutDownThread);
    }

验证动态修改配置是否生效测试

1、测试代码

public void testValueIfChange() {
        while (true) {
            String value = PropsUtil.getInstance().getValue("username");
            try {
                System.out.println(StringUtil.format("value--->{}", value));
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

application.properties

初始内容 username=helloworld

不停服务,将username修改为test,观察控制台打印value的值是否动态生效

value--->helloworld
2018-06-29 14:57:57.132  INFO 11988 --- [  watcherThread] com.demo.watchserver.util.WatcherThread  : 监控到application.properties发生ENTRY_MODIFY操作,将重新加载
value--->test

通过控制台可以说明,value已经动态修改,说明配置文件即时被加载

demo地址

https://github.com/lyb-geek/first-watchserver

原文发布于微信公众号 - Linyb极客之路(gh_c420b2cf6b47)

原文发表时间:2018-07-01

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Youngxj

[教程]黑客级别的批量处理文件

1993
来自专栏木木玲

Netty 源码解析 ——— Netty 优雅关闭流程

3703
来自专栏炉边夜话

JNI使用技巧点滴(二)

作者:normalnotebook 背景<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com...

1562
来自专栏用户2442861的专栏

web.xml文件的作用及基本配置

Java的web工程中的web.xml文件有什么作用呢?它是每个web工程都必须的吗?

1442
来自专栏Linux驱动

36.Linux驱动调试-根据oops定位错误代码行

1.当驱动有误时,比如,访问的内存地址是非法的,便会打印一大串的oops出来 1.1以LED驱动为例 将open()函数里的ioremap()屏蔽掉,直接使用物...

2498
来自专栏IMWeb前端团队

上手 yeoman generator

最近折腾脚手架相关的一些事情。说到脚手架,不得不谈的就是yeoman了。 是什么 yeoman是一个脚手架生成工具。 yeoman generator则是yeo...

2275
来自专栏北京马哥教育

Python imports指南

来源:Python程序员 ID:pythonbuluo 声明:如果你每天写Python,你会发现这篇文章中没有新东西。 这是专为那些像运维人员等偶尔使用Pyt...

2545
来自专栏iKcamp

iKcamp|基于Koa2搭建Node.js实战(含视频)☞ 错误处理

沪江CCtalk视频地址:https://www.cctalk.com/v/15114923887518 处理错误请求 爱能遮掩一切过错。 当我们在访问一个站...

4096
来自专栏钟绍威的专栏

linux常用命令之查阅文件用法选项功能键用法选项DEMO用法选项选项注意选项注意选项注意用法选项

CAT cat – concatenate print files 连续的输出文件内容 用法 cat [-nbA] file 选项 -n line number...

1945
来自专栏凉城

[教程]黑客级别的批量处理文件

2195

扫码关注云+社区