对天乙社区bbscs8实现的详细分析十一

本文详细介绍了论坛系统中各种任务调度的实现方法,包括基于时间的任务调度、邮件发送服务、用户在线状态清理等,并深入解析了Spring框架下的定时任务配置。

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

此文为转载:http://www.diybl.com/course/1_web/webjs/2007113/82989.html



到这里为此,我们已经将主要的业务逻辑给理解完成了,也将bean包、service包和service.imp及service.web,以及dao层和fio层包大部分内容都讲了一遍.现在我们将service层包中还剩下的几个主要包(scheduling和task)给讲一遍,首先我们还是从com.laoer.bbscs.service.mail包的TemplateMail开始,这是一个发mail的服务类文件,引入了tempConfiguartaion和sysConfig,并且使用了Jakarta发布了Commons Emails版HtmlEmail,使用时,先用init()初始化,再使用之:
public void init() throws Exception {
if (this.getSysConfig().getSmtpAuth() == 1) {//是否服务器需授权
   DefaultAuthenticator defaultAuthenticator = new DefaultAuthenticator(
     this.getSysConfig().getSmtpUser(), this.getSysConfig()
       .getSmtpPasswd());//加入帐号密码
   this.getHtmlEmail().setAuthenticator(defaultAuthenticator);
}

this.getHtmlEmail().setHostName(this.getSysConfig().getSmtpServer());
this.getHtmlEmail().setSmtpPort(this.getSysConfig().getSmtpPort());
this.getHtmlEmail().setFrom(this.getSysConfig().getSenderEmail());
this.getHtmlEmail().setTextMsg(
    "Your email client does not support HTML messages");
this.getHtmlEmail().setCharset(Constant.CHARSET);//stmp服务器配置

this.getTempConfiguration().setDirectoryForTemplateLoading(new File(Constant.ROOTPATH + Constant.FTL_PATH));
this.getTempConfiguration().setDefaultEncoding(Constant.CHARSET);
this.getTempConfiguration().setNumberFormat("0.##########");//freemarker模板初始化
}
使用时,用sendMainFromTemplate,附加一些参数,便能发送基于Html的邮件了!其中的ftlName可是补填充的mailSend.ftl或mailSendTopic.ftl(见WEB-INF/templates/..),这里需要知道的是java.io.StringWriter类extends Writer ,它将输出收集到一个字符缓存区中的一个字符流,用于构造一个串.(具体指的是将板里包含的所有内容(格式化后)输出成流形式吧)
/**
flush()
清空流。
getBuffer()
返回串缓存区。
toString()
返回作为一个串的缓存区的当前值
*/
public void sendMailFromTemplate(String to, String subject, String ftlName,
   Map root, Locale locale) {
this.getTempConfiguration().setLocale(locale);
try {
   this.getHtmlEmail().setSubject(subject);
   Template temp = this.getTempConfiguration().getTemplate(ftlName);
   StringWriter sw = new StringWriter();
   temp.process(root, sw);//ftl文件--->sw流,可见FreeMarker和Spring的API
   this.getHtmlEmail().setHtmlMsg(sw.toString());
   this.getHtmlEmail().addTo(to);
   this.getHtmlEmail().send();
   sw.flush();
} catch (Exception e) {
   logger.error(e);
}
}
接下来,我将分析spring中的计划任务和调度,资料请查考:
http://book.youkuaiyun.com/bookfiles/167/1001677368.shtml<spring in action>
第一步是从java.util.TimerTask中派生,run()方法定义了当任务运行时该做什么。调度定时器任务:Spring的ScheduledTimerTask定义了一个定时器任务的运行周期。属性timerTask告诉ScheduledTimerTask运行哪个TimerTask。属性period告诉ScheduledTimerTask以怎样的频度调用TimerTask的run()方法。这个属性以毫秒作为单位.最后一步是启动定时器。Spring的TimerFactoryBean负责启动定时任务。按以下方式在Spring配置文件中声明它,属性scheduledTimerTasks要求一个需要启动的定时器任务的列表,即使使用deplay属性,Task的第一次运行时间仍然是相对于应用程序的启动时间的。为了能够精确指定何时发送电子邮件,你需要使用Quartz调度器.
定义Quartz工作的第一步是创建一个类来定义工作。要做到这一点,你需要从Spring的QuartzJobBean中派生子类,QuartzJobBean是Quartz中与Java的TimerTask等价的类。它实现了org.quartz.Job接口。executeInternal()方法定义了当预定的时刻来临时应该执行哪些动作。JobDetailBean是applicationContext.xml中定义,jobClass和jobDataAsMap,Quartz的org.quartz.Trigger类描述了何时及以怎样的频度运行一个Quartz工作。CronTriggerBean允许你更精确地控制任务的运行时间(其中属性cronExpression告诉触发器何时触发).Spring的SchedulerFactoryBean是Quartz中与TimerFactoryBean等价的类,属性triggers接受一组触发器。OK!
我们的系统要两种调度方式是由于其中之一是对时间的精确度决定的,首先看BoardCountTimerTask,应该是对版区帖子数的计算吧:作为一个服务,先引入logger!它继承了TimerTask,并且注入了BoardService和CommendSerivce两个,可见applicationContext:
<bean id="boardCount"
class="com.laoer.bbscs.service.task.BoardCountTimerTask">
<property name="boardService">
   <ref local="boardService" />
</property>
<property name="commendService">
   <ref local="commendService" />
</property>
</bean>
看它的run()方法:
public void run() {
    try {
      logger.info("Board count start...");
      this.getBoardService().saveBoardsPostNumCount();//所有版区的帖子(包括主帖和帖子数统计,帖子有历史帖和forum帖)
      this.getCommendService().createCommendTopFile(10);//前十的推荐帖写入文件 hql:from Commend where commendTop = ? order by createTime desc commendTop是否推荐到首页0为是,注意写入到文件时的方法参数0指的文件名字符,没其它作用 include/Commend_0.html
      logger.info("Board count end");
    }
    catch (BbscsException ex) {
      logger.error(ex);
    }
}
好了,看下spring中怎么用这个Task:(调度配置)
<bean id="boardCountTimerTask"
class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="delay">
   <value>10000</value>//10秒
</property>
<property name="period">
   <value>1800000</value>//30分钟一次
</property>
<property name="timerTask">
   <ref local="boardCount" />//用的是谁?
</property>
</bean>
对于启动,则由timerFactory寄居:
<bean id="timerFactory"
class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
   <list>
    <ref local="loginErrorClearTimerTask" />//包括所有的TimerTask事件!
    <ref local="voteUserClearTimerTask" />
    <ref local="forumHistoryTimerTask" />
    <ref local="userOnlineClearTimerTask" />
    <ref local="boardCountTimerTask" />
    <ref local="subscibeSendTimerTask" />
   </list>
</property>
</bean>

接下来,我们看ForumHistoryTimerTask:
public void run() {
long htime = (long) (this.getSysConfig().getPostToHistoryDay()) * 24l * 3600000l;//用于了SysConfig配置服务,htime是个间隔时间,注意l为long!
/**
public int getPostToHistoryDay() {
return this.getIntValue("PostToHistoryDay", 90);
}
*/
long atime = System.currentTimeMillis() - htime;//90天前的long型时间值
try {
   logger.info("ForumHistory Move Start...");
   logger.info("htime:" + htime + " atime:" + atime);
   this.getForumService().removeToHistory(atime);移动到forumHistory表
   logger.info("ForumHistory Move End");
} catch (BbscsException ex) {
   logger.error(ex);
}
}
/**
public void removeToHistory(long atime) throws BbscsException {
List ml = this.getForumDAO().findForumsToHistory(atime);//见下
for (int i = 0; i < ml.size(); i++) {
   Forum f = (Forum) ml.get(i);
   List fl = this.getForumDAO().findForumsTopic(f.getBoardID(), f.getId(), 0, 0, -1, null);//找到以这个帖子为mainId版区内的所有回复帖,它们跟随一起进入历史!
   for (int j = 0; j < fl.size(); j++) {
    Forum mf = (Forum) fl.get(j);
    Forum fh = new ForumHistory();
    try {
     BeanUtils.copyProperties(fh, mf);//拷贝bean属性
     this.getForumHistoryDAO().saveForum(fh);//加入历史
     this.getForumDAO().removeForum(mf);//从froum中去之
    } catch (Exception ex) {
     logger.error(ex);
     throw new BbscsException(ex);
    }
   }
}
}

public List findForumsTopic(final long bid, final String mainID, final int delSign, final int auditing,
   final int auditingAttachFile, final OrderObj[] oo) {
return getHibernateTemplate().executeFind(new HibernateCallback() {
   public Object doInHibernate(Session s) throws HibernateException {
    Criteria c = s.createCriteria(getForumClass());
    c.add(Restrictions.eq("mainID", mainID));
    c.add(Restrictions.eq("boardID", new Long(bid)));
    if (delSign != -1) {
     c.add(Restrictions.eq("delSign", new Integer(delSign)));
    }
    if (auditing != -1) {
     c.add(Restrictions.eq("auditing", new Integer(auditing)));
    }
    if (auditingAttachFile != -1) {
     c.add(Restrictions.eq("auditingAttachFile", new Integer(auditingAttachFile)));
    }

    if (oo != null && oo.length > 0) {
     for (int i = 0; i < oo.length; i++) {
      if (StringUtils.isNotBlank(oo[i].getOrderBy())) {
       if (oo[i].getAscOrDesc() == Constant.ORDER_ASC) {
        c.addOrder(Order.asc(oo[i].getOrderBy()));
       }
       if (oo[i].getAscOrDesc() == Constant.ORDER_DESC) {
        c.addOrder(Order.desc(oo[i].getOrderBy()));
       }
      }
     }
    }
    return c.list();
   }
});
}
public List findForumsToHistory(long atime) {
String sql = "from ForumMain where isNew = 1 and elite = 0 and lastTime <= ?";
return this.getHibernateTemplate().find(sql, new Long(atime));
}
*/
我们看它的配置:
<bean id="forumHistoryTimerTask"
class="org.springframework.scheduling.timer.ScheduledTimerTask">
   <property name="delay">
   <value>43200000</value>
</property>
<property name="period">
   <value>43200000</value> //12个小时!
</property>
<property name="timerTask">
   <ref local="forumHistoryTimer" />
</property>
</bean>
<bean id="forumHistoryTimer"
class="com.laoer.bbscs.service.task.ForumHistoryTimerTask">
<property name="forumService">
   <ref local="forumService" />//需注意它加入了事务处理功能!!!
</property>
<property name="sysConfig">
   <ref bean="sysConfig" />
</property>
</bean>

下面看LoginErrorClearTimerTask:
public void run() {
    long atime = System.currentTimeMillis() - (15 * 6000);//比现在晚15*6000/1000=90秒以上的错误!
    try {
      logger.info("Start LoginErrorClearTimerTask...");
      this.getLoginErrorService().removeLoginErrorsOutTime(atime);//简单方法哦!
      logger.info("End LoginErrorClearTimerTask");
    }
    catch (BbscsException ex) {
      logger.error(ex);
    }
}
它在spring中的配置:
<bean id="loginErrorClearTimerTask"
class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="delay">
   <value>15000</value>//15秒
</property>
<property name="period">
   <value>900000</value>//15分钟
</property>
<property name="timerTask">
   <ref local="loginErrorClear" />
</property>
</bean>

看SubscibeSendTimerTask在applicationContext中的bean配置:
<bean id="subscibeSend"
class="com.laoer.bbscs.service.task.SubscibeSendTimerTask">
<property name="subscibeService">
   <ref local="subscibeService" />
</property>
<property name="subscibeQueue">
   <ref local="subscibeQueue" />
</property>
<property name="noteFactory">
   <ref local="noteFactory" />
</property>
<property name="noteService">
   <ref bean="noteService" />
</property>
<property name="messageSource">
   <ref bean="messageSource" />
</property>
<property name="templateMail">
   <ref bean="templateMail" />
</property>
<property name="sysConfig">
   <ref bean="sysConfig" />
</property>
<property name="boardService">
   <ref bean="boardService" />
</property>
<property name="forumService">
   <ref local="forumService" />
</property>
</bean>
--><bean id="boardService" parent="txProxyTemplate">
<property name="target">
   <ref bean="boardTarget" />
</property>
</bean>
<bean id="noteFactory"
class="com.laoer.bbscs.service.imp.NoteFactoryImp">
</bean>
<bean id="templateMail"
class="com.laoer.bbscs.service.mail.TemplateMail" scope="prototype"
init-method="init">
<property name="sysConfig">
   <ref bean="sysConfig" />
</property>
</bean>
public void run() {
logger.info("Send Subscibe, subscibeQueue's Num:" + this.getSubscibeQueue().size());
/**
subscibeQueue其实是com.laoer.bbscs.comm.SysQueue,它是一个队列类,由Vector同步存取东西,大多方法都是syncharonized:
public synchronized void add(Object o) {
aVector.add(o);
}
public synchronized Object get() {
if (isEmpty()) {
   return null;
}
Object o = aVector.elementAt(0);
aVector.removeElementAt(0);
return o;
}
*/
while (this.getSubscibeQueue().size() > 0) {//队列中有subscibe才执行!
   Forum f = (Forum) this.getSubscibeQueue().get();
/**
public synchronized Object get() {
if (isEmpty()) {
   return null;
}
Object o = aVector.elementAt(0);//队头取,并且减一
aVector.removeElementAt(0);
return o;
}
*/
   if (f != null) {//有数据
    List sendlist = this.getSubscibeService().findSubscibesSend(f.getMainID(), f.getBoardID());//最后查询的HQL"from Subscibe where postID = ?";//找到订阅了post为f的主帖的所有subscibe(因为有许多人订)
    Date sdate = new Date();
    for (int i = 0; i < sendlist.size(); i++) {
     Subscibe subs = (Subscibe) sendlist.get(i);
     if (!subs.getUserID().equals(f.getUserID())) {//不是自己啊!
      if (subs.getMsginform() == 1) {//短信方式
       Note inboxNote = this.getNoteFactory().getInstance(subs.getUserID());//由userID产生一个Note对象
       inboxNote.setCreateTime(sdate);
       inboxNote.setFromID(f.getUserID());
       inboxNote.setFromNickName(f.getNickName());
       inboxNote.setFromUserName(f.getUserName());
       inboxNote.setIsNew(1);
       inboxNote.setIsRe(0);
       inboxNote.setNeedRe(0);
       String t = "<a href=""
         + BBSCSUtil.getActionMappingURLWithoutPrefix("read?action=topic&bid="
           + f.getBoardID() + "&id=" + f.getMainID()) + "">" + f.getTitle() + "</a>";
       inboxNote.setNoteContext(this.getMessageSource().getMessage("subs.content",
         new String[] { t }, BBSCSUtil.getLocale(subs.getUserLocale())));
       inboxNote.setNoteTitle(this.getMessageSource().getMessage("subs.title",
         new String[] { BBSCSUtil.getSpeShortString(f.getTitle(), 40, "...") },
         BBSCSUtil.getLocale(subs.getUserLocale())));
       inboxNote.setNoteType(1);
       inboxNote.setToID(subs.getUserID());//to是订阅者
       inboxNote.setToNickName(subs.getNickName());
       inboxNote.setToUserName(subs.getUserName());
       inboxNote.setSysMsg(1);//系统消息
       try {
        this.getNoteService().saveNote(inboxNote);
       } catch (BbscsException ex) {
        logger.error(ex);
       }
      }
      if (subs.getEmailinform() == 1) {
       if (StringUtils.isNotBlank(subs.getUserEmail()) && this.getSysConfig().getUseEmail() == 1) {//可以发信并且用户信箱不为空
        Board board = this.getBoardService().getBoardByID(f.getBoardID());
        if (board != null) {//有这个帖子所在的论坛
         try {

          String detail = this.getForumService().getForumDetail(f, false);
          if (f.getEditType() == 0) {
           detail = BBSCSUtil.filterText(detail, (board.getAllowHTML() == 1),
             (board.getAllowUBB() == 1), true);

          }
Stringsubject = f.getTitle();
          Map<String, String> root = new HashMap<String, String>();
          root.put("website", this.getSysConfig().getWebName());//sysConfig服务
          root.put("title", f.getTitle());
          root.put("detail", detail);
          root.put("url", "");
          this.getTemplateMail().sendMailFromTemplate(subs.getUserEmail(), subject,
            "mailSend.ftl", root, BBSCSUtil.getLocale(subs.getUserLocale()));//调用TemplateMail完成发信

         } catch (Exception ex7) {
          ex7.printStackTrace();
          logger.error(ex7);
         }
        }
       }
      }
     }
    }
   }
}
logger.info("Send Subscibe End");

}
这里注入了MessageSource,注意它有三个参数:code,arg,locale.让我们进入它的内容BaseAction.properties:
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
   <list>
    <value>com.laoer.bbscs.web.action.BaseAction</value>
   </list>
</property>
</bean>
我们查找subs.content和subs.title两项内容:
subs.title=订阅主题通知:《{0}》
subs.content=您订阅的帖子有人回复了,标题《{0}》
new String[] { t }为content的arg,其中String t = "<a href=""
         + BBSCSUtil.getActionMappingURLWithoutPrefix("read?action=topic&bid="
           + f.getBoardID() + "&id=" + f.getMainID()) + "">" + f.getTitle() + "</a>";
好了,让我们看看subscibe的时间配置:
<bean id="subscibeSendTimerTask"
class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="delay">
   <value>300000</value>//5分钟
</property>
<property name="period">
   <value>300000</value>//5分钟
</property>
<property name="timerTask">
   <ref local="subscibeSend" />
</property>
</bean>


Go on!UserOnlineTimerTask:
public void run() {
    long atime = System.currentTimeMillis() - 3600000;//1个小时清理一次
    try {
      logger.info("UserOnline Clear...");
      this.getUserOnlineService().removeUserOnlineOutTime(atime);//最终的HQL:private static final String REMOVE_ALL_OUTTIME = "delete from UserOnline where onlineTime < ?";
      logger.info("UserOnline Clear End");
    }
    catch (BbscsException ex) {
      logger.error(ex);
    }
}
<bean id="userOnlineClearTimerTask"
class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="delay">
   <value>3600000</value>//1个小时
</property>
<property name="period">
   <value>3600000</value>
</property>
<property name="timerTask">
   <ref local="userOnlineClear" />
</property>
</bean>

还有一个VoteUserClearTimerTask:
public void run() {
    long atime = System.currentTimeMillis() - (24 * 3600000);//24小时
    try {
      logger.info("Vote user clear...");
      this.getAgreeAgainstService().removeOutTime(atime);//去掉过时的对帖子支持反对记录,最终HQL: private static final String REMOVE_OUTTIEM = "delete from AgreeAgainst where createTime < ?";//一天不一样!
      this.getVoteUserService().removeOutTime(atime);
      logger.info("Vote user clear end");
    }
    catch (BbscsException ex) {
      logger.error(ex);
    }
}
<bean id="voteUserClearTimerTask"
class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="delay">
   <value>45000</value> //45秒
</property>
<property name="period">
   <value>86400000</value>//24小时
</property>
<property name="timerTask">
   <ref local="voteUserClear" />
</property>
</bean>

好了,我们对scheduling包中的内容进行分析:
ForumArchivesJob首先继承了QuartzJobBean,而executeInternal()是它的重要方法:
protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
try {
   logger.info("###存档###");
   this.getForumArchivesService().createForumArchives();//见本文开头的讲述!
   logger.info("###存档结束###");
} catch (BbscsException e) {
   logger.error(e);
}
我们主要看它在spring的配置文件中的定义:
<bean name="forumArchivesJob"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
   <value>
    com.laoer.bbscs.service.scheduling.ForumArchivesJob
   </value>
</property>
<property name="jobDataAsMap">
   <map>
    <entry key="forumArchivesService">
     <ref local="forumArchivesService" />
    </entry>
   </map>
</property>
</bean>
}
其时间定制器:
<bean id="forumArchivesJobCronTrigger"
class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
   <ref bean="forumArchivesJob" />
</property>
<property name="cronExpression">
   <value>0 30 4 1 * ?</value> 每个月一号早上4:30运行
</property>
</bean>
而启动者:
<bean
class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
   <list>
    <ref local="sysNumStatJobCronTrigger" />
    <ref local="userTopFileJobCronTrigger" />
    <ref local="forumArchivesJobCronTrigger" />
   </list>
</property>
</bean>

看下一个:SysNumStatJob
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
java.util.Calendar cld = java.util.Calendar.getInstance();
cld.setTime(new Date());
cld.add(java.util.Calendar.DATE, -1);//5.19(统计前一天)
logger.info(Util.formatDate(cld.getTime()) + " 统计数据");

SysNumStat snsnow = new SysNumStat();//生成一个bean
snsnow.setCreateTime(System.currentTimeMillis());
long usernumall = this.getUserService().getAllUserNum();
logger.info("社区人数:" + usernumall);
long postNum = this.getForumService().getForumNum(-1) + this.getForumHistoryService().getForumNum(-1);
/**
public long getForumDelNum(long bid) {
return this.getForumDAO().getForumNum(bid, -1, 1, -1, -1);
}bid=-1为所有版区
*/
long postMainNum = this.getForumService().getForumMainNum(-1)
    + this.getForumHistoryService().getForumMainNum(-1);
logger.info("主题数:" + postMainNum);//今天数
logger.info("帖子总数:" + postNum);
snsnow.setNum0(usernumall);
snsnow.setNum1(postMainNum);
snsnow.setNum2(postNum);
snsnow.setNum3(0);
snsnow.setNum4(0);
snsnow.setNum5(0);

cld.add(java.util.Calendar.DATE, -1);//5.18
logger.info("查找 " + Util.formatDate(cld.getTime()) + " 数据");
SysNumStat sns = this.getSysNumStatService().findSysNumStatByRecDate(Util.formatDate4(cld.getTime()));//最终得到private static final String LOAD_BY_RECDATE = "from SysNumStat where recDate = ?";

if (sns == null) {
   snsnow.setNumInc0(0);
   snsnow.setNumInc1(0);
   snsnow.setNumInc2(0);
   snsnow.setNumInc3(0);
   snsnow.setNumInc4(0);
   snsnow.setNumInc5(0);
} else {
   snsnow.setNumInc0(usernumall - sns.getNum0());//昨天增加数,见下:
/**
`Num0` int(11) default ?', //注册人数
`NumInc0` int(11) NOT NULL default ?', //注册人数增加数
`Num1` int(11) NOT NULL default ?', //主题数
`NumInc1` int(11) NOT NULL default ?', //主题增加数
`Num2` int(11) NOT NULL default ?', //帖子总数
`NumInc2` int(11) NOT NULL default ?', //帖子总数增加数
*/
   snsnow.setNumInc1(postMainNum - sns.getNum1());
   snsnow.setNumInc2(postNum - sns.getNum2());
   snsnow.setNumInc3(0);
   snsnow.setNumInc4(0);
   snsnow.setNumInc5(0);
}

cld.add(java.util.Calendar.DATE, 1);//5.19
logger.info("记录 " + Util.formatDate(cld.getTime()) + " 数据");
try {
   this.getSysNumStatService().saveSysNumStat(Util.formatDate4(cld.getTime()), snsnow);//5.19
} catch (BbscsException ex) {
   logger.error(ex);
}
}
好,我们看它的配置:
<bean name="sysNumStatJob"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
   <value>
    com.laoer.bbscs.service.scheduling.SysNumStatJob
   </value>
</property>
<property name="jobDataAsMap">
   <map>
    <entry key="sysNumStatService">
     <ref local="sysNumStatService" />
    </entry>
    <entry key="userService">
     <ref local="userService" />
    </entry>
    <entry key="forumService">
     <ref local="forumService" />
    </entry>
    <entry key="forumHistoryService">
     <ref local="forumHistoryService" />
    </entry>
   </map>
</property>
</bean>
<bean id="sysNumStatJobCronTrigger"
class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
   <ref bean="sysNumStatJob" />
</property>
<property name="cronExpression">
   <value>0 0 1 * * ?</value>//每天早上1点的时候运行
</property>
</bean>
我们这里可以参考下面的资料:
cronExpression配置说明
字段   允许值   允许的特殊字符
秒    0-59    , - * /
分    0-59    , - * /
小时    0-23    , - * /
日期    1-31    , - * ? / L W C
月份    1-12 或者 JAN-DEC    , - * /
星期    1-7 或者 SUN-SAT    , - * ? / L C #
年(可选)    留空, 1970-2099    , - * /

OK!我们看最后一个:UserTopFileJob
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
    logger.info("Create User Top File Start");
    try {
      this.getUserTopService().createUserTopFile();//这个方法调用我们唯一讲过的UserTopServiceImp中的那个方法,建立三个html文件!
    }
    catch (BbscsException ex) {
      logger.error(ex);
    }
    logger.info("Create User Top File End");
}
我们看看spring在applicationContext.xml中配置:
<bean name="userTopFileJob"
class="org.springframework.scheduling.quartz.JobDetailBean">
<property name="jobClass">
   <value>
    com.laoer.bbscs.service.scheduling.UserTopFileJob
   </value>
</property>
<property name="jobDataAsMap">
   <map>
    <entry key="userTopService">
     <ref local="userTopService" />
    </entry>
   </map>
</property>
</bean>
<bean id="userTopFileJobCronTrigger"
class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail">
   <ref bean="userTopFileJob" />
</property>
<property name="cronExpression">
   <value>0 0 4 ? * 2</value>//星期二4点做事!天哪....
     </property>
</bean>
我们这样就完成了大部分(主要)的业务逻辑的分析了,但对于JSP界面层和web中以action包为主的web层我们仍然需要进行分析,以使我们的业务逻辑发挥作用!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值