6
请求日志
请求日志就是将请求的历史记录保存下来,通常以
日志文件
(Log File)
的形式永久存储在计算机中。很多系统都提供了日志文件,例如
Windows
日志文件、
Oracle
日志文件等,日志文件可以记录用户对系统的一些操作(例如对数据的更改)。请求日志文件可以实现很多功能,常用功能如下:
(1)
“天有不测风云”,一旦系统发生故障,日志文件可以为系统提供一种恢复机制,在请求日志文件中可以记录用户对系统的每一步操作,从而让系统能够顺利恢复到某一个特定的状态;
(2)
请求日志也可以用于实现批处理,在一个请求日志文件中可以存储一系列命令对象,例如一个命令队列;
(3)
可以将命令队列中的所有命令对象都存储在一个日志文件中,每执行一个命令则从日志文件中删除一个对应的命令对象,防止因为断电或者系统重启等原因造成请求丢失,而且可以避免重新发送全部请求时造成某些命令的重复执行,只需读取请求日志文件,再继续执行文件中剩余的命令即可。
在实现请求日志时,我们可以
将命令对象通过序列化写到日志文件中
,此时命令类必须实现
java.io.Serializable
接口。下面我们通过一个简单实例来说明日志文件的用途以及如何实现请求日志:
|
本实例完整代码如下所示:
-
import
java.io.*; -
import
java.util.*; -
//抽象命令类,由于需要将命令对象写入文件,因此它实现了Serializable接口
-
abstract
class
Command
implements
Serializable { -
protected
String name;
//命令名称
-
protected
String args;
//命令参数
-
protected
ConfigOperator configOperator;
//维持对接收者对象的引用
-
public
Command(String name) { -
this
.name = name; - }
-
public
String getName() { -
return
this
.name; - }
-
public
void
setName(String name) { -
this
.name = name; - }
-
public
void
setConfigOperator(ConfigOperator configOperator) { -
this
.configOperator = configOperator; - }
-
//声明两个抽象的执行方法execute()
-
public
abstract
void
execute(String args); -
public
abstract
void
execute(); - }
-
//增加命令类:具体命令
-
class
InsertCommand
extends
Command { -
public
InsertCommand(String name) { -
super
(name); - }
-
public
void
execute(String args) { -
this
.args = args; - configOperator.insert(args);
- }
-
public
void
execute() { -
configOperator.insert(
this
.args); - }
- }
-
//修改命令类:具体命令
-
class
ModifyCommand
extends
Command { -
public
ModifyCommand(String name) { -
super
(name); - }
-
public
void
execute(String args) { -
this
.args = args; - configOperator.modify(args);
- }
-
public
void
execute() { -
configOperator.modify(
this
.args); - }
- }
-
//省略了删除命令类DeleteCommand
-
//配置文件操作类:请求接收者。由于ConfigOperator类的对象是Command的成员对象,它也将随Command对象一起写入文件,因此ConfigOperator也需要实现Serializable接口
-
class
ConfigOperator
implements
Serializable { -
public
void
insert(String args) { -
System.out.println(
“增加新节点:”
+ args); - }
-
public
void
modify(String args) { -
System.out.println(
“修改节点:”
+ args); - }
-
public
void
delete(String args) { -
System.out.println(
“删除节点:”
+ args); - }
- }
-
//配置文件设置窗口类:请求发送者
-
class
ConfigSettingWindow { -
//定义一个集合来存储每一次操作时的命令对象
-
private
ArrayList<Command> commands =
new
ArrayList<Command>(); -
private
Command command; -
//注入具体命令对象
-
public
void
setCommand(Command command) { -
this
.command = command; - }
-
//执行配置文件修改命令,同时将命令对象添加到命令集合中
-
public
void
call(String args) { - command.execute(args);
- commands.add(command);
- }
-
//记录请求日志,生成日志文件,将命令集合写入日志文件
-
public
void
save() { - FileUtil.writeCommands(commands);
- }
-
//从日志文件中提取命令集合,并循环调用每一个命令对象的execute()方法来实现配置文件的重新设置
-
public
void
recover() { - ArrayList list;
- list = FileUtil.readCommands();
-
for
(Object obj : list) { - ((Command)obj).execute();
- }
- }
- }
-
//工具类:文件操作类
-
class
FileUtil { -
//将命令集合写入日志文件
-
public
static
void
writeCommands(ArrayList commands) { -
try
{ -
FileOutputStream file =
new
FileOutputStream(
“config.log”
); -
//创建对象输出流用于将对象写入到文件中
-
ObjectOutputStream objout =
new
ObjectOutputStream(
new
BufferedOutputStream(file)); -
//将对象写入文件
- objout.writeObject(commands);
- objout.close();
- }
-
catch
(Exception e) { -
System.out.println(
“命令保存失败!”
); - e.printStackTrace();
- }
- }
-
//从日志文件中提取命令集合
-
public
static
ArrayList readCommands() { -
try
{ -
FileInputStream file =
new
FileInputStream(
“config.log”
); -
//创建对象输入流用于从文件中读取对象
-
ObjectInputStream objin =
new
ObjectInputStream(
new
BufferedInputStream(file)); -
//将文件中的对象读出并转换为ArrayList类型
- ArrayList commands = (ArrayList)objin.readObject();
- objin.close();
-
return
commands; - }
-
catch
(Exception e) { -
System.out.println(
“命令读取失败!”
); - e.printStackTrace();
-
return
null
; - }
- }
- }
编写如下客户端测试代码:
-
class
Client { -
public
static
void
main(String args[]) { -
ConfigSettingWindow csw =
new
ConfigSettingWindow();
//定义请求发送者
-
Command command;
//定义命令对象
-
ConfigOperator co =
new
ConfigOperator();
//定义请求接收者
-
//四次对配置文件的更改
-
command =
new
InsertCommand(
“增加”
); - command.setConfigOperator(co);
- csw.setCommand(command);
-
csw.call(
“网站首页”
); -
command =
new
InsertCommand(
“增加”
); - command.setConfigOperator(co);
- csw.setCommand(command);
-
csw.call(
“端口号”
); -
command =
new
ModifyCommand(
“修改”
); - command.setConfigOperator(co);
- csw.setCommand(command);
-
csw.call(
“网站首页”
); -
command =
new
ModifyCommand(
“修改”
); - command.setConfigOperator(co);
- csw.setCommand(command);
-
csw.call(
“端口号”
); -
System.out.println(
“—————————-”
); -
System.out.println(
“保存配置”
); - csw.save();
-
System.out.println(
“—————————-”
); -
System.out.println(
“恢复配置”
); -
System.out.println(
“—————————-”
); - csw.recover();
- }
- }
编译并运行程序,输出结果如下:
增加新节点:网站首页
增加新节点:端口号
修改节点:网站首页
修改节点:端口号
—————————-
保存配置
—————————-
恢复配置
—————————-
增加新节点:网站首页
增加新节点:端口号
修改节点:网站首页
修改节点:端口号