EJB提供了一个简单易用的定时调度功能,它支持声明式的创建定时任务,可以用于周期性执行后台业务逻辑,例如关闭订单、报表生成、异步通知等。这篇笔记我们简单了解EJB中定时任务的编写。
下面例子中我们基于单例会话Bean实现了一个定时任务,它每隔3秒执行一次,打印一条日志信息。
package com.gacfox.netstore.ejb;
import org.jboss.logging.Logger;
import javax.ejb.Schedule;
import javax.ejb.Singleton;
@Singleton
public class StatisticsService {
private static final Logger logger = Logger.getLogger(StatisticsService.class);
@Schedule(second = "*/3", minute = "*", hour = "*")
public void statistics() {
logger.info("Statistics service invoked");
}
}
代码中,我们使用@Schedule
注解标注了一个方法,被标注的方法将被自动调度执行,这种定时器也被称为日历定时器(Calendar Timer)。@Schedule
支持很多配置参数,我们可以组合这些参数实现灵活的定时任务配置。
*
、*/3
的写法表示每时间单位执行、每3次时间单位执行。true
,即任务会在服务器重启后恢复TimerService是EJB维护的一个核心调度器,和@Schedule
声明式定时任务不同,使用TimerService
我们可以使用Java代码动态的注册或取消定时任务。
下面例子代码中,我们在一个EJB实现类里使用@Resource
注入了TimerService
,当EJB的beginScheduledTask()
方法被调用时,我们启动了一个固定间隔执行的定时任务,当stopScheduledTask()
方法被调用时定时任务取消。定时任务触发时,标注@Timeout
的方法将被定时执行。
package com.gacfox.netstore.ejb;
import com.gacfox.netstore.api.StatisticsService;
import org.jboss.logging.Logger;
import javax.annotation.Resource;
import javax.ejb.*;
@Singleton
public class StatisticsServiceImpl implements StatisticsService {
@Resource
private TimerService timerService;
private static final Logger logger = Logger.getLogger(StatisticsServiceImpl.class);
private Timer timer = null;
@Timeout
public void statistics(Timer timer) {
logger.info("Statistics service invoked");
}
@Override
public void beginScheduledTask() {
if (timer == null) {
timer = timerService.createIntervalTimer(0, 1000, new TimerConfig("statisticsTask", true));
}
}
@Override
public void stopScheduledTask() {
if (timer != null) {
timer.cancel();
}
}
}
下面的Servlet作为EJB的客户端,动态的控制着定时任务的注册和取消。
package com.gacfox.netstore.web.servlet;
import com.gacfox.netstore.api.StatisticsService;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "StatisticsTaskServlet", urlPatterns = "/task")
public class StatisticsTaskServlet extends HttpServlet {
@EJB
private StatisticsService statisticsService;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String action = req.getParameter("action");
if ("start".equals(action)) {
statisticsService.beginScheduledTask();
} else if ("stop".equals(action)) {
statisticsService.stopScheduledTask();
}
}
}