《模式——工程化实现及扩展》(设计模式Java 版)
Java SE 7 Tutorial中增加了一个监控目录变更情况的示例,用于介绍其新发布的WatchService API。
但对于用惯了.NET FileWatcher的用户而言,如果用于项目我认为它有两个欠缺:
1、应该提供一个独立线程后台运行机制,让这个监控过程自己在后台转,不影响前端处理
2、 Java不像.NET有内置的源生事件机制,不过可以借助它内置的Observer/Observable对象用观察者模式实现准事件
下面是把Java SE Tutorial示例中无关内容删除,补充上述两个扩展后的实现,因为这个API比较新,也希望能和大家多多探讨:
1、参考.NET定义事件参数对象
package
marvellousworks.practicalpattern.concept.unittest;
import
java.nio.file.WatchEvent.Kind;
/**
* 文件系统事件类型
*
@author
wangxiang
*
*/
public
final
class
FileSystemEventArgs {
private
final
String fileName;
private
final
Kind
<?>
kind;
public
FileSystemEventArgs(String fileName, Kind
<?>
kind){
this
.fileName
=
fileName;
this
.kind
=
kind;
}
/**
* 文件的路径
*/
public
String getFileName(){
return
fileName;}
/**
* 操作类型:变更、创建、删除
*/
@SuppressWarnings(
"
rawtypes
"
)
public
Kind getKind(){
return
kind;}
}
2、定义DirectoryWatcher,用于监控某个文件夹,至于如何扩展FileWatcher则可以在这个基础上通过限定文件名称和操作类型的方式扩展
package
marvellousworks.practicalpattern.concept.unittest;
import
java.io.IOException;
import
java.nio.file.FileSystems;
import
java.nio.file.Path;
import
java.nio.file.Paths;
import
java.nio.file.WatchEvent;
import
java.nio.file.WatchEvent.Kind;
import
java.nio.file.WatchKey;
import
java.nio.file.WatchService;
import
java.util.Observable;
import
java.util.concurrent.Callable;
import
java.util.concurrent.Executor;
import
java.util.concurrent.Executors;
import
java.util.concurrent.FutureTask;
import
static
java.nio.file.StandardWatchEventKinds.
*
;
/**
* 监控一个目录内文件的更新、创建和删除事件(不包括子目录)
*
* 对于http://download.oracle.com/javase/tutorial/essential/io/notification.html进行了改造
* 使其更接近.NET的DirectoryWatcher使用习惯
*
* 由于java没有类似.NET源生的事件机制
* 因此实现上采用了Java SE自带的Observer/Observable对象对外抛出“假”事件
*
* 适于Java SE 7
*
*
@author
wangxiang
*
*/
public
class
DirectoryWatcher
extends
Observable
{
private
WatchService watcher;
private
Path path;
private
WatchKey key;
private
Executor executor
=
Executors.newSingleThreadExecutor
();
FutureTask
<
Integer
>
task
=
new
FutureTask
<
Integer
>
(
new
Callable
<
Integer
>
(){
public
Integer call()
throws
InterruptedException{
processEvents();
return
Integer.valueOf(
0
);}});
@SuppressWarnings(
"
unchecked
"
)
static
<
T
>
WatchEvent
<
T
>
cast(WatchEvent
<?>
event) {
return
(WatchEvent
<
T
>
) event;
}
public
DirectoryWatcher(String dir)
throws
IOException {
watcher
=
FileSystems.getDefault().newWatchService();
path
=
Paths.get(dir);
//
监控目录内文件的更新、创建和删除事件
key
=
path.register(watcher, ENTRY_MODIFY, ENTRY_CREATE, ENTRY_DELETE);
}
/**
* 启动监控过程
*/
public
void
execute(){
//
通过线程池启动一个额外的线程加载Watching过程
executor.execute(task);
}
/**
* 关闭后的对象无法重新启动
*
@throws
IOException
*/
public
void
shutdown()
throws
IOException {
watcher.close();
executor
=
null
;
}
/**
* 监控文件系统事件
*/
void
processEvents() {
while
(
true
) {
//
等待直到获得事件信号
WatchKey signal;
try
{
signal
=
watcher.take();
}
catch
(InterruptedException x) {
return
;
}
for
(WatchEvent
<?>
event : signal.pollEvents()) {
Kind
<?>
kind
=
event.kind();
//
TBD - provide example of how OVERFLOW event is handled
if
(kind
==
OVERFLOW) {
continue
;
}
//
Context for directory entry event is the file name of entry
WatchEvent
<
Path
>
ev
=
cast(event);
Path name
=
ev.context();
notifiy(name.getFileName().toString(), kind);
}
//
为监控下一个通知做准备
key.reset();
}
}
/**
* 通知外部各个Observer目录有新的事件更新
*/
void
notifiy(String fileName, Kind
<?>
kind){
//
标注目录已经被做了更改
setChanged();
//
主动通知各个观察者目标对象状态的变更
//
这里采用的是观察者模式的“推”方式
notifyObservers(
new
FileSystemEventArgs(fileName, kind));
}
}
3、单元测试
package
marvellousworks.practicalpattern.concept.unittest;
import
static
org.junit.Assert.
*
;
import
java.io.File;
import
java.io.IOException;
import
java.util.ArrayList;
import
java.util.List;
import
java.util.Observable;
import
java.util.Observer;
import
org.junit.Test;
import
static
java.nio.file.StandardWatchEventKinds.
*
;
public
class
DirectoryWatcherFixture {
private
static
final
String DIR_PATH
=
System.getProperty(
"
user.dir
"
);
private
static
final
File DIR
=
new
File(DIR_PATH);
private
static
final
String SUFFIX
=
"
.txt
"
;
private
static
final
String PREFIX
=
"
test
"
;
private
static
final
int
ADD_TIMES
=
3
;
/**
* 观察者
*
@author
wangxiang
*
*/
public
class
Logger
implements
Observer{
@Override
public
void
update(Observable observable, Object eventArgs) {
FileSystemEventArgs args
=
(FileSystemEventArgs) eventArgs;
System.out.printf(
"
%s has been %s\n
"
, args.getFileName(), args.getKind());
assertTrue(args.getFileName().startsWith(PREFIX));
assertEquals(ENTRY_CREATE, args.getKind());
}
}
@Test
public
void
testWatchFile()
throws
IOException, InterruptedException{
DirectoryWatcher watcher
=
new
DirectoryWatcher(DIR_PATH);
Logger l1
=
new
Logger();
watcher.addObserver(l1);
watcher.execute();
//
创建一系列临时文件
List
<
String
>
files
=
new
ArrayList
<>
();
for
(
int
i
=
0
; i
<
ADD_TIMES; i
++
){
files.add(File.createTempFile(PREFIX, SUFFIX, DIR).toString());
}
//
延迟等待后台任务的执行
Thread.sleep(
4000
);
watcher.shutdown();
System.out.println(
"
finished
"
);
}
}
Console窗口显示的测试内容
test5769907807190550725
.
txt has been ENTRY_CREATE
test4657672246246330348
.
txt has been ENTRY_CREATE
test1823102943601166149
.
txt has been ENTRY_CREATE
finished
分享到:
相关推荐
asp.net通过WebService调用Java接口全过程。 asp.net---->WebService(SOAP)------>Java接口---->Java接口实现类------>RMI(Java远程方法调用)----->RMI服务器端------->RMI返回结果给asp.net
Java 调用.NET web服务
C# .net 使用Java公钥实现RSA加密
NULL 博文链接:https://wengmj.iteye.com/blog/376008
java.net 为实现网络应用程序提供类。 java.nio 定义作为数据容器的缓冲区,并提供其他 NIO 包的概述。 java.nio.channels 定义了各种通道,这些通道表示到能够执行 I/O 操作的实体(如文件和套接字)的连接;定义...
.NET调用JAVA web 服务
JAVA实现的调用梦网云通讯平台API接口实现短信发送Demo。详情请见 https://blog.csdn.net/LANSHANZHUYAO/article/details/88979026
《ASP.NET Web API设计》依托ASP.NET Web API阐述API设计与开发的通用技术,是一本全面介绍如何构建真实可演化API的实践指南。本书共分三部分。第一部分介绍Web/HTTP和API开发的基础知识,介绍ASP.NET Web API,为...
官方JDK 1.8 英文版编译,Java SE 8 API (JDK 1.8 API)
java调用.NET webAPI httpclient-4.2.5.jar httpclient-cache-4.2.5.jar httpcore-4.2.4.jar httpmime-4.2.5.jar fluent-hc-4.2.5.jar commons-codec-1.6.jar
也可以自己去官网下载自己需要的API 下载的地址 http://www.oracle.com/technetwork/java/javase/documentation/jdk8-doc-downloads-2133158.html 选择 Accept License Agreement 就可以下载了
Java 8 的简单 WatchService 包装器 基本的javadoc class io .ruck.filewatcher.Watcher static void register(Path base, WatchListener<Path> listener, WatchEvent.Kind<Path>... events) static void ...
最近用Java开发了一些项目,真心感觉Java的文件流真的没有C#.NET好用(说实话,我觉得Java就是没有C#好用)。所以,我用Java模仿了一下.NET里面的File类。
十几个网页模板,Java和.net都能运用
java jre7里的nio实现稳健监控,比jre6新添的watchService服务
java.net,觉得对初学者比较有用,就上传了
VB.net转换成JAVA的工具。包含说明和源代码。
Java或jdbc操作日期时间存在诸多不便,代码通过对Date、Calendar、SimpleDateFormat的封装,实现类似.NET DateTime的功能
Java™ Platform, Standard Edition 7 API Specification
JAVA 和.NET在安全功能的比较.doc JAVA 和.NET在安全功能的比较.doc