1. 程式人生 > >Tomcat連線池,以及 Webservice配置,以及log4j日誌輸出

Tomcat連線池,以及 Webservice配置,以及log4j日誌輸出

用java寫的webservice,建立資料庫連線的時候,因為webservice介面要供很多使用者使用,這時如果把資料庫連線語句寫在使用者呼叫的我方的方法裡面,在方法裡面用完再關閉,也可以。但是用tomcat連線池,一開始就申請25個連線放著,最多50個(這個25和50都可以配置),省了很多建立及關閉連線的時間,抗壓能力會好點。更科學的用法,是用Tomcat連線池

配置方法:

1.在tomcat的server.xml檔案中加入如下程式碼(紅色部分為要新增的,紫色字型為需要根據實際情況修改的。假如程式中既要連線oracle,又要連線sqlserver2005):

.....................

<Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="U4ser database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />

   <Resource name="DataSourceSql" auth="Container"
   type="javax.sql.DataSource"
   username="sa" password="pwd"
   driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
   url="jdbc:sqlserver://127.0.0.1:8080;databasename=dbname"  logAbandoned="true" maxActive="50" maxIdle="25" maxWait="20000"/>

 <Resource name="DataSourceOracle" auth="Container"
   type="javax.sql.DataSource"
   username="username" password="pwd"
   driverClassName="oracle.jdbc.driver.OracleDriver"
   url="jdbc:oracle:thin:@127.0.0.1:8080:dbname"  logAbandoned="true" maxActive="50" maxIdle="25" maxWait="20000"/>

</GlobalNamingResources>
........................

<Connector port="8899" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8483" URIEncoding="utf-8" />

<Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true"
            xmlValidation="false" xmlNamespaceAware="false">
       <Context path="/De_WS" docBase="E:\De_WS\WebRoot" reloadable="true" debug="0">
          <ResourceLink global="DataSourceSql" name="DataSourceSql" type="javax.sql.Datasource"/>
          <ResourceLink global="DataSourceOracle" name="DataSourceOracle" type="javax.sql.Datasource"/>
          </Context>

(說明:訪問介面地址時,如果是啟動本機tomcat,那麼就是

訪問地址為什麼是這個?這是上面綠色中配的路徑。

上面<Host name 中,只有紅色字型部分是要加的,其他都是配置檔案中本來就存在的。

綠色字型中:

webapps對應tomcat目錄下webapps件夾。如果不配下面的<Context path="/De_WS" docBase="E:\De_WS\WebRoot..  tomcat會到webapps目錄中找。

  <Context path="/De_WS" docBase="E:\De_WS\WebRoot" 中。path="/De_WS"是虛擬目錄的路徑,docBase="E:\De_WS\WebRoot"是虛擬目錄的實際實體地址(該地址要配置到WEB-INF的緊上一級目錄)。因為這裡配置了path="/De_WS" ,所以訪問的時候http://localhost:8899後面要加/De_WS。如果配置path="",那麼訪問介面時,只用訪問http://localhost:8899加後面的/services/ClientJK就可以了/services/這個名字,是在webservice裡的web.xml檔案裡配置的。ClientJK是在deploy.wsdd檔案裡配置的。

所以,訪問介面地址中是否要加/De_WS,取決於  <Context path="/De_WS"中path(虛擬目錄)的配置。

maxActive="50" maxIdle="25" maxWait="20000"/   意思分別是,連線池最大50個連線,啟動tomcat就申請25個連線,不管這25個是否一開始就用,這樣節約申請連線的時間。20000意思是當50個連線用完後,等待20S,如果有被釋放的連線,就拿著用,沒有,就tomcat報錯。

2.java程式中,連線資料庫的程式碼改成:

import java.sql.Connection;

import javax.naming.NamingException;
import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ConnectionManager {    //連線oracle類
	private static Log logger = LogFactory.getLog(ConnectionManager.class);   //此處是將列印列印到log日誌檔案,路徑配置在log4j檔案中
	private Connection conn = null;

	public static Connection getConnection() throws Exception {
			DataSource ds = getDataSource();
			return ds.getConnection();
	}	
	
	public static DataSource getDataSource() throws Exception {
		try {
			javax.naming.Context ctx = new javax.naming.InitialContext();
			Object obj = null;
			obj = ctx.lookup("java:comp/env/DataSourceOracle");  //步驟1中tomcat配好後,這裡只用寫配置中的名字即可

			DataSource ds = (javax.sql.DataSource) obj;
			return ds;
		} catch (NamingException ne) {
			logger.error("Context fail to lookup JNDIDataSourceName!"
					+ ne.getMessage());
			throw ne;
		}
         }

//	public static Connection getConnection() throws Exception {   //通過讀取配置檔案連線資料庫
//		Properties p = new Properties();
//		InputStream is= ConnectionManager.class.getResourceAsStream("/config/other/init.properties");
//		p.load(is);
//		Class.forName(p.getProperty("jdbc.driver"));
//		return DriverManager.getConnection(p.getProperty("jdbc.url"), p
//				.getProperty("jdbc.username"), p.getProperty("jdbc.password"));
//	}
}	
package com.tools;

import java.sql.Connection;

import javax.naming.NamingException;
import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class BaseDao {   //連線sqlserver2005資料庫
//	public Connection GetConn() throws Exception {    //通過讀取配置檔案連線資料庫
//		Connection conn = null;
//		Properties p = new Properties();
//		InputStream is = ConnectionManager.class
//				.getResourceAsStream("/config/other/init_sql2005.properties");
//		p.load(is);
//		Class.forName(p.getProperty("jdbc.driver"));
//		conn = DriverManager.getConnection(p.getProperty("jdbc.url"), p
//				.getProperty("jdbc.username"), p.getProperty("jdbc.password"));
//		return conn;
//	}
	
	private static Log logger = LogFactory.getLog(ConnectionManager.class);
	private Connection conn = null;

	public static Connection GetConn() throws Exception {
			DataSource ds = getDataSource();
			return ds.getConnection();
	}	
	
	public static DataSource getDataSource() throws Exception {
		try {
			javax.naming.Context ctx = new javax.naming.InitialContext();
			Object obj = null;
			obj = ctx.lookup("java:comp/env/DataSourceSql");

			DataSource ds = (javax.sql.DataSource) obj;
			return ds;
		} catch (NamingException ne) {
			logger.error("Context fail to lookup JNDIDataSourceName!"
					+ ne.getMessage());
			throw ne;
		}
	}

}

如果用讀取配置檔案連線資料庫(即其中註釋掉的方法,配置檔案內容如下):

init.properties

#created by Apusic
#Thu Nov 10 14:48:52 CST 2011
gis.ip=..
paging.number.per=10
jdbc.password=pwd
sms.ip=...
jdbc.maxActive=50
jdbc.url=jdbc\:oracle\:thin\:@192.168.1.1\:1521\:dbname
valuelisthandlerclass=oracle
jdbc.maxWait=50000
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.username=username
pci.ip=...

3.程式中呼叫webservice程式碼:

public class TestClient {
	  public static void main(String[] args) {
		String url ="http://192.168.1.1:8080/De_WS/services/ClientJK";   //ClientJK是介面名稱,訪問時,為什麼要加/De_WS目錄,在過程1中說明會有詳細介紹
		Service service = new Service();
		Call call =null;
		try {
			call = (Call) service.createCall();
			call.setTargetEndpointAddress(new URL(url));
			call.setOperationName("sendMsg");   //sendMsg是介面提供的方法名
			String myName = (String)call.invoke(new Object[]{"引數1", "引數2","引數3","引數4","引數5" });
			System.out.println("myName:"+myName);
		} catch (ServiceException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}
	}



4.題外話。log4j日誌輸出方法(要導包):

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

....

private Log logger = LogFactory.getLog(SendThread.class);

....

long startTime = System.currentTimeMillis(); // -------------------獲取開始時間

long endTime = System.currentTimeMillis(); // ------------------------獲取結束時間
     logger.info("執行緒中事務耗時: " + (endTime - startTime)   //輸出到日誌檔案
       + "ms");

.....

try {
     ps2.close();
     ps2 = null;
    } catch (SQLException e) {
     logger.error(e.getMessage());  //輸出到日誌檔案
    }

log4j.properties配置檔案:

log4j.rootLogger=info, A1,A2             //info是tomcat啟動方式為info(II),還有debug(I),warn(III),error(IV)。A1是輸出到終端,A2是輸出到日誌檔案
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%5p (%F%M:%L) - %m%n 

log4j.appender.A2=org.apache.log4j.DailyRollingFileAppender
log4j.appender.A2.file=c:/logs/XXX/info.log  //此處是配置日誌檔案路徑。目錄要自己事先建好,info.log檔案不用建
log4j.appender.A2.DatePattern='('yyyy-MM-dd')'
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
log4j.appender.A2.layout.ConversionPattern=%d [%p] %c -line:%L - %m%n

log4j.logger.org.apache.commons=off
log4j.logger.org.apache.struts=off
log4j.logger.org.springframework=off
log4j.logger.com.ysoft=off