电信采集系统项目

本文详细介绍了电信运营采集系统的设计与实现,包括数据采集、备份、网络传输及数据库入库等关键模块。作者作为JavaEE初学者,利用现有知识完成了该项目,通过实例代码展示了如何处理数据并备份不完整数据,以及客户端与服务器端的数据交互。同时,文章还分享了作者在项目中遇到的问题及解决心得。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

既然选择了远方 便只顾风雨兼程
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Woss:电信运营采集系统
1 流程:
   数据----采集数据---客户端--(发送信息)--服务器端---(jdbc)---数据库


2 项目模块的需求划分:
   采集模块  备份模块  网络模块  入库模块  日志模块 配置文件模块


3 注:
  1)数据的格式:
  AAA_Name | NAS_ip | 7(上线) 8(下线)| 时间戳(上/下)| logied_ip(用户登陆ip)
  2)我是学习JavaEE的一只菜鸟 然而目前为止 我只学过corejava + oracle+JDBC/Mybatis技术  后续的框架之类的各种知识没有学习,
所以就综合目前的知识做了这样的一个项目来练习 ~~~让我们一起进步 一起奋斗撒~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 各模块代码(主体代码)
1) 采集模块---得到完整数据,同时对不完整数据进行备份
package com.briup.client;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.briup.backup.BackByte;
import com.briup.backup.BackupImp;
import com.briup.bean.BIDR;
import com.briup.logger.LoggerImp;
import com.briup.util.Dom4jTest;
/*定义一个方法:存放对象BIDR
 *1 首先通过输入流,获取字节数,并跳过字节数 来 while循环读取文件中的数据,将数据以|分割变成一个数组
 *2 将每条数据中的标志位是7时:则表示上网 ----map??
 *                    是8时:表示下线-------list集合
 *并将读取到的每条数据中的各个元素赋值给BIDR对象   
 *3 将map集合中的数据 备份到备份文件中--store  
 *4 下一次读取时 将备份文件读取 继续处理---load
 *5 返回list集合中的数据
 */
//GatherImp采集类--实现接口IGTather:
public class GatherImp implements IGather {

FileInputStream fis = null;
InputStreamReader isr= null;
BufferedReader br  = null;
String line = null;
List<BIDR> list2= null;
Map<String, BIDR> map = null;
 
@Override
//采集数据方法:
public  Collection<BIDR>  gather() throws Exception{
//通过Dom4j解析 得到日志对象logger:
Object logger = Dom4jTest.mapCnameAndObject().get("com.briup.logger.LoggerImp");

String path = Dom4jTest.ParseXML("src-file");//采集数据路径
File file = new File(path);
list2 = new ArrayList<BIDR>();
map=new HashMap<String,BIDR>();
//通过解析文件得到对应类的对象backup:
Object backup = Dom4jTest.mapCnameAndObject().get("com.briup.backup.BackupImp");//得到备份对象
String buakupPath = Dom4jTest.ParseXML("back-temp");//备份文件路径
//读取数据文件radwtmp:
fis = new FileInputStream(file);
isr = new InputStreamReader(fis);         //字节流转换为字符流
br = new BufferedReader(isr);
int index = 0;
//若备份集合存在,则进行加载备份文件:
if(new File(buakupPath).exists()){

Map<String, BIDR> map2 = (Map<String, BIDR>) ((BackupImp) backup).load(buakupPath);
map.putAll(map2);        //将上一次的不完整数据map2添加到本次的map集合中 
}

BackByte backByte =new BackByte(); //字节对象
index = backByte.ReadByte(); //读取到文件中的字节数index
br.skip(index);
while((line = br.readLine())!=null){
index = index+line.getBytes().length+2; //计数每行的字节数index
//以 | 进行分割字符串
String[] Array = line.split("[|]");
String aaa_login_name = Array[0] ;
String nas_ip = Array[1];
Date date = new Date(Long.parseLong(Array[3])*1000);  //将 秒单位 转换 为毫秒数
String login_ip= Array[4];
//上网:
if(("7").equals(Array[2])){
BIDR bidr = new BIDR();
bidr.setAaa_login_name(aaa_login_name.substring(1));
bidr.setNas_ip(nas_ip);
bidr.setLogin_date(date);
bidr.setLogin_ip(login_ip);
//若标志位等于7:则将该用户放入集合map中:
map.put(Array[4],bidr);
}
//下线:
else {
//得到login_ip对应的对象,并将map集合中该数据删除,并返回该键对应的值类型
BIDR b = map.remove(login_ip);
b.setLogout_date(date);
//下线时间戳 - 上线时间戳:
long l = (long)(b.getLogout_date().getTime()-b.getLogin_date().getTime());
b.setTime_duration(l);
list2.add(b);   
}
}
//将备份文件 存储到 备份文件中
((BackupImp) backup).sore(buakupPath, map);

//将获取到的 字节数 写入到文件中
backByte.WriteByte(index);

((LoggerImp) logger).debug("采集到的字节数是: "+index+"字节");
((LoggerImp) logger).debug("备份数据 : "+map.size()+"条");
((LoggerImp) logger).debug("发送数据: "+list2.size()+"条");
return list2;
}
}


2) 备份模块:
package com.briup.backup;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
//BackupImp备份类--实现备份接口
public class BackupImp implements IBackup{

//存储备份文件:
@Override
public void sore(String fileName, Object obj) throws Exception {
//通过备份文件的路径得到备份文件:
File file= new File(fileName);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
oos.writeObject(obj);
}

//加载备份文件:
@Override
public Object load(String fileName) throws Exception {
File file = new File(fileName);
//读取文件中的备份数据
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
Object readObject = ois.readObject();
return readObject; //返回读取到的备份内容
}
}


3) 网络模块:客户端  服务器
/*

* 客户端---1 得到采集时的完整数据
*    2 将该数据发送给服务器端
*/
package com.briup.client;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Collection;
import com.briup.bean.BIDR;
import com.briup.logger.LoggerImp;
import com.briup.util.Dom4jTest;
//客户端IClientImp--实现IClient接口 
public class IClientImp implements IClient{

public static void main(String[] args) throws Exception {
//通过Dom4j解析 得到采集类对象gather:
Object gather = Dom4jTest.mapCnameAndObject().get("com.briup.client.GatherImp");
//客户端得到集合中的BIDR对象
Collection<BIDR> list = ((GatherImp) gather).gather();

Object Iclient = Dom4jTest.mapCnameAndObject().get("com.briup.client.IClientImp");
//客户端将list中的数据发送给服务器--send()方法
((IClientImp) Iclient).send(list);
}
@Override
public void send(Collection<BIDR> data) {
OutputStream os = null;
ObjectOutputStream oos = null;
try {
//得到日志对象logger:
Object logger = Dom4jTest.mapCnameAndObject().get("com.briup.logger.LoggerImp");
Socket socket = new Socket(Dom4jTest.ParseXML("ip"),Integer.parseInt(Dom4jTest.ParseXML("port"))); //创建套接字socket:
((LoggerImp) logger).debug("客户端接收到数据...");
((LoggerImp) logger).debug("客户端建立连接...");
os = socket.getOutputStream(); //得到输出流os--发送数据
((LoggerImp) logger).debug("客户端建立连接,准备发送数据...");
oos = new ObjectOutputStream(os);
oos.writeObject(data); //将data数据进行序列化(data:list集合中的完整数据)
oos.flush();
((LoggerImp) logger).debug("客户端发送数据成功...");
} catch (Exception e) {
e.printStackTrace();
}
//关闭流:
finally {
try {
oos.close();
os.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
package com.briup.server;
/*网络模块:
 * 服务器--接受客户端 传过来的数据(完整的数据)
         --将接收到的数据 存入 数据库中
 */
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collection;
import java.util.List;
import java.io.*;
import com.briup.bean.BIDR;
import com.briup.logger.LoggerImp;
import com.briup.util.Dom4jTest;
//服务端--实现Server接口
public class ServerTest implements Server{
InputStream is = null;
ObjectInputStream ois = null;
List<BIDR> list = null;
public static void main(String[] args) throws Exception {
//通过 xml解析 得到服务器类对象server:
Object server = Dom4jTest.mapCnameAndObject().get("com.briup.server.ServerTest");//得到服务器对象server
//接收到list集合中的数据:
Collection<BIDR> revicer = ((ServerTest) server).revicer();
}

//服务器要实现多线程:
@Override
public Collection<BIDR> revicer() throws Exception {
Thread t1 = new Thread(new Server1());
t1.start();    //启动线程
return list;  //返回集合
}
}
class Server1 implements Runnable{
ServerSocket ss = null;  //服务器套接字
Socket s = null;
@Override
public void run(){
try {
//得到日志对象logger:
Object logger = Dom4jTest.mapCnameAndObject().get("com.briup.logger.LoggerImp");

ss = new ServerSocket(Integer.parseInt(Dom4jTest.ParseXML("port")));
((LoggerImp) logger).debug("服务器已经启动...");
Socket s = ss.accept();
((LoggerImp) logger).debug("客户端连接成功...");
InputStream in = s.getInputStream(); //输入流
ObjectInputStream ois = new ObjectInputStream(in); //对象反序列化
List<BIDR> list = (List<BIDR>) ois.readObject(); //读取到对象
((LoggerImp) logger).debug("服务器接收到: "+list.size()+"条数据");
((LoggerImp) logger).debug("数据正在入库...");
//得到入库对象:
Object  dbStore= Dom4jTest.mapCnameAndObject().get("com.briup.server.DBStoreTest");
//System.out.println(dbStore);//输出入库对象dbStore


((DBStoreTest) dbStore).saveToDB(list); //将list集合中的完整数据发送出去
((LoggerImp) logger).debug("数据入库成功...");
} catch (Exception e) {
e.printStackTrace();
}
}
}


4) 日志模块
package com.briup.logger;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import com.briup.util.Dom4jTest;
//debug(调试)<info(信息)<warn(警告)<error(错误)<fatal(奔溃:操作系统一般使用)
public class LoggerImp implements ILogger{
Logger logger = Logger.getRootLogger();//初始化logger日志信息
static{
try {
String path = Dom4jTest.ParseXML("log-properties");//通过dom4j解析 得到日志路径path
PropertyConfigurator.configure(path); //加载日志路径
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void debug(String msg) {
logger.debug("debug maessage: "+ msg);//输出debug信息
}
@Override
public void info(String msg) {
logger.info("info maessage: "+msg);
}
@Override
public void warn(String msg) {
logger.warn("warn maessage: "+msg);
}
@Override
public void error(String msg) {
logger.error("error maessage: "+msg);
}
@Override
public void fatal(String msg) {
logger.fatal("fatal maessage: "+msg);
}
}


5) 入库模块: 通过JDBC技术 将list集合中的BIDR数据存入数据中


package com.briup.server;
/*
 * 入库---将list集合中的数据通过 JDBC技术 添加到 数据库中
 */
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.List;
//入库模块:---使用JDBC技术将数据传入到数据库中
import com.briup.bean.BIDR;
import com.briup.util.Dom4jTest;
public class DBStoreTest {
//定义jdbc所需的四个变量:
//   static String driver = "oracle.jdbc.driver.OracleDriver";
//     测试注册驱动是否成功:
//    url唯一标识:
//   static String url = "jdbc:oracle:thin:@127.0.0.1:1521:XE";
//   static String user = "briup";
//   static String password = "briup";
  
//入库操作:将(完整数据,即list集合中的对象)数据通过jdbc技术发送到数据库中:
public void saveToDB(List<BIDR> list) throws Exception {
//1 注册驱动
Class.forName(Dom4jTest.ParseXML("driver"));
//2 建立连接
Connection connection = DriverManager.getConnection(Dom4jTest.ParseXML("url"),Dom4jTest.ParseXML("username"),Dom4jTest.ParseXML("password")); 
//遍历BIDR对象:
for(BIDR b :list){

String aaa_login_name = b.getAaa_login_name(); //AAA服务器name
String nas_ip = b.getNas_ip();       //nas服务器ip
String login_ip = b.getLogin_ip(); //登录ip
//通过long类型的时间戳  将util下的date 转换为 sql下的date :
Date login_date = new java.sql.Date(b.getLogin_date().getTime()); //上线时间
Date logout_date = new java.sql.Date( b.getLogout_date().getTime());  //下线时间
long time_duration = b.getTime_duration();//时间差

int i_date  = b.getLogout_date().getDate();  //通过日号---对应的是表号

//定义31张表的sql语句模版:
String sql = "insert into t_detail_"+i_date+"(aaa_login_name,nas_ip,login_ip,login_date,logout_date,time_duration) "
+ "values(?,?,?,?,?,?)";
//3 创建会话ps:
PreparedStatement ps = connection.prepareStatement(sql);
//设置给ps值:
ps.setString(1,aaa_login_name);
ps.setString(2, nas_ip);
ps.setString(3, login_ip);
ps.setDate(4,login_date );
ps.setDate(5, logout_date); //将sql下的logout_date存入数据库中
ps.setLong(6, time_duration); //时间差
//4执行sql语句
ps.execute();
//关闭资源
ps.close();
}
}
}




6) 配置模块:利用 dom4j技术 解析 xml文件
----------从而直接从xml文件中直接得到各个属性,(即不用在各个类中定义变量和赋值)
---------同时提高的代码的灵活性


package com.briup.util;
/*通过Dom4j进行解析xml文件---得根 二级 三级标签名以及对应的属性值
*  注:这里用的ParseXML()方法 有缺陷 还需优化
*/
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class Dom4jTest {
static String StringName = null;
static String fileName1 = "src/config.xml";
static Map<String, Object> map2 =new HashMap<String, Object>();
//定义一个 输入三级标签 的方法:
//StringName:标签名 
public static String ParseXML(String StringName) throws Exception{
SAXReader reader = new SAXReader(); //获取解析器reader:
Document document =  reader.read(fileName1); //读取Xml文件,得到Dom4j对象,即得到整个文档
Element root = document.getRootElement(); //得到root根标签
List<Element> list2 = root.elements(); //获取二级标签 存放在list集合中(6个)
//遍历集合二级标签:
for(Element e2:list2){
List<Element> list3 = e2.elements(); //获取每个二级标签下的各个三级标签
//遍历三级标签:
for(Element e3:list3){
if(e3.getName().equals(StringName)){     //若传入的字符串与获到的标签名相同
String value = e3.getStringValue();  //得到该标签的属性值
//System.out.println(value);
return  value;
}
}
}
return null;
}
//定义返回类型为map集合的一个方法(全限定名  对象)
public static  Map<String, Object> mapCnameAndObject() throws Exception{

SAXReader reader = new SAXReader(); //获取解析器reader:
Document document =  reader.read(fileName1); //读取Xml文件,得到Dom4j对象,即得到整个文档
Element root = document.getRootElement(); //得到root根标签
List<Element> list2 = root.elements(); //获取二级标签 存放在list集合中(6个)
//遍历集合二级标签:
for(Element e2:list2){
Attribute attr = e2.attribute("class"); //得到二级标签中class属性
String value2 = attr.getValue(); //得到属性值,即全限定名称
Object object = Class.forName(value2).newInstance();//得到类的对象
map2.put(value2, object);    //将全限定名 该名对应的对象为键值存入map集合
}
return map2;
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
本菜鸟遇到的问题:
1 在刚开始项目时,对整体框架很模糊,就糊里糊涂的进入采集模块,通过标志位7/8将采集到的各个数据赋给每个BIDR对象,


若该数据标志位 7,则将该数据各个元素值 设置 给 BIDR对象  并将标志位为7的对象 存入map集合
若数据的标志位为8 在map集合中找到与对应的login_ip对应的BIDR对象,并将map集合中该数据删除 从而得到该对象的下下线、时间差属性   最后将BIDR完整对象存放在list集合中
最终实现 map集合中:不完整数据
list集合中: 完整数据


2 备份模块时  


(1)备份文件
store()存储备份文件 load()加载备份文件 这两方法写好后,我却不知在哪里被调用...很尴尬呐....


在老师讲解下 得知是在再一次采集数据时 若备份文件exit 则要load加载备份文件到本次的map集合(load是为了与本次的数据进行匹配),与本次新加入的数据 进行匹配
若标志位为7 加入map集合 若标志位为8 从map集合(本次没下线对象+加载得到的上一次备份文件)中找到与login_ip匹配的对象,进行下网


(2)备份字节数  
WriteByte()将字节数写入文件中  ReadByte() 将字节数读出来 并skip该字节数


遇到的问题:对于字节数 我当时理解的不透彻 没有理解根本意图 知道看完其他同学的代码 才明白也就类似于 备份不完整数据的load和store


启发: 做完整体项目后 我觉得采集和备份模块是一个难点 必须将该模块理解清楚 后续代码才写的顺利


3 网络模块:通过socket 网络编程  
客户端 得到采集数据(list集合中的BIDR对象)
       将该数据发送出去
服务器  接受数据
将数据进行入库 


遇到的问题: 当时我只是将服务器 与 客户端进行普通连接 
-----并没有对二者进行采集、发送 接受数据、将数据入库等操作的调用  我认为 这还是当时我对整体项目的不理解所导致的
------后来在自己的理解+同学之间的讨论下 明白的客户端 服务器对数据进行的操作,从而实现真正的功能
4 入库操作:JDBC技术
超出游标最大限制数:(1)在终端 通过命令 将syatem系统的游标限制扩大
    (2)在每执行完一个sql语句,就立即关闭资源,实现资源的不浪费  eg:ps.close()


5 配置模块:Dom Sax Dom4j三大技术 解析xml文件
遇到的问题:
实现整体功能后,突然跑出来配置文件 一脸懵13
在自己理解+老师讲解思路+同学讨论 最终明白是为了通过解析类 直接得到标签中的属性值 即使变量值 节省了内存




6 整合模块...注入依赖没有实现...后期继续优化...


领悟:
通过为其一周的项目,我学到的很多
在理解上: 不能急于编写代码 需明白整体需求 以及细节需求 只有这样 才会提高效率
在代码上: 不能有断开思路去编写的习惯 要专注于思考 坚持+专注思考
在演讲答辩中: 通过模块话讲解 首先自己必须要明白所有思路,只有这样 才不会讲解模糊 
--------------在讲解时 适当的穿插自己做项目时的一些想法+理解,体现出自己的逻辑与思路性
-----------------------适当的加一些解决办法 让听众了解到有自学以及自己解决的能力
-----------------------适当的语速 不能太快 不能太慢 声音一定要高! 不要太专注于讲解代码 要和老师以及同学眼神的交互
 
亲爱的你 不要犹豫 不要放弃 要继续努力 迈大步子 向南飞!






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值