Docs

Documentation versions (currently viewingVaadin 24)
Documentation translations (currently viewingChinese)

本页面由官方文档 http://vaadin.com/docs 机器翻译而来。内容可能包含错误、不准确或表述不当。Vaadin 不对译文的准确性、可靠性或时效性提供任何保证或声明。

实现作业

如何实现后台作业。

在实现后台作业时,需将其逻辑与其触发方式及触发位置解耦。这确保了能够从不同来源灵活地触发该作业。

例如,您可能希望在每次应用程序启动时运行某个作业。在这种情况下,您可能希望在主线程中运行它,阻塞应用程序剩余部分的初始化,直到该作业完成为止。您也可能希望每天在后台线程中运行一次该作业——例如在午夜,或在发布某个应用事件时运行。

以下是一个具有三种不同触发方式的作业的可视化示例:

Job with Three Triggers

在代码中,作业是一个 Spring bean,并用 @Service 注解标记。它包含一个或多个方法,当在调用线程中调用该作业时执行。

下面是实现单一后台作业的 Spring bean 示例:

Source code
Java
import org.springframework.stereotype.Service;

@Service
public class MyBackgroundJob {

    public void performBackgroundJob() {
        ...
    }
}

对于从同一包内 触发 的作业,该类可为包私有。需要由外部触发的作业必须为 public。

事务

操作数据库的作业应自行管理事务。由于作业为 Spring bean,您可以采用声明式或编程式事务管理。

下面是使用声明式事务管理确保作业在新事务内运行的后台作业示例:

Source code
Java
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class MyBackgroundJob {

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void performBackgroundJob() {
        ...
    }
}

有关事务管理的更多信息,请参阅 事务 文档页面。

安全性

应用服务 不同,后台作业不应依赖方法级安全性。原因在于,Spring Security 使用 SecurityContext 来访问当前用户的信息。该上下文通常为线程本地对象,意味着在后台线程中是不可用的。因此,每当后台线程执行作业时,Spring 都会拒绝访问。

如果后台作业需要当前用户的信息,应由 触发器 以不可变的方法参数将此信息传递给作业。

批处理作业

建议为批处理作业实现两个版本:一个处理所有适用输入;另一个处理特定输入集。这种方式在需要处理个别情况或从错误中恢复时提供了灵活性。

例如,用于为已发货订单生成发票的批处理作业可以如下所示:

Source code
Java
@Service
public class InvoiceCreationJob {

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void createInvoicesForOrders(Collection<OrderId> orders) {
        ...
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void createInvoicesForAllApplicableOrders() {
        ...
    }
}

本例中,第一个方法为作为参数传递的那些订单生成发票。第二个方法为所有已发货但尚未开具发票的订单生成发票。

从一开始就按此方式实现批处理作业并不会增加太多工作量,却能带来可能用得着的灵活性。以发票生成作业为例,假设您在生产环境中发现了一个 bug,导致某些订单在数据库中存在错误数据,因此批处理作业无法为这些订单生成发票。

修复 bug 很简单,但用户不希望等待下次批处理。因此,您可以在用户界面中添加一个按钮,让用户能够为单个订单触发发票生成。

幂等作业

每当开发更新或生成数据的后台作业时,都应考虑使其 幂等。幂等作业无论在相同输入上执行多少次,数据库均保持同一状态。

例如,为已发货订单生成发票的作业在生成新发票前应始终检查是否已有发票。否则,某些客户可能因错误而收到多张发票。

如何实现作业幂等取决于具体作业。该内容不属于本页面文档的范畴。