《模式——工程化实现及扩展》(设计模式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
分享到:
相关推荐
在Java中,没有直接对应的类可以完全等同于ADO.NET的DataTable,但我们可以使用Java的数据结构和API来实现类似的功能。下面将详细介绍如何在Java中构建一个类似的数据表对象。 1. **Java集合框架**: Java提供了...
在Java 7及以上版本中引入,它提供了一种有效的方式来进行实时监控,而无需频繁轮询文件系统,这极大地提高了效率,特别是在配置动态修改时,可以避免不必要的服务器重启。 `WatchService`的工作原理是通过注册对...
ASP.NET调用Java接口主要涉及的是跨平台的通信技术,其中关键步骤是通过WebService作为中间桥梁来实现。这里,我们详细解析整个过程: 1. **部署Java WebService**: - 使用Tomcat这样的应用服务器部署Java ...
官方JDK 1.8 英文版编译,Java SE 8 API (JDK 1.8 API)
java.net 为实现网络应用程序提供类。 java.nio 定义作为数据容器的缓冲区,并提供其他 NIO 包的概述。 java.nio.channels 定义了各种通道,这些通道表示到能够执行 I/O 操作的实体(如文件和套接字)的连接;定义...
总的来说,调用.NET接口在Java中可以通过标准Web服务方式或RESTful接口实现,选择哪种方法取决于.NET接口的具体设计和项目需求。熟悉这些技术对于提高跨平台开发的效率至关重要。记得在实际应用中,一定要确保兼容性...
《基于JDK7的FileMonitor:精简版文件监控服务详解》 在Java开发中,对文件系统的实时监控是一项常用且重要的任务。JDK7引入了`WatchService`接口,为开发者提供了一种监听文件系统变化的能力。然而,`WatchService...
4. **事件处理**:VB.NET的事件处理模型基于委托和事件,而在Java中通常通过接口和监听器实现。 5. **异常处理**:VB.NET的Try...Catch...Finally需要转换为Java的try...catch...finally。 6. **LINQ转换**:如果VB...
C# .net 使用Java公钥实现RSA加密
`Base64Helper.java`可能包含与`StringUtils.java`类似的功能,专注于Base64编码和解码。在.NET和Java中进行加密操作时,通常会先将密钥和加密后的数据进行Base64编码,以便于文本形式的传输。 在.NET和Java之间...
9. **第三方库**:虽然Java自带的WatchService API已经足够使用,但有些第三方库如Apache Commons IO、JNotify、FileWatcher等提供了更高级的功能和更好的跨平台兼容性,可以根据项目需求选择使用。 10. **应用场景...
在Java中,Socket类位于`java.net`包下,而在.NET中,Socket类位于`System.Net.Sockets`命名空间内。 2. **TCP连接**:Java和.NET的Socket通信通常基于TCP(传输控制协议),这是一种面向连接的、可靠的传输协议,...
在实际应用中,这种转换对于跨平台的移动应用或者Web服务特别有用,比如Java服务器端和.NET客户端之间的通信。通过这个转换工具,你可以确保数据在不同环境下的安全性,同时避免了因密钥格式不匹配导致的通信障碍。 ...
2. 使用WSDL2Java工具:通过.NET ASMX Web服务的WSDL地址,运行CXF的WSDL2Java命令生成Java客户端代码。这将生成一个服务接口和服务实现类,其中包含了调用Web服务的方法。 3. 编写Java代码:实例化生成的服务实现...
本篇文章将探讨如何在Java环境中利用Flash上传插件实现对.NET WebAPI的动态调用,以便进行批量文件上传。 首先,Java Flash上传插件是解决跨语言、跨平台文件上传的一种解决方案。Flash作为一个曾经流行的客户端...
2. **网络编程**:`java.net`包提供了网络通信的支持,包括Socket和ServerSocket类,用于实现客户端和服务器端的连接。 3. **多线程**:`java.concurrent`包提供了高级并发工具,如ExecutorService、Semaphore、...
《ASP.NET Web API设计》依托ASP.NET Web API阐述API设计与开发的通用技术,是一本全面介绍如何构建真实可演化API的实践指南。本书共分三部分。第一部分介绍Web/HTTP和API开发的基础知识,介绍ASP.NET Web API,为...
在Java编程语言中,实现对本地文件的简单监控是一项实用的技术,这可以帮助开发者在文件系统中检测到诸如移动、复制和粘贴等操作。本文将深入探讨如何利用Java的文件I/O API和事件监听机制来达成这个目标。 首先,...
本文将详细介绍如何通过Web服务实现Java与.NET之间的相互调用。 Web服务作为一种标准化的通信机制,使得不同语言和平台的应用程序能够相互通信。其核心组成部分包括XML、XSD、SOAP和WSDL。 1. XML(可扩展标记语言...
在.NET环境中,有时候我们需要将Java项目中的功能引入到C#项目中使用,这时就需要将Java的jar包转换为.NET能够识别的dll文件。这个过程主要涉及到Java与.NET之间的互操作性,具体步骤如下: 首先,我们需要了解Java...