如何在计划任务中使用 OAuth2RestTemplate?

How can I use an OAuth2RestTemplate in a scheduled task?

我有两台资源服务器:一台有一个 API 用于发送电子邮件通知,另一台运行计划任务。当计划任务开始时,我想调用电子邮件服务来通知用户他们的任务开始了。两种服务都使用 OAuth2 进行身份验证。计划任务服务设置了客户端凭据,以便它可以通过提供其客户端凭据来获取访问令牌:


为此,我使用 Spring Boot with Spring Security OAuth2。任务服务有一个 OAuth2RestTemplate 来调用电子邮件服务。当计划任务启动并尝试使用 OAuth2RestTemplate 时,它​​会尝试将 OAuth2ClientContext 作为会话范围的 bean。显然,它不会找到一个,因为我不是在请求线程中执行,而是在后台任务线程中运行。我得到这个例外:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
  'scopedTarget.oauth2ClientContext': Scope 'session' is not active for the current thread; 
  consider defining a scoped proxy for this bean if you intend to refer to it 
  from a singleton

由于我使用静态客户端凭据进行系统到系统身份验证,我看不出有充分的理由使用会话范围的数据来处理我的访问令牌。我更愿意有一个单例 OAuth2ClientContext bean,任何线程都可以使用它来通过 OAuth2RestTemplate 发出请求。

我该如何配置?

事实证明这很简单。我想要一个单例 bean,所以我创建了一个单例 bean:

@Primary
@Bean
public OAuth2ClientContext singletonClientContext() {
    return new DefaultOAuth2ClientContext();
}

在我的@Configuration class 中,Spring 将其连接到我的 OAuth2RestTemplate 并且我的计划任务能够调用电子邮件服务。为了更好地衡量,我添加了 @Primary 注释以确保此 bean 优于 Spring Boot 创建的任何内容(不确定是否需要)。