我正在使用从不同 API 下载数据的 Spring 应用程序。为此,我需要一个与 API 交互以获取所需数据的类 Fetcher。这个类的要求之一是它必须有一个方法来开始抓取和一个方法来停止它。此外,它必须异步下载所有内容,因为用户必须能够在获取数据时与仪表板交互。
实现这一目标的最佳方法是什么?我一直在阅读有关任务执行器和 Spring 的不同注释来安排任务并异步执行它们,但这个解决方案似乎并没有解决我的问题。
我正在使用从不同 API 下载数据的 Spring 应用程序。为此,我需要一个与 API 交互以获取所需数据的类 Fetcher。这个类的要求之一是它必须有一个方法来开始抓取和一个方法来停止它。此外,它必须异步下载所有内容,因为用户必须能够在获取数据时与仪表板交互。
实现这一目标的最佳方法是什么?我一直在阅读有关任务执行器和 Spring 的不同注释来安排任务并异步执行它们,但这个解决方案似乎并没有解决我的问题。
异步任务执行是您所追求的,从 Spring 3.0 开始,您也可以直接在要异步运行的方法上使用注释来实现这一点。
根据您是否有兴趣从异步过程中获取结果,有两种实现方式:
@Async
public Future<ReturnPOJO> asyncTaskWithReturn(){
//..
return new AsyncResult<ReturnPOJO>(yourReturnPOJOInstance);
}
或不:
@Async
public void asyncTaskNoReturn() {
//..
}
在前一种方法中,由 yourReturnPOJOInstance 对象实例传达的计算结果存储在一个实例中,该实例org.springframework.scheduling.annotation.AsyncResult<V>
返回实现java.util.concurrent.Future<V>
调用者稍后可以用来检索计算结果的实例。
要在 Spring 中激活上述功能,您必须在 XML 配置文件中添加:
<task: annotation-driven />
以及所需的任务命名空间。
最简单的方法是使用Thread
类。您提供一个Runnable
在方法中执行获取功能的对象,当线程启动时,它会在单独的执行线程中run()
调用该方法。run
所以是这样的:
public class Fetcher implements Runnable{
public void run(){
//do fetching stuff
}
}
//in your code
Thread fetchThread = new Thread(new Fetcher());
fetchThread.start();
现在,如果您希望能够取消,您可以通过几种方式来实现。最简单(尽管是最暴力和不可取的方法)是中断线程:
fetchThread.interrupt();
正确的方法是在你的类中实现逻辑Fetcher
,定期检查一个变量,看看它是否应该停止做它正在做的事情。
编辑关于让 Spring 自动运行它的问题,如果您希望它定期运行,则需要使用 Quartz 之类的调度框架。但是,如果您只想让它运行一次,您可以使用@PostConstruct
注释。带有注释的方法@PostConstruct
将在创建 bean 后执行。所以你可以做这样的事情
@Service
public class Fetcher implements Runnable{
public void run(){
//do stuff
}
@PostConstruct
public void goDoIt(){
Thread trd = new Thread(this);
trd.start();
}
}
编辑 2我实际上对此一无所知,但如果您还没有,请查看Spring 文档@Async
中的讨论。也可能是你想做的。
您可能只需要某些方法在单独的线程而不是整个类上运行。如果是这样,@Async
注释是如此简单易用。
只需将它添加到您想要异步运行的任何方法中,您还可以在具有返回类型的方法上使用它,这要归功于 Java 的Future
库。