Spring集成Quartz完成定时任务
在JavaEE系统中,我们经常会用到定时任务,比如每天晚上凌晨之后跑批处理或者是每天某个时刻群发消息等等.
我们可以使用java.util.Timer结合java.util.TimerTask来去完成需求,但是这种组合去调度会非常,代码量大且限制特别多.
所以出现了Quartz框架,Quartz与Spring可以非常好的集成,代码量少,且易于控制.下面我们来讲讲Spring与Quartz的集成,以及相关作业类及配置,还有corn表达式的用法.
需求:定时进行数据监测并发送邮件.
所用技术:spring+ strtus1 +hibernate
分析:首先接触到这个需求的时候,我想的是用TimeTask去完成,后来想了想TimeTask的缺陷: ①如果报错则无法进行之后的定时任务执行 ②对于时间上的设置不如Quartz好,所以决定用Quartz完成. 博主也是第一次用Quartz定时任务,有不足之处请之指出,互相学习.
首先,1.配置创建spring配置文件,在web-inf下我创建了applicationContext-task.xml并进行了配置. 配置bean的文件就不展示了,这里主要是将的怎么用Quartz完成定时发送邮件.
注:这里小讲一下配置文件中 <property name="a" ref="aa" />和<property name="a" ref bean ="b"/>的区别?
<property name="a" ref="aa" /> 就是找当前配置文件里的bean 也就是id为aa的bean
<property name="a" ref bean ="b"/> 就是找配置文件里的bean 也就是id为aa的bean.
2.进行包装作业配置
注:此处包装的是我们1中配置的bean,以及指定了1中class对应类的执行方法.
3.配置corn触发器 corn会在后面讲到.
注:红色框告诉我们,我们的corn配置是针对的哪一个bean,蓝色框是配置corn,此处是每两分钟执行一次定时任务.
4.建立实际调度,说白了就是最后一步的调用的配置
注:红色框是一个list集合,他可以配置很多调度,即:你可以写很多定时任务,这些定时任务可以用一个调度执行.
<ref local=" ">这代表的是我们调度所寻找的是当前配置文件中的bean. 也可以这样配置 <ref bean=" "> 这是在所有配置中寻找bean.
到此,不要以为spring文件的配置结束了,我就是因为对spring的不熟悉以为spring配置完了,这里再次提醒新人在项目报错的时候一定要先关注日志.
在我们的web.xml中,我们配置了spring文件的初始化,我这里初始化的是webApplicationContext.xml这个文件,所以我还需要把我写的applicationContext-task.xml
下面是将我们写的spring配置导入初始化文件中并同时配置数据库连接,即web.xml初始化加载.
到此,spring文件结束.
下面是struts文件配置. 这里就快速的带过了,struts文件中只是写了一些映射,没有什么好写的.说一下struts配置文件的组成.
1.
注:这里配置的是映射中需要用到的是实体类.
2.
注:红色的为前端界面写的user下的所有.do都到这里起来寻找映射关系.蓝色的对应的action处理类.黑色的parameter="{1}"就是路径中的*,比如add.do *就是add.黄色的就是对应action处理类处理之后返回的字段对应的返回界面.
此处需要在web.xml中进行配置struts初始化以及拦截.
struts配置文件到此结束.
下面需要建立对应的定时任务类就可以.
1 package com.ab.itws.common.job; 2 3 import java.sql.Connection; 4 import java.sql.SQLException; 5 import java.text.SimpleDateFormat; 6 7 import java.util.ArrayList; 8 import java.util.ResourceBundle; 9 10 11 import org.apache.log4j.Logger; 12 13 14 import com.ab.itws.common.Conts; 15 import com.ab.itws.common.DBUtil; 16 import com.ab.itws.common.Email; 17 import com.ab.itws.common.ExeSQL; 18 import com.ab.itws.common.PubFun; 19 import com.ab.itws.common.SSRS; 20 21 import com.ab.itws.common.TenSQL; 22 import com.ab.itws.dbcheck.dto.TDBConfigDTO; 23 import com.ab.itws.dbcheck.dto.TPersonInfoDTO; 24 25 import com.ab.itws.dbcheck.dto.TSqlCheckConfigDTO; 26 import com.ab.itws.dbcheck.dto.TSqlCheckResultDTO; 27 import com.ab.itws.dbcheck.service.IDBConfigManager; 28 import com.ab.itws.dbcheck.service.IPersonInfoManager; 29 import com.ab.itws.dbcheck.service.ISqlCheckConfigManager; 30 import com.ab.itws.dbcheck.service.ISqlCheckResultManager; 31 32 /** 33 * 34 * @author liujw 35 * 2017-11-14 36 * 邮箱发送添加查询内容 37 */ 38 39 public class dataCheckQuartzNew { 40 // 数据源服务类 41 private IDBConfigManager myIDBConfigManager; 42 // 校验信息类 43 private ISqlCheckConfigManager myISqlCheckConfigManager; 44 // 用户信息类 45 private IPersonInfoManager myIPersonInfoManager; 46 47 // 数据校验结果类 48 private ISqlCheckResultManager myISqlCheckResultManager; 49 50 51 private java.util.List dbidlist; 52 private String dbids = ""; 53 private String SMTPServer = ""; 54 private String Subject = "新版数据校验结果"; 55 private String From = ""; 56 private String MailPWD = ""; 57 private String Port = ""; 58 private String To = ""; 59 private String SendBody=""; 60 61 //dataCheckQuartzNew日志 62 private static final Logger log = Logger.getLogger(dataCheckQuartzNew.class); 63 private static final SimpleDateFormat formatDate = new SimpleDateFormat("yyyyMMddHHmmss"); 64 65 //定时操作 66 67 protected void executeNewjob(){ 68 69 log.info("定时任务启动!! dataCheckQuartzNew -------start ------------"); 70 71 if(!getCheckSQLCfg()){ 72 log.error("读取邮箱信息发生异常,停止执行"); 73 return; 74 } 75 Email tEmail = new Email(SMTPServer,From,MailPWD,To,Subject,Port); 76 TDBConfigDTO dbdto = new TDBConfigDTO(); 77 try{ 78 dbdto.setPageSize(999); 79 //根据下次执行时间查出可以选用的数据库 80 dbdto = this.myIDBConfigManager.listCanLinkTDBConfigDTO(dbdto);// 查询表为sqlconfig 81 dbidlist = dbdto.getResultList(); 82 }catch(Exception e){ 83 e.printStackTrace(); 84 } 85 //记录任务执行时间,为计算下次执行时间时用,避免每天的执行时间都有变化 86 java.util.Calendar c = java.util.Calendar.getInstance(); 87 //修改数据源下次执行时间用,C在下面需要减去DEFAULT_INTEVAL,在0点执行的时候会有问题,不能使用,需要重新创建一个cdb 88 java.util.Calendar cdb = java.util.Calendar.getInstance(); 89 //批次号,根据日期时间 90 String strbatchno = formatDate.format(c.getTime()); 91 log.info("strbatchno="+strbatchno); 92 c.add(java.util.Calendar.MINUTE, -Conts.DEFAULT_INTEVAL); 93 //从下面转移上了,解决由于dbidlist时提示信息没有被值空的问题 94 SendBody = ""; 95 if(null != dbidlist){ 96 log.info("开始定时数据源队列 数据校验!dbidlist size="+dbidlist.size()); 97 log.info("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); 98 try { 99 //如果是多个数据源,需要单个执行 100 for(int i=0;i<dbidlist.size();i++){ 101 //1.获取数据源信息 102 //2.获取该数据源所有的数据检查语句,执行语句 103 //3.获取该数据源的接受人,组装邮件内容发送email 104 TDBConfigDTO tdbConfigDto = (TDBConfigDTO)dbidlist.get(i); 105 106 log.info("开始执行单个数据源数据校验!dbid="+i+"---"+tdbConfigDto.getDbCode()); 107 Connection con = null; 108 try{ 109 //获取数据库连接 通过查询出的可用的数据库查找对应的SQL 110 con = new DBUtil().getConnByDBTYPE(tdbConfigDto); 111 if(null != con){ 112 //根据数据源信息,查询出所有该数据源下的数据检查记录,遍历执行 113 checkdataForDBSource(tdbConfigDto,con,c,strbatchno); 114 }else{ 115 //获取数据库连接失败,直接跳出本次循环,执行下一个数据源 116 log.error(tdbConfigDto.getDbCode()+"获取数据库连接失败,跳过,执行下一个"); 117 SendBody = SendBody+ tdbConfigDto.getDbCode()+"获取数据库连接失败。\n"; 118 continue; 119 } 120 121 }catch(Exception e){ 122 log.error("执行数据源数据检查发生异常 dbid="+tdbConfigDto.getDbId()+",跳过,执行下一个"); 123 SendBody = SendBody+"数据源数据检查发生异常dbid="+tdbConfigDto.getDbId()+"。\n"; 124 e.printStackTrace(); 125 }finally{ 126 if(con != null){ // 关闭连接对象 127 try{ 128 con.close() ; 129 }catch(SQLException e){ 130 e.printStackTrace() ; 131 } 132 } 133 } 134 } 135 log.info("执行数据校验完成!"); 136 //执行完数据检查操作以后,发送有问题的记录给用户(做判断,查出来的问题条数为0,则不发送邮件) 137 log.info("组装邮件内容给关系人开始!"); 138 sentPersons(strbatchno); 139 log.info("组装邮件内容给关系人结束!"); 140 141 142 log.info("置邮件发送状态开始!"); 143 //改变邮件发送状态 144 setAllSendMailStatus(strbatchno); 145 log.info("置SQL为邮件发送状态结束!"); 146 147 //因为短信功能尚未用到 所以注掉 148 /*//短信 此处的短信提醒是早期的功能,等后面的短信功能完善后可以删除此处代码 149 log.info("短信下发开始执行!"); 150 Sms sms = new Sms(); 151 sms.send(myISqlCheckConfigManager,strbatchno); 152 log.info("短信下发结束!");*/ 153 } catch (Exception e) { 154 log.error("执行数据校验,错误信息:" + e.getMessage()); 155 SendBody = SendBody+"执行数据校验,错误信息="+e.getMessage()+"。\n"; 156 e.printStackTrace(); 157 } 158 log.info("执行数据校验结束!"); 159 }else{ 160 log.error("dbidlist 为空,不执行批量操作!dbidlist="+dbidlist); 161 SendBody = SendBody+"配置参数 dbidlist 为空,不执行批量操作。\n"; 162 } 163 164 if(!SendBody.equals("")){ 165 try{ 166 tEmail.send(SendBody); 167 }catch(Exception e){ 168 log.error("发送邮件发生异常,ERROR="+e.getMessage()); 169 e.printStackTrace(); 170 } 171 } 172 //} 173 } 174 175 176 177 178 /** 179 * 检索数据源下的所有用户,根据数据检查的结果给每个接受人发送邮件 180 * @param tdbConfigDto 181 */ 182 public void sentPersons(String strbatchno){ 183 //获取该数据源下的所有用户数据 184 try{ 185 TPersonInfoDTO personInfodto = new TPersonInfoDTO(); 186 //personInfodto.setDbId(tdbConfigDto.getDbId()); 187 personInfodto.setPageSize(9999); 188 personInfodto = this.myIPersonInfoManager.serchPersonInfo(personInfodto); 189 java.util.List personInfodtolist = personInfodto.getResultList(); 190 if(null != personInfodtolist&&personInfodtolist.size()>0){ 191 //遍历用户,查询需要发送给它的记录 192 for(int i=0;i<personInfodtolist.size();i++){ 193 TPersonInfoDTO temppersonInfodto = (TPersonInfoDTO)personInfodtolist.get(i); 194 String stremailcontent = this.getEmailContent(temppersonInfodto,strbatchno); 195 //如果邮件内容不为空,需要发送给用户 196 if(!"".equals(stremailcontent)){ 197 try{ 198 Email mEmail = new Email(SMTPServer,From,MailPWD,temppersonInfodto.getEmail(),"数据校验结果,请审阅",Port); 199 log.info("发送给用户"+temppersonInfodto.getName()+",邮件内容:"+stremailcontent); 200 mEmail.send(stremailcontent); 201 }catch (Exception ex) { 202 SendBody=SendBody+ "\t邮件发送失败,相关人员编码:" +temppersonInfodto.getPersonID()+"\n"; 203 log.error("邮件发送失败!email="+temppersonInfodto.getEmail()); 204 ex.printStackTrace(); 205 } 206 } 207 208 log.info("未发现异常数据,无需发送邮件"); 209 } 210 }else{ 211 log.error("该数据源下没有配置任何接受用户信息"); 212 } 213 }catch(Exception e){ 214 log.error("给数据源下的用户发送邮件发生异常 error="+e.getMessage()); 215 e.printStackTrace(); 216 } 217 } 218 /** 219 * 拼接所有需要发送给该用户的数据校验结果 220 * @param personInfodto 221 * @return 222 */ 223 public String getEmailContent(TPersonInfoDTO personInfodto,String strbatchno){ 224 String stremailcontent = ""; 225 String strSmsconttent = ""; 226 try{ 227 TSqlCheckConfigDTO tsqlcheckconfigdto = new TSqlCheckConfigDTO(); 228 tsqlcheckconfigdto.setDbId(personInfodto.getDbId()); 229 tsqlcheckconfigdto.setPersonID(personInfodto.getPersonID()); 230 tsqlcheckconfigdto.setPageSize(9999); 231 tsqlcheckconfigdto.setValiFlag(Conts.STATUS_ABLE); 232 tsqlcheckconfigdto.setSendMail(Conts.MAIL_NOT_SEND); //未发邮件的记录 233 tsqlcheckconfigdto.setBatch(strbatchno); 234 tsqlcheckconfigdto = this.myISqlCheckConfigManager.serchSqlCheckConfig(tsqlcheckconfigdto); 235 java.util.List sqlcheckconfiglist = tsqlcheckconfigdto.getResultList(); 236 //判断是否配置了 数据检查sql 237 if(null != sqlcheckconfiglist&& sqlcheckconfiglist.size()>0){ 238 //执行 数据检查工作 获取执行的 sql 239 for(int i=0;i<sqlcheckconfiglist.size();i++){ 240 241 TSqlCheckConfigDTO temptsqlcheckconfigdto = (TSqlCheckConfigDTO)sqlcheckconfiglist.get(i); 242 //查询有错误记录的记录 243 if(!temptsqlcheckconfigdto.getErrCount().equals("0条")){ 244 //查询有错误记录的记录 245 if(temptsqlcheckconfigdto.getErrCount().endsWith("条")){ 246 // 2017/11/15 liujw 增加邮件内容 检查SQL 检查字段 247 stremailcontent = stremailcontent+"模块名称:"+temptsqlcheckconfigdto.getModuName()+"\t 模块代码:"+temptsqlcheckconfigdto.getModuCode()+"\t 校验结果:"+temptsqlcheckconfigdto.getErrCount()+"错误数据 \t 错误描述:"+temptsqlcheckconfigdto.getRemark()+"\n"+"执行SQL: "+temptsqlcheckconfigdto.getCalSql()+"\t 错误条数: "+temptsqlcheckconfigdto.getJobId()+"\n 错误信息: "+temptsqlcheckconfigdto.getJobName(); 248 }else{ 249 //执行sql时,发生异常的 250 stremailcontent = stremailcontent+"模块名称:"+temptsqlcheckconfigdto.getModuName()+"\t 模块代码:"+temptsqlcheckconfigdto.getModuCode()+"\t 校验结果:执行SQL发生异常,请检查SQL的正确性! \t \t 错误描述:"+temptsqlcheckconfigdto.getRemark()+"\n"+"执行SQL: "+temptsqlcheckconfigdto.getCalSql(); 251 } 252 253 /* //因为目前用不到短信功能 所以注掉 254 255 log.info("模块代码:"+temptsqlcheckconfigdto.getModuCode()+"是否进行短信提示,开始"); 256 log.info("短信提示设置"+temptsqlcheckconfigdto.getSmsalert()); 257 log.info("用户手机号"+personInfodto.getMobile()); 258 259 //判断是否需要做短信提示 260 if(Conts.HAS_SMS_ALERT.equals(temptsqlcheckconfigdto.getSmsalert())){ 261 log.info("准备发送提示短信-"+temptsqlcheckconfigdto.getModuCode()); 262 //检查是否还可以发送短信提示 263 boolean sendsmsflag = this.sendSmsAlertCheck(temptsqlcheckconfigdto,personInfodto); 264 if(sendsmsflag){ 265 this.sendSmsAlert(temptsqlcheckconfigdto,personInfodto); 266 } 267 }else{ 268 log.info("不发送提示短信-"+temptsqlcheckconfigdto.getModuCode()); 269 }*/ 270 } 271 272 } 273 //调用发送短信方法 274 275 }else{ 276 log.error("sqlcheckconfig表中没有该用户可用的SQL查询语句,请去配置!personInfodto="+personInfodto.getName()); 277 } 278 }catch(Exception e){ 279 log.error("getEmailContent to person error personid="+personInfodto.getName()); 280 e.printStackTrace(); 281 } 282 return stremailcontent; 283 } 284 285 286 287 288 //发送短信功能 目前用不到 注掉 289 /*private void sendSmsAlert(TSqlCheckConfigDTO tsqlcheckconfigdto,TPersonInfoDTO personInfodto){ 290 try{ 291 //组装TSMSLogDTO dto 292 TSMSLogDTO dto = new TSMSLogDTO(); 293 dto.setCalCode(tsqlcheckconfigdto.getCalCode()); 294 dto.setPersonID(personInfodto.getPersonID()); 295 dto.setMobile(personInfodto.getMobile()); 296 dto.setAlertType(Conts.SMS_CK_ALERT); 297 String strcontent = "模块名称:"+tsqlcheckconfigdto.getModuName()+"\t模块代码:"+tsqlcheckconfigdto.getModuCode()+"\t 校验结果:"+tsqlcheckconfigdto.getErrCount()+"错误数据 \t 错误描述:"+tsqlcheckconfigdto.getRemark(); 298 dto.setContent(strcontent); 299 //超过300个字,截取300, 300 if(strcontent.length()>300){ 301 strcontent= strcontent.substring(0,300)+"....更多内容,请查看邮件.."; 302 } 303 log.info("请求短信平台mobile="+personInfodto.getMobile()+",strcontent="+strcontent); 304 Sms sms = new Sms(); 305 String sendresult = sms.send(personInfodto.getMobile(), strcontent); 306 log.info("请求短信平台,返回结果="+sendresult); 307 if(sendresult.length()>50) 308 sendresult=sendresult.substring(0,49); 309 dto.setStrresult(sendresult); 310 if(null!=sendresult&&sendresult.startsWith("result=0")){ 311 dto.setStatus(Conts.SMS_SEND_OK); 312 }else{ 313 dto.setStatus(Conts.SMS_SEND_ERROR); 314 } 315 this.myISMSLogManager.addSMSLog(dto); 316 }catch(Exception e){ 317 log.error("发送短信提示信息错误"+e.getMessage()); 318 e.printStackTrace(); 319 } 320 }*/ 321 322 323 324 //发送短信功能 目前用不到 注掉 325 /*private boolean sendSmsAlertCheck(TSqlCheckConfigDTO tsqlcheckconfigdto,TPersonInfoDTO personInfodto){ 326 //1:判断手机号码,2:查询发送短信记录(根据modecode与手机号码),如果超过每小时、每天限量,不在发送 327 //3.调用发送短信方法,4.记录发送的log 328 Boolean cansend = false; 329 try{ 330 log.info("判断是否短信 提示方法开始执行:modecode="+tsqlcheckconfigdto.getModuCode()+",mobile="+personInfodto.getMobile()); 331 if(null==personInfodto.getMobile()||"".equals(personInfodto.getMobile())){ 332 log.info("判断是否短信 ,手机号为空,不做发送"); 333 return cansend; 334 } 335 Pattern p = Pattern.compile("^((13[0-9])|(15[^4,\\D])|(18[0,5-9]))\\d{8}$"); 336 Matcher m = p.matcher(personInfodto.getMobile()); 337 log.info("判断是否短信提示,手机号码"+personInfodto.getMobile()+",验证结果="+m.matches()); 338 if(m.matches()){ 339 int daymaxnum = 5,hourmaxnum=3; 340 try{ 341 ResourceBundle rb = ResourceBundle.getBundle("smsconfig"); 342 String strdaymax = rb.getString("dayMax"); 343 if(null != strdaymax){ 344 daymaxnum = Integer.parseInt(strdaymax); 345 } 346 String strhourmax = rb.getString("hourMax"); 347 if(null != strhourmax){ 348 hourmaxnum = Integer.parseInt(strhourmax); 349 } 350 log.info("系统配置,每天最大发送"+strdaymax+",每小时最大发送="+strhourmax); 351 }catch(Exception e){ 352 log.info("读取配置文件设置失败,使用默认的配置"+e.getMessage()); 353 } 354 355 TSMSLogDTO dto = new TSMSLogDTO(); 356 dto.setCalCode(tsqlcheckconfigdto.getModuCode()); 357 dto.setMobile(personInfodto.getMobile()); 358 java.util.List daysmslist = this.myISMSLogManager.serchSMSLogByDay(dto, null).getResultList(); 359 java.util.List hoursmslist = this.myISMSLogManager.serchSMSLogByHour(dto, null).getResultList(); 360 log.info("已发送数量查询,今天发送="+daysmslist.size()+",本小时发送="+hoursmslist.size()); 361 if(daymaxnum>daysmslist.size()){ 362 if(hourmaxnum>hoursmslist.size()){ 363 cansend = true; 364 }else{ 365 log.info("短信提示超过一小时最大限额,不发送短信提示,"+personInfodto.getMobile()); 366 } 367 }else{ 368 log.info("短信提示已超过一天的最大限额,不发送短信提示,"+personInfodto.getMobile()); 369 } 370 371 }else{ 372 log.info("短信提示无法发送,原因手机号格式不对,"+personInfodto.getMobile()); 373 } 374 375 }catch(Exception e){ 376 log.error("判断是否发送提示短信错误:"+e.getMessage()); 377 e.printStackTrace(); 378 } 379 return cansend; 380 }*/ 381 382 383 384 385 /** 386 * 查出所有关系人,遍历属于它的检查语句 387 * 置所有的检查语句邮件发送状态为已发送 388 * @param tdbConfigDto 389 */ 390 public void setAllSendMailStatus(String strbatchno){ 391 //获取该数据源下的所有用户数据 392 try{ 393 TPersonInfoDTO personInfodto = new TPersonInfoDTO(); 394 //personInfodto.setDbId(tdbConfigDto.getDbId()); 395 personInfodto.setPageSize(9999); 396 personInfodto = this.myIPersonInfoManager.serchPersonInfo(personInfodto); 397 java.util.List personInfodtolist = personInfodto.getResultList(); 398 if(null != personInfodtolist&&personInfodtolist.size()>0){ 399 //遍历用户,查询出结果需要抄送给他的检查语句,置为已发送 400 for(int i=0;i<personInfodtolist.size();i++){ 401 TPersonInfoDTO temppersonInfodto = (TPersonInfoDTO)personInfodtolist.get(i); 402 getAllSQLforPerson(temppersonInfodto,strbatchno); 403 } 404 }else{ 405 log.error("该数据源下没有配置任何接受用户信息"); 406 } 407 }catch(Exception e){ 408 log.error("给数据源下的用户发送邮件发生异常 error="+e.getMessage()); 409 e.printStackTrace(); 410 } 411 } 412 413 414 415 416 /** 417 * 拼接所有需要发送给该用户的数据校验结果 418 * @param personInfodto 419 * @return 420 */ 421 public void getAllSQLforPerson(TPersonInfoDTO personInfodto,String strbatchno){ 422 String stremailcontent = ""; 423 try{ 424 TSqlCheckConfigDTO tsqlcheckconfigdto = new TSqlCheckConfigDTO(); 425 tsqlcheckconfigdto.setPersonID(personInfodto.getPersonID()); 426 tsqlcheckconfigdto.setPageSize(9999); 427 tsqlcheckconfigdto.setValiFlag(Conts.STATUS_ABLE); 428 tsqlcheckconfigdto.setSendMail(Conts.MAIL_NOT_SEND); //未发邮件的记录 429 tsqlcheckconfigdto.setBatch(strbatchno); //同一批次 430 tsqlcheckconfigdto = this.myISqlCheckConfigManager.serchSqlCheckConfig(tsqlcheckconfigdto); 431 java.util.List sqlcheckconfiglist = tsqlcheckconfigdto.getResultList(); 432 //判断是否配置了 数据检查sql 433 if(null != sqlcheckconfiglist&& sqlcheckconfiglist.size()>0){ 434 //执行 数据检查工作 获取执行的 sql 435 log.info("置执行状态为执行完成,邮件已发送开始"); 436 for(int i=0;i<sqlcheckconfiglist.size();i++){ 437 TSqlCheckConfigDTO temptsqlcheckconfigdto = (TSqlCheckConfigDTO)sqlcheckconfiglist.get(i); 438 temptsqlcheckconfigdto.setSendMail(Conts.MAIL_ALREADY_SEND); 439 temptsqlcheckconfigdto.setStatus(Conts.SQL_RUN_OK); 440 this.myISqlCheckConfigManager.updateSqlCheckConfig(temptsqlcheckconfigdto); 441 } 442 log.info("置执行状态为执行完成,邮件已发送结束"); 443 }else{ 444 log.error("getAllSQLforPerson表中没有该用户需要接受的记录!personInfodto="+personInfodto.getName()); 445 } 446 }catch(Exception e){ 447 log.error("getAllSQLforPerson to person error personid="+personInfodto.getPersonID()+";stremailcontent="+stremailcontent); 448 e.printStackTrace(); 449 } 450 } 451 452 453 454 455 private void checkdataForDBSource(TDBConfigDTO tdbConfigDto,Connection conn,java.util.Calendar c,String strbatchno){ 456 //1.获取所有的执行sql,2.通过建立的连接,执行相应的sql,3.记录操作结果 457 //1.获取SqlCheckConfig 列表,根据数据源id 458 try{ 459 //查询出该数据源下的所有执行完成,并且下次执行时间小于等于当前时间 460 TSqlCheckConfigDTO tsqlcheckconfigdto = new TSqlCheckConfigDTO(); 461 tsqlcheckconfigdto.setDbId(tdbConfigDto.getDbId()); 462 tsqlcheckconfigdto.setPageSize(9999); 463 tsqlcheckconfigdto.setStatus("0,2"); //不查询执行中的SQL 464 tsqlcheckconfigdto.setValiFlag(Conts.STATUS_ABLE); //可用 465 tsqlcheckconfigdto.setNextRunTime(new java.util.Date()); 466 //通过给定的查询条件查询出所有可执行的SQL 467 tsqlcheckconfigdto = this.myISqlCheckConfigManager.getNeedRunTSqlCheckConfigDTO(tsqlcheckconfigdto); 468 java.util.List sqlcheckconfiglist = tsqlcheckconfigdto.getResultList(); 469 //判断是否配置了 数据检查sql 470 if(null != sqlcheckconfiglist&& sqlcheckconfiglist.size()>0){ 471 472 //2.通过建立的连接,执行相应的sql 473 log.info("置执行状态为执行中开始"); 474 for(int i=0;i<sqlcheckconfiglist.size();i++){ 475 //遍历所有检查配置记录,首先置执行状态为执行中,设置批次号 476 TSqlCheckConfigDTO temptsqlcheckconfigdto1 = (TSqlCheckConfigDTO)sqlcheckconfiglist.get(i); 477 temptsqlcheckconfigdto1.setStatus(Conts.SQL_RUNNING); 478 temptsqlcheckconfigdto1.setBatch(strbatchno); 479 this.myISqlCheckConfigManager.updateSqlCheckConfig(temptsqlcheckconfigdto1); 480 } 481 log.info("置执行状态为执行中结束"); 482 log.info("遍历执行检查配置记录开始"); 483 for(int j=0;j<sqlcheckconfiglist.size();j++){ 484 //遍历所有检查配置记录 485 TSqlCheckConfigDTO temptsqlcheckconfigdto = (TSqlCheckConfigDTO)sqlcheckconfiglist.get(j); 486 checkdataByTSqlCheckConfigDTO(temptsqlcheckconfigdto,conn,c); 487 } 488 log.info("遍历执行检查配置记录结束"); 489 }else{ 490 log.error("StatSqlConfig表中没有需要执行的检查语句!"); 491 } 492 493 }catch(Exception e){ 494 495 } 496 } 497 498 499 /** 500 * 执行单个 检查sql的执行 501 * @param temptsqlcheckconfigdto 502 */ 503 private void checkdataByTSqlCheckConfigDTO(TSqlCheckConfigDTO temptsqlcheckconfigdto,Connection conn,java.util.Calendar c){ 504 long starttime = System.currentTimeMillis(); 505 try{ 506 507 //首先置执行状态为执行中 508 temptsqlcheckconfigdto.setStatus(Conts.SQL_RUNNING); 509 this.myISqlCheckConfigManager.updateSqlCheckConfig(temptsqlcheckconfigdto); 510 511 512 SSRS rSSRS = new SSRS(); 513 //2017/11/21 新增接受查询数据库信息集合 514 ArrayList<TenSQL> list = new ArrayList<TenSQL>(); 515 //2017/11/15 查询字段放置类 516 //TenSQL tensql = new TenSQL(); 517 518 ExeSQL tExeSQL = new ExeSQL(conn); 519 String tCalSql = temptsqlcheckconfigdto.getCalSql(); 520 tCalSql = tCalSql.replaceAll("’", "'").replaceAll("‘", "'"); 521 if(tCalSql.startsWith("update")||tCalSql.startsWith("insert")||tCalSql.startsWith("delete")){ 522 //暂时屏蔽,如果需要是还原 523 rSSRS = tExeSQL.execUPDATESQL(tCalSql); 524 //rSSRS = tExeSQL.execSQL("select count(*) from (" + tCalSql + ") gq"); 525 }else{ 526 // 2017/11/14 liujw 正式查询SQL 527 //rSSRS = tExeSQL.execSQL("select count(*) from (" + tCalSql + ") gq"); 528 list = tExeSQL.execSQLNew(tCalSql); 529 } 530 531 532 java.util.Date curtime = new java.util.Date(); 533 int m = 0; 534 String listvalue = ""; 535 //执行没有出错 536 if (tExeSQL.mErrors.getErrorCount() == 0) { 537 if (/*rSSRS*/ list!= null) { 538 // 输出集合list中的每条数据 539 for(int i = 0;i<list.size();i++){ 540 log.info(list.get(i)); 541 listvalue += list.get(i)+"\r 下一条:"; 542 m = list.size(); 543 } 544 /* m = rSSRS.getMaxCol(); 545 */ 546 } else { 547 m = 0; 548 } 549 550 /*// for(int i=1;i<=m;i++){ 551 // SQLvalue += (rSSRS.GetText(0, i)+","); 552 // } 553 // 554 */ //更新 检查数据sql记录 ErrCount ,ValiFlag makedate maketime 555 temptsqlcheckconfigdto.setErrCount(m+"条"); 556 temptsqlcheckconfigdto.setValiFlag(Conts.STATUS_ABLE); 557 temptsqlcheckconfigdto.setMakeDate(curtime); 558 temptsqlcheckconfigdto.setMakeTime(PubFun.getCurrentTime()); 559 // 2017/11/22 liujw 新增字段 检查结果的错误信息 560 temptsqlcheckconfigdto.setJobName(listvalue); 561 if(m>0){ 562 //插入一条检查记录sqlcheckresult 563 TSqlCheckResultDTO tsqlcheckresultdto = new TSqlCheckResultDTO(); 564 tsqlcheckresultdto.setCalCode(temptsqlcheckconfigdto.getCalCode()); 565 tsqlcheckresultdto.setDbId(temptsqlcheckconfigdto.getDbId()); 566 tsqlcheckresultdto.setCkTimes(Long.valueOf(System.currentTimeMillis() - starttime).intValue()); 567 tsqlcheckresultdto.setErrCount(m+"条"); 568 tsqlcheckresultdto.setMakeDate(curtime); 569 tsqlcheckresultdto.setMakeTime(PubFun.getCurrentTime()); 570 // 2017/11/15 liujw 将查出的值赋值给JOB_ID字段 571 //2017/11/21 liujw 572 tsqlcheckresultdto.setJOB_ID(listvalue); 573 myISqlCheckResultManager.addSqlCheckResult(tsqlcheckresultdto); 574 } 575 }else { 576 temptsqlcheckconfigdto.setErrCount("SQL中的表或字段不存在"); 577 //temptsqlcheckconfigdto.setValiFlag(Conts.STATUS_ABLE); 578 temptsqlcheckconfigdto.setMakeDate(curtime); 579 temptsqlcheckconfigdto.setMakeTime(PubFun.getCurrentTime()); 580 } 581 582 //置邮件发送状态为未发送 583 temptsqlcheckconfigdto.setSendMail(Conts.MAIL_NOT_SEND); 584 java.util.Calendar c2 = java.util.Calendar.getInstance(); 585 //以执行开始的时间为基数计数下次执行时间,这样保证下次执行时间不会由于执行过程中花费的时间,而导致下次执行时间每次不一样 586 //c2.set(java.util.Calendar.HOUR_OF_DAY, c.get(java.util.Calendar.HOUR_OF_DAY)); 587 //c2.set(java.util.Calendar.MINUTE, c.get(java.util.Calendar.MINUTE)); 588 //c2.add(java.util.Calendar.MINUTE, temptsqlcheckconfigdto.getTimeInteval()); 589 //为解决如果应用故障了,根据上次执行时间,修改下次执行时间。 590 java.util.Calendar cpre = java.util.Calendar.getInstance(); 591 cpre.setTime(temptsqlcheckconfigdto.getNextRunTime()); 592 cpre.add(java.util.Calendar.MINUTE, temptsqlcheckconfigdto.getTimeInteval()); 593 594 log.info("执行"+temptsqlcheckconfigdto.getModuName()+":"+temptsqlcheckconfigdto.getModuCode()+":"+cpre.getTime()); 595 temptsqlcheckconfigdto.setNextRunTime(cpre.getTime()); 596 597 598 long usertime = System.currentTimeMillis() - starttime; 599 temptsqlcheckconfigdto.setUseTime(Long.valueOf(usertime).intValue()); 600 this.myISqlCheckConfigManager.updateSqlCheckConfig(temptsqlcheckconfigdto); 601 602 }catch(Exception e){ 603 //置邮件发送状态为未发送 604 temptsqlcheckconfigdto.setSendMail(Conts.MAIL_NOT_SEND); 605 java.util.Calendar c2 = java.util.Calendar.getInstance(); 606 //以执行开始的时间为基数计数下次执行时间,这样保证下次执行时间不会由于执行过程中花费的时间,而导致下次执行时间每次不一样 607 //c2.set(java.util.Calendar.HOUR_OF_DAY, c.get(java.util.Calendar.HOUR_OF_DAY)); 608 //c2.set(java.util.Calendar.MINUTE, c.get(java.util.Calendar.MINUTE)); 609 //c2.add(java.util.Calendar.MINUTE, temptsqlcheckconfigdto.getTimeInteval()); 610 //为解决如果应用故障了,根据上次执行时间,修改下次执行时间。 611 java.util.Calendar cpre = java.util.Calendar.getInstance(); 612 cpre.setTime(temptsqlcheckconfigdto.getNextRunTime()); 613 cpre.add(java.util.Calendar.MINUTE, temptsqlcheckconfigdto.getTimeInteval()); 614 log.error("执行"+temptsqlcheckconfigdto.getModuName()+":"+temptsqlcheckconfigdto.getModuCode()+":"+cpre.getTime()); 615 temptsqlcheckconfigdto.setNextRunTime(cpre.getTime()); 616 long usertime = System.currentTimeMillis() - starttime; 617 temptsqlcheckconfigdto.setUseTime(Long.valueOf(usertime).intValue()); 618 try{ 619 this.myISqlCheckConfigManager.updateSqlCheckConfig(temptsqlcheckconfigdto); 620 }catch(Exception e1){ 621 } 622 623 log.error("执行单个 检查sql的发生异常,error="+e.getMessage() +",sql="+temptsqlcheckconfigdto.getCalSql()); 624 e.printStackTrace(); 625 } 626 } 627 628 629 630 631 632 //从配置文件获取邮箱信息 633 public boolean getCheckSQLCfg() 634 { 635 try { 636 //ResourceByndle java.util 读取信息 本地化国际化 会自动寻找mainconfig.properties文件 637 ResourceBundle rb = ResourceBundle.getBundle("mailconfig"); 638 SMTPServer = rb.getString("SMTPServer"); 639 From = rb.getString("From"); 640 MailPWD = rb.getString("MailPWD"); 641 To = rb.getString("To"); 642 Port = rb.getString("Port"); 643 } catch (Exception e) { 644 // TODO Auto-generated catch block 645 log.error("读取邮箱信息配置文件mailconfig error="+e.getMessage()); 646 e.printStackTrace(); 647 return false; 648 } 649 return true; 650 } 651 652 653 public IDBConfigManager getMyIDBConfigManager() { 654 return myIDBConfigManager; 655 } 656 657 658 659 660 public void setMyIDBConfigManager(IDBConfigManager myIDBConfigManager) { 661 this.myIDBConfigManager = myIDBConfigManager; 662 } 663 664 665 666 667 public ISqlCheckConfigManager getMyISqlCheckConfigManager() { 668 return myISqlCheckConfigManager; 669 } 670 671 672 673 674 public void setMyISqlCheckConfigManager( 675 ISqlCheckConfigManager myISqlCheckConfigManager) { 676 this.myISqlCheckConfigManager = myISqlCheckConfigManager; 677 } 678 679 680 681 682 public IPersonInfoManager getMyIPersonInfoManager() { 683 return myIPersonInfoManager; 684 } 685 686 687 688 689 public void setMyIPersonInfoManager(IPersonInfoManager myIPersonInfoManager) { 690 this.myIPersonInfoManager = myIPersonInfoManager; 691 } 692 693 694 695 696 public ISqlCheckResultManager getMyISqlCheckResultManager() { 697 return myISqlCheckResultManager; 698 } 699 700 701 702 703 public void setMyISqlCheckResultManager( 704 ISqlCheckResultManager myISqlCheckResultManager) { 705 this.myISqlCheckResultManager = myISqlCheckResultManager; 706 } 707 708 709 710 711 public java.util.List getDbidlist() { 712 return dbidlist; 713 } 714 public void setDbidlist(java.util.List dbidlist) { 715 this.dbidlist = dbidlist; 716 } 717 public String getDbids() { 718 return dbids; 719 } 720 public void setDbids(String dbids) { 721 this.dbids = dbids; 722 } 723 public String getSMTPServer() { 724 return SMTPServer; 725 } 726 public void setSMTPServer(String sMTPServer) { 727 SMTPServer = sMTPServer; 728 } 729 public String getSubject() { 730 return Subject; 731 } 732 public void setSubject(String subject) { 733 Subject = subject; 734 } 735 public String getMailPWD() { 736 return MailPWD; 737 } 738 public void setMailPWD(String mailPWD) { 739 MailPWD = mailPWD; 740 } 741 public String getFrom() { 742 return From; 743 } 744 public void setFrom(String from) { 745 From = from; 746 } 747 public String getPort() { 748 return Port; 749 } 750 public void setPort(String port) { 751 Port = port; 752 } 753 public String getSendBody() { 754 return SendBody; 755 } 756 public void setSendBody(String sendBody) { 757 SendBody = sendBody; 758 } 759 }
package com.ab.itws.common; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import org.apache.log4j.Logger; import com.ab.itws.dbcheck.dto.TDBConfigDTO; public class DBUtil { private static final Logger log = Logger.getLogger(DBUtil.class); public Connection getConnByDBTYPE(TDBConfigDTO tdbConfigDto){ Connection conn = null; if(null != tdbConfigDto){ String IP = tdbConfigDto.getIp(); String Port = tdbConfigDto.getPort(); String DBName = tdbConfigDto.getDbSid(); String UserName = tdbConfigDto.getDbUser(); String PassWord = tdbConfigDto.getPassWord(); String dbType= tdbConfigDto.getDbType(); if(null==dbType||"".equals(dbType)){ dbType= Conts.DBTYPE_ORACLE; } if(dbType.equals(Conts.DBTYPE_ORACLE)){ log.info("开始获取oracle数据库连接"); conn = this.getOracleConn(tdbConfigDto); }else if(dbType.equals(Conts.DBTYPE_DB2)){ log.info("开始获取db2数据库连接"); conn = this.getDB2Conn(tdbConfigDto); }else if(dbType.equals(Conts.DBTYPE_MYSQL)){ log.info("开始获取mysql数据库连接"); conn = this.getMySQLConn(tdbConfigDto); }else if(dbType.equals(Conts.DBTYPE_SQLSERVER)){ log.info("开始获取sqlserver数据库连接"); conn = this.getSQLServerConn(tdbConfigDto); }else{ log.info("数据类型无对应的获取连接方法,dbType="+dbType); } } return conn; } /** * 获取oracle数据库连接 * @param tdbConfigDto * @return */ public Connection getOracleConn(TDBConfigDTO tdbConfigDto){ Connection conn = null; if(null != tdbConfigDto){ String IP = tdbConfigDto.getIp(); String Port = tdbConfigDto.getPort(); String DBName = tdbConfigDto.getDbSid(); String UserName = tdbConfigDto.getDbUser(); String PassWord = tdbConfigDto.getPassWord(); String dbUrl = "jdbc:oracle:thin:"+UserName+"/"+PassWord+"@"+IP+":"+Port+":"+DBName; try { Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); conn=DriverManager.getConnection(dbUrl,UserName,PassWord); } catch (Exception e) { log.error("数据库连接失败"); //给数据源创建者发送邮件 e.printStackTrace(); } } return conn; } /** * 获取DB2数据库连接 * @param tdbConfigDto * @return */ public Connection getDB2Conn(TDBConfigDTO tdbConfigDto){ Connection conn = null; if(null != tdbConfigDto){ String IP = tdbConfigDto.getIp(); String Port = tdbConfigDto.getPort(); String DBName = tdbConfigDto.getDbSid(); String UserName = tdbConfigDto.getDbUser(); String PassWord = tdbConfigDto.getPassWord(); String dbUrl = "jdbc:db2://"+IP+":"+Port+"/"+DBName; try { Class.forName("com.ibm.db2.jcc.DB2Driver").newInstance(); conn=DriverManager.getConnection(dbUrl,UserName,PassWord); } catch (Exception e) { log.error("数据库连接失败"); //给数据源创建者发送邮件 e.printStackTrace(); } } return conn; } /** * 获取MySQL数据库连接 * @param tdbConfigDto * @return */ public Connection getMySQLConn(TDBConfigDTO tdbConfigDto){ Connection conn = null; if(null != tdbConfigDto){ String IP = tdbConfigDto.getIp(); String Port = tdbConfigDto.getPort(); String DBName = tdbConfigDto.getDbSid(); String UserName = tdbConfigDto.getDbUser(); String PassWord = tdbConfigDto.getPassWord(); String dbUrl = "jdbc:mysql://"+IP+":"+Port+"/"+DBName+ "?useUnicode=true&characterEncoding=GB2312"; try { Class.forName("com.mysql.jdbc.Driver").newInstance(); conn=DriverManager.getConnection(dbUrl,UserName,PassWord); } catch (Exception e) { log.error("数据库连接失败"); //给数据源创建者发送邮件 e.printStackTrace(); } } return conn; } /** * 获取SQLServer数据库连接 * @param tdbConfigDto * @return */ public Connection getSQLServerConn(TDBConfigDTO tdbConfigDto){ Connection conn = null; if(null != tdbConfigDto){ String IP = tdbConfigDto.getIp(); String Port = tdbConfigDto.getPort(); String DBName = tdbConfigDto.getDbSid(); String UserName = tdbConfigDto.getDbUser(); String PassWord = tdbConfigDto.getPassWord(); String dbUrl = "jdbc:sqlserver://"+IP+":"+Port+";DatabaseName="+DBName; try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance(); conn=DriverManager.getConnection(dbUrl,UserName,PassWord); } catch (Exception e) { log.error("数据库连接失败"); //给数据源创建者发送邮件 e.printStackTrace(); } } return conn; } /** * @author liujw 2017/11/21 * @param rs 查询的结果集 * @param c 结果集的一条记录,一条记录对应一个dao * @return * @throws SQLException */ public static Object getFirstObjectFromRs(ResultSet rs,Class<?> c)throws SQLException{ Object o = null; try{ o= initObjectFromRsIfExist(rs, c); }catch (Exception e) { log.error("实例化"+c+"出错,我也不知道为嘛自己看"); e.printStackTrace(); } return o; } /** * @author liujw 2017/11/21 * 把数据库的一条记录映射到相应的dao对象中, * 如果dao中的字段与数据库字段不一致,返回的就是dao数据类型定义的默认值 * 如:dao的字段String contno;而数据库的字段是contno_id,那么返回的就对应的默认值"". * @param rs 查询的结果集 * @param c 结果集的一条记录,一条记录对应一个dao * @return * @throws IllegalAccessException * @throws InstantiationException * @throws SQLException * */ private static Object initObjectFromRsIfExist(ResultSet rs, Class<?> c) throws InstantiationException, IllegalAccessException, SQLException { Object o = c.newInstance(); //实例化新对象dao Method[] methods = o.getClass().getMethods(); //得到dao的所有方法 String ff; for(Method m : methods){ ff = m.getName().substring(3);//得到dao字段 get/set方法 从第三个字节截取 //查询dao映射的字段是否在记录在数据库包含的字段,dao方法对set开头的方法进行处理 //因为要将结果集映射到dao里面 if(m.getName().startsWith("set") && rsContainsFields(rs, ff)){ try{ m.invoke(o, getParamValueFromRs(rs, m)); }catch(IllegalArgumentException e) { log.error(e); throw new RuntimeException("IllegalArgumentException:" + e + "\nMethods:" + m.getName()); }catch (Exception e) { log.error(e); throw new RuntimeException("InvocationTargetException:" + e + "\nMethods:" + m.getName()); } } } return o; } /** * 2017/11/21 liujw * @param rs 查询的结果集 * @param m dao映射字段对应的一个set方法 * @return * @throws SQLException */ private static Object getParamValueFromRs(ResultSet rs, Method m) throws SQLException { String ff = m.getName().substring(3); //得到dao的字段名 Type type = m.getGenericParameterTypes()[0];//获取set方法参数的类型 return getValueFromRs(rs, ff, type); } /** * 获取数据库一条记录的一个列值 * @param rs 查询的结果集 * @param ff dao数据字段,也就是数据库记录的数据字段类型 * @param t 参数的数据类型 * @return * @throws SQLException */ private static Object getValueFromRs(ResultSet rs, String ff, Type t) throws SQLException { String type = t.toString(); try{ //因为目前定影的字段类型都是String 且String比较好用 建议都用String if(type.equals("int") || type.equals("class java.lang.Integer")){ return rs.getInt(ff); }else if(type.equals("class java.lang.String")){ return rs.getString(ff); } }catch(SQLException e){ throw new SQLException("SQLException when get field:" + ff + "\n" + e); } throw new RuntimeException("getValueFromRsByField fail, field type is:" + type + ",field name is:" + ff); } /** * 查询dao映射的字段是否在记录在数据库包含的字段 * @param rs 查询的结果集 * @param ff dao映射的字段 * @return 如果包含在数据库记录集里面,返回true,否则false * @throws SQLException */ private static boolean rsContainsFields(ResultSet rs, String ff) throws SQLException { ResultSetMetaData md = rs.getMetaData(); // 得到结果集(rs)的结构,比如字段数、字段名等。 for(int i = 0; i < md.getColumnCount(); i++){ //列数 if(md.getColumnName(i + 1).equalsIgnoreCase(ff)){ return true; } } return false; } }
其他的一些零碎的配置和代码就不一一展示了,这里只把主要的配置和逻辑展示出来,如果有问题和想法请联系我. 代码比较繁琐,没有用注解,最近在学习注解.