私は、Spring-MVC(4.2.5)とSpring-Security(4.0.3)を使ってWebアプリケーションを開発しています。私の問題は、30秒ごとなどの設定された時間間隔で実行されるメソッドが必要ですが、実行前にユーザーがログインしていることを確認する必要があります。Spring 4コンテナのスケジュールされたメソッド
ユーザーがログインフォームを送信すると、HTTP要求は外部サーバーに送信され、資格情報が正しい場合は、セッショントークンを含むHTTP応答が返されます。
セッショントークンは、タイムドメソッド内で転送したいものを含め、他のすべてのリクエストにとって基本的なものです。私のコントローラで
私はすべての瞬間には、春のセキュリティコンテキストからのセッショントークンを取得することができます。
String token = SecurityContextHolder.getContext().getAuthentication().getDetails().toString();
は私が動作しないようスケジュールされたタスクを使用しようとしましたが、残念ながら、これはで開始されているため、セッションがなく、サーブレットコンテナから分離されたスレッドで実行されている場合、アプリケーションの起動。 SecurityContextHolder.getContext()がnullであるため、次の例外がスローされます。
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)
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
**/
}
春-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>
何ができます代わりに使う?どうすれば修正できますか?
スコープセッションでBeanを追加すると、そのBeanはスケジュールされたタスクを実行しますか? – Schrieveslaach
[HttpSessionListener](https://tomcat.apache.org/tomcat-5.5-doc/servletapi/javax/servlet/http/HttpSessionListener.html)を定義する方法と、セッションが作成されるたびに、グローバルデータ構造(静的リストやスプリングシングルトンBeanなど)を使用すると、セッションが終了するたびにそのセッションを削除できます。スケジュールされたタスクが実行されると、その構造内のすべてのタスクに対して実行されます。 –
あなたは「あなたがログインしていることを確認してください」と言っています。一度に1人のユーザーだけがログインすることを期待していますか?もしそうでなければ、エドウィンは言っているように、ログインしているすべてのユーザーのために実行されるバックグラウンドジョブを書く方が良いです。誰が自分でログインしているかを管理するか、dbテーブルをスキャンするか、SpringのSessionRegistryを使用することができます(http://stackoverflow.com/questions/11271449/how-can-i-have-list-of-all-users-logged -in-via-spring-security-my-web-applicat) –