您如何建议在 JavaEE 中实现以下内容:
我需要在应用程序服务器中有一个后台进程(我在想一个有状态的会话 bean),它不断监视“某事”,如果某些条件适用,它会对数据库进行操作。
最重要的是,它必须由各种客户端远程操作。
所以,基本上,我需要一个持续运行的进程,保持其状态,并对许多远程客户端的方法调用开放。
由于我是 JavaEE 的新手,我有点困惑使用哪种方法/“技术”。帮助将不胜感激。
您如何建议在 JavaEE 中实现以下内容:
我需要在应用程序服务器中有一个后台进程(我在想一个有状态的会话 bean),它不断监视“某事”,如果某些条件适用,它会对数据库进行操作。
最重要的是,它必须由各种客户端远程操作。
所以,基本上,我需要一个持续运行的进程,保持其状态,并对许多远程客户端的方法调用开放。
由于我是 JavaEE 的新手,我有点困惑使用哪种方法/“技术”。帮助将不胜感激。
您可以将无状态会话或单例 bean 与 EJB 计时器和计时器服务结合使用。bean 将成为远程客户端用来控制后台进程的接口。计时器服务会定期回调 bean 上的方法来验证条件。计时器由 EJB 容器自动持久化,因此当您的 bean 客户端断开连接时,它们将完成它们的工作。
这是一个草图:
@Singleton
...
public TimerMangerbean implements TimerManager {
@Resource
private TimerService timerService;
public void startMonitoring() {
//start in 5 sec and timeout every 10 minutes
Timer timer = timerService.createTimer(5000, 60000, "MyTimer");
}
public void stopMonitoring() {
Collection<Timer> timers = timerService.getTimers();
for(Timer timer : timers) {
//look for your timer
if("MyTimer".equals(timer.getInfo())) {
timer.cancel();break;
}
}
}
//called every 10 minutes
@Timeout
public void onTimeout() {
//verify the condition and do your processing
}
}
Java EE 就是解决方案。您将需要遵循这些步骤:
构建一个 Java EE 应用程序,一个包含 EJB 的 jar:
1.1 你需要一个 IDE:Eclipse Juno 是我的最爱,1.2 网络上有很多 tuto。搜索 EJB3,你会发现,
编辑:一个完整的 Timer EJB 类(如果需要自动重新加载)
package clouderial.saas.commons.utils;
import java.util.Map;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.ejb.ScheduleExpression;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;
import javax.inject.Inject;
import jmcnet.libcommun.exception.ExceptionTechnique;
import jmcnet.libcommun.utilit.mail.MailException;
import org.apache.commons.configuration.event.ConfigurationEvent;
import org.apache.commons.configuration.event.ConfigurationListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import clouderial.saas.commons.email.EmailSender;
import clouderial.saas.commons.jpamongo.JPAMongoBasePersistenceContextAccessor;
/**
* A base class for a periodic process
* @author jmc
*
*/
public abstract class PeriodicProcessBase extends JPAMongoBasePersistenceContextAccessor implements ConfigurationListener {
private static Logger log = LoggerFactory.getLogger(PeriodicProcessBase.class);
@Resource
private TimerService timerService;
@Inject
protected GlobalConfiguration _config;
@Inject
protected EmailSender _emailSender;
private Timer _timer=null;
private String _processName=null;
private Logger _log = null;
protected void initTimer(String processName, Logger log) {
if (processName != null) _processName = processName;
if (log != null) _log = log;
String second = _config.getString("timer."+_processName+".second","0");
String minute = _config.getString("timer."+_processName+".minute","0");
String hour = _config.getString("timer."+_processName+".hours","4");
String dayOfWeek = _config.getString("timer."+_processName+".dayOfWeek","*");
ScheduleExpression scheduleExp =
new ScheduleExpression().second(second).minute(minute).hour(hour).dayOfWeek(dayOfWeek);
cancelTimer();
if (timerService != null) {
_timer = timerService.createCalendarTimer(scheduleExp, new TimerConfig(_processName, false));
_log.info("{} : timer programmed for '{}'h, '{}'m, '{}'s for days '{}'.", _processName, hour, minute, second, dayOfWeek);
}
else _log.error("{} : no timer programmed because timerService is not initialized. (Normal during tests)", _processName);
// Listen to change
_config.addModificationListener(this); // on timer modification, configurationChanged is called
}
@PreDestroy
private void cancelTimer() {
if (_log != null) _log.info("Stopping timer for '{}'", _processName);
if (_timer != null) _timer.cancel();
_timer = null;
}
@Override
public void configurationChanged(ConfigurationEvent event) {
if (_log != null) _log.info("Configuration have change. Reloading config for ProcessBilling.");
_config.removeModificationListener(this);
initTimer(null, null);
}
@Timeout
private void run(Timer timer) {
runProcess(timer);
}
/**
* The entry point for runner the process. Must be overriden by super class
* @param timer
*/
protected abstract void runProcess(Timer timer); // do the job here
}
我希望这有帮助。
正如您自己所说,您有两个要求:1)定期执行一些后台作业,以及 2)响应客户端请求。
对于 1),您可以使用TimerService
或使用ServletContextListener
. 第二个不完全符合,但有效。如果您使用计时器,您可以创建一个定期计时器(如@dcernahoschi 指出的那样),或者一个重新安排自身的独特计时器:
@Timeout
public void onTimeout() {
//do something
// create a new timer
}
如果您的定期计时器每 10 秒触发一次,并且您处理最后一个表单的时间超过 10 秒,那么您可能会遇到问题。如果处理时间不固定,那么拥有一个重新安排自身的计时器会更好。
对于 2) 您可以使用无状态或 staefull EJB,这正是他们的目的。