目录
附:Name jdbc is not bound in this Context 问题的解决方法
————————————————————————————————————————————————————————
正文:
参考书籍:Java Web编程技术(第二版)沈则刚
在设计需要访问数据库的web应用程序时,需要考虑的一个主要问题是如何管理web应用程序的通信(即servlet建立数据库连接、执行查询、处理结果集、请求结束关闭链接)。
固然可以每一次HTTP请求时创建一个连接对象,但这样会非常麻烦,同时是比较费时间的操作,且部分数据库对同时进行的连接数量支持比web服务器少。
因此从JDBC2.0开始,出现了使用连接池与数据源技术的访问方法。
原理:
事先建立若干连接,将它们放在数据库连接池(connection polling)中供数据访问组件来使用。当应用程序启动,只需要创建少量的连接对象即可。通过javax.sql.DataSource对象获得数据库连接,结束后再放回连接池。
使用:
通过数据源获得数据库连接对象不能直接在应用程序中通过实例化生成DataSource对象,而是通过采用Java命名与目录接口【JNDI】技术获得引用。【关于JNDI以后如果涉及会单独论述】。
在javax.naming包中提供了Context接口,该接口提供了将名字和对象绑定,通过名字检索对象的方法。可以通过该接口的InitialContext获得上下文对象。
举例:
(这里的方法仅仅为课程涉及,仅供参考:在Tomcat中配置使用DataSource建立数据库连接)
在Tomcat中可以配置两种数据源,局部数据源和全局数据源。前者只能被定义数据源的应用程序中使用,后者可被所有的应用程序使用。
配置局部数据源(全局数据源暂时不考虑,可见书p184页)
- 在Tomcat中的Lib文件夹下复制JDBC驱动(注意不同数据库不同驱动)。
- 在WEB文件中建立一个META-INF目录,在其中建立一个context.xml文件。
- 使用以下代码来配置context.xml文件
<?xml version="1.0" encoding="utf-8" ?> <Context reloadable="true"> <Resource name="jdbc/testDS"//这里可以自定 type="javax.sql.DataSource"//不用更改 maxActive="4"//可同时为连接池分配的活动连接实例的最大数 maxIdle="2"//连接池中可空闲连接的最大数 username="root"//数据库用户名 maxWait="1000"//没有连接时,连接池抛出异常前最大等待毫秒数 driverClassName="com.mysql.jdbc.Driver"//JDBC驱动名,不同数据库不同 password="123"//数据库密码 url="jdbc:mysql://localhost:3306/no9" />//传递给JDBC驱动程序的数据库URL,可以借用view视窗中的database功能快速生成 </Context>
-
在应用程序中使用数据源,使用javax.naming.Context接口的lookup()查找JNDI数据源,注意需要java:comp/env这个前缀,它是JNDI命名空间的一部分,之后加数据源的name
Context initContext=new InitialContext(); //注意,下一条语句和下面两行从理论上作用一样,但是前者偶尔会引发找不到JDBC的情况…… //语句1:DataSource ds=(DataSource)initContext.lookup("java:comp/env/jdbc/testDS"); //语句2: Context envContext =(Context) initContext.lookup("java:comp/env/"); DataSource ds=(DataSource)envContext.lookup("jdbc/testDS");
- 得到DataSource对象引用后就可以通过getconnection获得数据库连接对象Connection,使用后调用Connection的close()来将连接对象返回到数据库连接池。
Connection conn=ds.getConnection();
//这里注意使用?的时候,需要考虑数据库主键冲突问题,要么设置自动增长(AI),要么设置检测机制
String sql1="insert into student2 values(?,?,?,?,?)";
PreparedStatement statement =conn.prepareStatement(sql1);
statement.setInt(1,id);
statement.setString(2,name);
statement.setString(3,gender);
statement.setInt(4,age);
statement.setString(5,major);
//对插入语句进行更新
statement.executeUpdate();
//使用后将连接放回到连接池
statement.close();
conn.close();
附:当不使用连接池与数据源技术时的程序(参考)
可见连接池与数据源技术确实方便了很多,这里仅仅是一个程序进行连接,如果程序很多时,就需要反复写这几段
package no9.taor;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
@WebServlet(name = "no10record", urlPatterns={"/record"},loadOnStartup=1)
public class no10record extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置头信息
PrintWriter out=response.getWriter();//设置输出流
request.setCharacterEncoding("utf-8");//使用前设置字符集编码,此方法仅限post方法有限
response.setContentType("text/html;charset=UTF-8");
//获取
String name= request.getParameter("name");
int age= Integer.valueOf(request.getParameter("age")).intValue();
//数据库操作
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
out.println("driver loaded error!");
}
//设置数据库链接
String dbURL="jdbc:mysql://localhost:3306/no9";
Connection conn= null;
try {
conn = DriverManager.getConnection(dbURL,"root","123");
} catch (SQLException e) {
e.printStackTrace();
out.println("connection built error!");
}
//预处理方式处理语句,先插入再更新
String sql1="insert into student(name,age) values(?,?)";
PreparedStatement stmt= null;
try {
stmt = conn.prepareStatement(sql1);
stmt.setString(1,name);
stmt.setInt(2,age);
stmt.executeUpdate();
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
out.println(e.getMessage());
}
附:Name jdbc is not bound in this Context 问题的解决方法
有时我们按上述步骤进行后,会发现报错,报错内容如上,context中找不到那个jbdc驱动……
网上搜索会发现解决方法往往是这个
这个方法改动时,会带来更多的问题(像我这种学艺不精的人)
根据我的经验:
- context.xml文件没有创建好,包括打错字以,及类型错误等问题,甚至是创建文件先后的问题……
- 如之上局部配置步骤4中所述,两种方法之间的谜之BUG
- 此时,首先停止Tomcat,将context.xml文件重新创建一次,并且将应用程序中的数据源使用第四步第二种方法,再次运行,问题解决。