【发布时间】:2014-09-06 10:29:29
【问题描述】:
几天前我部署了我的第一个 Java Web 应用程序,并意识到发生了一件奇怪的事情。一段时间后,依赖于我的数据库连接的所有动态内容和功能(推荐提交、管理员登录)停止工作。这似乎每 24 小时左右就会发生一次。每天早上我都意识到它不再起作用了。
我通过进入 Tomcat Web 应用程序管理器并在有问题的 Web 应用程序上单击“重新加载”来解决此问题。网站的动态功能立即再次起作用。
我的服务器正在运行Tomcat 7 和MySQL 并且网络应用程序使用JDBC 驱动程序来建立与数据库的连接。我没有对 Apache 或 Tomcat 设置进行任何更改。
我有其他用 PHP 编写的 web 应用程序可以持续运行而没有错误,似乎只是这个 Java web 应用程序有这个问题。
什么会导致这种情况发生,我怎样才能做到这一点,以便网络应用程序不需要重新加载就可以再次建立数据库连接?
编辑:附上一些数据库连接代码
数据库连接
public class DBConnection {
private static Connection conn;
private static final Configuration conf = new Configuration();
private static final String dbDriver = conf.getDbDriver();
private static final String dbHostName = conf.getDbHostname();
private static final String dbDatabaseName = conf.getDbDatabaseName();
private static final String dbUsername = conf.getDbUsername();
private static final String dbPassword = conf.getDbPassword();
public Connection getConnection(){
try{
Class.forName(dbDriver);
Connection conn = (Connection) DriverManager.getConnection(dbHostName + dbDatabaseName, dbUsername, dbPassword);
return conn;
} catch(Exception e){
e.printStackTrace();
}
return conn;
}
public void disconnect(){
try{
conn.close();
} catch (Exception e){}
}
}
登录表单控制器:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String form = request.getParameter("form");
// check login details
if(form.equals("loginForm")){
String username = request.getParameter("username").trim();
String password = request.getParameter("password").trim();
password = loginService.hashPassword(password);
boolean isValidUser = loginService.checkUser(username, password);
if(isValidUser){
Cookie loggedIn = new Cookie("loggedIn", "true");
loggedIn.setMaxAge(60*60*24);
response.addCookie(loggedIn);
out.print("success");
}else{
out.print("nope");
}
}
}
登录服务检查登录详细信息是否正确:
public boolean checkUser(String username, String password){
boolean isValid = false;
try{
sql = "SELECT username, password FROM morleys_user WHERE username=? AND password=? AND isActive=1 LIMIT 1";
prep = conn.prepareStatement(sql);
prep.setString(1, username);
prep.setString(2, password);
rs = prep.executeQuery();
if(rs.next()){
return true;
}
}catch(Exception e){
e.printStackTrace();
}finally{
connection.disconnect();
}
return isValid;
}
更新
如果我理解正确,我不应该处理与数据库的直接连接,而是使用将为我管理连接的服务。
这是我建立与 MySQL 数据库的 DataSource 连接的示例。
建立这个类的一个新的DataSource实例:
package uk.co.morleys;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import javax.sql.DataSource;
import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;
public class DataSourceFactory {
public static DataSource getMySQLDataSource() {
Properties props = new Properties();
FileInputStream fis = null;
MysqlDataSource mysqlDS = null;
try {
fis = new FileInputStream("db.properties");
props.load(fis);
mysqlDS = new MysqlDataSource();
mysqlDS.setURL(props.getProperty("MYSQL_DB_URL"));
mysqlDS.setUser(props.getProperty("MYSQL_DB_USERNAME"));
mysqlDS.setPassword(props.getProperty("MYSQL_DB_PASSWORD"));
} catch (IOException e) {
e.printStackTrace();
}
return mysqlDS;
}
}
实例化一个新的 DataSource 以检查用户登录详细信息
public boolean checkUser(String username, String password){
boolean isValid = false;
DataSource ds = DataSourceFactory.getMySQLDataSource();
Connection con = null;
ResultSet rs = null;
PreparedStatement ps = null;
try{
con = ds.getConnection();
sql = "SELECT username, password FROM morleys_user WHERE username=? AND password=? AND isActive=1 LIMIT ";
ps = con.prepareStatement(sql);
ps.setString(1, username);
ps.setString(2, password);
rs = ps.executeQuery();
if(rs.next()){
return true;
}
}catch(SQLException e){
e.printStackTrace();
}finally{
try {
if(rs != null) rs.close();
if(ps != null) ps.close();
if(con != null) con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return isValid;
}
【问题讨论】:
-
你有什么例外吗?发布您获得的异常的完整堆栈跟踪。
-
我们的
DataSource是如何配置的? -
你能详细说明问题和配置吗? MySQL 有使用 mysql 连接器 j 的文档,即带有 tomcat dev.mysql.com/doc/connector-j/en/… 的 jdbc 驱动程序。
-
@DavieBrown 我希望不会,因为它只是使 cookie 过期,所以我只需要再次登录即可查看管理页面。
-
依赖注入框架将是执行此操作的合适候选者,但我假设您没有使用它。一种简单的方法是在初始化 Web 应用程序时创建该数据源,并将其放入某个类的公共静态变量中。当您使用池化数据源时,重用同一个数据源非常重要,因为您希望重用池管理的数据库连接。
标签: java mysql database tomcat jdbc