使用AspectJ实现将写入FTP服务的数据转存到Mysql数据库的解决方案

最近公司项目进行性能提升的整改,原定使用FTP将采集到的底层数据写入文件,客户端再读FTP文件,然后解析按需求展示;该方案在实际应用过程中,由于读FTP文件和解析过慢,导致显示效果不理想;由此提出将该部分写FTP的数据解析好后存储至数据库中,客户端直接读数据库,不需再读文件和解析,于此提升该部分的显示效果和性能。

经过几个方案取舍后,本着最小的改动和平稳过渡,原先写FTP的部分原封不动,客户端的解析展示功能也保留;采用AspectJ,以在FTP的写文件(upload())的方法为pointcut,一旦FTP写文件的时候即触发写数据库部分的操作,先获取upload()的参数,对这些参数进行解析处理,存储在全局的一个List中,构造SQL方法将通过该全局List构造插入语句,最后addbatch 执行,提交;考虑到频繁连接数据库进行插入会严重影响性能,所以将插入操作设置为一个定时调度任务,每隔60秒将根据全局List构造对应的insert SQL,执行并提交事务,以此来降低数据库的压力,同时清空当前的List;为确保数据安全,该插入和List清空操作放在一段synchronized语句段内,防止List在构造SQL的时候被更改。至此完成对原FTP数据的转移。

优点:1.切面编程,在完全不影响原系统架构和业务代码的前提下实现了功能的优化,依然保持着松耦合;

    2.留着原来的功能,进行平稳过渡;

       粘贴部分代码如下(在Spring框架下集成开发):

@Aspect

@EnableScheduling
@EnableAspectJAutoProxy //开启切面代理
@Component()
public class DBSyncAop {

//设置upload(..)为pointcut,并另命名为pointcustSignature()

@Pointcut("execution(* com.bjtct.oom.mms.service.FileManager.upload(..))")
public void pointcustSignature(){}

//1.在upload()执行前后均可执行该切面,2.将该uploadFileAspect方法的加载优先级设为高,先加载

@Around("pointcustSignature()")
@Order(value=1)
public Object uploadFileAspect(ProceedingJoinPoint pjp) throws Throwable{

//upload() execute before ,get upload() paramaters code here 

List<String> fileNames = (List<String>)pjp.proceed();

//upload() execute after ,handle upload() paramaters  here,and store data in mysql code here 

//handle upload() paramaters

List<Map<String, String>> fieldMapList = handleMsg(type, mqMsg);  

                  //param 为全局List,此处为将原本写FTP的数据保存至param,留待用来构造插入的SQL语句

synchronized(params){
List<Object> param;
for(int i=0; i<fieldMapList.size(); i++){
param = new ArrayList<Object>();
msg = fieldMapList.get(i);
System.out.println("msg: "+msg);
param.add(new Date());
param.add(msg);
param.add(type);

params.add(param);
}
}

//定时调度任务,定时执行该方法,插入从FTP获取的数据

@Scheduled(cron = "${DBSync.schedule.delay.cron}")
private void proceedInsertion()
{

if(!"Y".equalsIgnoreCase(DBSyncEnabled)){
return;
}
log.info("DBSyncAop scheduling start");
Connection conn = null;
PreparedStatement ps = null;
log.info("##params size: "+params.size());
synchronized(params){
if(!params.isEmpty()){
try{
conn = DataSourceUtils.getConnection(scheduleDataSource);
conn.setAutoCommit(false);
List param;
ps = conn.prepareStatement(insertSql);
for(int i=0; i<params.size(); i++){
param = params.get(i);
ps.setDate(1, new java.sql.Date(((Date)param.get(0)).getTime()));//timestamp
ps.setString(2, (String)param.get(1));//fileName
ps.setString(3, (String)param.get(2));//json msg
ps.setString(4, (String)param.get(3));//mq type
ps.addBatch();
log.info("DBSyncAop scheduling added batch");
}
ps.executeBatch();
conn.commit();
log.info("DBSyncAop scheduling committed");
conn.setAutoCommit(true);
params.clear();
} catch (Exception e) {
log.error("鎻掑叆mq淇℃伅鏁版嵁澶辫触"+e.getMessage());
e.printStackTrace();
} finally {
try {
DataSourceUtils.doCloseConnection(conn, scheduleDataSource);
} catch (SQLException e) {
log.error(e.getMessage());
e.printStackTrace();
}
}
}
}
log.info("DBSyncAop scheduling finish");

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值