使用Oracle發送http請求


使用Oracle發送http請求,實現的思路是:在某張表上配置觸發器,該觸發器調用存儲過程,使用存儲過程執行http請求的發送。

需要注意的幾點是:

1、http post請求,在發送的時候,跟數據庫的字符集有關,在處理不當的時候,會出現亂碼問題。

2、oracle訪問網絡服務的時候,需要配置acl權限。


創建觸發器:

  1. CREATE OR REPLACE TRIGGER “T_POST4REQHAND” AFTER INSERT ON “REQUESTHANDLERINFO” REFERENCING OLD AS “OLD” NEW AS “NEW” FOR EACH ROW   
  2. declare  
  3. begin  
  4.    PRO_POSTREQ(:new.id,:new.params);    
  5. 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;

創建存儲過程:

  1. create or replace procedure “PRO_POSTREQ”(r_id in varchar2,params in varchar2) as  
  2. begin  
  3.   
  4. DECLARE  
  5.   req   UTL_HTTP.REQ;  
  6.   resp  UTL_HTTP.RESP;  
  7.   value VARCHAR2(1024);  – URL to post to  
  8.    v_url VARCHAR2(4000) :‘http://192.168.0.156:8080/bzjw_platform/f/responseresult/responseResult/invokeOutRequest?rid=’||r_id||’&&params’||params;  
  9.    v_param VARCHAR2(4000) :‘1’;  
  10.   
  11.   
  12.   v_param_length NUMBER :LENGTHB(v_param);  
  13. BEGIN  
  14.    DBMS_OUTPUT.ENABLE (buffer_size=>null);  
  15.   req :UTL_HTTP.BEGIN_REQUEST (url=> v_url, method => ‘POST’);  
  16.   UTL_HTTP.SET_BODY_CHARSET(‘UTF-8’);  
  17.   UTL_HTTP.SET_HEADER (r      =>  req,  
  18.                        name   =>  ‘Content-Type’,  
  19.                        value  =>  ‘application/x-www-form-urlencoded’);  
  20.   UTL_HTTP.SET_HEADER(req, ‘Keep-Alive’, ’  timeout=1‘);  
  21.   UTL_HTTP.SET_HEADER (r      =>   req,  
  22.                        name   =>   ‘Content-Length’,  
  23.                        value  =>   v_param_length);  
  24.    
  25.    UTL_HTTP.WRITE_RAW (r    => req,  
  26.                     data => UTL_RAW.CAST_TO_RAW(v_param));   
  27.   
  28.   resp :UTL_HTTP.GET_RESPONSE(req);  
  29.   LOOP  
  30.     UTL_HTTP.READ_LINE(resp, value, TRUE);  
  31.     DBMS_OUTPUT.PUT_LINE(value);  
  32.   END LOOP;  
  33.   UTL_HTTP.END_RESPONSE(resp);  
  34. EXCEPTION  
  35.   WHEN UTL_HTTP.END_OF_BODY THEN  
  36.     UTL_HTTP.END_RESPONSE(resp);  
  37. END;  
  38. 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||'&&params'||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,則無法訪問網絡。

  1. –定義ACL 取名:httprequestpermission.xml  
  2.   
  3. BEGIN  
  4.     dbms_network_acl_admin.create_acl(acl         => ’httprequestpermission.xml’,  
  5.                                       DESCRIPTION => ’Normal Access’,  
  6.                                       principal   => ’CONNECT’,  
  7.                                       is_grant    => TRUE,  
  8.                                       PRIVILEGE   => ’connect’,  
  9.                                       start_date  => NULL,  
  10.                                       end_date    => NULL);  
  11. 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;
  1. –查看ACL是否增加成功  
  2. SELECT any_path  
  3. FROM resource_view   
  4. where any_path  like ‘/sys/acls/%.xml’  
  5. ;  
  6.   
  7. –給用戶增加acl權限,這裏是 SD_JY 注意是大寫,小寫不識別  
  8. begin  dbms_network_acl_admin.add_privilege(acl     => ‘httprequestpermission.xml’,  
  9.                                          principal  => ’SD_JY’,  
  10.                                          is_grant   => TRUE,  
  11.                                          privilege  => ’connect’,  
  12.                                          start_date => null,  
  13.                                          end_date   => null);  
  14. end;  
  15.   
  16.   
  17. –添加對應主機 ,將對應主機和端口添加到ACL。這裏是 192.168.0.156 和 8080 ,這個ip和端口要和上面存儲過程中定義的地址一致  
  18. begin  
  19.     dbms_network_acl_admin.assign_acl(acl        => ’httprequestpermission.xml’,  
  20.                                       host       => ’192.168.0.156’,  
  21.                                       lower_port => 8080,  
  22.                                       upper_port => NULL);  
  23. 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信息是否添加上

  1. SELECT  acl,  
  2.        principal,  
  3.        privilege,  
  4.        is_grant,  
  5.        TO_CHAR(start_date, ’DD-MON-YYYY’AS start_date,  
  6.        TO_CHAR(end_date, ’DD-MON-YYYY’AS end_date  
  7.   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;


至此,訪問存儲過程或者觸發器,測試對應的程序即可。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章