- 浏览: 252718 次
- 性别:
- 来自: 宁波
文章分类
最新评论
-
wangxiang243:
文件保存为utf8编码格式就可以了吧
java.util.Properties 乱码问题解决方案 -
uyiab:
真心感谢,之前搞了一套2.1.4的程序,一直发生这个问题,找了 ...
如何解决cocos2dx2.1.4回到前台后出现的黑屏现象 -
Tongqing-Qiu:
我用的Intellij IDEA集成的GIT工具,挺方便的。有 ...
git分支、合并的使用记录 -
nbtlxx:
...
三星s7572无法显示toast的问题解决 -
kouwoo:
这篇文章对我非常有用,谢谢
三星s7572无法显示toast的问题解决
项目需要将以下需求进行处理,通过log4j组建输出到log文件进行保存,方便今后运营维护中的分析和问题解决。
项目基本的基本流程包括:
1. 生成若干个独立线程
2. 启动线程进行工作
2.1 根据消息工程生产消息
2.2 将消息转成二进制方式放入输出队列
2.3 启动发送功能,将消息进行加密后发生到服务器端
2.4 等待并读取来自服务器端的消息
需要进行输出的内容主要包括:
1. 发送登陆时间
2. 接收完成登陆时间
3. 发送查询考题时间
4. 接收查询结果的时间
5. 单次登陆操作的花费时间
6. 单次查询考题操作的花费时间
输出到文件output.log
log4j.properties:
还有几个小问题:
1. log4j.properties默认是在代码的同一级目录(package)下,比如当前package是net.tuolian.test, 则配置文件放在这个package下就可以被成功加载
2. 根据自己的需要封装方法
比如:封装一个方法来打印业务名称、花费时间
logTime(name, starttime, endTime)
3. 另外log4j的配置文件读取的方法如代码所示:
Properties properties = new Properties();
InputStream is = getClass().getResourceAsStream(fileName);
try {
properties.load(is);
PropertyConfigurator.configure(properties);
logger = Logger.getLogger(Log4jUtil.class);
读取配置文件、设置配置文件,getLogger(类名)
4.将日志输出到数据库,需要对配置文件进行如下设置
输出到数据库
log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
log4j.appender.DATABASE.user=root
log4j.appender.DATABASE.password= root
log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
成功与否,笔者还没进行测试
其他方法,还包括输出地格式设定、输出的目标地址设定等等
项目基本的基本流程包括:
1. 生成若干个独立线程
2. 启动线程进行工作
2.1 根据消息工程生产消息
2.2 将消息转成二进制方式放入输出队列
2.3 启动发送功能,将消息进行加密后发生到服务器端
2.4 等待并读取来自服务器端的消息
需要进行输出的内容主要包括:
1. 发送登陆时间
2. 接收完成登陆时间
3. 发送查询考题时间
4. 接收查询结果的时间
5. 单次登陆操作的花费时间
6. 单次查询考题操作的花费时间
输出到文件output.log
log4j.properties:
log4j.rootLogger=DEBUG,stdout log4j.appender.stdout=org.apache.log4j.RollingFileAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %p %c{1}.%M(%L) | %m%n log4j.appender.stdout.MaxFileSize=30MB log4j.appender.stdout.MaxBackupIndex=1 log4j.appender.stdout.file=E:\\output.log
/** * */ package net.tuolian.test; /** * @author sean * * 1. 启动类 * 2. 循环产生100个独立线程 * 3. 启动线程执行任务 * */ public class MainTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub for(int i=0; i<500; i++){ UserThread user = new UserThread(i); new Thread(user).start(); } } }
/** * */ package net.tuolian.test; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import java.util.Date; import org.apache.log4j.Logger; /** * @author sean * 1. 建立连接 * 2. 填充数据:login, query * 3. 发生数据 * 4. 接收数据 * */ public class UserThread implements Runnable { Logger logger = null; Socket socket = null; private String ip = "192.168.1.2"; // private String ip = "tuolian.gicp.net"; // private String ip = "127.0.0.1"; private int port = 9999; DataInputStream dis; DataOutputStream dos; boolean isRunning = false; private byte[] outData; private int id; private int counter = 0; Log4jUtil log; private long startTime; private long endTime; public UserThread(int id) { outData = new byte[512]; this.id = id; System.out.println(id + " thread is created"); logger = Logger.getLogger(UserThread.class); log = new Log4jUtil(); } public void run() { // TODO Auto-generated method stub if (!connect()) { // System.out.println("没有连接"); logger.error("网络没有连接成功"); } while (isRunning) { // System.out.println(id + " thread is running"); if (!fillData()) { // System.out.println("没有添加数据"); logger.error("没有添加数据 "); } sendData(); recvData(); if (counter == 1) { recvData(); } try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * 建立网络连接 * * @return */ private boolean connect() { // TODO Auto-generated method stub boolean flag = false; try { socket = new Socket(ip, port); dis = new DataInputStream(socket.getInputStream()); dos = new DataOutputStream(socket.getOutputStream()); isRunning = true; flag = true; } catch (UnknownHostException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return flag; } /** * 添加测试数据 * 1. 登陆消息 * 2. 查少询数据库消息 * * * @return */ private boolean fillData() { // TODO Auto-generated method stub boolean flag = false; outData = null; counter++; // System.out.println("counter: " + counter); //记录操作的开始时间 startTime = System.currentTimeMillis(); if (counter == 1) { outData = MessageFactory.createMessage(MessageFactory.LOGIN); } else { outData = MessageFactory.createMessage(MessageFactory.GETCONTENT); } // System.out.println("outdata length: before decrypt " + outData.length); // 如果内容长度不为空,则设置返回值true if (outData.length > 0) { flag = true; } return flag; } /** * 发送数据到服务器端 数据从发生队列中读取 */ private void sendData() { if (outData.length == 0) { // System.out.println("发生数据位空,发送出错" + new Date()); log.debug("发生数据位空,发送出错" + new Date()); return; } startTime = System.currentTimeMillis(); try { // 1. tea加密数组 2. 长度数组 3. 发送长度 4. 发生加密后数据 5. flush // 第二個步骤(长度数组)可以不要 byte[] tempData = Tea.encryptByTea(outData); // System.out.println(" tempdata after decrypt: " + tempData.length); dos.write((byte) ((tempData.length & 0xFF))); // logger.info("temp data length: " // + ((byte) (tempData.length & 0xFF))); // System.out.println("temp data length: " // + ((byte) (tempData.length & 0xFF))); dos.write((byte) ((tempData.length >> 8 & 0xFF))); // logger.info("temp data length: " // + ((byte) (tempData.length >> 8 & 0xFF))); // System.out.println("temp data length: " // + ((byte) (tempData.length >> 8 & 0xFF))); dos.write(tempData); dos.flush(); // logger.info("outdata length: " + tempData.length); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } outData = null; } /** * 发生数据 */ private void recvData() { // TODO Auto-generated method stub if (dis == null) { return; } try { if (dis.available() < -1) { return; } // 1. 长度数组2位,读取, 2. 读取加密数据 3. 解密成正常数组 4. 读取包头12个字节 // 5. // byte[] len = new byte[2]; // dis.read(len); // //长度2位短整型表示 // int size = Util.BytetoInt2(len,0); // // byte[] data = new byte[size]; // dis.read(data); // // byte[] finalData = Tea.decryptByTea(data); // // //复制包头部分 // byte[] head = new byte[12]; // System.arraycopy(finalData, 0, head, 0, head.length); // // char[] tags = new char[2]; // tags[0] = (char) head[0]; // tags[0] = (char) head[1]; // // //包体长度 // int bodyLen = Util.BytetoInt2(head,2); // // //命令头 // int cmdType = Util.BytetoInt2(head,4); // // //playerId // int playerId = Util.BytetoInt4(head, 8); // // byte[] body = new byte[bodyLen]; // System.arraycopy(finalData, 12, body, 0, bodyLen); // // //进行数据解析和逻辑处理 // parseInputData(cmdType, body , head); // //通过包头属性,获得包体数据的长度 // //复制包体部分 byte[] datas = new byte[2]; dis.read(datas); // logger.info("收到消息长度为" + Util.toHexString1(datas)); // short lens=(short) (((datas[0] & 0xFF) << 8) + ((datas[1] & 0xFF) // << 0)); int len = Util.BytetoInt2(datas, 0);// (short) (((datas[0] & 0xff) // << 8) + ((datas[1] & 0xff) << // 0)); // logger.info("收到消息长度为" + len); // 读取通信流中的数据 datas = new byte[len]; dis.read(datas); datas = Tea.decryptByTea(datas); byte[] headdata = new byte[12]; System.arraycopy(datas, 0, headdata, 0, 12); // dis.read(headdata); // headdata=Tea.encryptByTea(headdata); char[] tags = new char[2]; tags[0] = (char) headdata[0]; tags[1] = (char) headdata[1]; // logger.info("收到body len " + headdata[0]); int bodyLen = Util.BytetoInt2(headdata, 2);// (short) (((headdata[2] // & 0xff) << 8) + // ((headdata[3] & 0xff) // << 0)); // logger.info("收到body len " + bodyLen); // headdata[4] int cmdtype = Util.BytetoInt2(headdata, 4);// (short) (((headdata[4] // & 0xff) << 8) + // ((headdata[5] & 0xff) // << 0)); // headdata[7] int playerid = Util.BytetoInt4(headdata, 8); // logger.info("收到player id is " + playerid + " cmd=" + cmdtype); byte[] bodydata = new byte[bodyLen]; System.arraycopy(datas, 12, bodydata, 0, bodyLen); // 进行数据解析和逻辑处理 parseInputData(cmdtype, bodydata, headdata); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 解析读取的数据,进行现场处理,打印结果 * * @param cmdType * @param body */ private void parseInputData(int cmdType, byte[] body, byte[] head) { // TODO Auto-generated method stub switch (cmdType) { case MessageFactory.RE_LOGIN: int playerId = Util.BytetoInt4(head, 8); // logger.info("playerId: " + playerId); endTime = System.currentTimeMillis(); Log4jUtil.logTime("login", startTime, endTime); // System.out.println("playerId: " + playerId); break; case MessageFactory.R_GETTYPE: // handleGetContent(body); break; case MessageFactory.R_GETCONTENT: handleGetContent(body); break; default: break; } } /** * * @param body */ private void handleGetContent(byte[] body) { // TODO Auto-generated method stub ByteArrayInputStream bis = new ByteArrayInputStream(body); DataInputStream dis = new DataInputStream(bis); try { int id = dis.read(); int style = dis.read(); int sub_style = dis.read(); byte[] data = new byte[2]; dis.read(data); int len = Util.BytetoInt2(data, 0); data = new byte[len]; dis.read(data); String title = new String(data, "utf-8"); // logger.info("question title: " + title); // System.out.println("question title: " + title); int slen = dis.read(); // System.out.println(" success in dealing with handleGetContent"); dis.close(); // String[] selects = new String[slen]; // for (int i = 0; i < slen; i++) { // data = new byte[2]; // dis.read(data); // int strlen = Util.BytetoInt2(data, 0); // data = new byte[strlen]; // dis.read(data); // selects[i] = new String(data, "utf-8"); // dis.close(); // } // int result = dis.read(); endTime = System.currentTimeMillis(); Log4jUtil.logTime("query", startTime, endTime); } catch (IOException e) { // TODO Auto-generated catch block logger.error("read question error "); // e.printStackTrace(); } } }
package net.tuolian.test; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; /** * 消息工厂 * 1. 产生登陆消息 * 2. 产生数据查询消息 * * 上述消息都直接写成二进制方式 * 包体+包头 * 放入outData数据队列 * * @author sean * */ public class MessageFactory { public static final int LOGIN = 3005; public static final int GETCONTENT = 2003; /** ******收到的命令******** */ public static final int RE_LOGIN = 3006; public static final int R_GETTYPE = 2002; public static final int R_GETCONTENT = 2004; private static final String TAG = "tl"; public static byte[] createMessage(int cmdType) { // TODO Auto-generated method stub ByteArrayOutputStream writeBos = new ByteArrayOutputStream(); DataOutputStream writeDos = new DataOutputStream(writeBos); switch (cmdType) { case LOGIN: loginWrite(writeDos); break; case GETCONTENT: getContent(writeDos); break; default: break; } // 返回加入包头的消息二进制数组 return addMessageHead(writeBos.toByteArray(),cmdType); // return writeBos.toByteArray(); } /** * 添加消息包头,根据具体情况定义包头 * @param body * @param cmdType * @return */ private static byte[] addMessageHead(byte[] body, int cmdType) { return data; // TODO Auto-generated method stub } /** * 编写登陆口命令体 * username * password * note: * log4j记录时间 * * @param dos */ private static void loginWrite(DataOutputStream dos) { // TODO Auto-generated method stub int userid = 1000; String name = "username"; String password = "password"; try { dos.writeInt(1000); byte data[] = name.getBytes("UTF-8"); dos.write(data.length & 0xff); dos.write(data.length >> 8 & 0xff); dos.write(data); data = password.getBytes("UTF-8"); dos.write(data.length & 0xff); dos.write(data.length >> 8 & 0xff); dos.write(data); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * 打印获得考试内容的时间 * @param dos */ private static void getContent(DataOutputStream dos) { // TODO Auto-generated method stub int examTypeId = 2; try { dos.write(examTypeId); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
package net.tuolian.test; import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.Properties; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; import org.apache.log4j.spi.Configurator; /** * log4j初始化配置 * * @author Administrator 1. Property 对象 2.读取配置文件 inputstream 3. * property.load(is) 4. configure(file); 5. * * 错误及解决: 1. log4j.properties文件,需要和代码放在同一级,也就是放在同一个包内 * 2. logger = * Logger.getLogger(Log4jUtil.class); 否则使用logger对象,报空指针错误 */ public class Log4jUtil { private static String fileName = "log4j.properties"; static Logger logger = null; public Log4jUtil() { Properties properties = new Properties(); InputStream is = getClass().getResourceAsStream(fileName); try { properties.load(is); PropertyConfigurator.configure(properties); logger = Logger.getLogger(Log4jUtil.class); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub long startTime = System.currentTimeMillis(); long endTime; new Log4jUtil(); for (int i = 0; i < 1000; i++) { System.out.println(" println :" + i); } endTime = System.currentTimeMillis(); long takeTime = (endTime - startTime); logger.info("hello: " + takeTime); logTime("query time", startTime, endTime); } public static void logTime(String logicName, long startTime, long endTime){ logger.info(logicName + "操作使用的时间为" + (endTime - startTime)); } public void debug(String string) { // TODO Auto-generated method stub logger.debug(string); } }
还有几个小问题:
1. log4j.properties默认是在代码的同一级目录(package)下,比如当前package是net.tuolian.test, 则配置文件放在这个package下就可以被成功加载
2. 根据自己的需要封装方法
比如:封装一个方法来打印业务名称、花费时间
logTime(name, starttime, endTime)
3. 另外log4j的配置文件读取的方法如代码所示:
Properties properties = new Properties();
InputStream is = getClass().getResourceAsStream(fileName);
try {
properties.load(is);
PropertyConfigurator.configure(properties);
logger = Logger.getLogger(Log4jUtil.class);
读取配置文件、设置配置文件,getLogger(类名)
4.将日志输出到数据库,需要对配置文件进行如下设置
输出到数据库
log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
log4j.appender.DATABASE.user=root
log4j.appender.DATABASE.password= root
log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES ('[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n')
log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d - %c -%-4r [%t] %-5p %c %x - %m%n
成功与否,笔者还没进行测试
其他方法,还包括输出地格式设定、输出的目标地址设定等等
发表评论
-
使用ant自动化构建android项目
2014-01-06 16:32 1596学习步骤 a. 学习简单的android项目打包 ... -
使用svn进行分支合并记录
2014-01-04 13:23 71341. svn版本保存baisonext svn commi ... -
java 回调函数的初步理解
2010-09-16 17:06 1114回调函数,主要是为了异步处理 通过callback接口方式实现 ... -
“走出软件作坊”有感
2010-09-01 16:28 939今天下午更新系统,趁着有空闲的时间,看了看走出软件作坊这本书。 ... -
关于线程同步的几点学习体会
2010-09-01 10:00 1107直接上代码 package com.nbgame.thre ... -
关于对象池的学习
2010-08-31 10:57 1072关于对象池的学习 代码以及文章参考: http://futur ... -
确保项目正常运行的小技巧:批处理、windows服务
2009-08-07 10:46 1710项目开发完成后的重要时期就是确保项目能够顺利运行。笔者结合自己 ... -
16条技术人员创业心得:从廉租房中最晚熄灭的灯谈起
2009-07-26 21:18 1041【Csdn.net 4月18日付江/文 ... -
Java如何进阶
2009-07-26 21:15 905基础阶段, 可能需要经 ... -
IT人如何收入500万?
2009-07-14 09:26 1146很久没写博客了, ... -
一个Java程序员应该掌握的10项技能
2009-07-12 16:30 9891、语法:必须比较熟悉,在写代码的时候IDE的编辑器对某一行报 ... -
memcache的简单使用及 插入对象的实现
2009-07-07 22:55 2264由于项目需要,今天学习了memcache的使用方法。 1. m ... -
Eclipse tomcat报错 java.lang.UnsupportedClassVersion
2009-06-16 11:24 2671今天生成servlet,然后启动tomcat, 系统报错: j ... -
java reflect反射机制的简单例子
2009-06-16 09:11 1364今天碰到一个关于反射的例子,写出一个简单的测试代码,作为记录。 ... -
09年六一有感
2009-06-01 09:25 1038今天是六一儿童节,没有太多异样的感觉,只是早上孩子给22个月宝 ... -
eclipse 项目打包时处理第三方插件的解决办法
2009-05-12 14:40 1720如题。 今天有个项目最后要打包等待验收。 原先只是简单的通过e ...
相关推荐
《深入理解Log4j2 Demo性能测试:探索异步日志的魅力》 ...通过深入理解和实践"Log4j2 Demo性能测试",开发者可以更好地掌握这一技术,从而在实际项目中发挥出Log4j2的潜力,优化系统的日志处理能力。
3. **Log4j**:Log4j是Apache软件基金会的一个项目,它是一个广泛使用的日志记录框架。`log4j1.2.17.jar`这个版本提供了灵活的日志配置,可以定制日志输出级别,格式,目标等,有助于开发者调试代码,监控系统运行...
我们在写日志的时候首先要获取logger,在每一个使用log4j的项目都有很多个地方要获取logger,这些logger是真实的被实例化的Logger对象,他们有可能被分散在无数不同的类中,日志体系结构讲的是这些logger对象是如何...
首先,我们来看一下"raven-log4j-5.0.zip",这个名字可能意味着它与Log4j框架的一个特定版本相关,Log4j是Java领域广泛应用的日志记录框架,而“raven”可能是用来集成错误追踪服务如Sentry的一个组件。在5.0版本中...
【标题】"公司真实项目源码(java)"揭示了一个基于Java编程语言的企业级实际开发项目。这样的项目源码对于学习者来说具有很高的价值,因为它提供了真实世界中的应用实例,帮助开发者了解如何在实践中运用Java技术。...
用Java写的项目,项目真实可靠,能正常运行,欢迎下载使用。用Java写的项目,项目真实可靠,能正常运行,欢迎下载使用。用Java写的项目,项目真实可靠,能正常运行,欢迎下载使用。用Java写的项目,项目真实可靠,能...
此外,商业项目源码还可能涉及到权限控制(如Spring Security)、用户认证(OAuth2)、日志记录(Log4j或Logback)、单元测试(JUnit或TestNG)、任务调度(Quartz或Spring Task)等常见的企业级功能。这些组件和...
《李腾飞CMS文档资料》中可能详细讲解了如何在实际项目中集成和配置Log4j,以实现有效和高效的日志管理。同时,它可能也涵盖了htmlprase的使用教程,包括基本的元素操作、选择器语法以及常见问题的解决方法。这些...
选材来自生活,项目真实感强,可用学习使用和就业面试使用,适合作为面试中提高实际项目经验...该项目前后端分离,满足前沿技术点..项目技术: - 数据库:MySQL8.0 - 后端技术:SpringBoot,MyBatisPlus,JWT 等 - ...
闪电狗监控(flash-dog)起源于杭州斯凯网络科技有限公司一个真实项目,主要优点是轻巧快捷,非侵入式,不影响业务代码,只需加入几个jar包和修改log4j配置文件,就能监控任意指标,如CPU,内存、线程,游戏收入,...
Java有内置的日志API,如java.util.logging,也可以使用Log4j或SLF4J等第三方库。调试工具如Eclipse或IntelliJ IDEA的调试器可以帮助开发者定位问题。 11. **版本控制**:项目通常使用Git进行版本控制,确保代码的...
我们可以使用try-catch语句来捕获异常,并使用如Log4j或SLF4J等日志框架记录测试过程中的重要信息。 **九、并行测试** 为了提高测试效率,我们可以利用TestNG的并行测试功能,同时运行多个测试用例或测试套件。这在...
7. **日志配置**:如`log4j.properties`,用于记录应用运行时的日志信息。 8. **启动脚本**:如`run.sh`或`start.bat`,用于启动应用程序。 通过这个项目,学员将有机会实践以下Java Web开发的重要知识点: 1. **...
3. 更新权重:\( \theta_j := \theta_j - \alpha \cdot \frac{\partial L}{\partial \theta_j} \),其中 \( \theta_j \) 是第j个参数,\( \alpha \) 是学习率。 4. 重复步骤2和3,直到损失函数收敛或达到预设的最大...
在本案例中,“logistic_lj”可能是一个项目或教程,旨在教授如何使用逻辑回归来识别数字字符串。 逻辑回归的核心在于构建一个线性模型,然后通过Sigmoid函数将线性组合转换为概率。线性模型的公式为: \[ \hat{y}...
本文将详细介绍Spring2.56版本中Spring MVC的配置与使用,包括基础配置、方法调用、定时器配置、Log4J配置、C3p0数据库连接池配置以及事务配置等多个方面。学习这些知识点后,开发者可以迅速上手进行真实项目的开发...
8. **异常处理与日志**:理解和测试异常处理逻辑,同时分析日志来定位问题,如使用Logback或Log4j进行日志记录。 9. **单元测试的最佳实践**:编写可读性强、易于维护的测试用例,遵循 Arrange-Act-Assert (AAA) ...
7. **日志记录**:为了调试和监控,可以使用Log4j、SLF4J等日志框架记录程序运行中的信息、警告和错误。 8. **单元测试**:使用JUnit或其他测试框架编写单元测试,确保代码的正确性。对于测试IP是否可达的功能,...
而`log4j-1.2.15.jar`是一个流行的日志记录框架,帮助开发者记录程序运行时的事件和错误信息,便于调试和问题追踪。 至于`epet`文件,它可能是项目的源代码压缩包,包含`.java`文件和其他资源。开发者可以通过解压...
另外,日志框架如Log4j用于记录应用程序的运行信息,便于调试和问题排查。 总之,这个【JAVA项目】全面展示了Java在实际开发中的各种应用场景,包括基础语法、数据库操作、并发编程以及框架的使用。通过学习和理解...