我需要实现连接池我的Web应用程序,它使用Servlet和JSP页面。我不希望跨服务器中的所有应用程序连接池,想要跨所有servlet实现连接池。
我有一个C3P0的工作实现,但我不知道这是正确的方法,并做到这给出了预期的结果。
以下是我的实施 有一个Datasource文件C3P0实现返回连接。 连接将在servelet init方法上检索,并在destroy方法上关闭。
请在
下找到我的连接池实现返回连接的数据源文件和使用连接的Servelt
数据源文件
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DataSource {
// JDBC driver name and database URL
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://dburl/dbName";
// Database credentials
static final String USER = "username";
static final String PASS = "password";
private static DataSource datasource;
private ComboPooledDataSource cpds;
private DataSource() throws IOException, SQLException, PropertyVetoException {
cpds = new ComboPooledDataSource();
cpds.setDriverClass("com.mysql.jdbc.Driver"); //loads the jdbc driver
cpds.setJdbcUrl(DB_URL);
cpds.setUser(USER);
cpds.setPassword(PASS);
// the settings below are optional -- c3p0 can work with defaults
cpds.setMinPoolSize(5);
cpds.setAcquireIncrement(5);
cpds.setMaxPoolSize(20);
cpds.setMaxStatements(180);
}
public static DataSource getInstance() throws IOException, SQLException, PropertyVetoException {
if (datasource == null) {
datasource = new DataSource();
return datasource;
} else {
return datasource;
}
}
public Connection getConnection() throws SQLException {
return this.cpds.getConnection();
}
}
的Servlet
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class ConnectionTest
*/
@WebServlet("/ConnectionTest")
public class ConnectionTest extends HttpServlet {
Connection connection = null;
Statement statement = null;
@Override
public void init() throws ServletException {
super.init();
try {
connection = DataSource.getInstance().getConnection();
} catch (PropertyVetoException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("<h1> Hi</h1>");
ResultSet resultSet = null;
try {
statement = connection.createStatement();
resultSet = statement
.executeQuery("SELECT VehicleRegistration FROM Registration");
while (resultSet.next()) {
String first = resultSet.getString("VehicleRegistration");
// Display values
out.println("<h1> " + first + "</h1>");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (resultSet != null)
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
if (statement != null)
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
@Override
public void destroy() {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
super.destroy();
}
}
我欢迎所有建议,即使它太小或太大,这有助于我改进此代码
感谢所有人
答案 0 :(得分:1)
所以,这可以改进。
您的Servlet应该在init(...)
中获取对DataSource的引用,而不是在Servlet的生命周期中保持未完成的Connection对象。应根据需要从Connection-pooling DataSource获取Connection
个对象,而不是长时间保持打开状态。你的doGet(...)
方法应该获取Connection(这将是快速的,因为它已经在池中了!),然后注意在其finally块中的Connection上调用close()
。
你改变这一点非常重要。除了持久打开Connection的ickiness和资源使用不足之外,在您当前的架构下,对Servlet的同时请求将同时在同一个Connection上运行,这可能导致意外和不正确的行为,特别是如果您的webapp中有servlet,利用交易(因为大多数非常重要的应用程序必须)。
您的DataSource类似乎并不特别有用。为什么不构造c3p0 DataSource而不是使用getConnection()
方法定义新类型的对象。我认为你的动机可能只是让静态成员datasource
成为真正的DataSource。但是如果你想将DataSource存储为静态成员,你可以在任何地方进行,不需要包装实际的DataSource。
但是,在JavaEE Web应用程序中保存连接池支持的DataSource的最佳位置不是静态成员。更好的方法是在ServletContextListener
中contextInitialized(...)
构建数据源,并将DataSource存储在应用程序范围内。在contextDestroyed(...)
致电close()
c3p0 ComboPooledDataSource
,并将其从应用范围中删除。