java - Web 应用程序的 Java Oracle 数据库更改通知问题
问题描述
我正在使用以下代码注册和收听 Oracle 数据库更改通知。当我将它作为独立的 java 程序运行时,此代码运行良好。它正在接收来自数据库的通知并按预期打印。
public class DBChangeNotification {
static final String USERNAME = "XXX";
static final String PASSWORD = "YYY";
static String URL = "jdbc:oracle:thin:@xxxx:xxxx:xxxx";
public static void main(String[] args) {
DBChangeNotification demo = new DBChangeNotification();
try {
demo.run();
} catch (SQLException mainSQLException) {
mainSQLException.printStackTrace();
}
}
public void run() throws SQLException {
OracleConnection conn = connect();
Properties prop = new Properties();
prop.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS, "true");
prop.setProperty(OracleConnection.DCN_QUERY_CHANGE_NOTIFICATION, "true");
prop.setProperty(OracleConnection.DCN_BEST_EFFORT, "true");
DatabaseChangeRegistration dcr = conn.registerDatabaseChangeNotification(prop);
try {
// add the listenerr:
DCNDemoListener list = new DCNDemoListener(this);
dcr.addListener(list);
// second step: add objects in the registration:
Statement stmt = conn.createStatement();
// associate the statement with the registration:
((OracleStatement) stmt).setDatabaseChangeRegistration(dcr);
ResultSet rs = stmt.executeQuery("select * from xxxxxxxx where yyyy='zzzzz'");
while (rs.next()) {
}
String[] tableNames = dcr.getTables();
for (int i = 0; i < tableNames.length; i++) {
System.out.println(tableNames[i] + " is part of the registration.");
}
rs.close();
stmt.close();
} catch (SQLException ex) {
// if an exception occurs, we need to close the registration in order
// to interrupt the thread otherwise it will be hanging around.
if (conn != null) {
conn.unregisterDatabaseChangeNotification(dcr);
}
ex.printStackTrace();
throw ex;
} finally {
try {
// Note that we close the connection!
conn.close();
} catch (Exception innerex) {
innerex.printStackTrace();
}
}
}
/**
* Creates a connection the database.
*/
OracleConnection connect() throws SQLException {
OracleDriver dr = new OracleDriver();
Properties prop = new Properties();
prop.setProperty("user", DBChangeNotification.USERNAME);
prop.setProperty("password", DBChangeNotification.PASSWORD);
return (OracleConnection) dr.connect(DBChangeNotification.URL, prop);
}
}
/**
* DCN listener: it prints out the event details in stdout.
*/
class DCNDemoListener implements DatabaseChangeListener {
DBChangeNotification demo;
DCNDemoListener(DBChangeNotification dem) {
System.out.println("DCNDemoListener");
demo = dem;
}
@Override
public void onDatabaseChangeNotification(DatabaseChangeEvent e) {
Thread t = Thread.currentThread();
System.out.println("DCNDemoListener: got an event (" + this + " running on thread " + t + ")");
System.out.println(e.toString());
synchronized (demo) {
demo.notify();
}
}
}
我的要求是在 Web 应用程序中使用此功能。Web 应用程序在服务器中启动时,必须监听数据更改通知(可能在单独的线程上)并通过 websocket 客户端通知应用程序。我在 servlet 上下文侦听器的 contextInitialized 方法中添加了以下代码,以便它在应用程序启动时立即启动。
public class MyServletContextListener implements ServletContextListener {
DBChangeNotification demo;
@Override
public void contextDestroyed(ServletContextEvent arg0) {
//Notification that the servlet context is about to be shut down.
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
demo = new DBChangeNotification();
try {
demo.run();
} catch (SQLException mainSQLException) {
mainSQLException.printStackTrace();
}
}
}
当注册表中发生数据库更改事件时,我没有看到 Web 应用程序收到任何通知。请帮助我解决问题。我不知道这是否是正确的方法....除了连续轮询之外,请提出任何替代方案。一旦我收到来自数据库的通知,我需要在服务器中启动一些东西。谢谢你。
解决方案
可能是您在没有可用通知 API 的 Oracle 实例上运行代码。 检查此 SO 以获取更多信息
推荐阅读
- c# - VB.net 中的 HTTP 发布请求
- ios - 将 UISearchController isActive 设置为 false 停止 segue
- python - 如何在python中的超时上下文中使用超时上下文
- r - 在 R 中通过应用传递给函数的对象的默认名称
- neo4j - 字符串属性值中的撇号
- javascript - 计算属性未更新
- python - Selenium-Python 选择具有空 Span 的元素
- angular - div内div的角度6轨道滚动位置
- reactjs - React Native Maps ,地图下方的组件显示在地图上方而不是下方
- java - 从java调用kotlin中的方法