1、web應(yīng)用在tomcat上運行,一切正常。
2、OS:windows XP sp3
3、weblogic version:8.1.3.0
二 、問題及解決方法
1 、 weblogic.utils.ParsingException: nested TokenStreamException: antlr.TokenStreamIOException: 在web應(yīng)用的WEB-INF目錄下新增(如果沒有)weblogic.xml文件,寫入下面內(nèi)容:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web Application 8.1//EN"
"http://www.bea.com/servers/wls810/dtd/weblogic810-web-jar.dtd">
<weblogic-web-app>
<session-descriptor>
</session-descriptor>
<jsp-descriptor>
<jsp-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</jsp-param>
<jsp-param>
<param-name>pageCheckSeconds</param-name>
<param-value>-1</param-value>
</jsp-param>
<jsp-param>
<param-name>compilerSupportsEncoding</param-name>
<param-value>true</param-value>
</jsp-param>
<jsp-param>
<param-name>verbose</param-name>
<param-value>false</param-value>
</jsp-param>
</jsp-descriptor>
<charset-params>
<input-charset>
<resource-path>/*</resource-path>
<java-charset-name>UTF-8</java-charset-name>
</input-charset>
</charset-params>
</weblogic-web-app>
保存,重新deploy應(yīng)用
2、 sun.io.MalformedInputException:修改區(qū)域和語言選型。
控制面板->區(qū)域和語言選型->高級->代碼頁轉(zhuǎn)換表,去掉54936(GB18030簡體中文)前面的對勾,保存更改。重新deploy應(yīng)用。
3 、weblogic.servlet.jsp.JspException: (line 1): page directive contentType at /unieap/ria3.3/pages/config.jsp:1 previously defined :修改jsp文件,不能重復(fù)定義:<%@ page contentType="text/html; charset=UTF-8"%>
在含有<%@ include file="/unieap/ria3.3/pages/config.jsp"%>這樣的代碼的JSP文件中,如果在文件頭部已經(jīng)定義了contentType,那么在被包含的文件中如果重復(fù)定義contentType,盡管相同,weblogoic也會報錯,只能改JSP文件,保證一個頁面中只有一個contentType的定義。這個問題在tomcat中是不存在的,可能是兩個應(yīng)用服務(wù)器的解析機制不同。
-- / 斜線回車
----------------------------------------------
如何查看錯誤信息:
show error 回車
--調(diào)用存儲過程
1.exec 過程名(參數(shù)1,2....);
2.call 過程名(參數(shù)1,2....);
---------------------------------------------------
set serveroutput on;打開輸出選項
set serveroutput off;關(guān)閉輸出選項
dbms_ 是包名的意思!
案例2:
dbms_output.put_line('helloWorld');
-----------------
declare
v_ename varchar2(5);--定義字符串變量
begin
--into v_ename意思:把查詢出來數(shù)據(jù) 賦值給 v_ename;&no是執(zhí)行的時候會彈出輸入框
select ename into v_ename from emp where empno=&no;
--||代表 連接符號;
dbms_output.put_line('用戶名是:'||v_ename);
end;
-----------
案例3:
declare
v_ename varchar2(5);--定義字符串變量
v_sal number(7,2);--定義字符串變量
begin
--如果是多個字段,用逗號隔開,順序必須一樣!!
select ename,sal into v_ename,v_sal from emp where empno=&no;
--||代表 連接符號;
dbms_output.put_line('用戶名是:'||v_ename||'工資:'||v_sal);
end;
---------------------
--異常的捕獲
exception
when no_data_found then --如果出現(xiàn)no_data_found異常就執(zhí)行下一句
dbms_output.put_line('輸入有誤!');
end;
------------
過程:
案例4:
創(chuàng)建帶輸入?yún)?shù)的過程;
create procedure sp_pro3(spNma varchar2,newSal number) is
begin
update emp set sal=newSal where ename=spName;
end;
------------
函數(shù):
函數(shù)用于返回特定的數(shù)據(jù),當(dāng)建立函數(shù)時,在函數(shù)頭部要求有return語句;
案例5:
--輸入雇員姓名,返回該雇員的年薪
--返回一個number類型;返回值名字是yearSal,類型是number(7,2);
create function sp_fun1(spName varchar2) return number is yearSal number(7,2);
begin
--執(zhí)行部分
select sal*12+nvl(comm,0)*12 into yearSal from emp where enamee=spName;
return yearSal;
end;
調(diào)用函數(shù)中
--隨便定義一個值
var abc number;
--掉用函數(shù)把結(jié)果賦值給 abc
call sp_fun1()'SCOTT' into:abc;
-------------
包
創(chuàng)建包:
--創(chuàng)建了一個包 sp_package
--聲明該包里有一個過程update_sal
--生命該包里有一個函數(shù)annual_income
create package sp_package is
procedure update_sal(name,varchar2,newsal number);
function annual_income(name varchar2, return number;
end;
給包sp_package 實現(xiàn)包體--把定義包中的 過程和函數(shù)實現(xiàn);
create package body sp_package is
procedure update_sal(name,varchar2,newsal number) is
begin
update emp set sal=newsal where ename=name;
end;
function annual_income(name varchar2)
return number isannual_salary number;
begin
select sal*12+nvl(comm,0) into annual_salary from emp where ename=name;
return annual_salary;
end;
end;
--------------
調(diào)用包中的過程或函數(shù)
exec sp_package.update_sal('SCOTT','120');
---------------------
觸發(fā)器
觸發(fā)器是指隱含的執(zhí)行的存儲過程。當(dāng)定義觸發(fā)器時,必須要指定觸發(fā)的時間和觸發(fā)的操作,常用觸發(fā)包括insert,pudate,delete語句,而觸發(fā)操作實際就是一個pl/sql塊。可以使用create trigger來建立觸發(fā)器。
觸發(fā)器是非常有用的,可維護數(shù)據(jù)庫的安全和一致性。
---------
定義并使用變量
包括:
1.標(biāo)量類型(scalar)
2.符合類型()
---------
標(biāo)量(scalar)-常用類型
語法:
identifier [constant] datatype [not null] [:=| default expr]
identifier:名稱
constant:指定常量。需要指定它的初始值,且其值是不能改變的
datatype:數(shù)據(jù)類型
not null: 指定變量值不能為null
:= 給變量或是常量指定初始值
default 用于指定初始值
expr:指定初始值的pl/sql表達式,文本值、其他變量、函數(shù)等
------------
標(biāo)量定義的案例
1.定義一個變長字符串
v_ename varchar2(10)
2.定義一個小數(shù) 范圍 -9999.99~9999.99
v_sal number(6,2)
3.定義一個小數(shù)并給一個初始值為5.4 :=pl/sql的賦值號
v_sal2 number(6,2):=5.4
4.定義一個日期類型的數(shù)據(jù)
v_hiredate date;
5.定義一個布爾變量,不能為空,初始值為false
v_valid boolean not null default false;
---------------
如何使用標(biāo)量
定義好變量后,就可以使用這些變量。這里需要說明的是pl/sql塊為變量賦值不同于其他的編程語言,需要在等號前面加冒號(:=)
下面以輸入員工號,顯示雇員名稱、工資、個人所得稅(稅率為0.03為例)。說明變量的使用,看看如何編寫:
declare
c_tax_rate number(3.2):=0.03; --定義賦值
--用戶名
v_ename varchar2(5);
v_sal number(7,2);
v_tax_sal number()7,2;
begin
--執(zhí)行
select ename,sal into v_ename,v_sal from emp where empno=$no;
--計算所得稅
v_tax_sal:=v_sal*c_tax_rate;
--輸出
dbms_output.put_line('姓名是:'||v_ename||'工資:'||v_sal||'所得稅:'||v_tax_sal);
end;
-----
標(biāo)量(scalar)--使用%type類型
對于上面的pl/sql塊有一個問題:
就是如果員工的姓名超過了5字符的話,就會有錯誤,為了降低pl/sql程序的維護工作量,可以使用%type屬性定義變量,這樣他會按照數(shù)據(jù)庫列來確定你定義的變量的類型和長度。
看看怎么使用。
語法: 標(biāo)識符名 表名.列名%type;
declare
v_ename emp.ename%type; --定義變量v_ename 和emp表中列名ename大小類型保持一致;
---
復(fù)合變量(composite)
用于存放多個值的變量。
包括:
1.pl/sql記錄
2.pl/sql表
---------------
復(fù)合類型-pl/sql記錄
類似與高級語言的結(jié)構(gòu)體,需要注意的是,當(dāng)引用pl/sql記錄成員時,必須要加記錄變量作為前綴(記錄變量.記錄成員)
如下:
declare
--定義一個pl/sql記錄類型是:emp_record_type,類型包括三個數(shù)據(jù)name,salary,title;該類型中可以存放三個類型的數(shù)據(jù);
type emp_record_type is record(name emp.ename%type,salary emp.sal%type,title emp.job%type);
--定義了一個sp_record變量,類型是emp_record_type
sp_record emp_record_type;
begin
select ename,sal,job into sp_record from emp where empno=7788;
dbms_output.put_line('員工名:'||sp_record.name); --顯示定義emp_record_type類型中 name的值;
end;
end;
----------------
復(fù)合類型--pl/sql表
相當(dāng)于高級語言中的數(shù)組。但是需要注意的是在高級語言中數(shù)組的下標(biāo)不能為負數(shù),而pl/sql是可以為負數(shù)的,并且表元素的下標(biāo)沒有限制。實例如下:
declare
--定義了一個pl/sql表類型sp_table_type,該類型是用于存放emp.ename%type類型的數(shù)組
--index by binary_integer標(biāo)識下標(biāo)是整數(shù)
type sp_table_type is table of emp.ename%type index by binary_integer;
--定義了一個sp_table變量,變量類型是sp_table_type
sp_table sp_table_type;
begin
--把查詢出來的ename放到 table(0)下標(biāo)為0的數(shù)據(jù)
select ename into sp_table(0) from emp where empno=7788;
dbms_output.put_lin('員工名:'||sp_table(0)); --要和存放下標(biāo)一樣
end;
說明:
sp_table_type 是pl/sql表類型
emp.ename%type 指定了表的元素的類型和長度
sp_table 為pl/sql表變量
sp_table(0) 表示下標(biāo)為0的
---------------
參照變量
參照變量是指用于存放數(shù)值指針的變量。通過使用參照變量,可以使用得應(yīng)用程序共享相同對象,從而降低占用的空間。在編寫pl/sql程序時,可以使用游標(biāo)變量和對象類型變量兩種參照變量類型
游標(biāo)變量用的最多
-----------
參照變量---游標(biāo)變量
使用游標(biāo)時,當(dāng)定義游標(biāo)時不需要指定相應(yīng)的select語句,但是當(dāng)使用游標(biāo)時需要指定select語句,這樣一個游標(biāo)就與一個select語句結(jié)合了。
如下
1.請使用pl/sql編寫一個塊,可以輸入部門號,并顯示該部門所有員工姓名和他的工資。
declare
--定義游標(biāo)類型
type sp_emp_cursor is ref cursor;
--定義一個游標(biāo)變量
test_cursor sp_emp_cursor;
--定義變量
v_ename emp。ename%type;
v_sal emp。sal%type;
begin
--執(zhí)行
--打開一個游標(biāo)test_cursor和一個select結(jié)合
open test_cursor for select ename,sal from emp where deptno=&no;
--循環(huán)取出
loop
--fetch就是取出。取出test_cursor中的數(shù)據(jù)放到 v_ename,v_sal里面去;
fetch test_cursor into v_ename,v_sal;
--判斷是否test_cursor為空
exit when test_cursor%notfound;
dbms_output.put_line('名字:'||v_ename||'工資:'||v_sal);
end loop;
end;
2.在1。基礎(chǔ)上,如果某個員工的工資低于200元,就增加100元。
declare
--定義游標(biāo)類型
type sp_emp_cursor is ref cursor;
--定義一個游標(biāo)變量
test_cursor sp_emp_cursor;
--定義變量
v_ename emp。ename%type;
v_sal emp。sal%type;
begin
--執(zhí)行
--打開一個游標(biāo)test_cursor和一個select結(jié)合
open test_cursor for select ename,sal from emp where deptno=&no;
--循環(huán)取出
loop
--fetch就是取出。取出test_cursor中的數(shù)據(jù)放到 v_ename,v_sal里面去;
fetch test_cursor into v_ename,v_sal;
if v_sal<200 then
update emp set sal=sal+100 where ename=v_ename;
end if;
--判斷是否test_cursor為空
exit when test_cursor%notfound;
dbms_output.put_line('名字:'||v_ename||'工資:'||v_sal);
end loop;
end;
----------
條件分支語句
if--then,
if--then--else,
if--then--elsif--else
----
循環(huán)語句
loop --end loop;至少會執(zhí)行一次。
create or replace procedure sp_pro6() is
--定義賦值
v_num number:=1;
begin
loop
insert into users1 values(v_num,spName);
--判斷是否要退出循環(huán)
exit when v_num=10;
--自增
v_num:=v_num+1;
end loop;
end;
-------------
循環(huán)語句-while先判斷后執(zhí)行
create or replace procedure sp_pro6() is
--定義賦值
v_num number:=11;
begin
while v_num<=20 loop
insert into users1 values(v_num,spName);
v_num:=v_num+1;
end loop;
end;
------------------
循環(huán)語句--for循環(huán)(不建議)
begin
for i in reverse 1。。10 loop
insert into users1 values(i,'aaa');
end loop;
end;
-------
循環(huán)語句--goto,null循環(huán)(不建議)
declare
i int:=1;
begin
loop
dbms_output.put_line('輸出i='||i);
if i=10 then
goto end_loop;
end if;
i:=i+1;
end loop;
<<end_loop>> --到i到10后直接跳到該標(biāo)記
dbms_output.put_line('循環(huán)結(jié)束');
end;
---------------------------
無返回值的存儲過程(有輸入?yún)?shù))
create table book(
bookId number;
bookName varchar2(100);
publishHouse varchar2(50);
);
--編寫過程
--in表示這是一個輸入?yún)?shù),不寫默認(rèn)是in
--out 表示一個輸出參數(shù)
create or replace procedure sp_pro7(spBookId in number,spbookName in varchar2,sppublishHouse in varchar2) is
begin
insert into book values(spBookId,spbookName,sppublishHouse);
end;
---------------
有返回值的存儲過程(有輸入和輸出參數(shù))
create or replace procedure sp_pro8(ename in number,spName out varchar2) is
begin
--spName自動返回 因為他是out
select ename into spName from emp where empno=spno;
end;
----------------
有返回值是集合數(shù)組的存儲過程(有輸入和輸出參數(shù))
1.建立一個包
--創(chuàng)建包 里面定義一個游標(biāo)類型;
create or replace package testpackage as
type test_cursor is ref cursor;
end testpackage;
2.建立存儲過程。
create or replace procedure sp_pro8(spNo in number,p_cursor out testpackage.test_cursor) is
begin
--spName自動返回 因為他是out
open p_cursor for select * from emp where deptno=spNo;
end;
------------
oracle的分頁 rn是別名
select t1.*,rownum rn from(select * from emp) t1;//多加一個列記錄個數(shù)
select t1.*,rownum rn from(select * from emp) t1 where rownum<10;
select * from (select t1.*,rownum rn from(select * from emp) t1 where rownum<10) where rn>=6;
編寫oracle的分頁
--建立一個包
create or replace package testpackage as
type test_cursor is ref cursor;
end testpackage;
--建立存儲過程
create or replace procedure fenye
(tableName in varchar2,
pageSize in number, --一頁顯示幾條記錄
pageNow in number, --顯示哪一頁
myrows out number, --總記錄數(shù)
myPageCount out number,--總頁數(shù)
p_cursor out testpackage.test_cursor --返回的記錄集
) is
--定義部分
--定義sql語句 字符串
v_sql varchar2(1000);
--定義兩個整數(shù)
v_begin number:=(pageNow-1)*pageSize+1;
v_end number:=pageNow*pageSize;
begin
--執(zhí)行部分
v_sql:='select * from (select t1.*,rownum rn from(select * from '||tableName||') t1 where rownum<10'||?||') where rn>='||?||';';
--把游標(biāo)和sql語句關(guān)聯(lián)起來
open p_cursor for v_sql;
--計算myrows
v_sql:='select count(*) from '||tableName||'';
--執(zhí)行sql,并把返回值,賦值給myrows;
execute immediate v_sql int myrows;
--計算myPagecount
if mod(myrows,pageSize)=0 then --mod()取余數(shù)
myPageCount:=myrows/pageSize;
else
myPageCount:=myrows/pagesize+1;
end if;
--關(guān)閉游標(biāo)
--close p_cursor;
end;
------------------------
例外的分類
1.預(yù)定義例外用于處理常見的oracle錯誤
2.非預(yù)定義例外用于處理預(yù)定義例外不能處理的例外 6.53
3.自定義例外用于處理與oracle錯誤無關(guān)的其他情況
------------------------------------------------
-----------------------------------------------
-------JAVA中-調(diào)用無返回值的存儲過程-----------------
try{
Class.forName();
Connection ct=DriverManager.getConnerction();
//調(diào)用無返回值存儲過程
CallableStatement cs=ct.prepareCall("{call 存儲過程名稱(?,?,?)}") // ?代表存儲過程參數(shù)
cs.setIn(1,10);
cs.setString(2,'java調(diào)用存儲過程');
cs.setString(3,'人民出版社');
//執(zhí)行
cs.execute();
}catch(Exception e)
{
e.printStackTrace();
}finally{
cs.close();
ct.close();
}
------------------------------------------------
-----------------------------------------------
------JAVA中--調(diào)用有回值的存儲過程-----------------
try{
Class.forName();
Connection ct=DriverManager.getConnerction();
//調(diào)用有返回值存儲過程
CallableStatement cs=ct.prepareCall("{call 存儲過程名稱(?,?)}") // ?代表存儲過程參數(shù) 第一是輸入,第二是輸出
//第一個?輸入?yún)?shù)
cs.setIn(1,10);
//給第二個?輸出值賦值
cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR); //
//執(zhí)行
cs.execute();
//取出返回值,
String name=cs。getString(2);
System.out。println("名稱是:"+name);
}catch(Exception e)
{
e.printStackTrace();
}finally{
cs.close();
ct.close();
}
------------------------------------------------
-----------------------------------------------
-------JAVA中-調(diào)用有回值是多個 數(shù)組2011-12-5的存儲過程-----------------
try{
Class.forName();
Connection ct=DriverManager.getConnerction();
//調(diào)用有返回值存儲過程
CallableStatement cs=ct.prepareCall("{call 存儲過程名稱(?,?)}") // ?代表存儲過程參數(shù) 第一是輸入,第二是輸出
//第一個?輸入?yún)?shù)
cs.setIn(1,10);
//給第二個?輸出值賦值
cs.registerOutParameter(2,oracle.jdbc.OracleTypes.cursor); //類型是cursor游標(biāo)
//執(zhí)行
cs.execute();
//取出返回值(結(jié)果集)
ReaultSet rs=(ResultSet)cs.getObject(2); //2是第二?
while(rs.next())
{
int =rs。getInt(1);
String name=rs。getString(2);
System.out。println("名稱是:"+name);
}
}catch(Exception e)
{
e.printStackTrace();
}finally{
cs.close();
ct.close();
}
------------------------------------------------
-----------------------------------------------
------JAVA中--調(diào)用有回值的存儲過程-----------------
try{
Class.forName();
Connection ct=DriverManager.getConnerction();
//調(diào)用有返回值存儲過程
CallableStatement cs=ct.prepareCall("{call 存儲過程名稱(?,?)}") // ?代表存儲過程參數(shù) 第一是輸入,第二是輸出
//第一個?輸入?yún)?shù)
cs.setIn(1,10);
//給第二個?輸出值賦值
cs.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR); //
//執(zhí)行
cs.execute();
//取出返回值,
String name=cs。getString(2);
System.out。println("名稱是:"+name);
}catch(Exception e)
{
e.printStackTrace();
}finally{
cs.close();
ct.close();
}
------------------------------------------------
-----------------------------------------------
-------JAVA中-測試分頁調(diào)用存儲過程-----------------
try{
Class.forName();
Connection ct=DriverManager.getConnerction();
//調(diào)用有返回值存儲過程
CallableStatement cs=ct.prepareCall("{call 分頁存儲過程名稱(?,?,?,?,?,?)}") // ?代表存儲過程參數(shù) 第一是輸入,第二是輸出
//?輸入?yún)?shù)
cs.setString(1,'表名'); //表名
cs.setInt(2,5); //一頁顯示幾條記錄
cs.setInt(3,1); //顯示第幾頁
//?輸出參數(shù)
//注冊總記錄數(shù)
cs.registerOutParameter(4,oracle.jdbc.OracleTypes.INTEGER);
//注冊總頁數(shù)
cs.registerOutParameter(4,oracle.jdbc.OracleTypes.INTEGER);
//注冊返回的結(jié)果集
cs.registerOutParameter(4,oracle.jdbc.OracleTypes.CURSOR); //類型是cursor游標(biāo)
//執(zhí)行
cs.execute();
//取出總記錄數(shù)
int rowNum=cs.getInt(4);//4表示參數(shù)中第四個?
//總頁數(shù)
int pageCount=cs.getInt(5);
//返回的記錄結(jié)果
ReaultSet rs=(ResultSet)cs.getObject(6);
while(rs.next())
{
int =rs。getInt(1);
String name=rs。getString(2);
System.out。println("名稱是:"+name);
}
}catch(Exception e)
{
e.printStackTrace();
}finally{
cs.close();
ct.close();
}
A . 嵌套表
1. 聲明數(shù)組類型
create or replace type tab_array is table of varchar2(38);暫時不要在包中聲明該類型
2. 創(chuàng)建存儲過程
-- 該例子存儲過程是在包中創(chuàng)建的,包名 arraydemo
procedure testArray(resNumber in tab_array,procResult out tab_array) is
begin
procResult := new tab_array();
for i in 1..resNumber.Count loop
procResult.EXTEND;
procResult(i) := resNumber(i) || 'lucifer' || i;
end loop;
end;
3. Java調(diào)用代碼
//必須使用Oracle的連接和Statement,使用了連接池的必須通過一些方法獲取原始的連接
OracleConnection conn = null;
OracleCallableStatement stmt = null;
String[] param = { "1001", "1002", "1006" };
stmt =(轉(zhuǎn)換類型) conn.prepareCall("{call arraydemo.testArray(?,?)}");
// 類型名必須大寫
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor("TAB_ARRAY", conn);
stmt.setARRAY(1, new ARRAY(descriptor,conn,param));
stmt.registerOutParameter(2, OracleTypes.ARRAY, "TAB_ARRAY");
stmt.execute();
ARRAY array = stmt.getARRAY(2);
Datum[] data = array.getOracleArray();
for (int i = 0; i < data.length; i++) {
System.out.println(i + " : " + new String(data.shareBytes()));
}
4 . 注意的問題及尚未解決的問題
拋出:Non supported character set: oracle-character-set-852 異常---解決:添加 nls_charset12.jar 到classpath,該包在oracle/ora92/jdbc/lib目錄下
待解決問題:
a) 如何調(diào)用在包聲明的自定義類型
b) 比較不同聲明類型的優(yōu)缺點,及使用場合
嵌套表其它應(yīng)用:http://zhouwf0726.itpub.net/post/9689/212253
B . 索引表
C . 內(nèi)置數(shù)組
D . 游標(biāo)方式
1、下載proxool 地址:http://proxool.sourceforge.net
2、解壓縮proxool-0.9.0RC2.zip,拷貝lib/proxool-0.9.0RC2.jar到web-info/lib
拷貝jdbc驅(qū)動到web-info/lib
3、在web-info下建立文件:proxool.xml
文件內(nèi)容如下:
<?xml version="1.0" encoding="UTF-8"?>
<something-else-entirely>
<proxool>
<alias>Develop</alias>
<driver-url>jdbc:oracle:thin:@192.168.100.18:1521:RNMS</driver-url>
<driver-class>oracle.jdbc.driver.OracleDriver</driver-class>
<driver-properties>
<property name="user" value="scmlp"/>
<property name="password" value="scmlpscmlp"/>
</driver-properties>
<maximum-connection-count>500</maximum-connection-count>
<house-keeping-test-sql>select CURRENT_DATE</house-keeping-test-sql>
</proxool>
</something-else-entirely>
4、在web.xml文件內(nèi)加入以下內(nèi)容:
<servlet>
<servlet-name>proxoolServletConfigurator</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>
<init-param>
<param-name>xmlFile</param-name>
<param-value>WEB-INF/proxool.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- proxool提供的管理監(jiān)控工具,可查看當(dāng)前數(shù)據(jù)庫連接情況。如果運行不成功,請刪除本行 -->
<servlet>
<servlet-name>Admin</servlet-name>
<servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Admin</servlet-name>
<url-pattern>/admin</url-pattern>
</servlet-mapping>
5、在調(diào)用數(shù)據(jù)庫連接代碼:
Class.forName("org.logicalcobwebs.proxool.ProxoolDriver");
Connection conn = DriverManager.getConnection("proxool.Develop");
6、利用proxool監(jiān)控工具查看數(shù)據(jù)庫運行狀態(tài)。地址:./admin
配置二:properties方法
1,下載proxool-0.8.3.jar并放到相應(yīng)的目錄,這個應(yīng)該比較簡單了
2,寫一個配置文件放到web-inf目錄下,配置文件內(nèi)容如下:
jdbc-0.proxool.alias=bidding
jdbc-0.proxool.driver-url=jjdbc:oracle:thin:@127.0.0.1:1521:dbname
jdbc-0.proxool.driver-class=oracle.jdbc.driver.oracledriver
jdbc-0.user=name
jdbc-0.password=pass
jdbc-0.proxool.maximum-connection-count=200
jdbc-0.proxool.house-keeping-test-sql=select *
3,在web-inf/web.xml中添加如下代碼:
<servlet>
<servlet-name>servletconfigurator</servlet-name>
<servlet-lass>org.logicalcobwebs.proxool.configuration.servletconfigurator</servlet-class>
<init-param>
<param-name>propertyfile</param-name>
<param-value>web-inf/proxool.properties</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
4,配置就這么簡單,下面給你一段怎么得到一個連接代碼,其他的應(yīng)該就比較簡單了
public connection getconnection() {
try {
conn = drivermanager.getconnection("proxool.bidding");
}catch(sqlexception ex){
ex.printstacktrace();
} finally {
try {
if (conn != null) {
conn.close();
}
} catch (sqlexception e) {
e.printstacktrace();
log("problem closing connection");
}
}
return conn;
}
}
class ClassB{
public ClassB(){
System.out.println("this is ClassB");
}
public Object invokeMehton(Object owner,String methodName,Object[] args) throws Exception{
//根據(jù)methodName獲得owner里面的方法。args是對應(yīng)方案參數(shù)。
Class wnerClass=owner.getClass();
Class[] argsClass=new Class[args.length];
for(int i=0,j=args.length;i<j;i++){
argsClass[i] = args[i].getClass();
}
Method method = ownerClass.getMethod(methodName, argsClass);
return method.invoke(owner, args);
}
}
輸出為
this is ClassB
300
outabccc
說明c調(diào)用Class方法成功。
public class ClassA {
//ClassA里面有add、和StringAdd兩個不同方法。c是ClassB的Object
ClassB c=new ClassB();
public void add(Integer param1, Integer param2) {
System.out.println(param1 + param2);
}
public void StringAdd(String abc){
System.out.println("out"+abc);
}
public static void main(String[] args){
ClassA a=new ClassA();
try {
a.c.invokeMehton(a, "add",new Object[] {new Integer(100),new Integer(200)});//反射調(diào)用方法add
a.c.invokeMehton(a, "StringAdd",new Object[] {new String("abccc")});//反射調(diào)用方法StringAdd
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void invokeActionHandler(ModelAndView mv , HttpServletRequest request) throws Exception{
String className = mv.getClassName();
String methodName = mv.getMethodName();
//load class
Class controllerClass = cache.loadClass(className);//== Class.forName(className);java反射機制,jvm加載lassName類
Class parentControllerClass = cache.loadClass(baseControllerClass);//class org.bluechant.mvc.controller.Controller
//load method參數(shù)1類,創(chuàng)建一個方法為setRequest參數(shù)為HttpServletRequest.class的方法與method = clazz.getDeclaredMethod(setRequest, HttpServletRequest.class);與HttpServletRequest的setRequest方法一致的方法.
Method setRequest = cache.loadMethod(parentControllerClass, "setRequest", new Class[] { HttpServletRequest.class }); //HttpServletRequest.class,java的反射機制得到自己的類,能夠擁有自己的方法值,(Method setRequest獲取成員函數(shù))
Method setModelAndView = cache.loadMethod(parentControllerClass, "setModelAndView", new Class[] { ModelAndView.class });//org.bluechant.mvc.controller.Controller-setModelAndView@6024418 public void org.bluechant.mvc.controller.Controller.setModelAndView(org.bluechant.mvc.controller.ModelAndView)
Method targetMethod = cache.loadMethod(controllerClass, methodName, new Class[]{});
//buiid controller instance and invoke target method以上setRequest,setModelAndView,targetMethod都放在cache(hashMap中)
Object instance = controllerClass.newInstance();//加載className類;//此方法引入數(shù)據(jù)庫連接
//以上剛進入頁面的時候instance調(diào)用三個類初始化,分別是繼承關(guān)系DaosupportController ,controller,和BeanFactory
/*--->>>其中DaoSupportController類中protected ObjectDao dao = (ObjectDao)BeanFactory.getBean("objectDao");
--->>>調(diào)用:getBean 方法public class BeanFactory {
public static ApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml") ;//此方法引入數(shù)據(jù)庫連接
public static Object getBean(String beanId) {
return context.getBean(beanId);
}
}*/
setRequest.invoke(instance, new Object[] { request });//對帶有指定參數(shù)的指定對象調(diào)用由此 Method 對象表示的基礎(chǔ)方法
setModelAndView.invoke(instance, new Object[] { mv });//instance立即為原型指針
// --->>>執(zhí)行指定的targetMethod方法實則為AccountController的login()登陸方法此時開始調(diào)用數(shù)據(jù)庫
targetMethod.invoke(instance, new Object[]{});
//調(diào)用instance類中targetMethod這個方法,Object[]{}這個作為參數(shù)..
//invoke根據(jù)實體獲得方法,添加所要造的參數(shù),就是個找實例的方法克隆工廠,由Method獲得實例模型,由方法鍛造樣子,傳入?yún)?shù)得出想要結(jié)果
}
}
首先你要明白在java里面任何class都要裝載在虛擬機上才能運行。這句話就是裝載類用的(和new 不一樣,要分清楚)。
至于什么時候用,你可以考慮一下這個問題,給你一個字符串變量,它代表一個類的包名和類名,你怎么實例化它?只有你提到的這個方法了,不過要再加一點。
A a = (A)Class.forName("pacage.A").newInstance();
這和你
A a = new A();
是一樣的效果。
關(guān)于補充的問題
答案是肯定的,jvm會執(zhí)行靜態(tài)代碼段,你要記住一個概念,靜態(tài)代碼是和class綁定的,class裝載成功就表示執(zhí)行了你的靜態(tài)代碼了。而且以后不會再走這段靜態(tài)代碼了。
Class.forName(xxx.xx.xx) 返回的是一個類
Class.forName(xxx.xx.xx);的作用是要求JVM查找并加載指定的類,也就是說JVM會執(zhí)行該類的靜態(tài)代碼段
動態(tài)加載和創(chuàng)建Class 對象,比如想根據(jù)用戶輸入的字符串來創(chuàng)建對象
String str = 用戶輸入的字符串
Class t = Class.forName(str);
t.newInstance();
在初始化一個類,生成一個實例的時候,newInstance()方法和new關(guān)鍵字除了一個是方法,一個是關(guān)鍵字外,最主要有什么區(qū)別?它們的區(qū)別在于創(chuàng)建對象的方式不一樣,前者是使用類加載機制,后者是創(chuàng)建一個新類。那么為什么會有兩種創(chuàng)建對象方式?這主要考慮到軟件的可伸縮、可擴展和可重用等軟件設(shè)計思想。
Java中工廠模式經(jīng)常使用newInstance()方法來創(chuàng)建對象,因此從為什么要使用工廠模式上可以找到具體答案。 例如:
class c = Class.forName(“Example”);
factory = (ExampleInterface)c.newInstance();
其中ExampleInterface是Example的接口,可以寫成如下形式:
String className = "Example";
class c = Class.forName(className);
factory = (ExampleInterface)c.newInstance();
進一步可以寫成如下形式:
String className = readfromXMlConfig;//從xml 配置文件中獲得字符串
class c = Class.forName(className);
factory = (ExampleInterface)c.newInstance();
上面代碼已經(jīng)不存在Example的類名稱,它的優(yōu)點是,無論Example類怎么變化,上述代碼不變,甚至可以更換Example的兄弟類Example2 , Example3 , Example4……,只要他們繼承ExampleInterface就可以。
從JVM的角度看,我們使用關(guān)鍵字new創(chuàng)建一個類的時候,這個類可以沒有被加載。但是使用newInstance()方法的時候,就必須保證:1、這個類已經(jīng)加載;2、這個類已經(jīng)連接了。而完成上面兩個步驟的正是Class的靜態(tài)方法forName()所完成的,這個靜態(tài)方法調(diào)用了啟動類加載器,即加載 java API的那個加載器。
現(xiàn)在可以看出,newInstance()實際上是把new這個方式分解為兩步,即首先調(diào)用Class加載方法加載某個類,然后實例化。 這樣分步的好處是顯而易見的。我們可以在調(diào)用class的靜態(tài)加載方法forName時獲得更好的靈活性,提供給了一種降耦的手段。
最后用最簡單的描述來區(qū)分new關(guān)鍵字和newInstance()方法的區(qū)別:
newInstance: 弱類型。低效率。只能調(diào)用無參構(gòu)造。
new: 強類型。相對高效。能調(diào)用任何public構(gòu)造。