感謝のプログラミング 10000時間

たどり着いた結果(さき)は、感謝でした。

Springフレームワークでスケジューラを作ってみた。

スポンサーリンク

■Springでタスクスケジューリング

タスクスケジューリングとは、処理(=タスク)をあらかじめ設定した時刻や一定間隔で実行するものである。
タスクとスケジュールはTaskSchedulerインターフェースを通して結びつく。

タスクスケジューリングを設定するためには、beans.xmlに名前空間taskを宣言する。
task:scheduler要素を使ってTaskSchedulerを登録する。

これを使うといちいちcronを仕込まなくても自動で時間指定でJavaを実行してくれる。

タスクスケジュールを使う時は、コードを記述する必要はない。
Spring設定ファイルに記述するだけでよい。

<task:scheduled-tasks>用をのscheduler属性にTaskSchedulerのidを指定し、
その子要素として<task:scheduled>要素を記述する。
<task:scheduled>要素のref属性にタスクとするBeanのidを指定する。
method属性にタスクとして実行させたいメソッドを指定する。

Springのcron

秒 分 時 月 年 曜日

の順。
Eclipse上でAntでコンパイルするときに、
「エラー: この文字は、エンコーディングUTF8にマップできません」
みたいなエラーが出た。
build.xmlのjavacに適当にencodingを設定したら、とりあえず回避できた。
(適当にしてしまってごめんなさい。もう深夜なのでw)

<javac destdir="${classes.dir}" debug="on" debuglevel="lines,vars,source" encoding="MS932">

http://www.ne.jp/asahi/hishidama/home/tech/ant/tag/javac.html

まずは結果から。
コンソールにメッセージを表示するメソッドを1秒おきに実行するスケジューラを作成した。
antを実行すると、こんな感じで表示される。

     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST
     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST
     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST
     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST
     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST
     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST
     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST
     [java] TASK NAME is TASK TESTTASK NUMBER is 1MESSAGE is SCHEDULER TEST

実行しているメソッドは、以下のようなソース。
インターフェースと共に載せる。

package schedule1;

public interface TaskBean {
	void doTask();
}

このdoTask()を1秒ごとに実行しているわけだ。

package schedule1;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.scheduling.annotation.Scheduled;

public class TaskBeanImpl implements TaskBean {

	private Log log = LogFactory.getLog(getClass());
	private String taskName;
	private String message;
	private int taskNumber;
	
	public TaskBeanImpl(String taskName) {
		this.taskName = taskName;
	}
	
	public void setMessage(String message) {
		this.message = message;
	}
	
	public void setTaskNumber(int taskNumber) {
		this.taskNumber = taskNumber;
	}
	
	@Scheduled(cron = "* * * * * ?")
	public void doTask() {
		System.out.println("TASK NAME is " + taskName + "TASK NUMBER is " + taskNumber 
				+ "MESSAGE is " + message);
		log.info("TASK NAME is:" + taskName + "TASK NUMBER is:" + taskNumber 
				+ " MESSAGE is" + message);
	}
	
}

ここにある@Scheduledがポイント。
ここで、cronの時刻を設定している。
全て「*」にしたから、毎秒という意味だ。

・・・と思ったけど、beans.xmlに書いたcronの通りに実行されるみたい。
アノテーションの役割は今後確認する。。

beans.xmlを読み込むクラスはこんな感じ。

package schedule1;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TaskTest {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
	}
}

読み込まれるbeans.xmlはこの通り。これもポイント。

<?xml version="1.0" encoding="Windows-31J" ?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/task
	http://www.springframework.org/schema/task/spring-task-3.0.xsd">

	<bean id="taskBean" class="schedule1.TaskBeanImpl">
		<constructor-arg>
			<value>TASK TEST</value>
		</constructor-arg>

		<property name="message">
			<value>SCHEDULER TEST</value>
		</property>
		<property name="taskNumber">
			<value>1</value>
		</property>
	</bean>

	<task:scheduler id="taskScheduler" pool-size="5" />

	<task:scheduled-tasks scheduler="taskScheduler">
		<task:scheduled ref="taskBean" method="doTask"
			cron="* * * * * ?" />
	</task:scheduled-tasks>

</beans>

scheduled-tasksのところで、taskBeanのdoTaskメソッドを実行する設定がされている。
このtaskBeanというのは、bean idで指定されたクラスだ。

ref="beanID"で、タスクを実行するクラスを指定して、methodで、叩くメソッドを指定する。
これをスケジュール通りに実行してくれる。

あとは、log4j.xml

<?xml version="1.0" encoding="Windows-31J" ?>

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/task
	http://www.springframework.org/schema/task/spring-task-3.0.xsd">

	<bean id="taskBean" class="schedule1.TaskBeanImpl">
		<constructor-arg>
			<value>TASK TEST</value>
		</constructor-arg>

		<property name="message">
			<value>SCHEDULER TEST</value>
		</property>
		<property name="taskNumber">
			<value>1</value>
		</property>
	</bean>

	<task:scheduler id="taskScheduler" pool-size="5" />

	<task:scheduled-tasks scheduler="taskScheduler">
		<task:scheduled ref="taskBean" method="doTask"
			cron="* * * * * ?" />
	</task:scheduled-tasks>

</beans>

commons-loging.properties

org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger

build.xml

<?xml version="1.0"?>

<project name="task1" basedir="." default="run.task1">
	<property name="src.dir" value="src"/>
	<property name="lib.dir" value="lib" />
	<property name="classes.dir" value="classes" />
	
	<path id="classpath">
		<fileset dir="${lib.dir}">
			<include name="*.jar"/>
		</fileset>
	</path>
	
	<target name="init" description="作業ディレクトリの初期化">
		<delete dir="${class.dir}"/>
		<mkdir dir="${class.dir}" />
	</target>
		
	<target name="compile" depends="init" description="コンパイルします">
		<javac destdir="${classes.dir}" debug="on" debuglevel="lines,vars,source" encoding="MS932">
			<src path="${src.dir}"/>
			<classpath refid="classpath"/>
		</javac>
		<copy todir="${classes.dir}">
			<fileset dir="${src.dir}">
				<include name="**/*.xml" />
			</fileset>
		</copy>
	</target>
	
	<target name="run.task1" depends="compile" description="アプリケーションを実行します">
		<java classname="schedule1.TaskTest" classpath="${classes.dir}" classpathref="classpath" fork="true"></java>
	</target>
</project>
			
			
	


1番苦戦しがちなファイル体系だが、こんな感じ。


Eclipse上でAntを実行するのは、Javaの道を参考にしました。
http://www.javaroad.jp/opensource/js_eclipse3.htm

参考書籍はこちら。この本、本当にいい。
サンプルの真似をするとだんだんわかってくる。説明も的確だし。

SpringによるWebアプリケーションスーパーサンプル 第2版

SpringによるWebアプリケーションスーパーサンプル 第2版

うまく動いたので、寝る。4時になってしまう。。

★★
ちょっと余談だけど、はてなブックマークのホットエントリーに「僕が読んだ300冊のうち影響を受けた10冊を紹介する」
とか、
「ブログで本を紹介しちゃいます」
的なのを見かけるけど、そういう本の紹介がほとんど自己啓発本やビジネス書なのはなんでだろう。
「アイデアが浮かぶ本!」を読んで、じゃあそのアイデアで何を作ったのかが知りたい。
自己啓発本は30分くらいで読み終える割に、書いてあることはみんな一緒で、読んだところで自分を劇的に変えることなんてできないと思うんだよね。
地道に、積み重ねるしかないと思うんだ。

ただ、カーネギーの「人を動かす」とドラッカーの「経営者の条件」だけは本当に良かった。

新版 ハンディーカーネギー・ベスト(3冊セット): 「人を動かす」「道は開ける」「カーネギー名言集」

新版 ハンディーカーネギー・ベスト(3冊セット): 「人を動かす」「道は開ける」「カーネギー名言集」

  • 作者: D・カーネギー,ドロシー・カーネギー,山口博,香山晶,神島康
  • 出版社/メーカー: 創元社
  • 発売日: 2011/11/22
  • メディア: 単行本
  • 購入: 4人 クリック: 14回
  • この商品を含むブログ (5件) を見る
ドラッカー名著集1 経営者の条件

ドラッカー名著集1 経営者の条件