首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring 4容器中的调度方法

Spring 4容器中的调度方法
EN

Stack Overflow用户
提问于 2016-11-01 14:37:28
回答 1查看 1K关注 0票数 0

我正在使用Spring (4.2.5)和Security (4.0.3)开发一个web应用程序。我的问题是,我需要一个按设定时间间隔运行的方法,比如每30秒运行一次,但在执行之前,我必须确保用户已登录。

当用户提交登录表单时,HTTP请求将发送到外部服务器,如果凭据正确,则返回包含会话令牌的HTTP响应。

会话令牌对于所有其他请求都是基本的,包括我希望在赋时方法中转发的请求。

在我的控制器中,我可以从Security上下文中获取会话令牌,在每一刻:

代码语言:javascript
复制
String token = SecurityContextHolder.getContext().getAuthentication().getDetails().toString();

我尝试使用一个预定的任务,但不幸的是,这不起作用,因为这是在应用程序启动时启动的,此时没有会话,并且运行在与servlet容器分离的线程中。引发以下异常:

代码语言:javascript
复制
GRAVE: Unexpected error occurred in scheduled task.
java.lang.NullPointerException
    at service.RetrieveBettingOdds.retrieveMatchByNationality(RetrieveBettingOdds.java:54)
    at tasks.OddsTask.run(OddsTask.java:36)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

因为SecurityContextHolder.getContext()是空的。

OddsTask

代码语言:javascript
复制
@Component
public class OddsTask {
    @Autowired
    private BettingService bettingService;
    @Autowired
    private MatchDao matchDao;
    private List<Match> betfairMatches;
    private List<Match> databaseMatches;

    public void run() {
        betfairMatches = new ArrayList<>();
        databaseMatches = new ArrayList<>();
        databaseMatches = matchDao.retrieveAllMatches();

        for(Country country : Country.values()) {
            betfairMatches = bettingService.retrieveMatchByNationality(country.name(), getCompetitionId(country.name()));
        }
    //cut code
}

RetrieveBettingOdds

代码语言:javascript
复制
@Service
public class RetrieveBettingOdds implements BettingService {
    private static final String BETTING_END_POINT = "https://api.betfair.com/exchange/betting/json-rpc/v1";
    private static final String APP_KEY = "my_app_key";
    private String token;

    @Override
    public List<Match> retrieveMatchByNationality(String country, String competitionId) {
        token = SecurityContextHolder.getContext().getAuthentication().getDetails().toString();
    /**
    * Cut the following code, in which I create an HTTP request including the token
    **/
}

spring-mvc.xml

代码语言:javascript
复制
<bean id="oddsTask" class="tasks.OddsTask">
</bean>

<task:scheduler id="myScheduler" pool-size="10" />

<task:scheduled-tasks scheduler="myScheduler">
    <task:scheduled ref="oddsTask" method="run"
        fixed-delay="10000" initial-delay="60000" />
</task:scheduled-tasks>

我能用什么代替?我怎么才能修好它?

EN

回答 1

Stack Overflow用户

发布于 2016-11-01 15:13:55

我有一个想法,不幸的是,我不能在这一点上测试,但我希望这在某种程度上有所帮助,或至少给你其他的想法,如何可以做到这一点。

如何定义使用活动会话更新数据结构的Http事件侦听器?

代码语言:javascript
复制
public class ActiveUsers implements HttpSessionListener {

    private ActiveUsersDao active = new ActiveUsersDao<>();

    @Override
    public void sessionCreated(HttpSessionEvent event) {
        active.add(event.getSession().getId());

    }

    @Override
    public void sessionDestroyed(HttpSessionEvent event) {
        active.remove(event.getSession().getId());
    }        
}

然后在web.xml中注册侦听器

代码语言:javascript
复制
<listener>
   <listener-class>com.stackoverflow.ActiveUsers</listener-class>
</listener>

最后,在您的计划bean中,您可以从DAO中获取数据。

代码语言:javascript
复制
@Service
public class TaskScheduler

   @Auotwired ActiveUsersDao activeUsers;

   @Scheduled
   public void run() {
      Set<String> snapshot = activeUsers.findAll();
      for(String user: snapshot) {
         //do what you've got to do
      }
   }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40362300

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档