Java 为并发性设计数据源连接
下面的代码是我们在项目中使用的“基本”servlet:Java 为并发性设计数据源连接,java,jsp,servlets,jdbc,concurrency,Java,Jsp,Servlets,Jdbc,Concurrency,下面的代码是我们在项目中使用的“基本”servlet: public class MyServlet extends Servlet { private static final long serialVersionUID = 1L; protected Connection conn; /** * @see HttpServlet#HttpServlet() */ public MyServlet() { super();
public class MyServlet extends Servlet {
private static final long serialVersionUID = 1L;
protected Connection conn;
/**
* @see HttpServlet#HttpServlet()
*/
public MyServlet() {
super();
}
protected void connectDB() throws NamingException, SQLException {
// get database settings
InitialContext cxt = new InitialContext();
DataSource ds =(DataSource)cxt.lookup( "java:/comp/env/jdbc/MyDB" );
conn = ds.getConnection();
}
protected void closeDB() throws SQLException {
try {
if (conn!=null) conn.close();
}
finally {
conn = null;
}
}
protected void addCacheControl(HttpServletResponse response) {
response.setHeader("Expires", "Thu, 01 Jan 1970 00:00:00 GMT");
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate, pre-check=0, post-check=0");
response.setHeader("Pragma", "no-cache");
}
}
例如,SomeServlet扩展了MyServlet
现在SomeServlet
可以在浏览器中访问,它对JSP页面执行forward()
,然后刷新一段时间(比如10秒)
页面打开一段时间后,此代码抛出NullPointerException:
stmt = conn.prepareCall("{call sp_someSP(?, ?, ?)}");
您不能像这样使用Servlet的实例字段,因为它将由多个线程共享
您需要通过程序显式地将连接作为参数和局部变量传递(以便它们位于堆栈上,每个线程都有自己的版本),或者如果您想要更“全局”的方法,可以使用ThreadLocal。当您的请求完成时,ServletFilter也可以可靠地关闭ThreadLocal连接。您的意思是从“SomeServlet”我不应该访问“conn”。。。比如stmt=conn.prepareCall({调用sp_someSP(?,?)}”)?不,我的意思是,
conn
字段应该根本不存在。它应该是一个局部变量或ThreadLocal;conn有时只是空的,我的意思是当servlet在浏览器中的多个选项卡中同时被访问时是的,这正是这里的问题所在。您的代码不是线程安全的。如果您想让它在“大部分时间”内正常工作,就需要摆脱非线程安全的共享状态。