tomcat配置和连接池原理.doc_第1页
tomcat配置和连接池原理.doc_第2页
tomcat配置和连接池原理.doc_第3页
tomcat配置和连接池原理.doc_第4页
tomcat配置和连接池原理.doc_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

tomcat 6.0如何配置虚拟目录?tomcat 6.0 不能列目录?一、具体配置方法如下:找到TOMCAT的安装目录,再打开conf目录下的server.xml.将元素加入元素中间。(不清楚话,可以参考XML这门语言,非常有用)D:testservlet为实际目录,而/testservlet为虚拟目录,在地址栏敲入http:/localhost:8080/testservlet实际访问的目录为D:testservlet,我们给D:testservlet做了一个映射。二、问题描述: 以前的tomcat 5.5时比如说 当访问目录test时,它会把test目录下的文件列出来,但是在tomcat 6.0中就提示没有!要把全名输入了才行,如http:/locahost/test/tes.jsp 才能正常显示,但如果是http:/localhost/test 它就提示没有,这是不是配置上的问题!或者是6.0故意这样做的?三、解决方案: 5.5的也是关闭了目录浏览功能的,你说的应该是5.0的,这个主要是处于安全性的考虑。要是你的目录下没有默认首页,那你的这个目录下的文件列表就泄露给别人了。这个是个配置选项,你可以手动打开,开发时有用,但是生产环境就最好关闭。配置选项在TOMCAT/conf/web.xml中找到defaultorg.apache.catalina.servlets.DefaultServletdebug0listingsfalse1将其中的listingsfalse设置改为true即可解决此问题Tomcat6.0连接池配置1. Tomcat6.0连接池配置 2. 1.配置tomcat下的conf下的server.xml中的host标签中添加连接池配置: 3. 4. 1. 14. 15. 2.配置你的应用下的web.xml中的web-app标签之间加入: 16. 1. 17. 2. DB Connection 18. 3. jdbc/sql 19. 4. javax.sql.DataSource 20. 5. Container 21. 6. 22. 3.把连接数据库的第三方驱动放到common/lib下面就ok了 23. 4.测试程序我就不写了 24. 25. Tomcat5.5x连接池配置 26. 27. 方式一、全局数据库连接池 28. 1、通过管理界面配置连接池,或者直接在tomcatconfserver.xml的GlobalNamingResources中增加 29. 30. 2、在tomcatwebappsmyappMETA-INFcontext.xml的Context中增加: 31. 32. 这样就可以了。 33. 方式二、全局数据库连接池 34. 1、同上 35. 2、在tomcatconfcontext.xml的Context中增加: 36. 37. 方式三、局部数据库连接池 38. 只需在tomcatwebappsmyappsMETA-INFcontext.xml的Context中增加: 39. 40. 参数说明: 41. driveClassName:JDBC驱动类的完整的名称; 42. maxActive:同时能够从连接池中被分配的可用实例的最大数; 43. maxIdle:可以同时闲置在连接池中的连接的最大数; 44. maxWait:最大超时时间,以毫秒计; 45. password:用户密码; 46. url:到JDBC的URL连接; 47. user:用户名称; 48. validationQuery:用来查询池中空闲的连接。 49. 以上三种方式在tomcat 5.5.4下都可以。另外,sql server的jdbc driver是从微软网站上下载的sql server jdbc (sp3)。 50. 51. tomcat5.0连接池配置 52. 在tomcat 的下面路径(Tomcat confCatalinalocalhost)下建一个xml文件,内容如下 53. 54. 55. 56. factory 57. mons.dbcp.BasicDataSourceFactory 58. 59. 63. 64. maxActive 65. 100 66. 67. 70. 71. maxIdle 72. 30 73. 74. 78. 79. maxWait 80. 10000 81. 82. 83. 84. username 85. sa 86. 87. 88. password 89. test 90. 91. 92. 93. driverClassName 94. net.sourceforge.jtds.jdbc.Driver 95. 96. 98. 99. defaultAutoCommit 100. true 101. 102. 107. 108. url 109. jdbc:jtds:sqlserver:/url/filedb;charset=gb2312;autoReconnect=true 110. 111. 112. 113. removeAbandoned 114. true 115. 116. 119. 120. removeAbandonedTimeout 121. 60 122. 123. 126. 127. logAbandoned 128. true 129. 130. 使用JAVA中的动态代理实现数据库连接池作者通过使用JAVA中的动态代理实现数据库连接池,使使用者可以以普通的jdbc连接的使用习惯来使用连接池。数据库连接池在编写应用服务是经常需要用到的模块,太过频繁的连接数据库对服务性能来讲是一个瓶颈,使用缓冲池技术可以来消除这个瓶颈。我们可以在互联网上找到很多关于数据库连接池的源程序,但是都发现这样一个共同的问题:这些连接池的实现方法都不同程度地增加了与使用者之间的耦合度。很多的连接池都要求用户通过其规定的方法获取数据库的连接,这一点我们可以理解,毕竟目前所有的应用服务器取数据库连接的方式都是这种方式实现的。但是另外一个共同的问题是,它们同时不允许使用者显式的调用Connection.close()方法,而需要用其规定的一个方法来关闭连接。这种做法有两个缺点:第一:改变了用户使用习惯,增加了用户的使用难度。首先我们来看看一个正常的数据库操作过程:int executeSQL(String sql) throws SQLExceptionConnection conn = getConnection();/通过某种方式获取数据库连接PreparedStatement ps = null;int res = 0;tryps = conn.prepareStatement(sql);res = ps.executeUpdate();finallytryps.close();catch(Exception e)tryconn.close();/catch(Exception e)return res;使用者在用完数据库连接后通常是直接调用连接的方法close来释放数据库资源,如果用我们前面提到的连接池的实现方法,那语句conn.close()将被某些特定的语句所替代。第二:使连接池无法对之中的所有连接进行独占控制。由于连接池不允许用户直接调用连接的close方法,一旦使用者在使用的过程中由于习惯问题直接关闭了数据库连接,那么连接池将无法正常维护所有连接的状态,考虑连接池和应用由不同开发人员实现时这种问题更容易出现。综合上面提到的两个问题,我们来讨论一下如何解决这两个要命的问题。首先我们先设身处地的考虑一下用户是想怎么样来使用这个数据库连接池的。用户可以通过特定的方法来获取数据库的连接,同时这个连接的类型应该是标准的java.sql.Connection。用户在获取到这个数据库连接后可以对这个连接进行任意的操作,包括关闭连接等。通过对用户使用的描述,怎样可以接管Connection.close方法就成了我们这篇文章的主题。为了接管数据库连接的close方法,我们应该有一种类似于钩子的机制。例如在Windows编程中我们可以利用Hook API来实现对某个Windows API的接管。在JAVA中同样也有这样一个机制。JAVA提供了一个Proxy类和一个InvocationHandler,这两个类都在java.lang.reflect包中。我们先来看看SUN公司提供的文档是怎么描述这两个类的。public interface InvocationHandlerInvocationHandler is the interface implemented by the invocation handler of a proxy instance. Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.SUN的API文档中关于Proxy的描述很多,这里就不罗列出来。通过文档对接口InvocationHandler的描述我们可以看到当调用一个Proxy实例的方法时会触发Invocationhanlder的invoke方法。从JAVA的文档中我们也同时了解到这种动态代理机制只能接管接口的方法,而对一般的类无效,考虑到java.sql.Connection本身也是一个接口由此就找到了解决如何接管close方法的出路。首先,我们先定义一个数据库连接池参数的类,定义了数据库的JDBC驱动程序类名,连接的URL以及用户名口令等等一些信息,该类是用于初始化连接池的参数,具体定义如下:public class ConnectionParam implements Serializableprivate String driver;/数据库驱动程序private String url;/数据连接的URLprivate String user;/数据库用户名private String password;/数据库密码private int minConnection = 0;/初始化连接数private int maxConnection = 50;/最大连接数private long timeoutValue = 600000;/连接的最大空闲时间private long waitTime = 30000;/取连接的时候如果没有可用连接最大的等待时间其次是连接池的工厂类ConnectionFactory,通过该类来将一个连接池对象与一个名称对应起来,使用者通过该名称就可以获取指定的连接池对象,具体代码如下:/* * 连接池类厂,该类常用来保存多个数据源名称合数据库连接池对应的哈希 * author liusoft */public class ConnectionFactory/该哈希表用来保存数据源名和连接池对象的关系表static Hashtable connectionPools = null;staticconnectionPools = new Hashtable(2,0.75F); /* * 从连接池工厂中获取指定名称对应的连接池对象 * param dataSource连接池对象对应的名称 * return DataSource返回名称对应的连接池对象 * throws NameNotFoundException无法找到指定的连接池 */public static DataSource lookup(String dataSource) throws NameNotFoundExceptionObject ds = null;ds = connectionPools.get(dataSource);if(ds = null | !(ds instanceof DataSource)throw new NameNotFoundException(dataSource);return (DataSource)ds;/* * 将指定的名字和数据库连接配置绑定在一起并初始化数据库连接池 * param name对应连接池的名称 * param param连接池的配置参数,具体请见类ConnectionParam * return DataSource如果绑定成功后返回连接池对象 * throws NameAlreadyBoundException一定名字name已经绑定则抛出该异常 * throws ClassNotFoundException无法找到连接池的配置中的驱动程序类 * throws IllegalAccessException连接池配置中的驱动程序类有误 * throws InstantiationException无法实例化驱动程序类 * throws SQLException无法正常连接指定的数据库 */public static DataSource bind(String name, ConnectionParam param)throws NameAlreadyBoundException,ClassNotFoundException,IllegalAccessException,InstantiationException,SQLExceptionDataSourceImpl source = null;trylookup(name);throw new NameAlreadyBoundException(name);catch(NameNotFoundException e)source = new DataSourceImpl(param);source.initConnection();connectionPools.put(name, source);return source;/* * 重新绑定数据库连接池 * param name对应连接池的名称 * param param连接池的配置参数,具体请见类ConnectionParam * return DataSource如果绑定成功后返回连接池对象 * throws NameAlreadyBoundException一定名字name已经绑定则抛出该异常 * throws ClassNotFoundException无法找到连接池的配置中的驱动程序类 * throws IllegalAccessException连接池配置中的驱动程序类有误 * throws InstantiationException无法实例化驱动程序类 * throws SQLException无法正常连接指定的数据库 */public static DataSource rebind(String name, ConnectionParam param)throws NameAlreadyBoundException,ClassNotFoundException,IllegalAccessException,InstantiationException,SQLExceptiontryunbind(name);catch(Exception e)return bind(name, param);/* * 删除一个数据库连接池对象 * param name * throws NameNotFoundException */public static void unbind(String name) throws NameNotFoundExceptionDataSource dataSource = lookup(name);if(dataSource instanceof DataSourceImpl)DataSourceImpl dsi = (DataSourceImpl)dataSource;trydsi.stop();dsi.close();catch(Exception e)finallydsi = null;connectionPools.remove(name);ConnectionFactory主要提供了用户将将连接池绑定到一个具体的名称上以及取消绑定的操作。使用者只需要关心这两个类即可使用数据库连接池的功能。下面我们给出一段如何使用连接池的代码:String name = pool;String driver = sun.jdbc.odbc.JdbcOdbcDriver ;String url = jdbc:odbc:datasource;ConnectionParam param = new ConnectionParam(driver,url,null,null);param.setMinConnection(1);param.setMaxConnection(5);param.setTimeoutValue(20000);ConnectionFactory.bind(name, param);System.out.println(bind datasource ok.);/以上代码是用来登记一个连接池对象,该操作可以在程序初始化只做一次即可/以下开始就是使用者真正需要写的代码DataSource ds = ConnectionFactory.lookup(name);tryfor(int i=0;i= connParam.getMaxConnection()conn = getFreeConnection(connParam.getWaitTime();else/没有超过连接数,重新获取一个数据库的连接connParam.setUser(user);connParam.setPassword(password);Connection conn2 = DriverManager.getConnection(connParam.getUrl(), user, password);/代理将要返回的连接对象_Connection _conn = new _Connection(conn2,true);synchronized(conns)conns.add(_conn);conn = _conn.getConnection();return conn;/* * 从连接池中取一个空闲的连接 * param nTimeout如果该参数值为0则没有连接时只是返回一个null * 否则的话等待nTimeout毫秒看是否还有空闲连接,如果没有抛出异常 * return Connection * throws SQLException */protected synchronized Connection getFreeConnection(long nTimeout) throws SQLExceptionConnection conn = null;Iterator iter = conns.iterator();while(iter.hasNext()_Connection _conn = (_Connection)iter.next();if(!_conn.isInUse()conn = _conn.getConnection();_conn.setInUse(true);break;if(conn = null & nTimeout 0)/等待nTimeout毫秒以便看是否有空闲连接tryThread.sleep(nTimeout);catch(Exception e)conn = getFreeConnection(0);if(conn = null)throw new SQLException(没有可用的数据库连接);return conn;DataSourceImpl类中实现getConnection方法的跟正常的数据库连接池的逻辑是一致的,首先判断是否有空闲的连接,如果没有的话判断连接数是否已经超过最大连接数等等的一些逻辑。但是有一点不同的是通过DriverManager得到的数据库连接并不是及时返回的,而是通过一个叫_Connection的类中介一下,然后调用_Connection.getConnection返回的。如果我们没有通过一个中介也就是JAVA中的Proxy来接管要返回的接口对象,那么我们就没有办法截住Connection.close方法。终于到了核心所在,我们先来看看_Connection是如何实现的,然后再介绍是客户端调用Connection.close方法时走的是怎样一个流程,为什么并没有真正的关闭连接。/* * 数据连接的自封装,屏蔽了close方法 * author Liudong */class _Connection implements InvocationHandlerprivate final static String CLOSE_METHOD_NAME = close;private Connection conn = null;/数据库的忙状态private boolean inUse = false;/用户最后一次访问该连接方法的时间private long lastAccessTime = System.currentTimeMillis();_Connection(Connection conn, boolean inUse)this.conn = conn;this.inUse = inUse;/* * Returns the conn. * return Connection */public Connection getConnection() /返回数据库连接conn的接管类,以便截住close方法Connection conn2 = (Connection)Proxy.newProxyInstance(conn.getClass().getClassLoader(),conn.getClass().getInterfaces(),this);return conn2;/* * 该方法真正的关闭了数据库的连接 * throws SQLException */void close() throws SQLException/由于类属性conn是没有被接管的连接,因此一旦调用close方法后就直接关闭连接conn.close();/* * Returns the inUse. * return boolean */public boolean isInUse() return inUse;/* * see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object) */public Object invoke(Object proxy, Method m, Object args) throws Throwable Object obj = null;/判断是否调用了close的方法,如果调用close方法则把连接置为无用状态if(CLOSE_METHOD_NAME.equals(m.getName()setInUse(false);elseobj = m.invoke(conn, args);/设置最后一次访问时间,以便及时清除超时的连接lastAccessTime = System.currentTimeMillis();return obj;/* * Returns the lastAccessTime. * return long */public long getLastAccessTime() return lastAccessTime;/* * Sets the inUse. * param inUse The inUse to set */public void setInUse(boolean inUse) this.inUse = inUse;一旦使用者调用所得到连接的close方法,由于用户的连接对象是经过接管后的对象,因此JAVA虚拟机会首先调用_Connection.invoke方法,在该方法中首先判断是否为close方法,如果不是则将代码转给真正的没有被接管的连接对象conn。否则的话只是简单的将该连接的状态设置为可用。到此您可能就明白了整个接管的过程,但是同时也有一个疑问:这样的话是不是这些已建立的连接就始终没有办法真正关闭?答案是可以的。我们来看看ConnectionFactory.unbind方法,该方法首先找到名字对应的连接池对象,然后关闭该连接池中的所有连接并删除掉连接池。在DataSourceImpl类中定义了一个close方法用来关闭所有的连接,详细代码如下:/* * 关闭该连接池中的所有数据库连接 * return int 返回被关闭连接的个数 * throws SQLException */public int close() throws SQLExceptionint cc = 0;S

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论