我有些擔心提供這個答案的內容可能會鼓勵一些人去做,但是作爲一個概念的證明,並且實際上爲任何人提供了一個解決方案,無論出於什麼原因(也許他們正在繼承一些應用程序,是否需要?),需要在正常請求上下文之外執行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更相關將成爲你的服務層。在一個奇怪的筆記你爲什麼要執行你的行動? –