我正在使用Spring (4.2.5)和Security (4.0.3)开发一个web应用程序。我的问题是,我需要一个按设定时间间隔运行的方法,比如每30秒运行一次,但在执行之前,我必须确保用户已登录。
当用户提交登录表单时,HTTP请求将发送到外部服务器,如果凭据正确,则返回包含会话令牌的HTTP响应。
会话令牌对于所有其他请求都是基本的,包括我希望在赋时方法中转发的请求。
在我的控制器中,我可以从Security上下文中获取会话令牌,在每一刻:
String token = SecurityContextHolder.getContext().getAuthentication().getDetails().toString();我尝试使用一个预定的任务,但不幸的是,这不起作用,因为这是在应用程序启动时启动的,此时没有会话,并且运行在与servlet容器分离的线程中。引发以下异常:
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
@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
@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
<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>我能用什么代替?我怎么才能修好它?
发布于 2016-11-01 15:13:55
我有一个想法,不幸的是,我不能在这一点上测试,但我希望这在某种程度上有所帮助,或至少给你其他的想法,如何可以做到这一点。
如何定义使用活动会话更新数据结构的Http事件侦听器?
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中注册侦听器
<listener>
<listener-class>com.stackoverflow.ActiveUsers</listener-class>
</listener>最后,在您的计划bean中,您可以从DAO中获取数据。
@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
}
}https://stackoverflow.com/questions/40362300
复制相似问题