2011年2月21日
--查詢表空間、表空間大小及表空間對應物理路徑select a.tablespace_name,b.file_name,a.block_size,a.block_size,b.bytes/1024 /1024 "Sum MB" from dba_tablespaces a,dba_data_files b where a.tablespace_name=b.tablespace_name; --查詢表空間使用情況 SELECT UPPER(F.TABLESPACE_NAME) "表空間名", D.TOT_GROOTTE_MB "表空間大小(M)", D.TOT_GROOTTE_MB - F.TOTAL_BYTES "已使用空間(M)", TO_CHAR(ROUND((D.TOT_GROOTTE_MB - F.TOTAL_BYTES) / D.TOT_GROOTTE_MB * 100,2),'990.99') || '%' "使用比", F.TOTAL_BYTES "空閑空間(M)", F.MAX_BYTES "最大塊(M)" FROM (SELECT TABLESPACE_NAME, ROUND(SUM(BYTES) / (1024 * 1024), 2) TOTAL_BYTES, ROUND(MAX(BYTES) / (1024 * 1024), 2) MAX_BYTES FROM SYS.DBA_FREE_SPACE GROUP BY TABLESPACE_NAME) F, (SELECT DD.TABLESPACE_NAME, ROUND(SUM(DD.BYTES) / (1024 * 1024), 2) TOT_GROOTTE_MB FROM SYS.DBA_DATA_FILES DD GROUP BY DD.TABLESPACE_NAME) D WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME ORDER BY 1; --查詢表空間的free space select tablespace_name, count(*) as extends, round(sum(bytes) / 1024 / 1024, 2) as MB, sum(blocks) as blocks from dba_free_space group by tablespace_name; --查詢表空間的總容量 select tablespace_name, sum(bytes) / 1024 / 1024 as MB from dba_data_files group by tablespace_name; --查詢表空間使用率 select total.tablespace_name, round(total.MB, 2) as Total_MB,考試大論壇 round(total.MB - free.MB, 2) as Used_MB, round((1 - free.MB / total.MB) * 100, 2) || '%' as Used_Pct from (select tablespace_name, sum(bytes) / 1024 / 1024 as MB from dba_free_space group by tablespace_name) free, (select tablespace_name, sum(bytes) / 1024 / 1024 as MB from dba_data_files group by tablespace_name) total where free.tablespace_name = total.tablespace_name; 1.查找當前表級鎖的SQL如下:select sess.sid, sess.serial#, lo.oracle_username, lo.os_user_name, ao.object_name, lo.locked_mode from v$locked_object lo, dba_objects ao, v$session sess where ao.object_id = lo.object_id and lo.session_id = sess.sid; 2.殺掉鎖表進程:alter system kill session '436,35123'; 3.RAC環境中鎖查找:SELECT inst_id,DECODE(request,0,'Holder: ','Waiter: ')||sid sess, id1, id2, lmode, request, type,block,ctime FROM GV$LOCK WHERE (id1, id2, type) IN (SELECT id1, id2, type FROM GV$LOCK WHERE request>0) ORDER BY id1, request; 4.監控當前數據庫誰在運行什么SQL語句select osuser, username, sql_text from v$session a, v$sqltext b where a.sql_address =b.address order by address, piece; 5.找使用CPU多的用戶sessionselect a.sid,spid,status,substr(a.program,1,40) prog, a.terminal,osuser,value/60/100 value from v$session a,v$process b,v$sesstat c where c.statistic#=12 and c.sid=a.sid and a.paddr=b.addr order by value desc; 6.查看死鎖信息SELECT (SELECT username FROM v$session WHERE SID = a.SID) blocker, a.SID, 'is blocking', (SELECT username FROM v$session WHERE SID = b.SID) blockee, b.SID FROM v$lock a, v$lock b WHERE a.BLOCK = 1 AND b.request > 0 AND a.id1 = b.id1 AND a.id2 = b.id2; 7.具有最高等待的對象SELECT o.OWNER,o.object_name, o.object_type, a.event, SUM (a.wait_time + a.time_waited) total_wait_time FROM v$active_session_history a, dba_objects o WHERE a.sample_time BETWEEN SYSDATE - 30 / 2880 AND SYSDATE AND a.current_obj# = o.object_id GROUP BY o.OWNER,o.object_name, o.object_type, a.event ORDER BY total_wait_time DESC; SELECT a.session_id, s.osuser, s.machine, s.program, o.owner, o.object_name, o.object_type, a.event, SUM (a.wait_time + a.time_waited) total_wait_time FROM v$active_session_history a, dba_objects o, v$session s WHERE a.sample_time BETWEEN SYSDATE - 30 / 2880 AND SYSDATE AND a.current_obj# = o.object_id AND a.session_id = s.SID GROUP BY o.owner, o.object_name, o.object_type, a.event, a.session_id, s.program, s.machine, s.osuser ORDER BY total_wait_time DESC; 8.查詢當前連接會話數select s.value,s.sid,a.username from v$sesstat S,v$statname N,v$session A where n.statistic#=s.statistic# and name='session pga memory' and s.sid=a.sid order by s.value; 9.等待最多的用戶SELECT s.SID, s.username, SUM (a.wait_time + a.time_waited) total_wait_time FROM v$active_session_history a, v$session s WHERE a.sample_time BETWEEN SYSDATE - 30 / 2880 AND SYSDATE GROUP BY s.SID, s.username ORDER BY total_wait_time DESC; 10.等待最多的SQLSELECT a.program, a.session_id, a.user_id, d.username, s.sql_text, SUM (a.wait_time + a.time_waited) total_wait_time FROM v$active_session_history a, v$sqlarea s, dba_users d WHERE a.sample_time BETWEEN SYSDATE - 30 / 2880 AND SYSDATE AND a.sql_id = s.sql_id AND a.user_id = d.user_id GROUP BY a.program, a.session_id, a.user_id, s.sql_text, d.username; 11.查看消耗資源最多的SQLSELECT hash_value, executions, buffer_gets, disk_reads, parse_calls FROM V$SQLAREA WHERE buffer_gets > 10000000 OR disk_reads > 1000000 ORDER BY buffer_gets + 100 * disk_reads DESC; 12.查看某條SQL語句的資源消耗SELECT hash_value, buffer_gets, disk_reads, executions, parse_calls FROM V$SQLAREA WHERE hash_Value = 228801498 AND address = hextoraw('CBD8E4B0'); 13.查詢會話執行的實際SQLSELECT a.SID, a.username, s.sql_text FROM v$session a, v$sqltext s WHERE a.sql_address = s.address AND a.sql_hash_value = s.hash_value AND a.status = 'ACTIVE' ORDER BY a.username, a.SID, s.piece; 14.顯示正在等待鎖的所有會話SELECT * FROM DBA_WAITERS; DDL-------------------------------------------------------------- /*注意點: 1.如果在PL/SQL 等工具里打開的話,直接修改下面的代碼中[斜體加粗部分]執行 2.確保路徑存在,比如【D:\oracle\oradata\Oracle9i\】也就是你要保存文件的路徑存在 /*分為四步 */ /*第1步:創建臨時表空間 */ create temporary tablespace user_temp tempfile 'D:\oracle\oradata\Oracle9i\user_temp.dbf' size 50m autoextend on next 50m maxsize 20480m extent management local; /*第2步:創建數據表空間 */ create tablespace user_data logging datafile 'D:\oracle\oradata\Oracle9i\user_data.dbf' size 50m autoextend on next 50m maxsize 20480m extent management local; /*第3步:創建用戶并指定表空間 */ create user username identified by password default tablespace user_data temporary tablespace user_temp; /*第4步:給用戶授予權限 */ grant connect,resource,dba to username;
摘自: http://www.douban.com/note/235086917/http://jackleechina.iteye.com/blog/1595397為什么一般要采用事件監聽而不是直接對元素的事件屬性(如:onclick、onmouseover)賦值? 原來用事件屬性只能賦值一種方法,即: button1.onclick = function() { alert(1); }; button1.onclick = function() { alert(2); }; 這樣后面的賦值語句就將前面的onclick屬性覆蓋了而使用添加事件監聽的方式就可以實現并行。特別是當團隊合作時,事件并行的需求增多,比如:監聽document對象的鼠標事件或者window對象的載入事件等。使用事件屬性則很容易造成事件覆蓋掉 使用事件監聽有兩種方式:attachEvent和addEventListener attachEvent與addEventListener區別 適應的瀏覽器版本不同,同時在使用的過程中要注意 attachEvent方法 按鈕onclick addEventListener方法 按鈕click attachEvent方法, (ie系列) addEventListener方法 Mozilla系列 例子如下:
1 <!DOCTYPE html> 2 <html> 3 4 <SCRIPT LANGUAGE="JavaScript"> 5 function method1() { 6 alert("method1"); 7 } 8 function method2() { 9 alert("method2"); 10 } 11 function method3() { 12 alert("method3"); 13 } 14 </SCRIPT> 15 <body> 16 <input type="button" value="dom 元素事件屬性綁定的按鈕" id="button1"/> 17 <input type="button" value="IE瀏覽器: attachEvent進行事件綁定的按鈕" id="btn1"/> 18 <input type="button" value="火狐瀏覽器: addEventListener進行事件綁定的按鈕" id="btn2"/> 19 20 <SCRIPT LANGUAGE="JavaScript"> 21 /**//**方法一: 使用元素的事件屬性. [這種方式事件只可綁定一次,最后綁定的執行]**/ 22 button1.onclick = function() { alert("1-1"); }; 23 button1.onclick = function() { alert("1-2"); }; 24 /**//**方法二: 使用attachEvent注冊事件. 格式如下object.attachEvent(event,function);**/ 25 var btn1Obj = document.getElementById("btn1"); 26 btn1Obj.attachEvent("onclick", method1); 27 btn1Obj.attachEvent("onclick", method2); 28 btn1Obj.attachEvent("onclick", method3); 29 /**//**方法三: addEventListener. 格式如下element.addEventListener(type,listener,useCapture);**/ 30 var btn2Obj = document.getElementById("btn2"); 31 btn2Obj.addEventListener("click",method1,false); 32 btn2Obj.addEventListener("click",method2,false); 33 btn2Obj.addEventListener("click",method3,false); 34 //執行順序為method1->method2->method3 35 </SCRIPT> 36 <br/>attachEvent按照注冊倒敘執行: 執行順序為method3->method2->method1 37 <br/>addEventListener按照注冊順序執行: 執行順序為method1->method2->method3 38 </body> 39 </html> 相關衍生閱讀:
摘要: 摘自http://zhangjunhd.blog.51cto.com/113473/20629/
1.Servlet過濾器
1.1 什么是過濾器
過濾器是一個程序,它先于與之相關的servlet或JSP頁面運行在服務器上。過濾器可附加到一個或多個servlet或JSP頁面上,并且可以檢查進入這些資源的請求信息。在這之后,過濾器可以作如下的選擇:
①以常規的方式調用資源(即,調... 閱讀全文
摘要: 摘自 http://www.sandzhang.com/blog/2010/04/07/mysql-show-status-explained-detail/
要查看MySQL運行狀態,要優化MySQL運行效率都少不了要運行show status查看各種狀態,下面是參考官方文檔及網上資料整理出來的中文詳細解釋:
如有問題,歡迎指正
狀態名
作用域
... 閱讀全文
摘要: 代碼中反復開關自動提交沒有必要. 其他方面寫得還是很不錯的.清晰.摘自 http://wangqinqin.iteye.com/blog/547277
PreparedStatement:
1) addBatch()將一組參數添加到PreparedStatement對象內部。
2) executeBatch()將一批參數提交給數據庫來執行,如果全部命令執行成功... 閱讀全文
摘自 http://neoremind.net/2010/12/preparedstatement_diff/
JDBC中Statement與PreparedStatement的區別
1. statement每次執行sql語句,相關數據庫都要執行sql語句的編譯;preparedstatement是預編譯的, 采用Cache機制(預編譯語句,放在Cache中,下次執行相同SQL語句時,則可以直接從Cache中取出來,有利于sql生成查詢計劃。),對于批量處理可以大大提高效率. 也叫JDBC存儲過程。
例如,如果要執行兩條sql語句
SELECT colume FROM TABLE WHERE colume=1;
SELECT colume FROM TABLE WHERE colume=2;
會生成兩個執行計劃
一千個查詢就生成一千個執行計劃!
PreparedStatement用于使用綁定變量重用執行計劃
SELECT colume FROM TABLE WHERE colume=:x;
通過set不同數據只需要生成一次執行計劃,可以重用
是否使用綁定變量對系統影響非常大,生成執行計劃極為消耗資源
兩種實現 速度差距可能成百上千倍
后者使用了PreparedStatement對象,而前者是普通的Statement對象。PreparedStatement對象不僅包含了SQL語句,而且大多數情況下這個語句已經被預編譯過,因而當其執行時,只需DBMS運行SQL語句,而不必先編譯。當你需要執行Statement對象多次的時候,PreparedStatement對象將會大大降低運行時間,當然也加快了訪問數據庫的速度。
這種轉換也給你帶來很大的便利,不必重復SQL語句的句法,而只需更改其中變量的值,便可重新執行SQL語句。選擇PreparedStatement對象與否,在于相同句法的SQL語句是否執行了多次,而且兩次之間的差別僅僅是變量的不同。如果僅僅執行了一次的話,在對數據庫只執行一次性存取的時侯,用 Statement 對象進行處理,PreparedStatement 對象的開銷比Statement大,對于一次性操作并不會帶來額外的好處。
2. PrepareStatement中執行的SQL語句中是可以帶參數的,也就是說可以替換變量,盡量采用使用?號的方式傳遞參數,增加代碼的可讀性又可以預編譯加速;而Statement則不可以。
3. 防止SQL注入。在SQL中包含特殊字符或SQL的關鍵字(如:’ or 1 or ‘)時,Statement將出現不可預料的結果(出現異常或查詢的結果不正確),可用PreparedStatement來解決。
SQL注入或者說SQL注入攻擊就是利用Statement的漏洞完成的,例如用個用戶登錄,那么form表單有用戶名和密碼
那么我提交時,在用戶名輸入框內 輸入 “aaa’ or ’a’=’a” 密碼框隨便輸入,那么這樣意味著 sql的
查詢語言就是 “select * from 表 where 用戶名=’aaa’ or ’a’=’a’ and 密碼=’123’ ”,這樣查詢出來所有的數據或者是混亂。那么不被授權的用戶照樣可以登錄,豈不是被黑了?!實際中現在java程序員早都不用這種方式寫查詢了,一般都用PreparedStatement來查詢,或干脆就用hibernate之類的持久層框架,這樣通過sql注入就無從談起了。
摘自:http://ryxxlong.iteye.com/blog/552884
如何修改mysql root密碼 忘記MySQL ROOT密碼是在MySQ使用中很常見的問題,可是有很多朋友并不會重置ROOT密碼,那叫苦啊,特寫此文章與大家交流:
1、編輯MySQL的配置文件:my.ini 一般在MySQL安裝目錄下有my.ini即MySQL的配置文件。 在此配置文件的最后添加如下一行: skip-grant-tables 保存退出編輯。
2、然后重啟MySQL服務 在命令行下執行: net stop MySQL net start MySQL
3、設置新的ROOT密碼 然后用命令提示符cd到對應安裝目錄的bin下執行: MySQL -u root -p MySQL或mysql -u root -p 直接回車無需密碼即可進入數據庫了。 此時,在命令行下執行 use mysql; 現在我們執行如下語句把root密碼更新為: update user set password=PASSWORD("root") where user='root'; (注意:此時不用使用mysqladmin -u root -p password '你的新密碼'這條命令修改密碼,因為'skip-grant-tables'配置, 不信的話,你可以試用一下,它肯定會報如下所示的錯誤: F:\Documents and Settings\long>mysqladmin -u root -p password 'root' Enter password: Warning: single quotes were not trimmed from the password by your command line client, as you might have expected. mysqladmin: You cannot use 'password' command as mysqld runs with grant tables disabled (was started with --skip-grant-tables). Use: "mysqladmin flush-privileges password '*'" instead) exit 退出MySQL。
4、還原配置文件并重啟服務
然后修改MySQL配置文件把剛才添加的那一行'skip-grant-tables'刪除。 再次重起MySQL服務,密碼修改完畢。 用新密碼root試一下吧,又能登入重新進入mysql了?
附mysql修改密碼的一些方法: 1. 用MYSQL的grant語句,例如 mysql -h hostname –u root 命令登錄到mysqld server 用grant 命令改變口令: mysql -h 192.168.1.101 -u root 上邊的192.168.1.101 是偶的mysqld 運行機器,你換成自己的,這樣登錄上去,就可以修改密碼了, 其實沒必要這么麻煩,直接mysql -u root就可以了。 GRANT ALL ON *.* TO 'root'@'localhost' IDENTIFIED BY 'root' WITH GRANT OPTION
2. mysqladmin -u 用戶名 -p 舊密碼 password 新密碼 例1:給root 加個密碼root。首先進入cmd中,然后鍵入 以下命令,至于在CMD下能否使用mysqladmin, 就要看你的Windows環境變量PATH中是否添加“E:\Program Files\MySQL\MySQL Server 5.1\bin;”(請改為你自己的安裝路徑)了。) mysqladmin -u root password root 注:因為開始時root 沒有密碼,所以-p 舊密碼一項就可以省略了。 例2:再將root 的密碼改為admin。 mysqladmin –u root -proot password admin(注意-p 不要和后面的密碼分 開寫,要寫在一起,不然會出錯,錯誤如下所示: F:\Documents and Settings\long>mysqladmin -u root -p root password admin Enter password: **** mysqladmin: Unknown command: 'root') 當然你也可以這樣寫:mysqladmin –u root -p password admin回車, 然后再輸入你的舊密碼,這樣也是完全也可以的,看你的愛好了. 例3:再將root用戶的密碼去掉. F:\Documents and Settings\long>mysqladmin -u root -p password ; Enter password: root 此時,root用戶又沒有密碼了.可以通過下面的方法設置: F:\Documents and Settings\long>mysql -u root mysql>set password for 'root'@'localhost'=password('root');(語法:SET PASSWORD FOR '用戶名'@'主機' = PASSWORD('密碼')) mysql>set password for 'root'@'%'=password('root'); //本條可選,這是在配置mysql數據庫,如果你選擇了允許root通過遠程登錄進來時,你在mysql數據庫下的user表中, use mysql; select * from user;可以看到有兩條記錄,如果你沒有配置這一項的話,只會第一條記錄! Host User Password 'localhost', 'root', '*9C9F4927129ECC3209D8550DC8B67156FDBF9418', ... '%', 'root', '*81F5E21E35407D884A6CD4A731AEBFB6AF209E1B', ... 通過以上設置,root的密碼將變為root這樣就完成了根用戶root密碼的設置工作。
3. use mysql; update user set password =password('yourpass') where user='root'
(注:下面的這些方法我本人沒有試過,不知對不對,我只是轉載了一下:) 下面的方法都在mysql提示符下使用,且必須有mysql的root權限: 方法4 mysql> INSERT INTO mysql.user (Host,User,Password) VALUES('%','jeffrey',PASSWORD('biscuit')); mysql> FLUSH PRIVILEGES 確切地說這是在增加一個用戶,用戶名為jeffrey,密碼為biscuit。 在《mysql中文參考手冊》里有這個例子,所以我也就寫出來了。 注意要使用PASSWORD函數,然后還要使用FLUSH PRIVILEGES。
方法5 和方法三一樣,只是使用了REPLACE語句 mysql> REPLACE INTO mysql.user (Host,User,Password) VALUES('%','jeffrey',PASSWORD('biscuit')); mysql> FLUSH PRIVILEGES
方法6 使用SET PASSWORD語句, mysql> SET PASSWORD FOR jeffrey@"%" = PASSWORD('biscuit'); 你也必須使用PASSWORD()函數, 但是不需要使用FLUSH PRIVILEGES。
方法7 使用GRANT ... IDENTIFIED BY語句 mysql> GRANT USAGE ON *.* TO jeffrey@"%" IDENTIFIED BY 'biscuit'; 這里PASSWORD()函數是不必要的,也不需要使用FLUSH PRIVILEGES。
注:mysql 新設置用戶或更改密碼后需用flush privileges刷新MySQL的系統權限相關表, 否則會出現拒絕訪問,還有一種方法,就是重新啟動mysql服務器,來使新設置生效。
怎么查看端口占用情況?
開始--運行--cmd 進入命令提示符 輸入netstat -ano 即可看到所有連接的PID 之后在任務管理器中找到這個PID所對應的程序如果任務管理器中沒有PID這一項,可以在任務管理器中選"查看"-"選擇列"
經常,我們在啟動應用的時候發現系統需要的端口被別的程序占用,如何知道誰占有了我們需要的端口,很多人都比較頭疼,下面就介紹一種非常簡單的方法,希望對大家有用
假如我們需要確定誰占用了我們的9050端口
1、Windows平臺 在windows命令行窗口下執行:
C:\>netstat -aon|findstr "9050"
TCP 127.0.0.1:9050 0.0.0.0:0 LISTENING 2016
看到了嗎,端口被進程號為2016的進程占用,繼續執行下面命令:
C:\>tasklist|findstr "2016"
tor.exe 2016 Console 0 16,064 K
很清楚吧,tor占用了你的端口。
JSON 即 JavaScript Object Natation,它是一種輕量級的數據交換格式,非常適合于服務器與 JavaScript 的交互。本文將快速講解 JSON 格式,并通過代碼示例演示如何分別在客戶端和服務器端進行 JSON 格式數據的處理。 管有許多宣傳關于 XML 如何擁有跨平臺,跨語言的優勢,然而,除非應用于 Web Services,否則,在普通的 Web 應用中,開發者經常為 XML 的解析傷透了腦筋,無論是服務器端生成或處理 XML,還是客戶端用 JavaScript 解析 XML,都常常導致復雜的代碼,極低的開發效率。實際上,對于大多數 Web 應用來說,他們根本不需要復雜的 XML 來傳輸數據,XML 的擴展性很少具有優勢,許多 AJAX 應用甚至直接返回 HTML 片段來構建動態 Web 頁面。和返回 XML 并解析它相比,返回 HTML 片段大大降低了系統的復雜性,但同時缺少了一定的靈活性。 現在, JSON 為 Web 應用開發者提供了另一種數據交換格式。讓我們來看看 JSON 到底是什么,同 XML 或 HTML 片段相比,JSON 提供了更好的簡單性和靈活性。
JSON 數據格式解析
和 XML 一樣,JSON 也是基于純文本的數據格式。由于 JSON 天生是為 JavaScript 準備的,因此,JSON 的數據格式非常簡單,您可以用 JSON 傳輸一個簡單的 String,Number,Boolean,也可以傳輸一個數組,或者一個復雜的 Object 對象。
String,Number 和 Boolean 用 JSON 表示非常簡單。例如,用 JSON 表示一個簡單的 String “ abc ”,其格式為:
這與絕大多數編程語言的表示方法一致,例如:
Boolean 類型表示為 true 或 false 。此外,JavaScript 中的 null 被表示為 null ,注意,true 、false 和 null 都沒有雙引號,否則將被視為一個 String 。
JSON 還可以表示一個數組對象,使用 [] 包含所有元素,每個元素用逗號分隔,元素可以是任意的 Value,例如,以下數組包含了一個 String,Number,Boolean 和一個 null:
Object 對象在 JSON 中是用 {} 包含一系列無序的 Key-Value 鍵值對表示的,實際上此處的 Object 相當于 Java 中的 Map<String, Object> ,而不是 Java 的 Class 。注意 Key 只能用 String 表示。
例如,一個 Address 對象包含如下 Key-Value:
city:Beijing street:Chaoyang Road postcode:100025(整數) |
用 JSON 表示如下:
{"city":"Beijing","street":" Chaoyang Road ","postcode":100025} |
其中 Value 也可以是另一個 Object 或者數組,因此,復雜的 Object 可以嵌套表示,例如,一個 Person 對象包含 name 和 address 對象,可以表示如下:
{"name":"Michael","address": {"city":"Beijing","street":" Chaoyang Road ","postcode":100025} } |
JavaScript 處理 JSON 數據
上面介紹了如何用 JSON 表示數據,接下來,我們還要解決如何在服務器端生成 JSON 格式的數據以便發送到客戶端,以及客戶端如何使用 JavaScript 處理 JSON 格式的數據。
我們先討論如何在 Web 頁面中用 JavaScript 處理 JSON 數據。我們通過一個簡單的 JavaScript 方法就能看到客戶端如何將 JSON 數據表示給用戶:
function handleJson() { var j={"name":"Michael","address": {"city":"Beijing","street":" Chaoyang Road ","postcode":100025} }; document.write(j.name); document.write(j.address.city); } |
假定服務器返回的 JSON 數據是上文的:
{"name":"Michael","address": {"city":"Beijing","street":" Chaoyang Road ","postcode":100025} } |
只需將其賦值給一個 JavaScript 變量,就可以立刻使用該變量并更新頁面中的信息了,相比 XML 需要從 DOM 中讀取各種節點而言,JSON 的使用非常容易。我們需要做的僅僅是發送一個 Ajax 請求,然后將服務器返回的 JSON 數據賦值給一個變量即可。有許多 Ajax 框架早已包含了處理 JSON 數據的能力,例如 Prototype(一個流行的 JavaScript 庫:http://prototypejs.org)提供了 evalJSON() 方法,能直接將服務器返回的 JSON 文本變成一個 JavaScript 變量:
new Ajax.Request("http://url", { method: "get", onSuccess: function(transport) { var json = transport.responseText.evalJSON(); // TODO: document.write(json.xxx); } }); |
服務器端輸出 JSON 格式數據
下面我們討論如何在服務器端輸出 JSON 格式的數據。以 Java 為例,我們將演示將一個 Java 對象編碼為 JSON 格式的文本。
將 String 對象編碼為 JSON 格式時,只需處理好特殊字符即可。另外,必須用 (" ) 而非 (' ) 表示字符串:
static String string2Json(String s) { StringBuilder sb = new StringBuilder(s.length()+20); sb.append('\"'); for (int i=0; i<s.length(); i++) { char c = s.charAt(i); switch (c) { case '\"': sb.append("\\\""); break; case '\\': sb.append("\\\\"); break; case '/': sb.append("\\/"); break; case '\b': sb.append("\\b"); break; case '\f': sb.append("\\f"); break; case '\n': sb.append("\\n"); break; case '\r': sb.append("\\r"); break; case '\t': sb.append("\\t"); break; default: sb.append(c); } } sb.append('\"'); return sb.toString(); }
|
將 Number 表示為 JSON 就容易得多,利用 Java 的多態,我們可以處理 Integer,Long,Float 等多種 Number 格式:
static String number2Json(Number number) { return number.toString(); }
|
Boolean 類型也可以直接通過 toString() 方法得到 JSON 的表示:
static String boolean2Json(Boolean bool) { return bool.toString(); }
|
要將數組編碼為 JSON 格式,可以通過循環將每一個元素編碼出來:
static String array2Json(Object[] array) { if (array.length==0) return "[]"; StringBuilder sb = new StringBuilder(array.length << 4); sb.append('['); for (Object o : array) { sb.append(toJson(o)); sb.append(','); } // 將最后添加的 ',' 變為 ']': sb.setCharAt(sb.length()-1, ']'); return sb.toString(); }
|
最后,我們需要將 Map<String, Object> 編碼為 JSON 格式,因為 JavaScript 的 Object 實際上對應的是 Java 的 Map<String, Object> 。該方法如下:
static String map2Json(Map<String, Object> map) { if (map.isEmpty()) return "{}"; StringBuilder sb = new StringBuilder(map.size() << 4); sb.append('{'); Set<String> keys = map.keySet(); for (String key : keys) { Object value = map.get(key); sb.append('\"'); sb.append(key); sb.append('\"'); sb.append(':'); sb.append(toJson(value)); sb.append(','); } // 將最后的 ',' 變為 '}': sb.setCharAt(sb.length()-1, '}'); return sb.toString(); }
|
為了統一處理任意的 Java 對象,我們編寫一個入口方法 toJson(Object) ,能夠將任意的 Java 對象編碼為 JSON 格式:
public static String toJson(Object o) { if (o==null) return "null"; if (o instanceof String) return string2Json((String)o); if (o instanceof Boolean) return boolean2Json((Boolean)o); if (o instanceof Number) return number2Json((Number)o); if (o instanceof Map) return map2Json((Map<String, Object>)o); if (o instanceof Object[]) return array2Json((Object[])o); throw new RuntimeException("Unsupported type: " + o.getClass().getName()); }
|
我們并未對 Java 對象作嚴格的檢查。不被支持的對象(例如 List)將直接拋出 RuntimeException 。此外,為了保證輸出的 JSON 是有效的,Map<String, Object> 對象的 Key 也不能包含特殊字符。細心的讀者可能還會發現循環引用的對象會引發無限遞歸,例如,精心構造一個循環引用的 Map,就可以檢測到 StackOverflowException :
@Test(expected=StackOverflowError.class) public void testRecurrsiveMap2Json() { Map<String, Object> map = new HashMap<String, Object>(); map.put("key", map); JsonUtil.map2Json(map); }
|
好在服務器處理的 JSON 數據最終都應該轉化為簡單的 JavaScript 對象,因此,遞歸引用的可能性很小。
最后,通過 Servlet 或 MVC 框架輸出 JSON 時,需要設置正確的 MIME 類型(application/json)和字符編碼。假定服務器使用 UTF-8 編碼,則可以使用以下代碼輸出編碼后的 JSON 文本:
response.setContentType("application/json;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter pw = response.getWriter(); pw.write(JsonUtil.toJson(obj)); pw.flush();
|
小結
JSON 已經是 JavaScript 標準的一部分。目前,主流的瀏覽器對 JSON 支持都非常完善。應用 JSON,我們可以從 XML 的解析中擺脫出來,對那些應用 Ajax 的 Web 2.0 網站來說,JSON 確實是目前最靈活的輕量級方案。
JNDI是 Java 命名與目錄接口(Java Naming and Directory Interface),在J2EE規范中是重要的規范之一,不少專家認為,沒有透徹理解JNDI的意義和作用,就沒有真正掌握J2EE特別是EJB的知識。 那么,JNDI到底起什么作用?
要了解JNDI的作用,我們可以從“如果不用JNDI我們怎樣做?用了JNDI后我們又將怎樣做?”這個問題來探討。
沒有JNDI的做法: 程序員開發時,知道要開發訪問MySQL數據庫的應用,于是將一個對 MySQL JDBC 驅動程序類的引用進行了編碼,并通過使用適當的 JDBC URL 連接到數據庫。 就像以下代碼這樣:
Connection conn=null; try {Class.forName("com.mysql.jdbc.Driver",true, Thread.currentThread().getContextClassLoader()); conn=DriverManager.getConnection("jdbc:mysql://MyDBServer?user=qingfeng&password=mingyue"); /* 使用conn并進行SQL操作 */...... conn.close(); } catch(Exception e) {e.printStackTrace();} finally {if(conn!=null) {try {conn.close();} catch(SQLException e) { }}}
這是傳統的做法,也是以前非Java程序員(如Delphi、VB等)常見的做法。這種做法一般在小規模的開發過程中不會產生問題,只要程序員熟悉Java語言、了解JDBC技術和MySQL,可以很快開發出相應的應用程序。
沒有JNDI的做法存在的問題: 1、數據庫服務器名稱MyDBServer 、用戶名和口令都可能需要改變,由此引發JDBC URL需要修改; 2、數據庫可能改用別的產品,如改用DB2或者Oracle,引發JDBC驅動程序包和類名需要修改; 3、隨著實際使用終端的增加,原配置的連接池參數可能需要調整; 4、......
解決辦法: 程序員應該不需要關心“具體的數據庫后臺是什么?JDBC驅動程序是什么?JDBC URL格式是什么?訪問數據庫的用戶名和口令是什么?”等等這些問題,程序員編寫的程序應該沒有對 JDBC 驅動程序的引用,沒有服務器名稱,沒有用戶名稱或口令 —— 甚至沒有數據庫池或連接管理。而是把這些問題交給J2EE容器來配置和管理,程序員只需要對這些配置和管理進行引用即可。
由此,就有了JNDI。
用了JNDI之后的做法: 首先,在在J2EE容器中配置JNDI參數,定義一個數據源,也就是JDBC引用參數,給這個數據源設置一個名稱;然后,在程序中,通過數據源名稱引用數據源從而訪問后臺數據庫。 具體操作如下(以JBoss為例): 1、配置數據源 在JBoss的 D:\jboss420GA\docs\examples\jca 文件夾下面,有很多不同數據庫引用的數據源定義模板。將其中的 mysql-ds.xml 文件Copy到你使用的服務器下,如 D:\jboss420GA\server\default\deploy。 修改 mysql-ds.xml 文件的內容,使之能通過JDBC正確訪問你的MySQL數據庫,如下: <?xml version="1.0" encoding="UTF-8"?> <datasources> <local-tx-datasource> <jndi-name>MySqlDS</jndi-name> <connection-url>jdbc:mysql://localhost:3306/lw</connection-url> <driver-class>com.mysql.jdbc.Driver</driver-class> <user-name>root</user-name> <password>rootpassword</password> <exception-sorter-class-name>org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter</exception-sorter-class-name> <metadata> <type-mapping>mySQL</type-mapping> </metadata> </local-tx-datasource> </datasources>
這里,定義了一個名為MySqlDS的數據源,其參數包括JDBC的URL,驅動類名,用戶名及密碼等。
2、在程序中引用數據源:
Connection conn=null; try { Context ctx=new InitialContext(); Object datasourceRef=ctx.lookup("java:MySqlDS"); //引用數據源 DataSource ds=(Datasource)datasourceRef; conn=ds.getConnection(); /* 使用conn進行數據庫SQL操作 */...... c.close(); } catch(Exception e) {e.printStackTrace();} finally {if(conn!=null) { try { conn.close(); } catch(SQLException e) { }}} 直接使用JDBC或者通過JNDI引用數據源的編程代碼量相差無幾,但是現在的程序可以不用關心具體JDBC參數了。 在系統部署后,如果數據庫的相關參數變更,只需要重新配置 mysql-ds.xml 修改其中的JDBC參數,只要保證數據源的名稱不變,那么程序源代碼就無需修改。
由此可見,JNDI避免了程序與數據庫之間的緊耦合,使應用更加易于配置、易于部署。
JNDI的擴展: JNDI在滿足了數據源配置的要求的基礎上,還進一步擴充了作用:所有與系統外部的資源的引用,都可以通過JNDI定義和引用。
所以,在J2EE規范中,J2EE 中的資源并不局限于 JDBC 數據源。引用的類型有很多,其中包括資源引用(已經討論過)、環境實體和 EJB 引用。特別是 EJB 引用,它暴露了 JNDI 在 J2EE 中的另外一項關鍵角色:查找其他應用程序組件。
EJB 的 JNDI 引用非常類似于 JDBC 資源的引用。在服務趨于轉換的環境中,這是一種很有效的方法。可以對應用程序架構中所得到的所有組件進行這類配置管理,從 EJB 組件到 JMS 隊列和主題,再到簡單配置字符串或其他對象,這可以降低隨時間的推移服務變更所產生的維護成本,同時還可以簡化部署,減少集成工作。 外部資源”。
總結: J2EE 規范要求所有 J2EE 容器都要提供 JNDI 規范的實現。JNDI 在 J2EE 中的角色就是“交換機” —— J2EE 組件在運行時間接地查找其他組件、資源或服務的通用機制。在多數情況下,提供 JNDI 供應者的容器可以充當有限的數據存儲,這樣管理員就可以設置應用程序的執行屬性,并讓其他應用程序引用這些屬性(Java 管理擴展(Java Management Extensions,JMX)也可以用作這個目的)。JNDI 在 J2EE 應用程序中的主要角色就是提供間接層,這樣組件就可以發現所需要的資源,而不用了解這些間接性。
在 J2EE 中,JNDI 是把 J2EE 應用程序合在一起的粘合劑,JNDI 提供的間接尋址允許跨企業交付可伸縮的、功能強大且很靈活的應用程序。這是 J2EE 的承諾,而且經過一些計劃和預先考慮,這個承諾是完全可以實現的。
在Oracle中,要按特定條件查詢前N條記錄,用個rownum就搞定了。 select * from emp where rownum <= 5 結果只查詢5條記錄, oracle會自動展現一個rownum的屬性表示記錄排序號
而select * from emp where rownum > 5 ;則是失敗的。 因為:rownum是oracle預處理字段,默認標序是1,只有記錄集已經滿足條件后才會進行后續編號。由于第一條記錄rownum默認是1,而你的條件是rownum>=6 對第一條記錄比較它的rownum肯定不大于6 所以不滿足條件 oracle舍棄第一條記錄將數據庫第二條記錄標序為1再進行比較 肯定都不滿足rownum>=6 這樣循環也就是說由于沒有記錄滿足rownum>=6所以記錄一直被舍棄,rownum一直是1 。
解決方案: 利用查詢時,自動生成的rownum屬性. 排序方法: select * from ( select a1.*, rownum rwn from emp a1 where rownum <=10 ) where rwn >= 6; 或者 select * from ( select qx.*,row_number() over(order by qx.empno) rwn from emp qx ) where rwn between 6 and 10 ------------------------------------------------------------------------- 使用注意:
1排序導致數據重復:
table1中表有字段(其余字段省) ID 主鍵 DATA_UPDATE_TIME 數據更新時間(只存儲了年月日)
分頁查詢的語句如下 select * from ( select row_.*, rownum rownum_ from ( select p.id from table1 p order by p.DATA_UPDATE_TIME desc ) row_ where rownum <= ) where rownum_ >
以每頁顯示10條為例 第一次 rownum <= 10) where rownum_ > 0 第二次 rownum <= 20) where rownum_ > 10
發現有一條記錄在兩次查詢結果中重復出現,不知道問題出在哪里,請忙幫看看。
另: DATA_UPDATE_TIME 的值有重復,不知道跟它有沒有關系。 如果按ID排的話就不會出現這個問題
解答: 如果order by 不能唯一確定記錄的順序就會出現這個問題。 解決的方法是把分頁部分全部拿到最外層進行。
- select * from (
- select row_.*, rownum rownum_
- from (
- select p.id from table1 p
- order by p.DATA_UPDATE_TIME desc
- ) row_
- )
- where rownum_ > ? and rownum_ <= ?
2 排序的id順序: Oracle中的rownum的是在取數據的時候產生的序號,所以想對指定排序的數據去指定的rowmun行數據就必須注意了。 SQL> select rownum ,id,name from student order by name; ROWNUM ID NAME ---------- ------ --------------------------------------------------- 3 200003 李三 2 200002 王二 1 200001 張一 4 200004 趙四 可以看出,rownum并不是按照name列來生成的序號。系統是按照記錄插入時的順序給記錄排的號,rowid也是順序分配的。為了解決這個問題,必須使用子查詢 SQL> select rownum ,id,name from (select * from student order by name); ROWNUM ID NAME ---------- ------ --------------------------------------------------- 1 200003 李三 2 200002 王二 3 200001 張一 4 200004 趙四 這樣就成了按name排序,并且用rownum標出正確序號(有小到大)
------------ 參考Oracle的rownum原理和使用 http://tenn.iteye.com/blog/99339
在Oracle中,要按特定條件查詢前N條記錄,用個rownum就搞定了。 select * from emp where rownum <= 5 而且書上也告誡,不能對rownum用">",這也就意味著,如果你想用 select * from emp where rownum > 5 則是失敗的。要知道為什么會失敗,則需要了解rownum背后的機制: 1 Oracle executes your query.
2 Oracle fetches the first row and calls it row number 1.
3 Have we gotten past row number meets the criteria? If no, then Oracle discards the row, If yes, then Oracle return the row.
4 Oracle fetches the next row and advances the row number (to 2, and then to 3, and then to 4, and so forth).
5 Go to step 3.
了解了原理,就知道rownum>不會成功,因為在第三步的時候查詢出的行已經被丟棄,第四步查出來的rownum仍然是1,這樣永遠也不會成功。
同樣道理,rownum如果單獨用=,也只有在rownum=1時才有用。
對于rownum來說它是oracle系統順序分配為從查詢返回的行的編號,返回的第一行分配的是1,第二行是2,依此類推,這個偽字段可以用于限制查詢返回的總行數,而且rownum不能以任何表的名稱作為前綴。 舉例說明: 例如表:student(學生)表,表結構為: ID char(6) --學號 name VARCHAR2(10) --姓名 create table student (ID char(6), name VARCHAR2(100)); insert into sale values('200001',‘張一’); insert into sale values('200002',‘王二’); insert into sale values('200003',‘李三’); insert into sale values('200004',‘趙四’); commit; (1) rownum 對于等于某值的查詢條件 如果希望找到學生表中第一條學生的信息,可以使用rownum=1作為條件。但是想找到學生表中第二條學生的信息,使用rownum=2結果查不到數據。因為rownum都是從1開始,但是1以上的自然數在rownum做等于判斷是時認為都是false條件,所以無法查到rownum = n(n>1的自然數)。 SQL> select rownum,id,name from student where rownum=1;(可以用在限制返回記錄條數的地方,保證不出錯,如:隱式游標) SQL> select rownum,id,name from student where rownum=1; ROWNUM ID NAME ---------- ------ --------------------------------------------------- 1 200001 張一 SQL> select rownum,id,name from student where rownum =2; ROWNUM ID NAME ---------- ------ --------------------------------------------------- (2)rownum對于大于某值的查詢條件 如果想找到從第二行記錄以后的記錄,當使用rownum>2是查不出記錄的,原因是由于rownum是一個總是從1開始的偽列,Oracle 認為rownum> n(n>1的自然數)這種條件依舊不成立,所以查不到記錄 SQL> select rownum,id,name from student where rownum >2; ROWNUM ID NAME ---------- ------ --------------------------------------------------- 那如何才能找到第二行以后的記錄呀。可以使用以下的子查詢方法來解決。注意子查詢中的rownum必須要有別名,否則還是不會查出記錄來,這是因為rownum不是某個表的列,如果不起別名的話,無法知道rownum是子查詢的列還是主查詢的列。 SQL>select * from(select rownum no ,id,name from student) where no>2; NO ID NAME ---------- ------ --------------------------------------------------- 3 200003 李三 4 200004 趙四 SQL> select * from(select rownum,id,name from student)where rownum>2; ROWNUM ID NAME ---------- ------ --------------------------------------------------- (3)rownum對于小于某值的查詢條件 如果想找到第三條記錄以前的記錄,當使用rownum<3是能得到兩條記錄的。顯然rownum對于rownum<n((n>1的自然數)的條件認為是成立的,所以可以找到記錄。 SQL> select rownum,id,name from student where rownum <3; ROWNUM ID NAME ---------- ------ --------------------------------------------------- 1 200001 張一 2 200002 王二 綜上幾種情況,可能有時候需要查詢rownum在某區間的數據,那怎么辦呀從上可以看出rownum對小于某值的查詢條件是人為true的,rownum對于大于某值的查詢條件直接認為是false的,但是可以間接的讓它轉為認為是true的。那就必須使用子查詢。例如要查詢rownum在第二行到第三行之間的數據,包括第二行和第三行數據,那么我們只能寫以下語句,先讓它返回小于等于三的記錄行,然后在主查詢中判斷新的rownum的別名列大于等于二的記錄行。但是這樣的操作會在大數據集中影響速度。 SQL> select * from (select rownum no,id,name from student where rownum<=3 ) where no >=2; NO ID NAME ---------- ------ --------------------------------------------------- 2 200002 王二 3 200003 李三 (4)rownum和排序 Oracle中的rownum的是在取數據的時候產生的序號,所以想對指定排序的數據去指定的rowmun行數據就必須注意了。 SQL> select rownum ,id,name from student order by name; ROWNUM ID NAME ---------- ------ --------------------------------------------------- 3 200003 李三 2 200002 王二 1 200001 張一 4 200004 趙四 可以看出,rownum并不是按照name列來生成的序號。系統是按照記錄插入時的順序給記錄排的號,rowid也是順序分配的。為了解決這個問題,必須使用子查詢 SQL> select rownum ,id,name from (select * from student order by name); ROWNUM ID NAME ---------- ------ --------------------------------------------------- 1 200003 李三 2 200002 王二 3 200001 張一 4 200004 趙四 這樣就成了按name排序,并且用rownum標出正確序號(有小到大)
僅為個人理解.請指正Hibernate Session, 其作用無需多言. 在運用中為避免資源消耗,一般都會手動封裝一個HibernateUtil類(未使用Spring管理的前提下). 該類的作用使Hibernate加載配置文件config, 創建sessionFactory等只運行一次. 實際運用中,經常需要將當前線程和session綁定.一般的用法為使用ThreadLocal: 在HibernateUtil類中封裝hibernate的管理.通過openSession取得 session,并將其放入ThreadLocal變量中. 這樣業務邏輯中僅需通過工具類取得當前線程對應的session.使用完畢后,調用工具類closeSession方法將 session關閉,當前線程的ThreadLocal變量置為NULL. 保證線程歸還線程池復用后,ThreadLocal為空,以免出現導致其他線程訪問到本線程變量. 而后,Hibernate的SessionFactory提供獲取session的新方法getCurrentSession (獲得與當前線程綁定的session). 內部通過代理封裝,此方式得到的session 不僅和當前線程綁定,也無需手動開關. 默認在事務提交之后,session自動關閉. 需注意的是,必須在事務開啟的前提之下才可使用此種方式獲得的session.此外hibernate.cfg.xml配置文件中也許配置 <property name="current_session_context_class">thread</property> 基于線程 末了,引入Spring之后.sessionfactory的創建等都交給spring管理.Spring也提供了HibernateTemplate,HibernateDaoSupport這樣的封裝方法. 用戶可以不再考慮session的管理,事務的開啟關閉.只需配置事務即可. 而所謂session關閉后,因延遲加載導致前臺無法顯示的問題以往解決方式為強制全部加載,現在也可通過在web.xml中配置 org.springframework.orm.hibernate3.support.OpenSessionInViewFilter來解決. ------------------------------以下內容為工地資料------------------------------------------------------------------------------- 1 OpenSession : 手動打開,需手動關閉.[所以代碼中充斥著try catch --sf.openSession --打開事務,提交-回滾 finall關閉session的代碼]
2 threadlocal : hibernate給出的提示. 在HibernateUtil工具類中,new出threadlocal ,放入opensession.這樣可以使當前線程綁定session.
使用后需關閉session,將threadlocal中session變量置為null .
3 getCurrentSession: hibernate3的新特性. 無需手動關閉session,自動獲取當前線程的session,若無則新建之. 需在配置文件中配置thread屬性.表明和當前線程綁定.
參考網友資料,getCurrentSession模式,內部開啟了session自動提交的功能且使用getCurrentSession的session,及時做load操作,也需要打開事務.
以下為ThreadLocal的參考資料
http://space.itpub.net/9252210/viewspace-594453 今天在做數據導出的時候,由于用戶名的密碼使用的是特殊字符,所以遇到了錯誤 代碼:“EXP-00056: 遇到 ORACLE 錯誤 12154”,網上查找原因,需要用引號擴起來,但是os不同,方式也不同: windows os: exp username/"""password"""@devdb --3個雙引號擴密碼 linux/unix os: exp 'username/"password"@devdb' --1個雙引號擴密碼,1個單引號擴全部 實驗結果如下: 1.創建帶有特殊字符密碼的用戶 C:\Documents and Settings\Home>sqlplus /nolog SQL*Plus: Release 10.2.0.1.0 - Production on 星期四 5月 7 17:37:36 2009 Copyright (c) 1982, 2005, Oracle. All rights reserved. SQL> connsys/oracle@devdbas sysdba 已連接。 SQL> create user exp identified by "12345!@#$%"; 用戶已創建。 SQL> grant connect, resource to exp; 授權成功。 SQL> conn exp/"12345!@#$%"@devdb2 已連接。 SQL> create table table1 as select * from dual; 表已創建。 SQL> exit 2.windows os導出測試 C:\Documents and Settings\Home>expexp/12345!@#$%@devdbfile=c:\exp.dmp wner=exp Export: Release 9.2.0.1.0 - Production on 星期四 5月 7 17:39:42 2009 Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. EXP-00056: 遇到 ORACLE 錯誤 12154 ORA-12154: TNS: 無法處理服務名 EXP-00000: 導出終止失敗 C:\Documents and Settings\Home>exp exp/"12345!@#$%"@devdb2file=c:\exp.dmp wner=exp Export: Release 9.2.0.1.0 - Production on 星期四 5月 7 17:39:57 2009 Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. EXP-00056: 遇到 ORACLE 錯誤 12154 ORA-12154: TNS: 無法處理服務名 EXP-00000: 導出終止失敗 C:\Documents and Settings\Home>exp exp/"""12345!@#$%"""@devdb2file=c:\exp.dmp wner=exp Export: Release 9.2.0.1.0 - Production on 星期四 5月 7 17:41:54 2009 Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. 連接到: Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production With the Partitioning, Real Application Clusters, OLAP, Data Mining and Real Application Testing options 已導出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集 . 正在導出 pre-schema 過程對象和操作 . 正在導出用戶 EXP 的外部函數庫名稱 . 導出 PUBLIC 類型同義詞 . 導出私有類型同義詞 . 正在導出用戶 EXP 的對象類型定義 即將導出 EXP 的對象 ... . 正在導出數據庫鏈接 . 正在導出序號 . 正在導出群集定義 . 即將導出 EXP 的表通過常規路徑 ... . . 正在導出表 TABLE1 1 行被導出 . 正在導出同義詞 . 正在導出視圖 . 正在導出存儲的過程 . 正在導出運算符 . 正在導出引用完整性約束條件 . 正在導出觸發器 . 正在導出索引類型 . 正在導出位圖, 功能性索引和可擴展索引 . 正在導出后期表活動 . 正在導出實體化視圖 . 正在導出快照日志 . 正在導出作業隊列 . 正在導出刷新組和子組 . 正在導出維 . 正在導出 post-schema 過程對象和操作 . 正在導出統計 在沒有警告的情況下成功終止導出。 3.linux/unix os導出測試 [oracle@rac2 ~]$ expexp/12345!@#$%@devdbfile=./exp.dmp wner=exp -bash:!@#$%@devdb: event not found [oracle@rac2 ~]$ exp exp/"""12345!@#$%"""@devdbfile=./exp.dmp wner=exp -bash:!@#$%"""@devdb: event not found [oracle@rac2 ~]$exp 'exp/"12345!@#$%"@devdb'file=./exp.dmp wner=exp Export: Release 10.2.0.4.0 - Production on Thu May 7 19:21:32 2009 Copyright (c) 1982, 2007, Oracle. All rights reserved. Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production With the Partitioning, Real Application Clusters, OLAP, Data Mining and Real Application Testing options Export done in US7ASCII character set and AL16UTF16 NCHAR character set server uses ZHS16GBK character set (possible charset conversion) . exporting pre-schema procedural objects and actions . exporting foreign function library names for user EXP . exporting PUBLIC type synonyms . exporting private type synonyms . exporting object type definitions for user EXP About to export EXP's objects ... . exporting database links . exporting sequence numbers . exporting cluster definitions . about to export EXP's tables via Conventional Path ... . . exporting table TABLE1 1 rows exported . exporting synonyms . exporting views . exporting stored procedures . exporting operators . exporting referential integrity constraints . exporting triggers . exporting indextypes . exporting bitmap, functional and extensible indexes . exporting posttables actions . exporting materialized views . exporting snapshot logs . exporting job queues . exporting refresh groups and children . exporting dimensions . exporting post-schema procedural objects and actions . exporting statistics Export terminated successfully without warnings.
關于group by 的應用問題 數據庫內容為下面

寫一SQL得出下面內容: 
貼出SQL結果如下:(MySQL版本) create table gosin_temp(rq varchar(10),shengfu nchar(1)); insert into gosin_temp values('2009-05-09','勝'); insert into gosin_temp values('2009-05-09','勝'); insert into gosin_temp values('2009-05-09','負'); insert into gosin_temp values('2009-05-09','負'); insert into gosin_temp values('2009-05-10','勝'); insert into gosin_temp values('2009-05-10','負'); insert into gosin_temp values('2009-05-10','負'); select * from gosin_temp; 得到結果的SQL: select a1.rq,a1.勝,b1.負 from (select a.rq, count(a.shengfu) 勝 from gosin_temp a where a.shengfu='勝' group by a.rq) a1, (select b.rq, count(b.shengfu) 負 from gosin_temp b where b.shengfu='負' group by b.rq) b1 where a1.rq = b1.rq 類似的題目還有很多,如: 勝 負 1 a b 2 b a 3 b a 要求寫一SQL語句,輸出如下結果: 勝 負 a 1 2 b 2 1 其實都一樣 只要熟悉使用group by 就不覺得難了。
摘自: http://www.iteye.com/topic/766418 ----------------------------------------- 1,什么是Servlet 2,Servlet有什么作用 3,Servlet的生命周期 4,Servlet怎么處理一個請求 5,Servlet與JSP有什么區別 6,Servlet里的cookie技術 7,Servlet里的過濾器 8,Servlet里的監聽器 一,什么是Servlet? Servlet是一個Java編寫的程序,此程序是基于Http協議的,在服務器端運行的(如tomcat), 是按照Servlet規范編寫的一個Java類。
二,Servlet有什么作用? 主要是處理客戶端的請求并將其結果發送到客戶端。
三,Servlet的生命周期? Servlet的生命周期是由Servlet的容器來控制的,它可以分為3個階段;初始化,運行,銷毀。
初始化階段: 1,Servlet容器加載servlet類,把servlet類的.class文件中的數據讀到內存中。 2,然后Servlet容器創建一個ServletConfig對象。ServletConfig對象包含了Servlet的初始化配置信息。 3,Servlet容器創建一個servlet對象。 4,Servlet容器調用servlet對象的init方法進行初始化。
運行階段: 當servlet容器接收到一個請求時,servlet容器會針對這個請求創建servletRequest和servletResponse對象。 然后調用service方法。并把這兩個參數傳遞給service方法。Service方法通過servletRequest對象獲得請求的 信息。并處理該請求。再通過servletResponse對象生成這個請求的響應結果。然后銷毀servletRequest和 servletResponse對象。我們不管這個請求是post提交的還是get提交的,最終這個請求都會由service方法來處理。
web服務器接受到一個http請求后,web服務器會將請求移交給 servlet容器,servlet容器首先對所請求的URL進行解析并根據 web.xml 配置文件找到相應的處理servlet,同時將request、response對象傳遞給它,servlet通過request對象可知道客戶端 的請求 者、請求信息以及其他的信息等,servlet在處理完請求后會把所有需要返回的信息放入response對象中并返回到客戶端, servlet一旦處理 完請求,servlet容器就會刷新response對象,并把控制權重新返回給web服務器。 銷毀階段: 當Web應用被終止時,servlet容器會先調用servlet對象的destrory方法,然后再銷毀servlet對象, 同時也會銷毀與servlet對象相關聯的servletConfig對象。我們可以在destroy方法的實現中,釋放 servlet所占用的資源,如關閉數據庫連接,關閉文件輸入輸出流等。
在這里該注意的地方: 在servlet生命周期中,servlet的初始化和和銷毀階段只會發生一次,而service方法執行的次數則取決于servlet被客戶 端訪問的次數 四,Servlet怎么處理一個請求? 當用戶發送一個請求到某個Servlet的時候,Servlet容器會創建一個ServletRequst和ServletResponse對象。 在ServletRequst對象中封裝了用戶的請求信息,然后Servlet容器把ServletRequst和ServletResponse對象 傳給用戶所請求的Servlet,Servlet把處理好的結果寫在ServletResponse中,然后Servlet容器把響應結果傳 給用戶。 五,Servlet與JSP有什么區別? 1,jsp經編譯后就是servlet,也可以說jsp等于servlet。 2,jsp更擅長頁面(表現)。servlet更擅長邏輯編輯。 (最核心的區別)。 3,在實際應用中采用Servlet來控制業務流程,而采用JSP來生成動態網頁.在struts框架中, JSP位于MVC設計模式的視圖層,而Servlet位于控制層。 六,Servlet里的cookie技術? cookies是一種WEB服務器通過瀏覽器在訪問者的硬盤上存儲信息的手段,是由Netscape公司開發出來的。 cookie技術的好處: 1,Cookie有效期限未到時,Cookie能使用戶在不鍵入密碼和用戶名的情況下進入曾經瀏覽過的一些站點。 2,Cookie能使站點跟蹤特定訪問者的訪問次數、最后訪問時間和訪問者進入站點的路徑。 創建一個cookie Java代碼  - //里面的兩個參數分別是cookie的名和cookie的值
-
- response.addCookie(new Cookie("abc","10000000"));
使用cookie Java代碼  - Cookie[] cook =request.getCookies();//用一個Cookie數組來接收
-
- for(int j=0;j<cook.length;j++){//通過循環來打印Cookie
-
- cook[j].getName()://取cookie的名
- cook[j].getValue()://去cookie的值
-
- }
七,Servlet里的過濾器? 過濾器的主要作用 1,任何系統或網站都要判斷用戶是否登錄。 2,網絡聊天系統或論壇,功能是過濾非法文字 3,統一解決編碼 (2)怎么創建一個過濾器: 1,生成一個普通的class類,實現Filter接口(javax.servlet.Filter;)。 2,重寫接口里面的三個方法:init,doFilter,destroy。 3,然后在web.xml配置過濾器。
八,Servlet里的監聽器? 監聽器的作用:自動執行一些操作。
三種servlet監聽器: 對request的監聽。對session的監聽。對application的監聽。
怎么創建一個session監聽器: 1,生成一個普通的class類,如果是對session的監聽,則實現HttpSessionListener。 2,然后重寫里面的五個方法: Java代碼  - public void sessionCreated(HttpSessionEvent arg0) {} // 創建
-
- public void sessionDestroyed(HttpSessionEvent arg0) {} // 銷毀
-
- public void attributeAdded(HttpSessionEvent arg0) {} // 增加
-
- public void attributeRemoved(HttpSessionEvent arg0) {} // 刪除
-
- public void attributeReplaced(HttpSessionEvent arg0) {} // 替換
這個寫的不錯.有的沒看懂. 目前沒時間細看,暫時先轉載. 摘自: http://www.jdon.com/artichect/state.htm --------------------------------------------------- 板橋里人 http://www.jdon.com 2006/1/2(轉載請保留) 這是一個實戰中非常重要但是容易被忽視的概念,說它重要,是因為它比數據庫重要;說它容易被忽視也是同樣的原因,它經常被數據庫概念替代。 如果你經驗和經歷中沒有狀態這個概念,極端地說:可能你的Java系統經驗還未積累到一定程度,狀態是每個Java程序員深入Java系統后必然碰到的問題。 本文我想試圖表達的是:狀態分兩種:活動的狀態對象和持久化的狀態。而數據庫中的數據只是狀態的一種持久化結果,而Java系統 運行時,我們更多的可能是和一種活動的狀態打交道,這種活動的狀態存在內存中,而不是持久化到硬盤上,當然,需要時你可以通過數據庫/文件持久化到硬盤上。 但是,如果你以數據庫數據替代狀態,那么就可能導致數據庫的頻繁訪問,而且 你的系統會變成一個非對象化的、緊耦合、到處是分散數據塊的糟糕系統。這樣的系統并不比傳統的兩層結構好到哪里!也不會比Jsp里嵌入Java代碼偽三層系統高明到什么地方。 什么是狀態? 只要有對象就可能有狀態,任何一個對象活動時,都有自己的狀態屬性,類的 字段屬性極有可能成為狀態,我們現在經常使用的Domain model其實就是一種 包含狀態的對象,如果你對狀態沒有深入掌握,就不可能真正掌握對象系統特點,或者是Domain Model的執行情況。 對于初學者,經常會疑問:我是將數據放在HttpSession中還是Request中,這里 其實已經開始接觸狀態,一旦你接觸狀態,你就要開始小心,因為你可能會將內存泄漏的惡魔導引進來。 內存泄漏的惡魔爆發時刻取決于你狀態的生存周期和系統并發訪問量。 狀態的生存周期也就是包含這個狀態的對象的生命周期,在簡單系統中,我們只 需要通過new創建對象,然后它的消亡就會依靠JVM垃圾回收機制回收,但是事情會這么簡單嗎? 狀態的危險還會發生在多線程環境下,當多個線程對同一個內存中狀態寫操作時,這時怎么辦?如果這個狀 態持久化在數據庫中,我們會依賴數據庫提供的強大事務機制防止這種并發死鎖,但是如果是在內存中,你就很難辦,因此,我們就盡量避免發生這種多線程同時訪 問一個狀態的現象,而Singleton單例模式極容易發生這種現象,因此實踐中,單例模式是J2EE開發中需要避免的,相關帖子討論見: http://www.jdon.com/jive/article.jsp?forum=91&thread=17578 我們接觸的Web容器或Jsp/Servlet本質就是一個多線程,這也是很多初學者不知道的, 因為多線程編程是復雜或困難的,因此才有jsp/Servlet這樣的上層封裝,但是我們使用他們 時,實際在進行多線程編程。 生命周期和多線程并發使得我們簡單的面向對象系統變得異常復雜和難以掌握起來。下面我從這個兩個角度,給出兩種模式思維解決之道。 生命周期(Scope) 生命周期(Scope)就是指狀態的活動周期,狀態對象是什么時候被創建;然后什么時候被銷毀,很顯然,如果狀態對象還沒有被創建或已經被銷毀,你再 訪問這個狀態對象可能失敗,而狀態的生命周期控制是可能散落在運行程序的各個地方,如果不象狀態模式那樣進行統一控制,有可能整個系統是危機四伏的。 狀態的生命周期其實就是對象生命周期,更加細化地說:是Domain Model這個對象的生命周期。這在一個以領域模型為驅動的設計概念中不可回避的課題,而領域模型實戰的復雜性就復雜在此。 狀態的生命周期在J2EE中目前有三種:Request/Session和 Application,Request是每個客戶端發出的一次請求,這是J2EE系統中最基本的事件激活單元, 當服務器端推出一個頁面到客戶端時,意味著這個Request的結束。那么如果我們的狀態保存在Request中,意味著在request結束之前,這個 請求經歷的任何一個環節都可以對這個狀態(對象)進行操作。(掌握這個原理,對于你學習Struts和JSF很有幫助) 如果是Session,則一直和該客戶端有關,只要是該客戶端發出的每次request的任何環節都可以對這個狀態(對象)進行操作。 如果是Application,則意味著這個狀態是當前Web項目的全局狀態。 這三種狀態形式都是以將狀態保存在內存中形式存在的,是和持久化狀態相對的。是一種內存活動狀態。 生命周期的選取當然是越短越好,這樣,這個狀態對象就可以被自動銷毀,從而避免了 大訪問量下的內存泄漏,但是在大訪問量下,對象頻繁創建和銷毀是耗費性能的。 那么,我們可能經常使用HttpSession來保存狀態,這時你極有可能造成內存泄漏,我經常在 Jdon論壇上看到將很多數據庫數據暫時保存在HttpSession中想法,這是相當危險的,因為一旦并發用戶很多,相當多的HttpSession包 含了狀態,而狀態中有可能有更多其他引用,因此內存很快會爆滿,或者垃圾回收機制頻繁啟動,造成應用系統運行暫停或緩慢。 當你將狀態放入HttpSession時,難道沒有考慮將其手工消除嗎?你要知道所有Web容器 (Tomcat/Weblogic等)都不會自動替你清除那些你可能不用的狀態對象啊。如果每個人只管新增元素,不管重整或管理,這個系統能不變得混亂 嗎?代碼上這種現象我們是通過Refactoring等結構/行為模式來解決,那么在運行時的狀態管理呢? 狀態管理模式或者說對象管理模式正是解決這種問題的。 按照該模式,你必須手工自己管理放在HttpSession的狀態,比如你為每個HttpSession 設立一個狀態容器最大尺寸,當超過這個尺寸時,你需要將不用的狀態從容器去除, 但是如果這個客戶端在Session失效期內又來訪問這個狀態怎么辦?那么你可能需要先臨時將狀態序列化保存到硬盤上,等Session失效期到達后再真正刪除。 是不是覺得很麻煩? 捷徑是有: 1. 盡量少使用HttpSession保存狀態,這對集群環境也是有利的,見該貼討論: http://www.jdon.com/jive/article.jsp?forum=121&thread=22282 那么這些狀態放在哪里?使用Application的緩存中, 2. 使用狀態管理中間件,目前有幾個選擇:EJB的有態Bean;NanoContainer之類狀態相關的微容器。那么Spring可以嗎?目前沒有發現有 該功能,甚至在Spring容器內無法直接使用Session性質的狀態,只能通過線程級別的ThreadLocal來實現(對不起,你又要開始回到遠古 的匯編線程時代了);而Jdon框架則可以。 下面我們談談Application的狀態,在這個范圍內,一個對象狀態可以被多個用戶反復訪問,在這個級別,狀態類似數據庫中數據,因為可以使用數據庫來替代這個級別的狀態,所以將狀態放入緩存這個深層次技術被大多數初學者忽視了,甚至產生了對數據庫依賴心理。 緩存中的狀態 雖然我們將狀態保存在Application中,但是我們不可避免還是遇到Session同樣的狀態管理問題,這個問題所幸的是有專門緩存中間件解決 了,當然,在一個多服務器集群系統,如果一個客戶端在一個服務器中存放了狀態,那么能否在另外一個服務器的內存中訪問到呢?回答是肯定的,前提是你必須使 用分布式緩存系統。 目前分布式緩存系統是靠EJB服務器完成,當JBoss 5在2006變成完全解耦、可肢解時, 我們就可以使用原本只支持EJB的JBoss分布式緩存系統來支持我們的普通JavaBeans了(POJO)。這其中目前可能會花費一些力氣,因為還沒有一個統一的POJO構件接口標準,我相信以后 可能會有。 如果你不想花費力氣,而且可能就只是一臺服務器,可以通過雙核芯片提升性能,那么單態緩存如果實現?很簡單,使用一個緩存產品如OsCache等,將其設定保存在 Application中,或者在web.xml中進行一下簡單的配置即可。 但是,這時你可能碰到另外一個問題:狀態的唯一標識,如何通過唯一標識從緩存中那么 多對象狀態中取出你要的那一個呢?比較瑣碎。 有沒有一個框架幫助你省卻這些麻煩,當然推薦Jdon Framework,只要將包含狀態的類(主要是Domain Model)繼承特定的類或接口(接口在1.4版本實現)即可,這個類的對象運行時就會被緩存或從緩存中讀取,再也無需你照料緩存了,就這么簡單。 當然,Jdon Framework的底層緩存器是可以被替代,使用你喜歡的緩存產品,因為jdon Framework是基于Ioc設計,構件之間是完全解耦、可徹底肢解,能夠通過配置替代和更換的。 如果你不明白這個道理,需要好好研究一下Ioc模式帶給我們革命性的新變化。 從以上也可以看出:java復雜性還在于我們需要在編碼時,卻要想象其運行時的情形。而這種翻譯聯想沒有深厚的實踐功底,是很難順利完成的。 狀態管理中間件 自從J2EE開辟中間件時代以來,就有相當多的高級中間件提供與具體應用無關的通用功能,狀態管理中間件很早就有之,EJB的有態Session Bean是一個代表。 一個中間件不但要有良好的松耦合設計,我們暫時稱為靜態設計;更要有優秀的動態設計,例如狀態管理就屬于一種動態設計。 當然,如果你比較謙虛,不但要選擇一些靜態設計很好的框架或中間件;而且還要依賴一些擁有良好的動態運行管理的中間件。 EJB無論是EJB1.X/EJB2.X/EJB3.X.在狀態管理上要更加優秀,當然EJB3.X又吸收了優秀的靜態設計概念,但是因為需要有一個具體服務器實現過程,這個過程中存在一些陷阱,如In-Box問題等。 Spring無疑是一個靜態設計非常優秀框架,它一直在AOP上孜孜不倦,力圖探索一條從AOP角度進行動態運行管理干預捷徑,相信會有驚人結果,當然,這種細粒度的AOP需要實踐檢驗,當然如果整入JDK 6.0就更好。 而Jdon Framework則試圖在目前兩者之間尋求了一個平衡,既有Ioc/AOP優秀的靜態設計,雖然在AOP上不及Spring前衛;但提供了切實Session和Cache狀態管理; 如果你不需要EJB的分布式多服務器集群功能;又不是AOP的超級粉絲,無疑使用Jdon Framework之類的框架無疑是簡化方便的。 狀態設計的難點 最后,我不得不重申,并不是有了良好的狀態管理框架就可以高枕無憂了,狀態的設計其實是我們每個項目必須面臨的可變課題,如果狀態復雜了可以使用狀態模式對付,可惜往往狀態不夠復雜。 一個對象本身屬性和狀態是應該耦合在一起,還是進行分離,屬性和狀態沒有明顯的涇渭分明的界限,我們舉一個例子: 論壇Forum這個對象,它有一些字段屬性,如論壇名稱、論壇描述,還有其他一些相關屬性:如該論壇 的最新發帖;該論壇的發貼量,后兩者好像也是論壇字段,但是他們可能經常變化的,應該屬于狀態,那么狀態和Forum這個主體對象是什么關系?是將該論壇 的最新發帖和該論壇的發貼量兩個字段并入Forum這個Domain Model中,還是應該單獨建立一個狀態對象?如果進行分離,分離的依據是什么? 當然,這里分離的依據是因為對象的生存周期不同。對于我們熟悉的課題,我們能夠馬上分辨出其中的生存周期,如果是不熟悉領域的建模呢? 所以,大家已經明白:狀態設計的難點是:如何粒度細化地創建模型對象;然后分辨出其中動態的狀態性質。這是域建模實戰中一個難點。 很多人問我:你提倡的域建模、設計模式和框架是什么意思?為什么說他們是Java開發設計的三件寶呢?或者說三個典型知識點呢?我想通過本篇我已經通過狀態這個概念稍微解釋了域建模的一些特點。 當前,MDA中的四色原型模式Archetype將幫助我們更好地分辨出類的屬性、狀態和行為,這是一場帶來以后十年的軟件革命,
我對瀏覽器請求流程的理解: (1) 訪問流程: (1.1) 系統運行在某web容器,如Tomcat(其運行和weblogic不同,Tomcat只有一個進程). 其預設有初始的線程數. (1.2) 瀏覽器打開某網站,網站及給其分配一個sessionID(頁面隱式的發起request, 由Tomcat 某個特定的監聽線程給予response一個sessionid). 該sessionid用以識別本次訪問. (1.3) 用戶點擊登錄/注冊, 瀏覽器發起一個新的request, 由Tomcat線程池中空閑的線程進行 處理. 反饋結果于前臺展現.如線程池中線程不足,則Tomcat每次按照一定規則創建出更多的空閑線程(其初始值,增加值,及最大值依據配置文件/JDK/硬件).
來源: http://www.iteye.com/topic/960652 http://godsend-jin.iteye.com/blog/1004386 -------------------------------------------------------------------- 最近在做登錄和權限控制模塊,用到了session,發現session的好多方法都不熟悉,而且以前也聽說過JsessionId 之類session竊取的事, 對這些一直都是一知半解。今天索性google了很多資料,先上sun的官網去看session的文檔了解一些方法,又找了別人關于session的看法。 總結如下: 1,session是什么? what session經常譯為會話,以打電話為例,從開始撥號到掛斷電話就是你會話的生存周期。 2,session 做什么用的 why? 首先舉個例子: 咖啡店舉行 消費滿5杯咖啡贈送一杯的活動,可每個人一次消費5杯的時候非常少。這時候有3種辦法: 1,店員看到每個顧客時都能記住其消費了多少杯,從而給其優惠,這是協議本身具有狀態 2,給每個顧客一個卡片,上面記錄顧客的每次消費,這是客戶端保存狀態 3,給每個顧客一個卡片,卡片上只有一個編號,顧客每次的消費記錄在店里,這就是 服務端有狀態 而http本身是無狀態的,所以我們只能使用2,3中方法,來保存一些信息。 實際采用的是第3種方法,服務器段保存一次會話所有的信息,并生成一個唯一的id,這個id沒有規律而且不會重復,將這個id傳回到客戶段, 保存到cookie中。每次訪問服務器時,客戶端都會偷偷將這個id傳到服務器,服務器根據id查到這次會話保存的內容。就能實現會話中共享一些數據。 3,session怎樣創建和銷毀 ? how session是保存在內存中的,所以會有一些性能上的影響。因此本著這個原則,session是只有在使用到的時候才會被創建,如果始終沒有用到 session,這個session是永遠不會被創建的。 比如: 訪問servlet ,只要你代碼中沒有 request.getSession()或request.getSession(true);這兩行是等價的,那session是不會創建。 又 當你訪問靜態頁面時,根本不會生成servlet,所以也不會創建session。 下面解釋一些疑惑: session是第一次請求時創建的? 大家都知道 jsp是被編譯成servlet才執行的,問題就在jsp編譯的過程。 jsp中有個<%@ page session="true/false"%> 這個開關表示是否創建session,當你不寫這行時,它會默認給你加上這句。所以會造成上面的疑惑。 當然還有一些標簽中可能有getSession()操作,會產生一些不必要的session。 session只能在服務端銷毀,有三種途徑: 1,到達session的最大請求間隔時間時,2,session。invalidate() 3,服務器進程當掉。 這里也有一些疑惑: 瀏覽器關閉時,session就會注銷。 首先瀏覽器關閉時,瀏覽器并沒有給服務器發送任何消息,所以服務器不會知道瀏覽器何時關閉了。 上面我們知道取得session 是因為瀏覽器cookie中有sessionid,而普通cookie通常會是會話cookie,也就是說瀏覽器關閉時,這個cookie會被注銷, 所以當你再訪問服務器時就沒有sessionid了,所以造成session關閉了的假象,如果昵稱通過特殊方法將sessionid傳遞給服務器,你會發現session還在。 如果想讓cookie保存時間長一些,就需要手動指定cookie的過期時間 4,實際項目中的難點: 1,瀏覽器禁用cookie 這就沒辦法保存sessionid了,可以采用url重寫,轉發,加隱藏字段等方法來將sessionid傳給服務器。 如: baidu.com:jsessionid=adfasdfasdfasdfasdfafdadf?asdfasdf baidu.com?jsessionid=asdfasdfasdfadsfad&&adfdf 這根據服務器的不同實現,第一種可以將普通參數區分開。 2,多人共用session的問題 例: a 訪問 baidu.com ,但他沒有帳號,于是他將連接 baidu.com/login.jsp?jsessionid=adsfasdfad(這個a的sessionid) 發給B, B登錄 后,a就相當于用b的帳號登錄了。你們可以在在本地試試。 解決方法: 當發現通過sessionid從url指定時, 創建一個新的session,將舊session的信息復制到 新sessoin中,然后將新session注銷。 就能防止上面那種情況了。 3,一個帳號多地方登錄 比如: 你用abc帳號登錄了baidu.com,有打開了一個瀏覽器,又用abc帳號登錄了一次。當不設計敏感操作時,這無所謂,而當你做一些敏感操 作時就必須禁止這樣情況,防止同時操作,造成重復操作,或者數據損壞。 解決方法: 監聽session,將username和sessionid對應起來,當username再次登錄時,注銷掉以前的session,保存現在的session,這也是 一種比較不錯的方案。 這是 sghcel 畫的圖,挺不錯的:  其他: 1、session在何時被創建 2、session何時被刪除
3、如何做到在瀏覽器關閉時刪除session
4、有個HttpSessionListener是怎么回事 你可以創建這樣的listener去監控session的創建和銷毀事件,使得在發生這樣的事件時你可以做一些相應的工作。注意是session的創建和銷毀動作觸發listener, 而不是相反。類似的與HttpSession有關的listener還有 HttpSessionBindingListener,HttpSessionActivationListener和 HttpSessionAttributeListener。 5、存放在session中的對象必須是可序列化的嗎 6、如何才能正確的應付客戶端禁止cookie的可能性 7、開兩個瀏覽器窗口訪問應用程序會使用同一個session還是不同的session 參見第三小節對cookie的討論,對session來說是只認id不認人,因此不同的瀏覽器,不同的窗口打開方式以及不同的cookie存儲方式都會對這個問題 的答案有影響。 8、如何防止用戶打開兩個瀏覽器窗口操作導致的session混亂 9、為什么在Weblogic Server中改變session的值后要重新調用一次session.setValue
10、HttpSession 和 hibernate session 有什么區別?
AOP術語介紹
1. 正常的編程為從上到下的調用,執行

2. 加入了安全性檢查,日志這樣的代碼. 這是一個橫切的問題,其于正常的業務毫無關系.
橫切的問題會散布在代碼的各個角落 .
3.這個橫切就是橫切性的關注點: Cross cutting concern

4. 將橫切的關注點都放在一個類中(如動態代理項目中的SecurityHandler.java).這個類就叫做切面.
對橫切關注點進行模塊化,這個模塊化的類就叫做切面類(Aspect對應的類) ,

5. 在切面類中對某個問題如日志或安全性檢查的具體實現方法,叫做橫切關注點的具體實現(稱為Advice).


6. 這個Advice可以進行分類. :在業務方法執行之前,之后.異常時候……

7. Advice應用的目標方法范圍(那些方法之前,之后,異常….)這個過濾范圍叫做切入點Pointcut()

8 .植入
Advice應用的目標方法的過程叫做植入(Weave)
Spring只支持針對業務方法執行前,執行后進行植入. 即只支持方法級別的植入
植入的地方就叫做連接點.
Spring的Aop是使用代理模式.
橫切問題的處理思路:
發現橫切性的問題,將其模塊化(切片).然后形成切片類,在其中實現這些橫切性的功能.
對象: pickTicket 出庫 1 : N pickTicketDetail 出庫明細數據庫: pickTicket的id作為pickTicketDetail 的外鍵(pickTicket.id)---------在對pickTicketDetail 某行數據進行insert/update/delete的事務提交給數據庫進行持久化處理時,數據庫會將pickTicket整個表給予只讀鎖. 此為避免修改pickTicketDetail 時,pickTicket的數據進行修改而出現pickTicketDetail中的pickTicket.id對應在pickTicket中不存在.(即確保數據庫的數據完整性)發生場景: 事件A增刪改某表A時,會對該表的所有外鍵對應的表給予只讀鎖.如此時其他事務B正提交數據庫,類似的需要鎖定事件A中已鎖定的表. 此時2個事務都在等待對方表解鎖.產生死鎖. 可以處理方案: 1盡量縮短事務處理的時間.2對pickTicketDetail 增加pickTicket.id的索引. ------------ 相關參考:http://it.china-b.com/sjk/oracle/20090826/177376_1.html 測試: session 1: SQL> delete from emp where emp.deptno=10; session 2: SQL> delete from dept where deptno=40; 現象:在emp的字段deptno沒有索引時session 2等待, 有索引則不等待. 結論:如果沒有索引時,對父表的操作,會級聯加一個TM S鎖(level 4)到子表上; 如果有索引時,對父表的操作,會級聯加一個TM RS鎖(level 2)到子表上; 這時如果子表上本身就有個TM RX鎖(這種鎖很容易產生,insert update delete都會產生這種鎖), TM S鎖和TM RX鎖是互斥的, TM RS鎖和TM RX鎖是相容的.
------- 最后:其實想記錄的是"外鍵未加索引的問題" .此問題可以google下了解. 本文寫的較亂,只為存疑記錄.有待進一步了解學習.
摘自: http://www.iteye.com/topic/257191 ----------------- 今天下午研究了半天hashcode()和equals()方法,終于有了一點點的明白,寫下來與大家分享(zhaoxudong 2008.10.23晚21.36)。 1. 首先equals()和hashcode()這兩個方法都是從object類中繼承過來的。 equals()方法在object類中定義如下: public boolean equals(Object obj) { return (this == obj); } 很明顯是對兩個對象的地址值進行的比較(即比較引用是否相同)。但是我們必需清楚,當String 、Math、還有Integer、Double。。。。等這些封裝類在使用equals()方法時,已經覆蓋了object類的equals()方法。比 如在String類中如下: public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = count; if (n == anotherString.count) { char v1[] = value; char v2[] = anotherString.value; int i = offset; int j = anotherString.offset; while (n-- != 0) { if (v1[i++] != v2[j++]) return false; } return true; } } return false; } 很明顯,這是進行的內容比較,而已經不再是地址的比較。依次類推Double、Integer、Math。。。。等等這些類都是重寫了equals()方法的,從而進行的是內容的比較。當然了基本類型是進行值的比較,這個沒有什么好說的。 我們還應該注意,Java語言對equals()的要求如下,這些要求是必須遵循的: • 對稱性:如果x.equals(y)返回是“true”,那么y.equals(x)也應該返回是“true”。 • 反射性:x.equals(x)必須返回是“true”。 • 類推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也應該返回是“true”。 • 還有一致性:如果x.equals(y)返回是“true”,只要x和y內容一直不變,不管你重復x.equals(y)多少次,返回都是“true”。 • 任何情況下,x.equals(null),永遠返回是“false”;x.equals(和x不同類型的對象)永遠返回是“false”。 以上這五點是重寫equals()方法時,必須遵守的準則,如果違反會出現意想不到的結果,請大家一定要遵守。 2. 其次是hashcode() 方法,在object類中定義如下: public native int hashCode(); 說明是一個本地方法,它的實現是根據本地機器相關的。當然我們可以在自己寫的類中覆蓋hashcode()方法,比如String、 Integer、Double。。。。等等這些類都是覆蓋了hashcode()方法的。例如在String類中定義的hashcode()方法如下: public int hashCode() { int h = hash; if (h == 0) { int off = offset; char val[] = value; int len = count; for (int i = 0; i < len; i++) { h = 31*h + val[off++]; } hash = h; } return h; } 解釋一下這個程序(String的API中寫到): s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1] 使用 int 算法,這里 s[i] 是字符串的第 i 個字符,n 是字符串的長度,^ 表示求冪。(空字符串的哈希碼為 0。) 3.這里我們首先要明白一個問題: equals()相等的兩個對象,hashcode()一定相等; equals()不相等的兩個對象,卻并不能證明他們的hashcode()不相等。換句話說,equals()方法不相等的兩個對象,hashcode()有可能相等。(我的理解是由于哈希碼在生成的時候產生沖突造成的)。 反過來:hashcode()不等,一定能推出equals()也不等;hashcode()相等,equals()可能相等,也可能不等。解釋 下第3點的使用范圍,我的理解是在object、String等類中都能使用。在object類中,hashcode()方法是本地方法,返回的是對象的 地址值,而object類中的equals()方法比較的也是兩個對象的地址值,如果equals()相等,說明兩個對象地址值也相等,當然 hashcode()也就相等了;在String類中,equals()返回的是兩個對象內容的比較,當兩個對象內容相等時, Hashcode()方法根據String類的重寫(第2點里面已經分析了)代碼的分析,也可知道hashcode()返回結果也會相等。以此類 推,可以知道Integer、Double等封裝類中經過重寫的equals()和hashcode()方法也同樣適合于這個原則。當然沒有經過重寫的 類,在繼承了object類的equals()和hashcode()方法后,也會遵守這個原則。 4.談到hashcode()和equals()就不能不說到hashset,hashmap,hashtable中的使用,具體是怎樣呢,請看如下分析: Hashset是繼承Set接口,Set接口又實現Collection接口,這是層次關系。那么hashset是根據什么原理來存取對象的呢? 在hashset中不允許出現重復對象,元素的位置也是不確定的。在hashset中又是怎樣判定元素是否重復的呢?這就是問題的關鍵所在,經過一下午的查詢求證終于獲得了一點啟示,和大家分享一下,在java的集合中,判斷兩個對象是否相等的規則是: 1),判斷兩個對象的hashCode是否相等 如果不相等,認為兩個對象也不相等,完畢 如果相等,轉入2) (這一點只是為了提高存儲效率而要求的,其實理論上沒有也可以,但如果沒有,實際使用時效率會大大降低,所以我們這里將其做為必需的。后面會重點講到這個問題。) 2),判斷兩個對象用equals運算是否相等 如果不相等,認為兩個對象也不相等 如果相等,認為兩個對象相等(equals()是判斷兩個對象是否相等的關鍵) 為什么是兩條準則,難道用第一條不行嗎?不行,因為前面已經說了,hashcode()相等時,equals()方法也可能不等,所以必須用第2條準則進行限制,才能保證加入的為非重復元素。 比如下面的代碼: public static void main(String args[]){ String s1=new String("zhaoxudong"); String s2=new String("zhaoxudong"); System.out.println(s1==s2);//false System.out.println(s1.equals(s2));//true System.out.println(s1.hashCode());//s1.hashcode()等于s2.hashcode() System.out.println(s2.hashCode()); Set hashset=new HashSet(); hashset.add(s1); hashset.add(s2); /*實質上在添加s1,s2時,運用上面說到的兩點準則,可以知道hashset認為s1和s2是相等的,是在添加重復元素,所以讓s2覆蓋了s1;*/ Iterator it=hashset.iterator(); while(it.hasNext()) { System.out.println(it.next()); } 最后在while循環的時候只打印出了一個”zhaoxudong”。 輸出結果為:false true -967303459 -967303459 這是因為String類已經重寫了equals()方法和hashcode()方法,所以在根據上面的第1.2條原則判定時,hashset認為它們是相等的對象,進行了重復添加。 但是看下面的程序: import java.util.*; public class HashSetTest { public static void main(String[] args) { HashSet hs=new HashSet(); hs.add(new Student(1,"zhangsan")); hs.add(new Student(2,"lisi")); hs.add(new Student(3,"wangwu")); hs.add(new Student(1,"zhangsan")); Iterator it=hs.iterator(); while(it.hasNext()) { System.out.println(it.next()); } } } class Student { int num; String name; Student(int num,String name) { this.num=num; this.name=name; } public String toString() { return num+":"+name; } } 輸出結果為: 1:zhangsan 1:zhangsan 3:wangwu 2:lisi 問題出現了,為什么hashset添加了相等的元素呢,這是不是和hashset的原則違背了呢?回答是:沒有 因為在根據hashcode()對兩次建立的new Student(1,"zhangsan")對象進行比較時,生成的是不同的哈希碼值,所以hashset把他當作不同的對象對待了,當然此時的 equals()方法返回的值也不等(這個不用解釋了吧)。那么為什么會生成不同的哈希碼值呢?上面我們在比較s1和s2的時候不是生成了同樣的哈希碼 嗎?原因就在于我們自己寫的Student類并沒有重新自己的hashcode()和equals()方法,所以在比較時,是繼承的object類中的 hashcode()方法,呵呵,各位還記得object類中的hashcode()方法比較的是什么吧!! 它是一個本地方法,比較的是對象的地址(引用地址),使用new方法創建對象,兩次生成的當然是不同的對象了(這個大家都能理解吧。。。),造成 的結果就是兩個對象的hashcode()返回的值不一樣。所以根據第一個準則,hashset會把它們當作不同的對象對待,自然也用不著第二個準則進行 判定了。那么怎么解決這個問題呢?? 答案是:在Student類中重新hashcode()和equals()方法。 例如: class Student { int num; String name; Student(int num,String name) { this.num=num; this.name=name; } public int hashCode() { return num*name.hashCode(); } public boolean equals(Object o) { Student s=(Student)o; return num==s.num && name.equals(s.name); } public String toString() { return num+":"+name; } } 根據重寫的方法,即便兩次調用了new Student(1,"zhangsan"),我們在獲得對象的哈希碼時,根據重寫的方法hashcode(),獲得的哈希碼肯定是一樣的(這一點應該沒有疑問吧)。 當然根據equals()方法我們也可判斷是相同的。所以在向hashset集合中添加時把它們當作重復元素看待了。所以運行修改后的程序時,我們會發現運行結果是: 1:zhangsan 3:wangwu 2:lisi 可以看到重復元素的問題已經消除。 關于在hibernate的pojo類中,重新equals()和hashcode()的問題: 1),重點是equals,重寫hashCode只是技術要求(為了提高效率) 2),為什么要重寫equals呢,因為在java的集合框架中,是通過equals來判斷兩個對象是否相等的 3),在hibernate中,經常使用set集合來保存相關對象,而set集合是不允許重復的。我們再來談談前面提到在向hashset集合中添加元素時,怎樣判斷對象是否相同的準則,前面說了兩條,其實只要重寫equals()這一條也可以。 但當hashset中元素比較多時,或者是重寫的equals()方法比較復雜時,我們只用equals()方法進行比較判斷,效率也會非常低, 所以引入了hashcode()這個方法,只是為了提高效率,但是我覺得這是非常有必要的(所以我們在前面以兩條準則來進行hashset的元素是否重復 的判斷)。 比如可以這樣寫: public int hashCode(){ return 1;}//等價于hashcode無效 這樣做的效果就是在比較哈希碼的時候不能進行判斷,因為每個對象返回的哈希碼都是1,每次都必須要經過比較equals()方法后才能進行判斷是否重復,這當然會引起效率的大大降低。 我有一個問題,如果像前面提到的在hashset中判斷元素是否重復的必要方法是equals()方法(根據網上找到的觀點),但是這里并沒有涉及到關于哈希表的問題,可是這個集合卻叫hashset,這是為什么?? 我想,在hashmap,hashtable中的存儲操作,依然遵守上面的準則。所以這里不再多說。這些是今天看書,網上查詢資料,自己總結出來 的,部分代碼和語言是引述,但是千真萬確是自己總結出來的。有錯誤之處和不詳細不清楚的地方還請大家指出,我也是初學者,所以難免會有錯誤的地方,希望大 家共同討論。
摘自: http://shitou521.iteye.com/blog/696006 JNDI的一篇文章 前端時間總是在搞不清JNDI到底是干什么,雖然是一值在用,卻不知道他最初出現的原因,用來,說不清是用來干什么,下面我相信介能解開這個迷霧里。 【 轉貼一篇】 ------------ JNDI是 Java 命名與目錄接口(Java Naming and Directory Interface),在J2EE規范中是重要的規范之一,不少專家認為,沒有透徹理解JNDI的意義和作用,就沒有真正掌握J2EE特別是EJB的知識。 那么,JNDI到底起什么作用? //帶著問題看文章是最有效的 要了解JNDI的作用,我們可以從“如果不用JNDI我們怎樣做?用了JNDI后我們又將怎樣做?”這個問題來探討。 沒有JNDI的做法: 程序員開發時,知道要開發訪問MySQL數據庫的應用,于是將一個對 MySQL JDBC 驅動程序類的引用進行了編碼,并通過使用適當的 JDBC URL 連接到數據庫。 就像以下代碼這樣: - Connection conn=null;
- try {
- Class.forName("com.mysql.jdbc.Driver",
- true, Thread.currentThread().getContextClassLoader());
- conn=DriverManager.
- getConnection("jdbc:mysql://MyDBServer?user=qingfeng&password=mingyue");
- ......
- conn.close();
- } catch(Exception e) {
- e.printStackTrace();
- } finally {
- if(conn!=null) {
- try {
- conn.close();
- } catch(SQLException e) {}
- }
- }
這是傳統的做法,也是以前非Java程序員(如Delphi、VB等)常見的做法。這種做法一般在小規模的開發過程中不會產生問題,只要程序員熟悉Java語言、了解JDBC技術和MySQL,可以很快開發出相應的應用程序。 沒有JNDI的做法存在的問題: 1、數據庫服務器名稱MyDBServer 、用戶名和口令都可能需要改變,由此引發JDBC URL需要修改; 2、數據庫可能改用別的產品,如改用DB2或者Oracle,引發JDBC驅動程序包和類名需要修改; 3、隨著實際使用終端的增加,原配置的連接池參數可能需要調整; 4、...... 解決辦法: 程 序員應該不需要關心“具體的數據庫后臺是什么?JDBC驅動程序是什么?JDBC URL格式是什么?訪問數據庫的用戶名和口令是什么?”等等這些問題,程序員編寫的程序應該沒有對 JDBC 驅動程序的引用,沒有服務器名稱,沒有用戶名稱或口令 —— 甚至沒有數據庫池或連接管理。而是把這些問題交給J2EE容器來配置和管理,程序員只需要對這些配置和管理進行引用即可。 由此,就有了JNDI。 //看的出來,是為了一個最最核心的問題:是為了解耦,是為了開發出更加可維護、可擴展//的系統 用了JNDI之后的做法: 首先, 在在J2EE容器中配置JNDI參數,定義一個數據源,也就是JDBC引用參數,給這個數據源設置一個名稱;然后,在程序中,通過數據源名稱引用數據源從而訪問后臺數據庫。 //紅色的字可以看出,JNDI是由j2ee容器提供的功能 具體操作如下(以JBoss為例): 1、配置數據源 在JBoss 的 D:\jboss420GA\docs\examples\jca 文件夾下面,有很多不同數據庫引用的數據源定義模板。將其中的 mysql-ds.xml 文件Copy到你使用的服務器下,如 D:\jboss420GA\server\default\deploy。 修改 mysql-ds.xml 文件的內容,使之能通過JDBC正確訪問你的MySQL數據庫,如下: - <?xml version="1.0" encoding="UTF-8"?>
- <datasources>
- <local-tx-datasource>
- <jndi-name>MySqlDS</jndi-name>
- <connection-url>jdbc:mysql://localhost:3306/lw</connection-url>
- <driver-class>com.mysql.jdbc.Driver</driver-class>
- <user-name>root</user-name>
- <password>rootpassword</password>
- <exception-sorter-class-name>
- org.jboss.resource.adapter.jdbc.vendor.MySQLExceptionSorter
- </exception-sorter-class-name>
- <metadata>
- <type-mapping>mySQL</type-mapping>
- </metadata>
- </local-tx-datasource>
- </datasources>
這里,定義了一個名為MySqlDS的數據源,其參數包括JDBC的URL,驅動類名,用戶名及密碼等。 2、在程序中引用數據源: - Connection conn=null;
- try {
- Context ctx=new InitialContext();
- Object datasourceRef=ctx.lookup("java:MySqlDS"); //引用數據源
- DataSource ds=(Datasource)datasourceRef;
- conn=ds.getConnection();
- ......
- c.close();
- } catch(Exception e) {
- e.printStackTrace();
- } finally {
- if(conn!=null) {
- try {
- conn.close();
- } catch(SQLException e) { }
- }
- }
直接使用JDBC或者通過JNDI引用數據源的編程代碼量相差無幾,但是現在的程序可以不用關心具體JDBC參數了。 //解藕了,可擴展了 在系統部署后,如果數據庫的相關參數變更,只需要重新配置 mysql-ds.xml 修改其中的JDBC參數,只要保證數據源的名稱不變,那么程序源代碼就無需修改。 由此可見, JNDI避免了程序與數據庫之間的緊耦合,使應用更加易于配置、易于部署。 JNDI的擴展: JNDI在滿足了數據源配置的要求的基礎上,還進一步擴充了作用:所有與系統外部的資源的引用,都可以通過JNDI定義和引用。 //注意什么叫資源 所以,在J2EE規范中,J2EE 中的資源并不局限于 JDBC 數據源。引用的類型有很多,其中包括資源引用(已經討論過)、環境實體和 EJB 引用。特別是 EJB 引用,它暴露了 JNDI 在 J2EE 中的另外一項關鍵角色:查找其他應用程序組件。 EJB 的 JNDI 引用非常類似于 JDBC 資源的引用。在服務趨于轉換的環境中,這是一種很有效的方法。可以對應用程序架構中所得到的所有組件進行這類配置管理,從 EJB 組件到 JMS 隊列和主題,再到簡單配置字符串或其他對象,這可以降低隨時間的推移服務變更所產生的維護成本,同時還可以簡化部署,減少集成工作。外部資源”。 總結: J2EE 規范要求所有 J2EE 容器都要提供 JNDI 規范的實現。//sun 果然喜歡制定規范JNDI 在 J2EE 中的角色就是“交換機” —— J2EE 組件在運行時間接地查找其他組件、資源或服務的通用機制。在多數情況下,提供 JNDI 供應者的容器可以充當有限的數據存儲,這樣管理員就可以設置應用程序的執行屬性,并讓其他應用程序引用這些屬性(Java 管理擴展(Java Management Extensions,JMX)也可以用作這個目的)。JNDI 在 J2EE 應用程序中的主要角色就是提供間接層,這樣組件就可以發現所需要的資源,而不用了解這些間接性。 在 J2EE 中,JNDI 是把 J2EE 應用程序合在一起的粘合劑,JNDI 提供的間接尋址允許跨企業交付可伸縮的、功能強大且很靈活的應用程序。這是 J2EE 的承諾,而且經過一些計劃和預先考慮,這個承諾是完全可以實現的。 從上面的文章中可以看出: 1、JNDI 提出的目的是為了解藕,是為了開發更加容易維護,容易擴展,容易部署的應用。 2、JNDI 是一個sun提出的一個規范(類似于jdbc),具體的實現是各個j2ee容器提供商,sun 只是要求,j2ee容器必須有JNDI這樣的功能。 3、JNDI 在j2ee系統中的角色是“交換機”,是J2EE組件在運行時間接地查找其他組件、資源或服務的通用機制。 4、JNDI 是通過資源的名字來查找的,資源的名字在整個j2ee應用中(j2ee容器中)是唯一的。
再轉一篇文章:
JNDI全稱 Java Naming and Directory Interface JNDI 是Java平臺的一個標準擴展,提供了一組接口、類和關于命名空間的概念。如同其它很多Java技術一樣,JDNI是provider-based的技 術,暴露了一個API和一個服務供應接口(SPI)。這意味著任何基于名字的技術都能通過JNDI而提供服務,只要JNDI支持這項技術。JNDI目前所 支持的技術包括LDAP、CORBA Common Object Service(COS)名字服務、RMI、NDS、DNS、Windows注冊表等等。很多J2EE技術,包括EJB都依靠JNDI來組織和定位實體。 JDNI通過綁定的概念將對象和名稱聯系起來。在一個文件系統中,文件名被綁定給文件。在DNS中,一個IP地址綁定一個URL。在目錄服務中,一個對象名被綁定給一個對象實體。 JNDI 中的一組綁定作為上下文來引用。每個上下文暴露的一組操作是一致的。例如,每個上下文提供了一個查找操作,返回指定名字的相應對象。每個上下文都提供了綁 定和撤除綁定名字到某個對象的操作。JNDI使用通用的方式來暴露命名空間,即使用分層上下文以及使用相同命名語法的子上下文。 jndi的用途: 1。你可以用jndi來得到object類的屬性 如: - Attribute attr =directory.getAttributes(personName).get("email");
- String email = (String)attr.get();
2。你可以用jndi來搜索對象 如: - foxes = directory.search("o=Wiz,c=US", "sn=Fox", controls);
查找誰的名字叫Fox在wiz部門的員工? 3。你可以用jndi通過naming/directory服務查詢像printers和databases的對象 如:查詢 Printer - Printer printer = (Printer)namespace.lookup(printerName);
- printer.print(document);
4。你可以用jndi列表出命名空間的特殊級別的內容 如: - NamingEnumeration list = namespace.list("o=Widget, c=US";
- while (list.hasMore()) {
- NameClassPair entry = (NameClassPair)list.next();
- display(entry.getName(), entry.getClassName());
- }
各種數字類型轉換成字符串型:
String s = String.valueOf( value); // 其中 value 為任意一種數字類型。
字符串型轉換成各種數字類型:
String s = "169";
byte b = Byte.parseByte( s );
short t = Short.parseShort( s );
int i = Integer.parseInt( s );
long l = Long.parseLong( s );
Float f = Float.parseFloat( s );
Double d = Double.parseDouble( s );
數字類型與數字類對象之間的轉換:
byte b = 169;
Byte bo = new Byte( b );
b = bo.byteValue();
short t = 169;
Short to = new Short( t );
t = to.shortValue();
int i = 169;
b = bo.byteValue();
short t = 169;
Short to = new Short( t );
t = to.shortValue();
int i = 169;
Integer io = new Integer( i );
i = io.intValue();
long l = 169;
Long lo = new Long( l );
l = lo.longValue();
float f = 169f;
Float fo = new Float( f );
f = fo.floatValue();
double d = 169f;
Double dObj = new Double( d );
d = dObj.doubleValue();
|
|
CALENDER
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|
30 | 31 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
|
常用鏈接
留言簿(3)
隨筆分類(22)
隨筆檔案(76)
文章分類(12)
文章檔案(17)
搜索
積分與排名
最新評論

評論排行榜
Powered By: 博客園 模板提供:滬江博客
|