使用Oracle發送http請求,實現的思路是:在某張表上配置觸發器,該觸發器調用存儲過程,使用存儲過程執行http請求的發送。
需要注意的幾點是:
1、http post請求,在發送的時候,跟數據庫的字符集有關,在處理不當的時候,會出現亂碼問題。
2、oracle訪問網絡服務的時候,需要配置acl權限。
創建觸發器:
- CREATE OR REPLACE TRIGGER “T_POST4REQHAND” AFTER INSERT ON “REQUESTHANDLERINFO” REFERENCING OLD AS “OLD” NEW AS “NEW” FOR EACH ROW
- declare
- begin
- PRO_POSTREQ(:new.id,:new.params);
- end T_POST4REQHAND;
CREATE OR REPLACE TRIGGER "T_POST4REQHAND" AFTER INSERT ON "REQUESTHANDLERINFO" REFERENCING OLD AS "OLD" NEW AS "NEW" FOR EACH ROW
declare
begin
PRO_POSTREQ(:new.id,:new.params);
end T_POST4REQHAND;
創建存儲過程:
- create or replace procedure “PRO_POSTREQ”(r_id in varchar2,params in varchar2) as
- begin
- DECLARE
- req UTL_HTTP.REQ;
- resp UTL_HTTP.RESP;
- value VARCHAR2(1024); – URL to post to
- v_url VARCHAR2(4000) := ‘http://192.168.0.156:8080/bzjw_platform/f/responseresult/responseResult/invokeOutRequest?rid=’||r_id||’&¶ms’||params;
- v_param VARCHAR2(4000) := ‘1’;
- v_param_length NUMBER := LENGTHB(v_param);
- BEGIN
- DBMS_OUTPUT.ENABLE (buffer_size=>null);
- req := UTL_HTTP.BEGIN_REQUEST (url=> v_url, method => ‘POST’);
- UTL_HTTP.SET_BODY_CHARSET(‘UTF-8’);
- UTL_HTTP.SET_HEADER (r => req,
- name => ‘Content-Type’,
- value => ‘application/x-www-form-urlencoded’);
- UTL_HTTP.SET_HEADER(req, ‘Keep-Alive’, ’ timeout=1‘);
- UTL_HTTP.SET_HEADER (r => req,
- name => ‘Content-Length’,
- value => v_param_length);
- UTL_HTTP.WRITE_RAW (r => req,
- data => UTL_RAW.CAST_TO_RAW(v_param));
- resp := UTL_HTTP.GET_RESPONSE(req);
- LOOP
- UTL_HTTP.READ_LINE(resp, value, TRUE);
- DBMS_OUTPUT.PUT_LINE(value);
- END LOOP;
- UTL_HTTP.END_RESPONSE(resp);
- EXCEPTION
- WHEN UTL_HTTP.END_OF_BODY THEN
- UTL_HTTP.END_RESPONSE(resp);
- END;
- end PRO_POSTREQ;
create or replace procedure "PRO_POSTREQ"(r_id in varchar2,params in varchar2) as
begin
DECLARE
req UTL_HTTP.REQ;
resp UTL_HTTP.RESP;
value VARCHAR2(1024); -- URL to post to
v_url VARCHAR2(4000) := 'http://192.168.0.156:8080/bzjw_platform/f/responseresult/responseResult/invokeOutRequest?rid='||r_id||'&¶ms'||params;
v_param VARCHAR2(4000) := '1';
v_param_length NUMBER := LENGTHB(v_param);
BEGIN
DBMS_OUTPUT.ENABLE (buffer_size=>null);
req := UTL_HTTP.BEGIN_REQUEST (url=> v_url, method => 'POST');
UTL_HTTP.SET_BODY_CHARSET('UTF-8');
UTL_HTTP.SET_HEADER (r => req,
name => 'Content-Type',
value => 'application/x-www-form-urlencoded');
UTL_HTTP.SET_HEADER(req, 'Keep-Alive', ' timeout=1');
UTL_HTTP.SET_HEADER (r => req,
name => 'Content-Length',
value => v_param_length);
UTL_HTTP.WRITE_RAW (r => req,
data => UTL_RAW.CAST_TO_RAW(v_param));
resp := UTL_HTTP.GET_RESPONSE(req);
LOOP
UTL_HTTP.READ_LINE(resp, value, TRUE);
DBMS_OUTPUT.PUT_LINE(value);
END LOOP;
UTL_HTTP.END_RESPONSE(resp);
EXCEPTION
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(resp);
END;
end PRO_POSTREQ;
該請求爲post,但是所有的參數傳遞均放置在URL中,原因是,放置在v_param 這個參數中時,數據庫字符集爲utf8的時候,一切正常,但是若是gbk,則發生亂碼。
原因是 oracle的參數拼接字符 “||”會進行一次編碼。 按照網上所說的,使用轉碼等一系列操作,最終仍沒有解決。
定義ACL,若沒有ACL,則無法訪問網絡。
- –定義ACL 取名:httprequestpermission.xml
- BEGIN
- dbms_network_acl_admin.create_acl(acl => ’httprequestpermission.xml’,
- DESCRIPTION => ’Normal Access’,
- principal => ’CONNECT’,
- is_grant => TRUE,
- PRIVILEGE => ’connect’,
- start_date => NULL,
- end_date => NULL);
- END;
--定義ACL 取名:httprequestpermission.xml
BEGIN
dbms_network_acl_admin.create_acl(acl => 'httprequestpermission.xml',
DESCRIPTION => 'Normal Access',
principal => 'CONNECT',
is_grant => TRUE,
PRIVILEGE => 'connect',
start_date => NULL,
end_date => NULL);
END;
- –查看ACL是否增加成功
- SELECT any_path
- FROM resource_view
- where any_path like ‘/sys/acls/%.xml’
- ;
- –給用戶增加acl權限,這裏是 SD_JY 注意是大寫,小寫不識別
- begin dbms_network_acl_admin.add_privilege(acl => ‘httprequestpermission.xml’,
- principal => ’SD_JY’,
- is_grant => TRUE,
- privilege => ’connect’,
- start_date => null,
- end_date => null);
- end;
- –添加對應主機 ,將對應主機和端口添加到ACL。這裏是 192.168.0.156 和 8080 ,這個ip和端口要和上面存儲過程中定義的地址一致
- begin
- dbms_network_acl_admin.assign_acl(acl => ’httprequestpermission.xml’,
- host => ’192.168.0.156’,
- lower_port => 8080,
- upper_port => NULL);
- end;
--查看ACL是否增加成功
SELECT any_path
FROM resource_view
where any_path like '/sys/acls/%.xml'
;
--給用戶增加acl權限,這裏是 SD_JY 注意是大寫,小寫不識別
begin dbms_network_acl_admin.add_privilege(acl => 'httprequestpermission.xml',
principal => 'SD_JY',
is_grant => TRUE,
privilege => 'connect',
start_date => null,
end_date => null);
end;
--添加對應主機 ,將對應主機和端口添加到ACL。這裏是 192.168.0.156 和 8080 ,這個ip和端口要和上面存儲過程中定義的地址一致
begin
dbms_network_acl_admin.assign_acl(acl => 'httprequestpermission.xml',
host => '192.168.0.156',
lower_port => 8080,
upper_port => NULL);
end;
ACL的增加過程爲:建立新的acl文件,對該文件中,用戶授權,對該文件中,URL和端口授權。
可查看對應的ACL信息是否添加上
- SELECT acl,
- principal,
- privilege,
- is_grant,
- TO_CHAR(start_date, ’DD-MON-YYYY’) AS start_date,
- TO_CHAR(end_date, ’DD-MON-YYYY’) AS end_date
- FROM dba_network_acl_privileges;
SELECT acl,
principal,
privilege,
is_grant,
TO_CHAR(start_date, 'DD-MON-YYYY') AS start_date,
TO_CHAR(end_date, 'DD-MON-YYYY') AS end_date
FROM dba_network_acl_privileges;
至此,訪問存儲過程或者觸發器,測試對應的程序即可。