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