轉載:
http://peak.javaeye.com/blog/52606
1、
PermGen space的全稱是Permanent Generation
space,是指內存的永久保存區域OutOfMemoryError:
PermGen space從表面上看就是內存益出,解決方法也一定是加大內存。說說為什么會內存益出:這一部分用于存放Class和Meta的信息,Class在被 Load的時候被放入
PermGen space區域,它和和存放Instance的Heap區域不同,GC(Garbage Collection)不會在主程序運行期對
PermGen space進行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現
PermGen space錯誤。這種錯誤常見在web服務器對JSP進行pre compile的時候。
改正方法:-Xms256m -Xmx256m -XX:MaxNewSize=256m -XX:MaxPermSize=256m
2、
在tomcat中redeploy時出現outofmemory的錯誤.
可以有以下幾個方面的原因:
1,使用了proxool,因為proxool內部包含了一個老版本的cglib.
2, log4j,最好不用,只用common-logging
3, 老版本的cglib,快點更新到最新版。
4,更新到最新的hibernate3.2
3、
這里以tomcat環境為例,其它WEB服務器如jboss,weblogic等是同一個道理。
一、
java.
lang.OutOfMemoryError:
PermGen space
PermGen space的全稱是Permanent Generation
space,是指內存的永久保存區域,
這塊內存主要是被JVM存放Class和Meta信息的,Class在被Loader時就會被放到
PermGen space中,
它和存放類實例(Instance)的Heap區域不同,GC(Garbage Collection)不會在主程序運行期對
PermGen space進行清理,所以如果你的應用中有很多CLASS的話,就很可能出現
PermGen space錯誤,
這種錯誤常見在web服務器對JSP進行pre compile的時候。如果你的WEB APP下都用了大量的第三方jar, 其大小
超過了jvm默認的大小(4M)那么就會產生此錯誤信息了。
解決方法: 手動設置MaxPermSize大小
修改TOMCAT_HOME/bin/catalina.sh
在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:
JAVA_OPTS="-server -XX:PermSize=64M -XX:MaxPermSize=128m
建議:將相同的第三方jar文件移置到tomcat/shared/lib目錄下,這樣可以達到減少jar 文檔重復占用內存的目的。
二、
java.
lang.OutOfMemoryError:
Java heap
space
Heap size 設置
JVM堆的設置是指
java程序運行過程中JVM可以調配使用的內存空間的設置.JVM在啟動的時候會自動設置Heap size的值,
其初始空間(即-Xms)是物理內存的1/64,最大空間(-Xmx)是物理內存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等選項可
進行設置。Heap size 的大小是Young Generation 和Tenured Generaion 之和。
提示:在JVM中如果98%的時間是用于GC且可用的Heap size 不足2%的時候將拋出此異常信息。
提示:Heap Size 最大不要超過可用物理內存的80%,一般的要將-Xms和-Xmx選項設置為相同,而-Xmn為1/4的-Xmx值。
解決方法:手動設置Heap size
修改TOMCAT_HOME/bin/catalina.sh
在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行:
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:MaxNewSize=256m"
三、實例,以下給出1G內存環境下
java jvm 的參數設置參考:
JAVA_OPTS="-server -Xms800m -Xmx800m -XX:PermSize=64M -XX:MaxNewSize=256m -XX:MaxPermSize=128m -Djava.awt.headless=true "
三、相關資料
http://www.tot.name/show/3/7/20061112220131.htm
http://www.tot.name/show/3/7/20061112220054.htm
http://www.tot.name/show/3/7/20061112220201.htm
題外話:經常看到網友抱怨tomcat的性能不如...,不穩定等,其實根據筆者幾年的經驗,從"互聯星空“到現在的房產門戶網,我們
均使用tomcat作為WEB服務器,每天訪問量百萬多,tomcat仍然運行良好。建議大家有問題多從自己程序入手,多看看
java的DOC文檔
并詳細了解JVM的知識。這樣開發的程序才會健壯。
JVM 性能調整的一些基本概念
http://www.wujianrong.com/archives/2007/02/jvm_1.html#more
apache+Tomcat負載平衡設置詳解
http://www.wujianrong.com/archives/2006/11/apachetomcat.html
java - the
Java application launcher
http://java.sun.com/j2se/1.3/docs/tooldocs/linux/java.html
posted @
2008-11-21 17:16 jiafang83 閱讀(163) |
評論 (0) |
編輯 收藏
轉自:http://www.java-cn.com/technology/tech/4310.html
本文闡述了怎么使用DBMS存儲過程。我闡述了使用存儲過程的基本的和高級特性,比如返回ResultSet。本文假設你對DBMS和JDBC已經非常熟悉,也假設你能夠毫無障礙地閱讀其它語言寫成的代碼(即不是Java的語言),但是,并不要求你有任何存儲過程的編程經歷。
存儲過程是指保存在數據庫并在數據庫端執行的程序。你可以使用特殊的語法在Java類中調用存儲過程。在調用時,存儲過程的名稱及指定的參數通過JDBC連接發送給DBMS,執行存儲過程并通過連接(如果有)返回結果。
使用存儲過程擁有和使用基于EJB或CORBA這樣的應用服務器一樣的好處。區別是存儲過程可以從很多流行的DBMS中免費使用,而應用服務器大都非常昂貴。這并不只是許可證費用的問題。使用應用服務器所需要花費的管理、編寫代碼的費用,以及客戶程序所增加的復雜性,都可以通過DBMS中的存儲過程所整個地替代。
你可以使用Java,Python,Perl或C編寫存儲過程,但是通常使用你的DBMS所指定的特定語言。Oracle使用PL/SQL,PostgreSQL使用pl/pgsql,DB2使用Procedural SQL。這些語言都非常相似。在它們之間移植存儲過程并不比在Sun的EJB規范不同實現版本之間移植Session Bean困難。并且,存儲過程是為嵌入SQL所設計,這使得它們比Java或C等語言更加友好地方式表達數據庫的機制。
因為存儲過程運行在DBMS自身,這可以幫助減少應用程序中的等待時間。不是在Java代碼中執行4個或5個SQL語句,而只需要在服務器端執行1個存儲過程。網絡上的數據往返次數的減少可以戲劇性地優化性能。
使用存儲過程
簡單的老的JDBC通過CallableStatement類支持存儲過程的調用。該類實際上是PreparedStatement的一個子類。假設我們有一個poets數據庫。數據庫中有一個設置詩人逝世年齡的存儲過程。下面是對老酒鬼Dylan Thomas(old soak Dylan Thomas,不指定是否有關典故、文化,請批評指正。譯注)進行調用的詳細代碼:
try{
int age = 39;
String poetName = "dylan thomas";
CallableStatement proc = connection.prepareCall("{ call set_death_age(?, ?) }");
proc.setString(1, poetName);
proc.setInt(2, age);
cs.execute();
}catch (SQLException e){ // ....}
傳給prepareCall方法的字串是存儲過程調用的書寫規范。它指定了存儲過程的名稱,?代表了你需要指定的參數。
和JDBC集成是存儲過程的一個很大的便利:為了從應用中調用存儲過程,不需要存根(stub)類或者配置文件,除了你的DBMS的JDBC驅動程序外什么也不需要。
當這段代碼執行時,數據庫的存儲過程就被調用。我們沒有去獲取結果,因為該存儲過程并不返回結果。執行成功或失敗將通過例外得知。失敗可能意味著調用存儲過程時的失敗(比如提供的一個參數的類型不正確),或者一個應用程序的失敗(比如拋出一個例外指示在poets數據庫中并不存在“Dylan Thomas”)
結合SQL操作與存儲過程
映射Java對象到SQL表中的行相當簡單,但是通常需要執行幾個SQL語句;可能是一個SELECT查找ID,然后一個INSERT插入指定ID的數據。在高度規格化(符合更高的范式,譯注)的數據庫模式中,可能需要多個表的更新,因此需要更多的語句。Java代碼會很快地膨脹,每一個語句的網絡開銷也迅速增加。
將這些SQL語句轉移到一個存儲過程中將大大簡化代碼,僅涉及一次網絡調用。所有關聯的SQL操作都可以在數據庫內部發生。并且,存儲過程語言,例如PL/SQL,允許使用SQL語法,這比Java代碼更加自然。下面是我們早期的存儲過程,使用Oracle的PL/SQL語言編寫:
create procedure set_death_age(poet VARCHAR2, poet_age NUMBER)
poet_id NUMBER;
begin SELECT id INTO poet_id FROM poets WHERE name = poet;
INSERT INTO deaths (mort_id, age) VALUES (poet_id, poet_age);
end set_death_age;
很獨特?不。我打賭你一定期待看到一個poets表上的UPDATE。這也暗示了使用存儲過程實現是多么容易的一件事情。set_death_age幾乎可以肯定是一個很爛的實現。我們應該在poets表中添加一列來存儲逝世年齡。Java代碼中并不關心數據庫模式是怎么實現的,因為它僅調用存儲過程。我們以后可以改變數據庫模式以提高性能,但是我們不必修改我們代碼。
下面是調用上面存儲過程的Java代碼:
public static void setDeathAge(Poet dyingBard, int age) throws SQLException{
Connection con = null;
CallableStatement proc = null;
try {
con = connectionPool.getConnection();
proc = con.prepareCall("{ call set_death_age(?, ?) }");
proc.setString(1, dyingBard.getName());
proc.setInt(2, age);
proc.execute();
}
finally {
try { proc.close(); }
catch (SQLException e) {}
con.close();
}
}
為了確保可維護性,建議使?孟裾舛?庋??tatic方法。這也使得調用存儲過程的代碼集中在一個簡單的模版代碼中。如果你用到許多存儲過程,就會發現僅需要拷貝、粘貼就可以創建新的方法。因為代碼的模版化,甚至也可以通過腳本自動生產調用存儲過程的代碼。
Functions
存儲過程可以有返回值,所以CallableStatement類有類似getResultSet這樣的方法來獲取返回值。當存儲過程返回一個值時,你必須使用registerOutParameter方法告訴JDBC驅動器該值的SQL類型是什么。你也必須調整存儲過程調用來指示該過程返回一個值。
下面接著上面的例子。這次我們查詢Dylan Thomas逝世時的年齡。這次的存儲過程使用PostgreSQL的pl/pgsql:
create function snuffed_it_when (VARCHAR) returns integer 'declare
poet_id NUMBER;
poet_age NUMBER;
begin
--first get the id associated with the poet.
SELECT id INTO poet_id FROM poets WHERE name = $1;
--get and return the age.
SELECT age INTO poet_age FROM deaths WHERE mort_id = poet_id;
return age;
end;' language 'pl/pgsql';
另外,注意pl/pgsql參數名通過Unix和DOS腳本的$n語法引用。同時,也注意嵌入的注釋,這是和Java代碼相比的另一個優越性。在Java中寫這樣的注釋當然是可以的,但是看起來很凌亂,并且和SQL語句脫節,必須嵌入到Java String中。
下面是調用這個存儲過程的Java代碼:
connection.setAutoCommit(false);
CallableStatement proc = connection.prepareCall("{ ? = call snuffed_it_when(?) }");
proc.registerOutParameter(1, Types.INTEGER);
proc.setString(2, poetName);
cs.execute();
int age = proc.getInt(2);
如果指定了錯誤的返回值類型會怎樣?那么,當調用存儲過程時將拋出一個RuntimeException,正如你在ResultSet操作中使用了一個錯誤的類型所碰到的一樣。
復雜的返回值
關于存儲過程的知識,很多人好像就熟悉我們所討論的這些。如果這是存儲過程的全部功能,那么存儲過程就不是其它遠程執行機制的替換方案了。存儲過程的功能比這強大得多。
當你執行一個SQL查詢時,DBMS創建一個叫做cursor(游標)的數據庫對象,用于在返回結果中迭代每一行。ResultSet是當前時間點的游標的一個表示。這就是為什么沒有緩存或者特定數據庫的支持,你只能在ResultSet中向前移動。
某些DBMS允許從存儲過程中返回游標的一個引用。JDBC并不支持這個功能,但是Oracle、PostgreSQL和DB2的JDBC驅動器都支持在ResultSet上打開到游標的指針(pointer)。
設想列出所有沒有活到退休年齡的詩人,下面是完成這個功能的存儲過程,返回一個打開的游標,同樣也使用PostgreSQL的pl/pgsql語言:
create procedure list_early_deaths () return refcursor as 'declare
toesup refcursor;
begin
open toesup for SELECT poets.name, deaths.age FROM poets, deaths
-- all entries in deaths are for poets. -- but the table might become generic.
WHERE poets.id = deaths.mort_id AND deaths.age < 60;
return toesup;
end;' language 'plpgsql';
下面是調用該存儲過程的Java方法,將結果輸出到PrintWriter:
PrintWriter:
static void sendEarlyDeaths(PrintWriter out){
Connection con = null;
CallableStatement toesUp = null;
try {
con = ConnectionPool.getConnection();
// PostgreSQL needs a transaction to do this... con.
setAutoCommit(false); // Setup the call.
CallableStatement toesUp = connection.prepareCall("{ ? = call list_early_deaths () }");
toesUp.registerOutParameter(1, Types.OTHER);
toesUp.execute();
ResultSet rs = (ResultSet) toesUp.getObject(1);
while (rs.next()) {
String name = rs.getString(1);
int age = rs.getInt(2);
out.println(name + " was " + age + " years old.");
}
rs.close();
}
catch (SQLException e) { // We should protect these calls. toesUp.close(); con.close();
}
}
因為JDBC并不直接支持從存儲過程中返回游標,我們使用Types.OTHER來指示存儲過程的返回類型,然后調用getObject()方法并對返回值進行強制類型轉換。
這個調用存儲過程的Java方法是mapping的一個好例子。Mapping是對一個集上的操作進行抽象的方法。不是在這個過程上返回一個集,我們可以把操作傳送進去執行。本例中,操作就是把ResultSet打印到一個輸出流。這是一個值得舉例的很常用的例子,下面是調用同一個存儲過程的另外一個方法實現:
public class ProcessPoetDeaths{
public abstract void sendDeath(String name, int age);
}
static void mapEarlyDeaths(ProcessPoetDeaths mapper){
Connection con = null;
CallableStatement toesUp = null;
try {
con = ConnectionPool.getConnection();
con.setAutoCommit(false);
CallableStatement toesUp = connection.prepareCall("{ ? = call list_early_deaths () }");
toesUp.registerOutParameter(1, Types.OTHER);
toesUp.execute();
ResultSet rs = (ResultSet) toesUp.getObject(1);
while (rs.next()) {
String name = rs.getString(1);
int age = rs.getInt(2);
mapper.sendDeath(name, age);
}
rs.close();
} catch (SQLException e) { // We should protect these calls. toesUp.close();
con.close();
}
}
這允許在ResultSet數據上執行任意的處理,而不需要改變或者復制獲取ResultSet的方法:
static void sendEarlyDeaths(final PrintWriter out){
ProcessPoetDeaths myMapper = new ProcessPoetDeaths() {
public void sendDeath(String name, int age) {
out.println(name + " was " + age + " years old.");
}
};
mapEarlyDeaths(myMapper);
}
這個方法使用ProcessPoetDeaths的一個匿名實例調用mapEarlyDeaths。該實例擁有sendDeath方法的一個實現,和我們上面的例子一樣的方式把結果寫入到輸出流。當然,這個技巧并不是存儲過程特有的,但是和存儲過程中返回的ResultSet結合使用,是一個非常強大的工具。
結論
存儲過程可以幫助你在代碼中分離邏輯,這基本上總是有益的。這個分離的好處有:
?6?1 快速創建應用,使用和應用一起改變和改善的數據庫模式。
?6?1 數據庫模式可以在以后改變而不影響Java對象,當我們完成應用后,可以重新設計更好的模式。
?6?1 存儲過程通過更好的SQL嵌入使得復雜的SQL更容易理解。
?6?1 編寫存儲過程比在Java中編寫嵌入的SQL擁有更好的工具--大部分編輯器都提供語法高亮!
?6?1 存儲過程可以在任何SQL命令行中測試,這使得調試更加容易。
并不是所有的數據庫都支持存儲過程,但是存在許多很棒的實現,包括免費/開源的和非免費的,所以移植并不是一個問題。Oracle、PostgreSQL和DB2都有類似的存儲過程語言,并且有在線的社區很好地支持。
存儲過程工具很多,有像TOAD或TORA這樣的編輯器、調試器和IDE,提供了編寫、維護PL/SQL或pl/pgsql的強大的環境。
存儲過程確實增加了你的代碼的開銷,但是它們和大多數的應用服務器相比,開銷小得多。
posted @
2008-11-20 15:25 jiafang83 閱讀(187) |
評論 (0) |
編輯 收藏
首先建立兩個存儲過程:
存儲過程p_1----從cell表中取出數據
create proc p_1
as
select * from cell
go
存儲過程p_2----往cell表里插入數據
create proc p_2
@name varchar(40),
@remark varchar(40)
as
insert into cell(name,remark) values(@name,@remark)
go
調用存儲過程p_1:
import java.sql.*;
/**
* jdbc中調用存儲過程
* @author jiafang83
*
*/
public class Procedure2 {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
String url = "jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=fish";
String user = "bm";
String pwd = "bm";
Connection conn = null;
CallableStatement proc = null;//執行sql存儲過程的接口
ResultSet rs = null;
// 調用存儲過程p_1:從Cell表中取出數據
try{
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
conn = DriverManager.getConnection(url,user,pwd);
proc = conn.prepareCall("{? = call p_1 ()}");
proc.registerOutParameter(1, Types.REAL);
rs = proc.executeQuery();//取得結果集
while(rs.next()){
System.out.println(rs.getString("name"));
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(rs!=null) rs.close();
if(proc!=null)proc.close();
if(conn!=null)conn.close();
}
}
}
調用存儲過程p_2:
import java.sql.*;
/**
* jdbc中調用存儲過程
* @author jiafang83
*
*/
public class Procedure {
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
String url = "jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=fish";
String user = "bm";
String pwd = "bm";
Connection conn = null;
CallableStatement proc = null;//執行sql存儲過程的接口
// 調用存儲過程p_2:向Cell表中插入數據
try{
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
conn = DriverManager.getConnection(url,user,pwd);
proc = conn.prepareCall("{call p_2 (?,?)}");
proc.setString(1, "測試");
proc.setString(2, "測試");
proc.execute();
System.out.println("成功調用存儲過程,插入數據!");
}catch(Exception e){
e.printStackTrace();
}finally{
if(proc!=null)proc.close();
if(conn!=null)conn.close();
}
}
posted @
2008-11-20 14:25 jiafang83 閱讀(3021) |
評論 (0) |
編輯 收藏
轉載自:
http://www.htmer.com/article/329.htm
我們在裝完SQL Server 2000數據庫后,用企業管理器打開數據庫,會發現里面默認安裝了master、model、msdb、Northwind、pubs、tempdb這6個數據庫,這些數據庫是干什么的呢?下面就一一介紹之。
1、master數據庫
master 數據庫記錄SQL Server系統的所有系統級別信息。它記錄所有的登錄帳戶和系統配置設置。它還記錄所有其它的數據庫,其中包括數據庫文件的位置。master數據庫記錄SQL Server的初始化信息,它始終有一個可用的最新master數據庫備份。
2、model數據庫
model 數據庫用作在系統上創建的所有數據庫的模板。當發出Create DATABASE語句時,新數據庫的第一部分通過復制model數據庫中的內容創建,剩余部分由空頁填充。由于SQL Server每次啟動時都要創建tempdb數據庫,model數據庫必須一直存在于SQL Server系統中。
3、msdb數據庫
msdb數據庫供SQL Server代理程序調度警報和作業以及記錄操作員時使用。
4、Northwind數據庫
Northwind數據庫包含一個名為Northwind Traders的虛構公司的銷售數據,該公司從事世界各地的特產食品進出口貿易。
5、pubs數據庫
pubs數據庫以一個圖書出版公司為模型,用于演示SQL Server數據庫中可用的許多選項。該數據庫及其中的表經常在文檔內容所介紹的示例中使用。
6、tempdb數據庫
tempdb 數據庫保存所有的臨時表和臨時存儲過程。它還滿足任何其它的臨時存儲要求,例如存儲SQL Server生成的工作表。tempdb數據庫是全局資源,所有連接到系統的用戶的臨時表和存儲過程都存儲在該數據庫中。tempdb數據庫在SQL Server每次啟動時都重新創建,因此該數據庫在系統啟動時總是干凈的。臨時表和存儲過程在連接斷開時自動除去,而且當系統關閉后將沒有任何連接處于活 動狀態,因此tempdb數據庫中沒有任何內容會從SQL Server的一個會話保存到另一個會話。
默認情況下,在SQL Server在運行時tempdb數據庫會根據需要自動增長。不過,與其它數據庫不同,每次啟動數據庫引擎時,它會重置為其初始大小。如果為tempdb 數據庫定義的大小較小,則每次重新啟動SQL Server時,將tempdb數據庫的大小自動增加到支持工作負荷所需的大小這一工作可能會成為系統處理負荷的一部分。為避免這種開銷,可以使用 Alter DATABASE增加tempdb數據庫的大小。
posted @
2008-11-19 14:06 jiafang83 閱讀(557) |
評論 (0) |
編輯 收藏
轉自:http://c21.cnblogs.com/archive/2006/05/08/393779.html
CREATE PROCEDURE
創建存儲過程,存儲過程是保存起來的可以接受和返回用戶提供的參數的 Transact-SQL 語句的集合。可以創建一個過程供永久使用,或在一個會話中臨時使用(局部臨時過程),或在所有會話中臨時使用(全局臨時過程)。也可以創建在 Microsoft SQL Server啟動時自動運行的存儲過程。
語法
CREATE PROC [ EDURE ] procedure_name [ ; number ]
[ { @parameter data_type }
[ VARYING ] [ = default ] [ OUTPUT ]
] [ ,...n ]
[ WITH
{ RECOMPILE | ENCRYPTION | RECOMPILE , ENCRYPTION } ]
[ FOR REPLICATION ]
AS sql_statement [ ...n ]
參數
procedure_name
新存儲過程的名稱。過程名必須符合標識符規則,且對于數據庫及其所有者必須唯一。有關更多信息,請參見使用標識符。
要創建局部臨時過程,可以在 procedure_name 前面加一個編號符 (#procedure_name),要創建全局臨時過程,可以在 procedure_name 前面加兩個編號符 (##procedure_name)。完整的名稱(包括 # 或 ##)不能超過 128 個字符。指定過程所有者的名稱是可選的。
;number
是可選的整數,用來對同名的過程分組,以便用一條 DROP PROCEDURE 語句即可將同組的過程一起除去。例如,名為 orders 的應用程序使用的過程可以命名為 orderproc;1、orderproc;2 等。DROP PROCEDURE orderproc 語句將除去整個組。如果名稱中包含定界標識符,則數字不應包含在標識符中,只應在 procedure_name 前后使用適當的定界符。
@parameter
過程中的參數。在 CREATE PROCEDURE 語句中可以聲明一個或多個參數。用戶必須在執行過程時提供每個所聲明參數的值(除非定義了該參數的默認值)。存儲過程最多可以有 2.100 個參數。
使用 @ 符號作為第一個字符來指定參數名稱。參數名稱必須符合標識符的規則。每個過程的參數僅用于該過程本身;相同的參數名稱可以用在其它過程中。默認情況下,參數只能代替常量,而不能用于代替表名、列名或其它數據庫對象的名稱。有關更多信息,請參見 EXECUTE。
data_type
參數的數據類型。所有數據類型(包括 text、ntext 和 image)均可以用作存儲過程的參數。不過,cursor 數據類型只能用于 OUTPUT 參數。如果指定的數據類型為 cursor,也必須同時指定 VARYING 和 OUTPUT 關鍵字。有關 SQL Server 提供的數據類型及其語法的更多信息,請參見數據類型。
說明 對于可以是 cursor 數據類型的輸出參數,沒有最大數目的限制。
VARYING
指定作為輸出參數支持的結果集(由存儲過程動態構造,內容可以變化)。僅適用于游標參數。
default
參數的默認值。如果定義了默認值,不必指定該參數的值即可執行過程。默認值必須是常量或 NULL。如果過程將對該參數使用 LIKE 關鍵字,那么默認值中可以包含通配符(%、_、[] 和 [^])。
OUTPUT
表明參數是返回參數。該選項的值可以返回給 EXEC[UTE]。使用 OUTPUT 參數可將信息返回給調用過程。Text、ntext 和 image 參數可用作 OUTPUT 參數。使用 OUTPUT 關鍵字的輸出參數可以是游標占位符。
n
表示最多可以指定 2.100 個參數的占位符。
{RECOMPILE | ENCRYPTION | RECOMPILE, ENCRYPTION}
RECOMPILE 表明 SQL Server 不會緩存該過程的計劃,該過程將在運行時重新編譯。在使用非典型值或臨時值而不希望覆蓋緩存在內存中的執行計劃時,請使用 RECOMPILE 選項。
ENCRYPTION 表示 SQL Server 加密 syscomments 表中包含 CREATE PROCEDURE 語句文本的條目。使用 ENCRYPTION 可防止將過程作為 SQL Server 復制的一部分發布。
說明 在升級過程中,SQL Server 利用存儲在 syscomments 中的加密注釋來重新創建加密過程。
FOR REPLICATION
指定不能在訂閱服務器上執行為復制創建的存儲過程。.使用 FOR REPLICATION 選項創建的存儲過程可用作存儲過程篩選,且只能在復制過程中執行。本選項不能和 WITH RECOMPILE 選項一起使用。
AS
指定過程要執行的操作。
sql_statement
過程中要包含的任意數目和類型的 Transact-SQL 語句。但有一些限制。
n
是表示此過程可以包含多條 Transact-SQL 語句的占位符。
注釋
存儲過程的最大大小為 128 MB。
用戶定義的存儲過程只能在當前數據庫中創建(臨時過程除外,臨時過程總是在 tempdb 中創建)。在單個批處理中,CREATE PROCEDURE 語句不能與其它 Transact-SQL 語句組合使用。
默認情況下,參數可為空。如果傳遞 NULL 參數值并且該參數在 CREATE 或 ALTER TABLE 語句中使用,而該語句中引用的列又不允許使用 NULL,則 SQL Server 會產生一條錯誤信息。為了防止向不允許使用 NULL 的列傳遞 NULL 參數值,應向過程中添加編程邏輯或為該列使用默認值(使用 CREATE 或 ALTER TABLE 的 DEFAULT 關鍵字)。
建議在存儲過程的任何 CREATE TABLE 或 ALTER TABLE 語句中都為每列顯式指定 NULL 或 NOT NULL,例如在創建臨時表時。ANSI_DFLT_ON 和 ANSI_DFLT_OFF 選項控制 SQL Server 為列指派 NULL 或 NOT NULL 特性的方式(如果在 CREATE TABLE 或 ALTER TABLE 語句中沒有指定的話)。如果某個連接執行的存儲過程對這些選項的設置與創建該過程的連接的設置不同,則為第二個連接創建的表列可能會有不同的為空性,并且表現出不同的行為方式。如果為每個列顯式聲明了 NULL 或 NOT NULL,那么將對所有執行該存儲過程的連接使用相同的為空性創建臨時表。
在創建或更改存儲過程時,SQL Server 將保存 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 的設置。執行存儲過程時,將使用這些原始設置。因此,所有客戶端會話的 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 設置在執行存儲過程時都將被忽略。在存儲過程中出現的 SET QUOTED_IDENTIFIER 和 SET ANSI_NULLS 語句不影響存儲過程的功能。
其它 SET 選項(例如 SET ARITHABORT、SET ANSI_WARNINGS 或 SET ANSI_PADDINGS)在創建或更改存儲過程時不保存。如果存儲過程的邏輯取決于特定的設置,應在過程開頭添加一條 SET 語句,以確保設置正確。從存儲過程中執行 SET 語句時,該設置只在存儲過程完成之前有效。之后,設置將恢復為調用存儲過程時的值。這使個別的客戶端可以設置所需的選項,而不會影響存儲過程的邏輯。
說明 SQL Server 是將空字符串解釋為單個空格還是解釋為真正的空字符串,由兼容級別設置控制。如果兼容級別小于或等于 65,SQL Server 就將空字符串解釋為單個空格。如果兼容級別等于 70,則 SQL Server 將空字符串解釋為空字符串。有關更多信息,請參見 sp_dbcmptlevel。
獲得有關存儲過程的信息
若要顯示用來創建過程的文本,請在過程所在的數據庫中執行 sp_helptext,并使用過程名作為參數。
說明 使用 ENCRYPTION 選項創建的存儲過程不能使用 sp_helptext 查看。
若要顯示有關過程引用的對象的報表,請使用 sp_depends。
若要為過程重命名,請使用 sp_rename。
引用對象
SQL Server 允許創建的存儲過程引用尚不存在的對象。在創建時,只進行語法檢查。執行時,如果高速緩存中尚無有效的計劃,則編譯存儲過程以生成執行計劃。只有在編譯過程中才解析存儲過程中引用的所有對象。因此,如果語法正確的存儲過程引用了不存在的對象,則仍可以成功創建,但在運行時將失敗,因為所引用的對象不存在。有關更多信息,請參見延遲名稱解析和編譯。
延遲名稱解析和兼容級別
SQL Server 允許 Transact-SQL 存儲過程在創建時引用不存在的表。這種能力稱為延遲名稱解析。不過,如果 Transact-SQL 存儲過程引用了該存儲過程中定義的表,而兼容級別設置(通過執行 sp_dbcmptlevel 來設置)為 65,則在創建時會發出警告信息。而如果在運行時所引用的表不存在,將返回錯誤信息。有關更多信息,請參見 sp_dbcmptlevel 和延遲名稱解析和編譯。
執行存儲過程
成功執行 CREATE PROCEDURE 語句后,過程名稱將存儲在 sysobjects 系統表中,而 CREATE PROCEDURE 語句的文本將存儲在 syscomments 中。第一次執行時,將編譯該過程以確定檢索數據的最佳訪問計劃。
使用 cursor 數據類型的參數
存儲過程只能將 cursor 數據類型用于 OUTPUT 參數。如果為某個參數指定了 cursor 數據類型,也必須指定 VARYING 和 OUTPUT 參數。如果為某個參數指定了 VARYING 關鍵字,則數據類型必須是 cursor,并且必須指定 OUTPUT 關鍵字。
說明 cursor 數據類型不能通過數據庫 API(例如 OLE DB、ODBC、ADO 和 DB-Library)綁定到應用程序變量上。因為必須先綁定 OUTPUT 參數,應用程序才可以執行存儲過程,所以帶有 cursor OUTPUT 參數的存儲過程不能通過數據庫 API 調用。只有將 cursor OUTPUT 變量賦值給 Transact-SQL 局部 cursor 變量時,才可以通過 Transact-SQL 批處理、存儲過程或觸發器調用這些過程。
Cursor 輸出參數
在執行過程時,以下規則適用于 cursor 輸出參數:
對于只進游標,游標的結果集中返回的行只是那些存儲過程執行結束時處于或超出游標位置的行,例如:
在過程中的名為 RS 的 100 行結果集上打開一個非滾動游標。
過程提取結果集 RS 的頭 5 行。
過程返回到其調用者。
返回到調用者的結果集 RS 由 RS 的第 6 到 100 行組成,調用者中的游標處于 RS 的第一行之前。
對于只進游標,如果存儲過程完成后,游標位于第一行的前面,則整個結果集將返回給調用批處理、存儲過程或觸發器。返回時,游標將位于第一行的前面。
對于只進游標,如果存儲過程完成后,游標的位置超出最后一行的結尾,則為調用批處理、存儲過程或觸發器返回空結果集。
說明 空結果集與空值不同。
對于可滾動游標,在存儲過程執行結束時,結果集中的所有行均會返回給調用批處理、存儲過程或觸發器。返回時,游標保留在過程中最后一次執行提取時的位置。
對于任意類型的游標,如果游標關閉,則將空值傳遞回調用批處理、存儲過程或觸發器。如果將游標指派給一個參數,但該游標從未打開過,也會出現這種情況。
說明 關閉狀態只有在返回時才有影響。例如,可以在過程中關閉游標,稍后再打開游標,然后將該游標的結果集返回給調用批處理、存儲過程或觸發器。
臨時存儲過程
SQL Server 支持兩種臨時過程:局部臨時過程和全局臨時過程。局部臨時過程只能由創建該過程的連接使用。全局臨時過程則可由所有連接使用。局部臨時過程在當前會話結束時自動除去。全局臨時過程在使用該過程的最后一個會話結束時除去。通常是在創建該過程的會話結束時。
臨時過程用 # 和 ## 命名,可以由任何用戶創建。創建過程后,局部過程的所有者是唯一可以使用該過程的用戶。執行局部臨時過程的權限不能授予其他用戶。如果創建了全局臨時過程,則所有用戶均可以訪問該過程,權限不能顯式廢除。只有在 tempdb 數據庫中具有顯式 CREATE PROCEDURE 權限的用戶,才可以在該數據庫中顯式創建臨時過程(不使用編號符命名)。可以授予或廢除這些過程中的權限。
說明 頻繁使用臨時存儲過程會在 tempdb 中的系統表上產生爭用,從而對性能產生負面影響。建議使用 sp_executesql 代替。sp_executesql 不在系統表中存儲數據,因此可以避免這一問題。
自動執行存儲過程
SQL Server 啟動時可以自動執行一個或多個存儲過程。這些存儲過程必須由系統管理員創建,并在 sysadmin 固定服務器角色下作為后臺過程執行。這些過程不能有任何輸入參數。
對啟動過程的數目沒有限制,但是要注意,每個啟動過程在執行時都會占用一個連接。如果必須在啟動時執行多個過程,但不需要并行執行,則可以指定一個過程作為啟動過程,讓該過程調用其它過程。這樣就只占用一個連接。
在啟動時恢復了最后一個數據庫后,即開始執行存儲過程。若要跳過這些存儲過程的執行,請將啟動參數指定為跟蹤標記 4022。如果以最低配置啟動 SQL Server(使用 -f 標記),則啟動存儲過程也不會執行。有關更多信息,請參見跟蹤標記。
若要創建啟動存儲過程,必須作為 sysadmin 固定服務器角色的成員登錄,并在 master 數據庫中創建存儲過程。
使用 sp_procoption 可以:
將現有存儲過程指定為啟動過程。
停止在 SQL Server 啟動時執行過程。
查看 SQL Server 啟動時執行的所有過程的列表。
存儲過程嵌套
存儲過程可以嵌套,即一個存儲過程可以調用另一個存儲過程。在被調用過程開始執行時,嵌套級將增加,在被調用過程執行結束后,嵌套級將減少。如果超出最大的嵌套級,會使整個調用過程鏈失敗。可用 @@NESTLEVEL 函數返回當前的嵌套級。
若要估計編譯后的存儲過程大小,請使用下列性能監視計數器。
性能監視器對象名 性能監視計數器名稱
SQLServer:緩沖區管理器 高速緩存大小(頁面數)
SQLServer:高速緩存管理器 高速緩存命中率
高速緩存頁
高速緩存對象計數*
* 各種分類的高速緩存對象均可以使用這些計數器,包括特殊 sql、準備 sql、過程、觸發器等。
有關更多信息,請參見 SQL Server:Buffer Manager 對象和 SQL Server:Cache Manager 對象。
sql_statement 限制
除了 SET SHOWPLAN_TEXT 和 SET SHOWPLAN_ALL 之外(這兩個語句必須是批處理中僅有的語句),任何 SET 語句均可以在存儲過程內部指定。所選擇的 SET 選項在存儲過程執行過程中有效,之后恢復為原來的設置。
如果其他用戶要使用某個存儲過程,那么在該存儲過程內部,一些語句使用的對象名必須使用對象所有者的名稱限定。這些語句包括:
ALTER TABLE
CREATE INDEX
CREATE TABLE
所有 DBCC 語句
DROP TABLE
DROP INDEX
TRUNCATE TABLE
UPDATE STATISTICS
權限
CREATE PROCEDURE 的權限默認授予 sysadmin 固定服務器角色成員和 db_owner 和 db_ddladmin 固定數據庫角色成員。sysadmin 固定服務器角色成員和 db_owner 固定數據庫角色成員可以將 CREATE PROCEDURE 權限轉讓給其他用戶。執行存儲過程的權限授予過程的所有者,該所有者可以為其它數據庫用戶設置執行權限。
示例
A. 使用帶有復雜 SELECT 語句的簡單過程
下面的存儲過程從四個表的聯接中返回所有作者(提供了姓名)、出版的書籍以及出版社。該存儲過程不使用任何參數。
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'au_info_all' AND type = 'P')
DROP PROCEDURE au_info_all
GO
CREATE PROCEDURE au_info_all
AS
SELECT au_lname, au_fname, title, pub_name
FROM authors a INNER JOIN titleauthor ta
ON a.au_id = ta.au_id INNER JOIN titles t
ON t.title_id = ta.title_id INNER JOIN publishers p
ON t.pub_id = p.pub_id
GO
au_info_all 存儲過程可以通過以下方法執行:
EXECUTE au_info_all
-- Or
EXEC au_info_all
如果該過程是批處理中的第一條語句,則可使用:
au_info_all
B. 使用帶有參數的簡單過程
下面的存儲過程從四個表的聯接中只返回指定的作者(提供了姓名)、出版的書籍以及出版社。該存儲過程接受與傳遞的參數精確匹配的值。
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'au_info' AND type = 'P')
DROP PROCEDURE au_info
GO
USE pubs
GO
CREATE PROCEDURE au_info
@lastname varchar(40),
@firstname varchar(20)
AS
SELECT au_lname, au_fname, title, pub_name
FROM authors a INNER JOIN titleauthor ta
ON a.au_id = ta.au_id INNER JOIN titles t
ON t.title_id = ta.title_id INNER JOIN publishers p
ON t.pub_id = p.pub_id
WHERE au_fname = @firstname
AND au_lname = @lastname
GO
au_info 存儲過程可以通過以下方法執行:
EXECUTE au_info 'Dull', 'Ann'
-- Or
EXECUTE au_info @lastname = 'Dull', @firstname = 'Ann'
-- Or
EXECUTE au_info @firstname = 'Ann', @lastname = 'Dull'
-- Or
EXEC au_info 'Dull', 'Ann'
-- Or
EXEC au_info @lastname = 'Dull', @firstname = 'Ann'
-- Or
EXEC au_info @firstname = 'Ann', @lastname = 'Dull'
如果該過程是批處理中的第一條語句,則可使用:
au_info 'Dull', 'Ann'
-- Or
au_info @lastname = 'Dull', @firstname = 'Ann'
-- Or
au_info @firstname = 'Ann', @lastname = 'Dull'
C. 使用帶有通配符參數的簡單過程
下面的存儲過程從四個表的聯接中只返回指定的作者(提供了姓名)、出版的書籍以及出版社。該存儲過程對傳遞的參數進行模式匹配,如果沒有提供參數,則使用預設的默認值。
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'au_info2' AND type = 'P')
DROP PROCEDURE au_info2
GO
USE pubs
GO
CREATE PROCEDURE au_info2
@lastname varchar(30) = 'D%',
@firstname varchar(18) = '%'
AS
SELECT au_lname, au_fname, title, pub_name
FROM authors a INNER JOIN titleauthor ta
ON a.au_id = ta.au_id INNER JOIN titles t
ON t.title_id = ta.title_id INNER JOIN publishers p
ON t.pub_id = p.pub_id
WHERE au_fname LIKE @firstname
AND au_lname LIKE @lastname
GO
au_info2 存儲過程可以用多種組合執行。下面只列出了部分組合:
EXECUTE au_info2
-- Or
EXECUTE au_info2 'Wh%'
-- Or
EXECUTE au_info2 @firstname = 'A%'
-- Or
EXECUTE au_info2 '[CK]ars[OE]n'
-- Or
EXECUTE au_info2 'Hunter', 'Sheryl'
-- Or
EXECUTE au_info2 'H%', 'S%'
D. 使用 OUTPUT 參數
OUTPUT 參數允許外部過程、批處理或多條 Transact-SQL 語句訪問在過程執行期間設置的某個值。下面的示例創建一個存儲過程 (titles_sum),并使用一個可選的輸入參數和一個輸出參數。
首先,創建過程:
USE pubs
GO
IF EXISTS(SELECT name FROM sysobjects
WHERE name = 'titles_sum' AND type = 'P')
DROP PROCEDURE titles_sum
GO
USE pubs
GO
CREATE PROCEDURE titles_sum @@TITLE varchar(40) = '%', @@SUM money OUTPUT
AS
SELECT 'Title Name' = title
FROM titles
WHERE title LIKE @@TITLE
SELECT @@SUM = SUM(price)
FROM titles
WHERE title LIKE @@TITLE
GO
接下來,將該 OUTPUT 參數用于控制流語言。
說明 OUTPUT 變量必須在創建表和使用該變量時都進行定義。
參數名和變量名不一定要匹配,不過數據類型和參數位置必須匹配(除非使用 @@SUM = variable 形式)。
DECLARE @@TOTALCOST money
EXECUTE titles_sum 'The%', @@TOTALCOST OUTPUT
IF @@TOTALCOST < 200
BEGIN
PRINT ' '
PRINT 'All of these titles can be purchased for less than $200.'
END
ELSE
SELECT 'The total cost of these titles is $'
+ RTRIM(CAST(@@TOTALCOST AS varchar(20)))
下面是結果集:
Title Name
------------------------------------------------------------------------
The Busy Executive's Database Guide
The Gourmet Microwave
The Psychology of Computer Cooking
(3 row(s) affected)
Warning, null value eliminated from aggregate.
All of these titles can be purchased for less than $200.
E. 使用 OUTPUT 游標參數
OUTPUT 游標參數用來將存儲過程的局部游標傳遞回調用批處理、存儲過程或觸發器。
首先,創建以下過程,在 titles 表上聲明并打開一個游標:
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'titles_cursor' and type = 'P')
DROP PROCEDURE titles_cursor
GO
CREATE PROCEDURE titles_cursor @titles_cursor CURSOR VARYING OUTPUT
AS
SET @titles_cursor = CURSOR
FORWARD_ONLY STATIC FOR
SELECT *
FROM titles
OPEN @titles_cursor
GO
接下來,執行一個批處理,聲明一個局部游標變量,執行上述過程以將游標賦值給局部變量,然后從該游標提取行。
USE pubs
GO
DECLARE @MyCursor CURSOR
EXEC titles_cursor @titles_cursor = @MyCursor OUTPUT
WHILE (@@FETCH_STATUS = 0)
BEGIN
FETCH NEXT FROM @MyCursor
END
CLOSE @MyCursor
DEALLOCATE @MyCursor
GO
F. 使用 WITH RECOMPILE 選項
如果為過程提供的參數不是典型的參數,并且新的執行計劃不應高速緩存或存儲在內存中,WITH RECOMPILE 子句會很有幫助。
USE pubs
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'titles_by_author' AND type = 'P')
DROP PROCEDURE titles_by_author
GO
CREATE PROCEDURE titles_by_author @@LNAME_PATTERN varchar(30) = '%'
WITH RECOMPILE
AS
SELECT RTRIM(au_fname) + ' ' + RTRIM(au_lname) AS 'Authors full name',
title AS Title
FROM authors a INNER JOIN titleauthor ta
ON a.au_id = ta.au_id INNER JOIN titles t
ON ta.title_id = t.title_id
WHERE au_lname LIKE @@LNAME_PATTERN
GO
G. 使用 WITH ENCRYPTION 選項
WITH ENCRYPTION 子句對用戶隱藏存儲過程的文本。下例創建加密過程,使用 sp_helptext 系統存儲過程獲取關于加密過程的信息,然后嘗試直接從 syscomments 表中獲取關于該過程的信息。
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'encrypt_this' AND type = 'P')
DROP PROCEDURE encrypt_this
GO
USE pubs
GO
CREATE PROCEDURE encrypt_this
WITH ENCRYPTION
AS
SELECT *
FROM authors
GO
EXEC sp_helptext encrypt_this
下面是結果集:
The object's comments have been encrypted.
接下來,選擇加密存儲過程內容的標識號和文本。
SELECT c.id, c.text
FROM syscomments c INNER JOIN sysobjects o
ON c.id = o.id
WHERE o.name = 'encrypt_this'
下面是結果集:
說明 text 列的輸出顯示在單獨一行中。執行時,該信息將與 id 列信息出現在同一行中。
id text
---------- ------------------------------------------------------------
1413580074 ?????????????????????????????????e??????????????????????????????????????????????????????????????????????????
(1 row(s) affected)
H. 創建用戶定義的系統存儲過程
下面的示例創建一個過程,顯示表名以 emp 開頭的所有表及其對應的索引。如果沒有指定參數,該過程將返回表名以 sys 開頭的所有表(及索引)。
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'sp_showindexes' AND type = 'P')
DROP PROCEDURE sp_showindexes
GO
USE master
GO
CREATE PROCEDURE sp_showindexes
@@TABLE varchar(30) = 'sys%'
AS
SELECT o.name AS TABLE_NAME,
i.name AS INDEX_NAME,
indid AS INDEX_ID
FROM sysindexes i INNER JOIN sysobjects o
ON o.id = i.id
WHERE o.name LIKE @@TABLE
GO
USE pubs
EXEC sp_showindexes 'emp%'
GO
下面是結果集:
TABLE_NAME INDEX_NAME INDEX_ID
---------------- ---------------- ----------------
employee employee_ind 1
employee PK_emp_id 2
(2 row(s) affected)
I. 使用延遲名稱解析
下面的示例顯示四個過程以及延遲名稱解析的各種可能使用方式。盡管引用的表或列在編譯時不存在,但每個存儲過程都可創建。
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'proc1' AND type = 'P')
DROP PROCEDURE proc1
GO
-- Creating a procedure on a nonexistent table.
USE pubs
GO
CREATE PROCEDURE proc1
AS
SELECT *
FROM does_not_exist
GO
-- Here is the statement to actually see the text of the procedure.
SELECT o.id, c.text
FROM sysobjects o INNER JOIN syscomments c
ON o.id = c.id
WHERE o.type = 'P' AND o.name = 'proc1'
GO
USE master
GO
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'proc2' AND type = 'P')
DROP PROCEDURE proc2
GO
-- Creating a procedure that attempts to retrieve information from a
-- nonexistent column in an existing table.
USE pubs
GO
CREATE PROCEDURE proc2
AS
DECLARE @middle_init char(1)
SET @middle_init = NULL
SELECT au_id, middle_initial = @middle_init
FROM authors
GO
-- Here is the statement to actually see the text of the procedure.
SELECT o.id, c.text
FROM sysobjects o INNER JOIN syscomments c
ON o.id = c.id
WHERE o.type = 'P' and o.name = 'proc2'
posted @
2008-11-19 13:49 jiafang83 閱讀(604) |
評論 (0) |
編輯 收藏
轉載:http://tgyd2006.javaeye.com/blog/169820
web.xml元素介紹
每一個站的WEB-INF下都有一個web.xml的設定文件,它提供了我們站臺的配置設定.
web.xml定義:
.站臺的名稱和說明
.針對環境參數(Context)做初始化工作
.Servlet的名稱和映射
.Session的設定
.Tag library的對映
.JSP網頁設定
.Mime Type處理
.錯誤處理
.利用JDNI取得站臺資源
要了解web.xml的設定值,必須了解它的schema,從web.xml中知道它的schema是由Sum Microsystems公司定制的,如果你想更為詳細的了解它,
可以到http://java.sun.com/xml/ns/j2ee/web-mapp_2_4.xsd網頁,那里有更為詳細的介紹。這里我介紹我們平常見得最都的.
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<web-app>
這是一般在寫XML時所做的聲明,定義了XML的版本,編碼格式,還有重要的指明schema的來源,為http://java.sun.com/xml/ns/j2ee
/web-app_2_4.xsd.
<description>,<display-name>,<icon>
____________________________________________
<description>站臺描述</discription>
對站臺做出描述.
<display-name>站臺名稱</display-name>
定義站臺的名稱.
<icon>
icon元素包含small-icon和large-icon兩個子元素.用來指定web站臺中小圖標和大圖標的路徑.
<small-icon>/路徑/smallicon.gif</small-icon>
small-icon元素應指向web站臺中某個小圖標的路徑,大小為16 X 16 pixel,但是圖象文件必須為GIF或JPEG格式,擴展名必須為:.gif或
.jpg.
<large-icon>/路徑/largeicon-jpg</large-icon>
large-icon元素應指向web站臺中某個大圖表路徑,大小為32 X 32 pixel,但是圖象文件必須為GIF或JPEG的格式,擴展名必須為; gif
或jpg.
范例:
<display-name>Develop Example</display-name>
<description>JSP 2.0 Tech Book's Examples</description>
<icon>
<small-icon>/images/small.gif</small-icon>
<large-icon>/images/large.gir</large-icon>
</icon>
<distributable>
______________________________________
<distributable>
distributable 元素為空標簽,它的存在與否可以指定站臺是否可分布式處理.如果web.xml中出現這個元素,則代表站臺在開發時已經
被設計為能在多個JSP Container 之間分散執行.
范例:
<distributable/>
<context-param>
___________________________________
<context-param>
context-param 元素用來設定web站臺的環境參數(context),它包含兩個子元素:
param-name和param-value.
<param-name>參數名稱</param-name>
設定Context名稱
<param-value>值</param-value>
設定Context名稱的值
</context-param>
范例:
<context-param>
<param-name>param_name</param-name>
<param-value>param_value</param-value>
</context-param>
此所設定的參數,在JSP網頁中可以使用下列方法來取得:
${initParam.param_name}
若在Servlet可以使用下列方法來獲得:
String param_name=getServletContext().getInitParamter("param_name");
<filter>
_________________________________
filter元素用來聲明filter的相關設定.filter元素除了下面介紹的的子元素之外,還包括<servlet>介紹過的<icon>,<display-name>
,<description>,<init-param>,其用途一樣.
<filter-name>Filter的名稱</filter-name>
定義Filter的名稱.
<filter-class>Filter的類名稱</filter-class>
定義Filter的類名稱.例如:com.foo.hello
</filter>
范例:
<filter>
<filter-name>setCharacterEncoding</filter-name>
<filter-class>coreservlet.javaworld.CH11.SetCharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GB2312</param-value>
</init-param>
</filter>
<filter-mapping>
______________________________________
<filter-mapping>
filter-mapping 元素的兩個主要子元素filter-name和url-pattern.用來定義Filter所對應的URL.
<filter-name>Filter的名稱</filter-name>
定義Filter的名稱.
<url-pattern>URL</url-pattern>
Filter所對應的RUL.例如:<url-pattern>/Filter/Hello</url-pattern>
<servlet-name>Servlet的名稱<servlet-name>
定義servlet的名稱.
<dispatcher>REQUEST|INCLUDE|FORWARD|ERROR</disaptcher>
設定Filter對應的請求方式,有RQUEST,INCLUDE,FORWAR,ERROR四種,默認為REQUEST.
</filter-mapping>
范例:
<filter-mapping>
<filter-name>GZIPEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
___________________________________________
<listener>
listener元素用來定義Listener接口,它的主要子元素為<listener-class>
<listen-class>Listener的類名稱</listener-class>
定義Listener的類名稱.例如: com.foo.hello
<listener>
范例:
<listener>
<listener-class>coreservlet.javaworld.CH11.ContenxtListener</listener-class>
</listener>
<servlet-mapping>
_____________________________________________
servlet-mapping元素包含兩個子元素servlet-name和url-pattern.用來定義servlet所對應URL.
<servlet-name>Servlet的名稱</servlet-name>
定義Servlet的名稱.
<url-pattern>Servlet URL</url-pattern>
定義Servlet所對應的RUL.例如:<url-pattern>/Servlet/Hello</url-pattern>
</servlet-mapping>
范例:
<servlet-mapping>
<servlet-name>LoginChecker</servlet-name>
<url-pattern>/LoginChecker</url-pattern>
</servlet-mapping>
<session-cofing>
__________________________________
<session-config>
session-config包含一個子元素session-timeout.定義web站臺中的session參數.
<session-timeout>分鐘</session-timeout>
定義這個web站臺所有session的有效期限.單位為分鐘.
</session-config>
范例:
<session-config>
<session-timeout>20</session-timeout>
</session-config>
<mime-mapping>
___________________________________________________
<mima-mapping>
mime-mapping包含兩個子元素extension和mime-type.定義某一個擴展名和某一MIME Type做對映.
<extension>擴展名名稱</extension>
擴展名稱
<mime-type>MIME格式</mime-type>
MIME格式.
</mime-mapping>
范例:
<mime-mapping>
<extension>doc</extension>
<mime-type>application/vnd.ms-word</mime-type>
</mime-mapping>
<mime-mapping>
<extension>xls</extension>
<mime-type>application/vnd.ms-excel</mime-type>
</mime-mapping>
<mime-mapping>
<extension>ppt</extesnion>
<mime-type>application/vnd.ms-powerpoint</mime-type>
</mime-mapping>
<welcome-file-list>
_____________________________________________
<welcome-file-list>
welcome-file-list包含一個子元素welcome-file.用來定義首頁列單.
<welcome-file>用來指定首頁文件名稱</welcome-flie>
welcome-file用來指定首頁文件名稱.我們可以用<welcome-file>指定幾個首頁,而服務器會依照設定的順序來找首頁.
范例:
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>
<error-page>
_________________________
<error-page>
error-page元素包含三個子元素error-code,exception-type和location.將錯誤代碼(Error Code)或異常(Exception)的種類對應
到web站臺資源路徑.
<error-code>錯誤代碼</error-code>
HTTP Error code,例如: 404
<exception-type>Exception</exception-type>
一個完整名稱的Java異常類型
<location>/路徑</location>
在web站臺內的相關資源路徑
</error-page>
范例:
<error-page>
<error-code>404</error-code>
<location>/error404.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/except.jsp</location>
</error-page>
<jsp-config>
_______________________________________________
<jsp-config>
jsp-config元素主要用來設定JSP的相關配置,<jsp:config>包括<taglib>和<jsp-property-group>兩個子元素.其中<taglib>元素
在JSP 1.2時就已經存在了;而<jsp-property-group>是JSP 2.0新增的元素.
<taglib>
taglib元素包含兩個子元素taglib-uri和taglib-location.用來設定JSP網頁用到的Tag Library路徑.
<taglib-uri>URI</taglib-uri>
taglib-uri定義TLD文件的URI,JSP網頁的taglib指令可以經由這個URI存取到TLD文件.
<taglib-location>/WEB-INF/lib/xxx.tld</taglib-laction>
TLD文件對應Web站臺的存放位置.
</taglib>
<jsp-property-group>
jsp-property-group元素包含8個元素,分別為:
<description>Description</descrition>
此設定的說明
<display-name>Name</display-name>
此設定的名稱
<url-pattern>URL</url-pattern>
設定值所影響的范圍,如:/CH2 或者/*.jsp
<el-ignored>true|false</el-ignored>
若為true,表示不支持EL語法.
<scripting-invalid>true|false</scripting-invalid>
若為true表示不支持<%scription%>語法.
<page-encoding>encoding</page-encoding>
設定JSP網頁的編碼
<include-prelude>.jspf</include-prelude>
設置JSP網頁的抬頭,擴展名為.jspf
<include-coda>.jspf</include-coda>
設置JSP網頁的結尾,擴展名為.jspf
</jsp-property-group>
</jsp-config>
范例:
<jsp-config>
<taglib>
<taglib-uri>Taglib</taglib-uri>
<taglib-location>/WEB-INF/tlds/MyTaglib.tld</taglib-location>
</taglib>
<jsp-property-group>
<description>
Special property group for JSP Configuration JSP example.
</description>
<display-name>JSPConfiguration</display-name>
<uri-pattern>/*</uri-pattern>
<el-ignored>true</el-ignored>
<page-encoding>GB2312</page-encoding>
<scripting-inivalid>true</scripting-inivalid>
............
</jsp-property-group>
</jsp-config>
<resource-ref>
________________________________________________
<resource-ref>
resource-ref元素包括五個子元素description,res-ref-name,res-type,res-auth,res-sharing-scope.利用JNDI取得站臺可
利用資源.
<description>說明</description>
資源說明
<rec-ref-name>資源名稱</rec-ref-name>
資源名稱
<res-type>資源種類</res-type>
資源種類
<res-auth>Application|Container</res-auth>
資源由Application或Container來許可
<res-sharing-scope>Shareable|Unshareable</res-sharing-scope>
資源是否可以共享.默認值為 Shareable
范例:
<resource-ref>
<description>JNDI JDBC DataSource of JSPBook</description>
<res-ref-name>jdbc/sample_db</res-ref-name>
<res-type>javax.sql.DataSoruce</res-type>
<res-auth>Container</res-auth>
</resource-ref>
posted @
2008-11-18 14:19 jiafang83 閱讀(260) |
評論 (0) |
編輯 收藏
jforum是一個不錯的開源BBS論壇,支持中文,操作方便,容易擴展,是一個不錯的選擇。通過參考網上的資料,下面給出了jforum與web項目整合的方法:
1、實現SSO類:
package net.jforum.sso;
import javax.servlet.http.Cookie;
import net.jforum.ControllerUtils;
import net.jforum.context.RequestContext;
import net.jforum.entities.UserSession;
import net.jforum.util.preferences.ConfigKeys;
import net.jforum.util.preferences.SystemGlobals;
import org.apache.log4j.Logger;
public class CookieUserSSO implements SSO {
static final Logger logger = Logger.getLogger(CookieUserSSO.class.getName());
public String authenticateUser(RequestContext request) {
// myapp login cookie, contain logged username
Cookie myCookie = ControllerUtils.getCookie("jforumSSOCookieNameUser");
String username = null;
if (myCookie != null) username = myCookie.getValue();
System.out.println("cookie_name1="+myCookie.getName());
System.out.println("cookie value1="+myCookie.getValue());
if (myCookie == null || username.trim().equals("")) {
//JForumExecutionContext.setRedirect(SystemGlobals.getValue(ConfigKeys.SSO_REDIRECT));
return null; // no cookie found
}
System.out.println("cookie_name2="+myCookie.getName());
System.out.println("cookie value2="+myCookie.getValue());
return username; // jforum username
}
public boolean isSessionValid(UserSession userSession, RequestContext request) {
System.out.println("執行isSessionValid方法");
Cookie SSOCookie = ControllerUtils.getCookie("jforumSSOCookieNameUser"); // myapp login cookie
String remoteUser = null;
if (SSOCookie != null) remoteUser = SSOCookie.getValue(); // jforum username
// user has since logged out
if(remoteUser == null &&
userSession.getUserId() != SystemGlobals.getIntValue(ConfigKeys.ANONYMOUS_USER_ID)) {
return false;
// user has since logged in
} else if(remoteUser != null &&
userSession.getUserId() == SystemGlobals.getIntValue(ConfigKeys.ANONYMOUS_USER_ID)) {
return false;
// user has changed user
} else if(remoteUser != null && !remoteUser.equals(userSession.getUsername())) {
return false;
}
return true; // myapp user and forum user the same
}
}
把該類放在
jforum\WEB-INF\classes下,然后用javac -d . CookieUserSSO .java 命令編譯,.class文件存放在jforum\WEB-INF\classes\net\jforum\sso下。
2、修改SystemGlobals.properties
有些JForum版本為jforum-custom.conf文件。
查找“SSO”字樣,找到“SSO / User authentication”配置部分,將其修改為以下內容:
authentication.type = sso-----------特別注意:sso用小寫,不能用大寫
##...
sso.implementation = net.jforum.sso.CookieUserSSO----------你自己實現的SSO類
##...
sso.redirect=http://localhost:port/jforum---------------例如:sso.redirect=http://localhost:8082/jforum
3、在程序的登錄或注銷部分加入如下代碼:
登錄:
Cookie cookie = new Cookie("jforumSSOCookieNameUser",name);-------name為從登錄界面取得的用戶名,把它加入到cookie里面
cookie.setPath("/");
cookie.setMaxAge(-1);//設置cookie的生命周期為:會話級,即瀏覽器關閉,該cookie就消失了
response.addCookie(cookie);
注銷:
Cookie cookie = new Cookie(jforumSSOCookieNameUser, "");
cookie.setMaxAge(0); // delete the cookie.
response.addCookie(cookie);
4、在html/jsp頁面加入超鏈接:
<a href="/jforum">轉到論壇</a>
這就配置完成了。
posted @
2008-11-18 11:39 jiafang83 閱讀(1918) |
評論 (0) |
編輯 收藏
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
cookies[i].setValue(null);
cookies[i].setMaxAge(0);
response.addCookie(cookies[i]);
}
}
posted @
2008-11-17 11:58 jiafang83 閱讀(128) |
評論 (0) |
編輯 收藏
轉發:
http://hi.baidu.com/unaras/blog/item/43c8338109cd27dcbd3e1e27.html
一.什么是cookies?
大家都知道,瀏覽器與WEB服務器之間是使用HTTP協議進行通信的,當某個用戶發出頁面請求時,WEB服務器只是簡單的進行響應,然后就關閉與該用戶的連接。因此當一個請求發送到WEB服務器時,無論其是否是第一次來訪,服務器都會把它當作第一次來對待,這樣的不好之處可想而知。為了彌補這個缺陷,Netscape開發出了cookie這個有效的工具來保存某個用戶的識別信息,因此人們昵稱為“小甜餅”。cookies是一種WEB服務器通過瀏覽器在訪問者的硬盤上存儲信息的手段:Netscape Navigator使用一個名為cookies.txt本地文件保存從所有站點接收的Cookie信息;而IE瀏覽器把Cookie信息保存在類似于C:\\windows\\cookies的目錄下。當用戶再次訪問某個站點時,服務端將要求瀏覽器查找并返回先前發送的Cookie信息,來識別這個用戶。
cookies給網站和用戶帶來的好處非常多:
1、Cookie能使站點跟蹤特定訪問者的訪問次數、最后訪問時間和訪問者進入站點的路徑
2、Cookie能告訴在線廣告商廣告被點擊的次數,從而可以更精確的投放廣告
3、Cookie有效期限未到時,Cookie能使用戶在不鍵入密碼和用戶名的情況下進入曾經瀏覽過的一些站點
4、Cookie能幫助站點統計用戶個人資料以實現各種各樣的個性化服務
在JSP中,我們也可以使用Cookie,來編寫一些功能強大的應用程序。
下面,我想介紹一下如何用JSP創建和處理Cookie。
二.如何創建Cookie
說了這么多,大家一定很想知道JSP是如何創建cookie了。JSP是使用如下的語法格式來創建cookie的:
Cookie cookie_name =new Cookie("Parameter","Value");
例如:Cookie newCookie =new Cookie("username","waynezheng"); response.addCookie(newCookie);
解釋:JSP是調用Cookie對象相應的構造函數Cookie(name,value)用合適的名字和值來創建Cookie,然后Cookie可以通過HttpServletResponse的addCookie方法加入到Set-Cookie應答頭,本例中Cookie對象有兩個字符串參數:username,waynezheng。注意,名字和值都不能包含空白字符以及下列字符:@ : ;? , " / [ ] ( ) =
處理Cookie的屬性
看到這里,有的朋友又要問了:我光知道如何創建Cookie有什么用呀?是呀,光知道如何創建Cookie而不知道怎么使用是不夠的。在JSP中,程序是通過cookie.setXXX設置各種屬性,用cookie.getXXX讀出cookie的屬性,現把Cookie的主要屬性,及其方法列于下,供大家參考:
類型方法名方法解釋
String getComment() 返回cookie中注釋,如果沒有注釋的話將返回空值.
String getDomain() 返回cookie中Cookie適用的域名. 使用getDomain() 方法可以指示瀏覽器把Cookie返回給同一域內的其他服務器,而通常Cookie只返回給與發送它的服務器名字完全相同的服務器。注意域名必須以點開始(例如.yesky.com)
int getMaxAge() 返回Cookie過期之前的最大時間,以秒計算。
String getName() 返回Cookie的名字。名字和值是我們始終關心的兩個部分,筆者會在后面詳細介紹getName/setName。
String getPath() 返回Cookie適用的路徑。如果不指定路徑,Cookie將返回給當前頁面所在目錄及其子目錄下的所有頁面。
boolean getSecure() 如果瀏覽器通過安全協議發送cookies將返回true值,如果瀏覽器使用標準協議則返回false值。
String getValue() 返回Cookie的值。筆者也將在后面詳細介紹getValue/setValue。
int getVersion() 返回Cookie所遵從的協議版本。
void setComment(String purpose) 設置cookie中注釋。
void setDomain(String pattern) 設置cookie中Cookie適用的域名
void setMaxAge(int expiry) 以秒計算,設置Cookie過期時間。
void setPath(String uri) 指定Cookie適用的路徑。
void setSecure(boolean flag) 指出瀏覽器使用的安全協議,例如HTTPS或SSL。
void setValue(String newValue) cookie創建后設置一個新的值。
void setVersion(int v) 設置Cookie所遵從的協議版本。
讀取客戶端的Cookie
在Cookie發送到客戶端前,先要創建一個Cookie,然后用addCookie方法發送一個HTTP Header。JSP將調用request.getCookies()從客戶端讀入Cookie,getCookies()方法返回一個HTTP請求頭中的內容對應的Cookie對象數組。你只需要用循環訪問該數組的各個元素,調用getName方法檢查各個Cookie的名字,直至找到目標Cookie,然后對該Cookie調用getValue方法取得與指定名字關聯的值。
例如
<%
String userName=request.getParameter("username");//從提交的HTML表單中獲取,用戶名
Cookie theUsername=new Cookie("username",userName);//以"username",userName值/對創建一個Cookie
theUsername.setMaxAge(60*60*24*365);
response.addCookie(theUsername);
%>
..............
<%
Cookie myCookie[]=request.getCookies();//創建一個Cookie對象數組
for(int n=0;n=cookie.length-1;i++);//設立一個循環,來訪問Cookie對象數組的每一個元素
Cookie newCookie= myCookie[n];
if(newCookie.getName().equals("username")); //判斷元素的值是否為username中的值
{%>
你好,<%=newCookie.getValue()%>!//如果找到后,向他問好
<%}
%>
設置Cookie的存在時間,及刪除Cookie 在JSP中,使用setMaxAge(int expiry)方法來設置Cookie的存在時間,參數expiry應是一個整數。正值表示cookie將在這么多秒以后失效。注意這個值是cookie將要存在的最大時間,而不是cookie現在的存在時間。負值表示當瀏覽器關閉時,Cookie將會被刪除。零值則是要刪除該Cookie。如:
<%
Cookie deleteNewCookie=new Cookie("newcookie",null);
deleteNewCookie.setMaxAge(0);
deleteNewCookie.setPath("/");
response.addCookie(deleteNewCookie);
%>
posted @
2008-11-17 11:03 jiafang83 閱讀(1381) |
評論 (1) |
編輯 收藏
1、簡單Bean裝配
<bean id="foo" class="com.jiafang.Foo">
<property name="name">
<value>jiafang</value>
</property>
</bean>
2、引用其它Bean
<bean id="foo" class="com.jiafang.Foo">
<property name="bar">
<ref bean="bar">
</property>
</bean>
<bean id="bar" class="com.spring.Bar" />
3、內部Bean
<bean id="courseService" class="com.jiafang.CourseService" >
<property name="studentService" >
<bean class="com.student.StudentService" >
</property>
</bean>
4、裝配集合
4、1 裝配List和數組
<property name="barList" >
<list>
<value>bar1</value>
<ref bean="bar2" >------list里的元素可以是任何一種元素,包括<value>、<ref>、甚至是其它<list>
</list>
</property>
4、2 裝配Set
<property name="barSet" >
<set>
<value>bar1</value>
<ref bean="bar2" >------set里的元素可以是任何一種元素,包括<value>、<ref>、甚至是其它<set>
</set>
</property>
4、3 裝配Map
<property name="barMap" >
<map>
<entry key="key1">------key的值只能是String類型
<value>bar1</value>
</entry >------entry里的元素可以是任何一種元素,包括<value>、<ref>、甚至是其它<entry>
</map>
</property>
4、4 裝配Properties
<property name="barProps" >
<props>
<prop key="key1"> bar1 </prop>
<prop key="key2"> bar2 </prop>
</props>
</property>
5、設置null
<property name="foo">
<null />
</property>
posted @
2008-11-12 11:13 jiafang83 閱讀(270) |
評論 (0) |
編輯 收藏