説明:フレームワークなしで Linux に Java Web アプリケーション (jsp + tomcat) があります。DBMS として postgresql を使用しています。
テーブル ( options ) とそれをカプセル化するシングルトン クラス ( Options ) があります。Options インスタンスは、アプリケーションの起動時に読み込まれ、そこに無期限に残ります。
ユーザーがオプションを変更すると、メソッド ( .refreshData() ) がメモリに保持されているインスタンスを更新します。
問題は、DB に直接アクセスし、オプションテーブルのいくつかのフィールドを更新するリモート サービスが存在することです。このコードを制御することはできません。
外部サービスがオプション テーブルを更新するときに、refresh メソッドをトリガーしたいと考えています。また、サービスが 1 日 1 回午後 3 時に開始されることも知っていますが、いつ終了するかはわかりません。
postgresql によって提供される LISTEN - NOTIFY 機能 ( Javaキャッシュを更新する Postgres トリガー) は、この目標を達成するための最もエレガントな方法のように思えます。このトピックに続いて、私は単純なリスナーを試しており、自分のニーズに合わせて「適応」しています( Postgress ドキュメントのコードのサンプル)。
@Craigの提案後に編集:
public class OptionsListener extends Thread {
private int threadMills = 1000;
private Connection conn;
private org.postgresql.PGConnection pgconn;
private Options optionsInstance;
private static final String DB_URL;
private static final String DB_USERNAME;
private static final String DB_PASSWORD;
static {
try {
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
DB_URL = (String) envContext.lookup("application/DB/url");
DB_USERNAME = (String) envContext.lookup("application/DB/username");
DB_PASSWORD = (String) envContext.lookup("application/DB/password");
} catch (NamingException e) {
throw new RuntimeException(e);
}
}
OptionsListener(Options instance, int threadMillis) {
optionsInstance = instance;
this.threadMills = threadMillis;
try {
Class.forName("org.postgresql.Driver");
conn = DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD);
pgconn = (PGConnection) DriverManager.getConnection(DB_URL, DB_USERNAME, DB_PASSWORD);
Statement stmt = conn.createStatement();
stmt.execute("LISTEN otionsUpdate");
stmt.close();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
@Override
public void run() {
while (true) {
Log.addItem("Polling ?");
try {
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT 1");
rs.close();
stmt.close();
PGNotification notifications[] = pgconn.getNotifications();
if (notifications != null) {
Log.addItem("NOTIFY received");
optionsInstance.loadDbData();
}
Thread.sleep(threadMills); //tempo di attesa in millisecondi
} catch (Exception e) {
Log.addItem(getClass().getName() + " " + e.getMessage());
}
}
}
}
Options クラスでは、次のメソッドを使用してリスナーを手動で開始します。
public static void startExternalChangesListener(Options instance, int millis) {
OptionsListener listener = new OptionsListener(instance, millis);
listener.start();
}
そして最後に
Options.startExternalChangesListener(options, 5000);
スレッドを改ざんするのはこれが初めてです...
チャネルに通知するAFTER UPDATE トリガーを作成し、PGAdmin3 でテストしました。それは魅力のように機能しますが、Javaは気付かないようです...