我有些担心提供这个答案的内容可能会鼓励一些人去做,但是作为一个概念的证明,并且实际上为任何人提供了一个解决方案,无论出于什么原因(也许他们正在继承一些应用程序,是否需要?),需要在正常请求上下文之外执行Struts2操作。
但是,这里是原始(它是作为一个起点,而不是一个最优的实现),但工作,解决方法:
首先,这三个类添加到一个名为com.stackoverflow.struts2包。石英:
一个简单的工作,只是要求对于给定的工作方面的代理,并执行它:
package com.stackoverflow.struts2.quartz;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class ActionJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
try {
QuartzActionProxyFactory.getActionProxy(context).execute();
} catch (Exception e) {
e.printStackTrace();
throw new JobExecutionException(e);
}
}
}
一些常数绕过动作细节:
package com.stackoverflow.struts2.quartz;
public class QuartzActionConstants {
public static final String NAMESPACE = "struts.action.namespace";
public static final String NAME = "struts.action.name";
public static final String METHOD = "struts.action.method";
}
,可以静态地从ActionJob访问自定义ActionProxyFactory:
package com.stackoverflow.struts2.quartz;
import java.util.HashMap;
import java.util.Map;
import org.apache.struts2.impl.StrutsActionProxyFactory;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionProxyFactory;
public class QuartzActionProxyFactory extends StrutsActionProxyFactory {
private static ActionProxyFactory actionProxyFactory;
public QuartzActionProxyFactory() {
actionProxyFactory = this;
}
public static ActionProxy getActionProxy(JobExecutionContext context) throws JobExecutionException {
ActionProxy actionProxy = null;
try {
@SuppressWarnings("unchecked")
Map<String, Object> actionParams = context.getJobDetail().getJobDataMap();
Map<String, Object> actionContext = new HashMap<String, Object>();
actionContext.put(ActionContext.PARAMETERS, actionParams);
actionProxy = actionProxyFactory.createActionProxy(
(String) actionParams.get(QuartzActionConstants.NAMESPACE),
(String) actionParams.get(QuartzActionConstants.NAME),
(String) actionParams.get(QuartzActionConstants.METHOD),
actionContext,
false, //set to false to prevent execution of result, set to true if this is desired
false);
} catch (Exception e) {
throw new JobExecutionException(e);
}
return actionProxy;
}
}
然后,在你的struts.xml中,添加:
<bean name="quartz" type="com.opensymphony.xwork2.ActionProxyFactory" class="com.stackoverflow.struts2.quartz.QuartzActionProxyFactory"/>
<constant name="struts.actionProxyFactory" value="quartz"/>
然后你就可以安排动作执行一些简单的代码:
SchedulerFactory sf = new StdSchedulerFactory();
Scheduler scheduler = sf.getScheduler();
scheduler.start();
JobDetail jobDetail = new JobDetail("someActionJob", Scheduler.DEFAULT_GROUP, ActionJob.class);
@SuppressWarnings("unchecked")
Map<String, Object> jobContext = jobDetail.getJobDataMap();
jobContext.put(QuartzActionConstants.NAMESPACE, "/the/action/namespace");
jobContext.put(QuartzActionConstants.NAME, "theActionName");
jobContext.put(QuartzActionConstants.METHOD, "theActionMethod");
Trigger trigger = new SimpleTrigger("actionJobTrigger", Scheduler.DEFAULT_GROUP, new Date(), null, SimpleTrigger.REPEAT_INDEFINITELY, 1000L);
scheduler.deleteJob("someActionJob", Scheduler.DEFAULT_GROUP);
scheduler.scheduleJob(jobDetail, trigger);
就是这样。这段代码将导致无限期地每秒执行一次该操作,拦截器将全部触发并且依赖关系将被注入。当然,依赖于Servlet对象(如HttpServletRequest)的任何逻辑或拦截器都无法正常运行,但是无论如何,将这些操作安排在servlet上下文之外没有任何意义。
你为什么要这么做? S2具体是一个网页层;可以被任意进程调用的功能应该被隔离在服务中。您需要复制什么S2功能?注射?使用Spring。拦截器? –
我需要渲染一个FreeMarker模板来生成电子邮件的HTML。我可以做到这一点 - 使用一些我继承的代码,但我只能理解 - 从一个Action中,但它在其他地方不起作用。 – jsalvata
最近我在Quartz上工作了很多,我没有看到你的需求和S2之间有任何关系.Quartz主要用于触发某种Job,它们独立于你使用的容器,因为它与Quartz更相关将成为你的服务层。在一个奇怪的笔记你为什么要执行你的行动? –