2012-07-26

Schedule in Spring 3.1.2

排程執行就是在背景執行,Spring 提供兩種背景執行的功能,第一種是排程(@Scheduled),第二種是丟了就跑(@Async),差別在於前者是系統啟動,後者是人工啟動。

先看主程式:

public interface ScheduledInterface {

  public void doIn10Seconds();

  public void doIn5Seconds();

  public void doIn3Seconds();

  public Future<Integer> longCalculatioin();
}

@Service("scheduledTask")
public class ScheduledTask implements ScheduledInterface {

  /**
   * fixedRate 表示每次呼叫的間隔,不管執行時間
   * 所以執行可能重疊,也就是上一次尚未執行結束,就開始執行下一次
   */
  @Scheduled(fixedRate = 10000)
  public void doIn10Seconds() {
    System.out.println("doIn10Seconds - " + new Date().getTime() / 1000);
    try {
      Thread.sleep(1000);
    }
    catch (InterruptedException e) {
    }
  }

  /**
   * fixedDelay - 表示每次執行的間隔,也就是上一次執行完成後到下一次開始執行的間隔
   * 保證執行不會重疊
   */
  @Scheduled(fixedDelay = 5000)
  public void doIn5Seconds() {
    System.out.println("doIn5Seconds - " + new Date().getTime() / 1000);
    try {
      Thread.sleep(1000);
    }
    catch (InterruptedException e) {
    }
  }

  /**
   * cron - 固定的時間或週期,週期式行為同 fixedRate
   * 固定六個值:秒(0-59) 分(0-59) 時(0-23) 日(1-31) 月(1-12) 週(1,日-7,六)
   * 日與週互斥,其中之一必須為 ?
   * 可使用的值有:單一數值(26)、範圍(50-55)、清單(9,10)、不指定(*)與週期(* / 3)
   */
  @Scheduled(cron = "*/3 50-55 9,10 26 * ?")
  public void doIn3Seconds() {
    System.out.println("doIn3Seconds - " + new Date().getTime() / 1000);
    try {
      Thread.sleep(1000);
    }
    catch (InterruptedException e) {
    }
  }

  /**
   * 丟了就跑,但是可以回傳?
   * Future 是 Java Concurrent 定義的 class,用來追蹤執行結果
   * Spring 提供的 Future 實做為 AsyncResult
   */
  @Async
  public Future<Integer> longCalculatioin() {
    int cnt = 0;
    for (int i = 0; i < 10; i++) {
      cnt += i;
      System.out.println("longCalculatioin - " + cnt);
      try {
        Thread.sleep(1000);
      }
      catch (InterruptedException e) {
      }
    }
    return new AsyncResult<Integer>(cnt);
  }
}
AsyncController
@Controller
@SessionAttributes("future")
public class AsyncController {

  private ScheduledInterface scheduledTask;

  @Inject
  public AsyncController(ScheduledInterface scheduledTask) {
    this.scheduledTask = scheduledTask;
  }

  /**
   * 丟了就跑
   */
  @RequestMapping("/dropAndRun")
  public String home(Model model) {
    Future<Integer> f = this.scheduledTask.longCalculatioin();
    model.addAttribute("future", f);
    return "dropAndRun";
  }

  /**
   * 追蹤執行結果
   */
  @RequestMapping("/whatHappened")
  public String result(@ModelAttribute("future") Future<Integer> future,
      Model model) throws InterruptedException, ExecutionException {
    if (future.isDone()) {
      model.addAttribute("result", future.get());
    }
    else if (future.isCancelled()) {
      model.addAttribute("result", "Cancelled");
    }
    else {
      model.addAttribute("result", "Calculating...");
    }
    return "whatHappened";
  }
}
spring-app.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:context="http://www.springframework.org/schema/context"
  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/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/task
    http://www.springframework.org/schema/task/spring-task-3.0.xsd">

  <context:component-scan
    base-package="idv.neil.springmvc312.service,idv.neil.springmvc312.dao,idv.neil.springmvc312.model" />

  <!-- 一定要有,不然排程不會動 -->
  <bean id="scheduledTask" class="idv.neil.springmvc312.task.ScheduledTask" />

  <task:annotation-driven />

</beans>
spring-web.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">

  <mvc:annotation-driven />

  <context:component-scan base-package="idv.neil.springmvc312.web" />

  <bean
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="viewClass"
      value="org.springframework.web.servlet.view.JstlView" />
    <property name="prefix" value="/WEB-INF/views/" />
    <property name="suffix" value=".jsp" />
  </bean>

</beans>
web.xml
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  version="2.5">
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-app.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <servlet>
    <servlet-name>springmvc312</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value> /WEB-INF/spring-web.xml </param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc312</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>idv.neil.springmvc312</groupId>
  <artifactId>springmvc312</artifactId>
  <packaging>war</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>springmvc312 Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>3.1.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.glassfish.hk2.external</groupId>
      <artifactId>javax.inject</artifactId>
      <version>2.1.13</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
  </dependencies>
  <build>
    <finalName>springmvc312</finalName>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-eclipse-plugin</artifactId>
        <configuration>
          <!-- 更改 output 目錄 -->
          <buildOutputDirectory>src/main/webapp/WEB-INF/classes</buildOutputDirectory>
          <!-- 讓產生的 .classpath 包含 source jar -->
          <downloadSources>true</downloadSources>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.5.1</version>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.2</version>
      </plugin>
    </plugins>
  </build>
</project>
補充:Schedule in Spring 3.2.0 - Continued
---
---
---
-->

沒有留言:

張貼留言