同样用io流读取备份文件,根据登录ip查询异常数据
代码如下:
ObjectInputStream ois=new ObjectInputStream(new FileInputStream(filepath));
Map map=(Map) ois.readObject();
for(String key:map.keySet()){
//根据参数中的IP值,获取对应的对象
if (key.equals(arg0)) {
return map.get(key);
}
}
ois.close();//关流
# 日志模块:用日志记录项目的流程,该模块我们需要掌握的是采用log4j技术写一个自定义日志输出器,也就是写一个自定义的log4j的配置文件 #
log4j配置文件编程步骤:
1)配置日志记录器 Logger:分为五个级别:DEBUG、INFO、WARN、ERROR和FATAL。
Log4j有一个规则:只输出级别不低于设定级别的日志信息,假设Loggers级别设定为INFO,则INFO、WARN、ERROR和FATAL级别的日志信息都会输出,而级别比INFO低的DEBUG则不会输出。
配置语法:log4j.rootLogger = 日志级别,appenderName,appenderName (配置根记录器)
log4j.logger.自定义记录器名= 日志级别,appenderName ,appenderName (配置自定义记录器)
2)配置日志信息输出的地方 Appender:允许把日志输出到不同的地方,如控制台(Console)、文件(Files),可以根据天数或者文件大小产生新的文件,可以以流的形式发送到其它地方等等。
配置语法:log4j.appender.appenderName = className
className=org.apache.log4j.ConsoleAppender(控制台)
className=org.apache.log4j.FileAppender(文件)
className=org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
className=org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
className=org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
若是FileAppender选项有四个参数需要注意:
Threshold=日志级别:指定日志信息的最低输出级别,默认为DEBUG。
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。
File=文件路径:指定消息输出到某个文件中。
log4j.appender.file1 = org.apache.log4j.FileAppender
log4j.appender.file1.File = 文件路径
log4j.appender.file1.Append = true
3)配置日志信息的布局 Layout:提供四种日志输出样式,如根据HTML样式、自由指定样式、包含日志级别与信息的样式和包含日志时间、线程、类别等信息的样式。
log4j.appender.appenderName.layout =className
className=org.apache.log4j.HTMLLayout(以HTML表格形式布局)
className=org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
className=org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
className=org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等信息)
若是自由布局模式,应添加一个参数:写入具体的自定义的布局样式
log4j.appender.appender2.layout.ConversionPattern=利用%x的特定含义进行自定义。
-: 信息输出时左对齐;
%p: 输出日志信息优先级,即DEBUG,INFO,WARN,ERROR,FATAL,
%d: 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
%r: 输出自应用启动到输出该log信息耗费的毫秒数
%c: 输出日志信息所属的类目,通常就是所在类的全名
%t: 输出产生该日志事件的线程名
%l: 输出日志事件的发生位置,相当于%C.%M(%F:%L)的组合,包括类目名、发生的线程,以及在代码中的行数。
%x: 输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%%: 输出一个"%"字符
%F: 输出日志消息产生时所在的文件名称
%L: 输出代码中的行号
%m: 输出代码中指定的消息,产生的日志具体信息
%n: 输出一个回车换行符,Windows平台为"\r\n",Unix平台为"\n"输出日志信息换行
## 配置根记录器代码 ##
log4j.rootLogger = debug,console1,file1
log4j.appender.console1 = org.apache.log4j.ConsoleAppender
log4j.appender.console1.layout = org.apache.log4j.SimpleLayout
log4j.appender.file1 = org.apache.log4j.FileAppender
log4j.appender.file1.File = log.txt
log4j.appender.file1.Append = true
log4j.appender.file1.layout = org.apache.log4j.PatternLayout
log4j.appender.file1.layout.ConversionPattern=[woss_gather] -%d %p -------%m%n
## 配置自定义记录器代码 ##
log4j.logger.mylogger= debug,console,file
log4j.appender.console = org.apache.log4j.ConsoleAppender
log4j.appender.console.layout = org.apache.log4j.SimpleLayout
log4j.appender.appender2 = org.apache.log4j.FileAppender
log4j.appender.file.File = mylogger.txt
log4j.appender.file1.Append = true
log4j.appender.file.layout = org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[woss_gather]-%d %-5p -[%m]%n
## log4j日志的使用##
注册log4j: PropertyConfigurator.configure("log4j配置文件路径");
配置不同的级别的日志:
Logger.getLogger("记录器名").日志级别(String string);
# 配置模块:将配置信息(不要写死在代码中的常量信息)写入xml文件用来做配置文件,采用dom4j技术,进行解析xml文件并将配置信息的值传入每个模块中进行初始化 #
采用dom4j的解析步骤:
1)导入dom4j的jar包
2)创建解析器
SAXReader reader=new SAXReader();
3)获取document对象:使用read()方法读入解析文件
Document doc=reader.read("解析文件的路径");
4)获取根元素:使用getRootElement()方法
Element root = doc.getRootElement();
5)获取所有一级子元素:使用elements()方法,返回元素集合对象
List element1 = root.elements();//记得加泛型哦
6)遍历一级子元素的集合:使用增强for循环
for (Element e1 : element1) {
String name=e1.getName();//得到一级子元素的标签名
7)获取所有一级子元素的属性:使用attributes()方法,返回属性集合对象
List attribute = e1.attributes();//记得加泛型哦
//遍历所有一级子元素的属性的集合:使用增强for循环
for (Attribute attribute : attribute) {
String attName=attribute.getName();//得到属性名
String attValue=attribute.getValue();//得到属性值
}
8)获取所有二级子元素:使用elements()方法,返回元素集合对象
List element2 = element.elements();
for (Element e2 : element2) {
String name2=e2.getName();
String value2 = e2.getText();
}
}
## 配置模块编程步骤: ##
第一步:解析xml文件:采用dom4j技术
第二步:将解析好的配置信息以键值对的方式保存在properties对象中;
private static Properties properties=new Properties();//存放的是一级子元素的标签名和属性值,为了通过反射拿到该类的实例
properties.setProperty(name, attValue);
private static Properties properties2=new Properties();//存放的是二级子元素的标签名和文本内容,为了对每个实例需要的常量信息传值(即初始化)
properties2.setProperty(name2, value2);
private static Properties properties3=new Properties();//存放的是一级子元素的标签名和二级子元素的所有内容
注意:properties3起的是唯一标识作用(通过一级子元素的名字找到它相应的二级子元素的值),但是假设properties2这个存放二级子元素的集合中出现了相同的子元素,值却不相同,这时后一个值会覆盖掉前一个值的内容,这也是一个需要改进的地方哦。
第三步:通过反射得到每个模块的实例,并且调用它们的init()方法进行动态传值。
以备份模块为例:
public BackUP getBackup() throws Exception {
String classname=properties.getProperty("backup");//得到全限定名:包名+类名
BackUP backup=(BackUP) Class.forName(classname).newInstance();//通过反射拿到备份模块的实例
backup.init((Properties) properties3.get("backup"));//调用备份模块的init()方法进行传值
return backup;
}
这时backup的init()方法应该拿到配置信息,使用getProperty()方法,并且传入二级子元素的标签名
public void init(Properties arg0) {
backfile=arg0.getProperty("back-temp");
}
其他模块代码同理可得。
注意:配置模块已完成,那么进行测试是不能在new一个类的实例,而是首先得到配置模块的实例,调用它相对应的方法进行对其他类的实例化。
new ConfigurationImp1().getBackup();//得到了备份模块的一个实例
## 优化代码: 既然每个模块都需要通过反射获取实例并且调用init()方法进行初始化,那么我们可以将这几行代码进行封装##
private WossModule getModule(String name) throws Exception{
String className=properties1.getProperty(name);
WossModule wm=(WossModule) Class.forName(className).newInstance();
wm.init((Properties)properties2.get(name));
return wm;
}
WossModule是所有类的父类;
以备份模块举例进行调用该方法;
public BackUP getBackup() throws Exception {
return (BackUP)getModule("backup");
}
其他模块调用该方法同理可得。