1

Quartz ジョブ内から Struts2 Action を実行しようとしています-HTTP リクエストの処理ではない任意のコンテキストから一般化します。

ここから始めましたhttp://struts.apache.org/2.0.6/docs/how-can-we-schedule-quartz-jobs.htmlしかし、ドキュメントはかなり時代遅れのようです。

私は信じています (しかし、私は間違っているかもしれません) Container オブジェクトを取得する必要性に要約しました:

import java.util.HashMap;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.DefaultActionProxyFactory;

...

HashMap ctx = new HashMap();
DefaultActionProxyFactory factory= new DefaultActionProxyFactory();
factory.setContainer(HOW DO I GET THE CONTAINER??);
ActionProxy proxy = factory.createActionProxy("", "scheduled/myjob", ctx);

解決策の 1 つは、localhost に対して (TCP 経由で) http 要求を発行することです。私はそれを避けたいと思います。

4

2 に答える 2

2

この回答を提供することで、一部の人々が何をするようになるのでしょうか、しかし概念の証明として、そして何らかの理由で(おそらく、彼らはこれが必要ないくつかの打ち砕かれたアプリケーションを継承している可能性がありますか?) 、通常のリクエスト コンテキスト外で Struts2 アクションを実行する必要があります。

ただし、これは生の (最適な実装ではなく、開始点として提供されている) が、機能するソリューションです。

まず、次の 3 つのクラスを com.stackoverflow.struts2.quartz というパッケージに追加します。

指定されたジョブ コンテキストのプロキシを要求して実行する単純なジョブ:

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);

以上です。このコードにより、アクションが毎秒無期限に実行され、インターセプターがすべて起動し、依存関係が注入されます。もちろん、HttpServletRequest のようなサーブレット オブジェクトに依存するロジックやインターセプターは適切に動作しませんが、サーブレット コンテキストの外部でこれらのアクションをスケジュールすることは意味がありません。

于 2012-06-01T23:34:37.747 に答える
0

freemarker で電子メールをフォーマットするために HttpServletRequest は必要ありません。次の回答を参照してください。

Spring 3 JavaMail を介して MIME 形式の Freemarker テンプレートでマルチパート メッセージを作成する

mail を送信するために、春を使用してメールコンポーネントを Quartz ジョブに注入できます。HttpServlet リクエストを取得する RequestContextHolder クラスがあっても、Quartz ジョブから HttpServletRequest を取得することはできません。

于 2012-06-01T06:29:27.877 に答える