我的一些servlet有一个非常奇怪的问题。以下是我的配置:
经过一定的时间或点击文件夹B中的任何servlet后,它会停止正常工作,而同时文件夹A的所有servlet都能正常工作。
我无法追查我所犯的错误。
两个文件夹的servlet的所有编码都是相同的,唯一的区别是它们与不同的DB交互,但它只是对DB的非常简单的只读操作。
有什么想法吗?
答案 0 :(得分:1)
问题在于Logger。当线程完成执行时,不会隐式释放Logger实例,并且由于没有明显的方法(如close()来关闭Logger实例),因此doGet / doPost线程无法正常退出。
删除Logger,或者显式地销毁实例/将其指定为null将解决问题。
答案 1 :(得分:0)
检查此类问题的两个重要事项:
读取服务器日志以查找任何异常和堆栈跟踪。在Tomcat中,它位于/logs
文件夹中。如果您找到了,那么这些应该提供足够的信息来自行解决问题。但是如果您不了解原因,那么您需要更新您的问题以包含相关的异常和堆栈跟踪。通过这种方式,我们可以帮助解释原因,以便解决方案足够明显。
确保代码不会在任何地方吞下重要的例外情况。即你需要在捕获后至少重新抛出或记录它们。例如。因此不:
try {
// ...
} catch (SQLException e) {
}
但更重要的是:
try {
// ...
} catch (SQLException e) {
throw new ServletException(e);
}
或者,至少:
try {
// ...
} catch (SQLException e) {
e.printStackTrace();
}
这样他们就会被记录到服务器日志中。
在您的特定情况下首先想到的一件事是代码没有在finally
块中正确关闭数据库资源,因此DB耗尽资源导致连接失败,准备语句和/或执行查询。通过适当的异常处理,这应该已经在服务器日志中提示。这是一个如何以正确的方式编写JDBC代码的基本启动示例。通常的做法是在尽可能短的范围内获取和关闭数据库资源:
public List<Entity> list() throws SQLException {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
List<Entity> entities = new ArrayList<Data>();
try {
connection = database.getConnection();
statement = connection.createStatement("SELECT id, name, value FROM entity");
resultSet = statement.executeQuery();
while (resultSet.next()) {
Entity entity = new Entity();
entity.setId(resultSet.getLong("id"));
entity.setName(resultSet.getString("name"));
entity.setValue(resultSet.getInteger("value"));
entities.add(entity);
}
} finally {
// Close in reversed order.
if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {}
if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
return entities;
}
close()
上的任何异常都可以忽略,但我更喜欢记录它们,这样你就不会丢失任何失败的证据,即使它很小。
答案 2 :(得分:0)
这可能是数据库超时相关问题。也许你的数据库有不同的超时时间?你使用connection pooling吗? (你应该!)两个连接的池设置是否相同?数据库是否配置为超出池超时值的超时时间?您是否在连接参数中设置了autoReconnect = true?