如有转载,请声明出处: 极致博客: http://blog.youkuaiyun.com/u011218159
这段时间经历太多太多,工作忙的不要不要的!感觉自己哪里都不在状态了,今天总算抽出了点时间总结下这个奇葩的问题了!这个问题的起因是得从从项目的初期开始说
了,作为一家外包公司一切的客户需求都必须的满足,即使是项目框架的设计也是如此;对于这个项目我真的是抹着泪给做完的 ...
客户是一位传统行业的老板,对于即将要上市的企业想做一款能够面向用户的APP,而且必须基于他们陈旧的、笨重的ERP开工,从此我就陷入水生火热之中了....
好像被我扯偏题了,废话就不想再说了,把问题说说吧:为了不污染他们的ERP所使用的oracle数据库,我们必须得做到ORACLE <——> MYSQL之间的同步;最开始想使用
OGG做数据库同步,但是担心时间来不及所幸使用了下面的方式简单处理了,毕竟我们只是需要ERP少量商品信息而已!通过触发器 ——> 存储过程 ——> http请求来做到同步 ...
是不是觉得有点坑,这个都是次要的因为接下来是对问题进行处理!oracle11G与10G的网络通信所控制的粒度完全不一样,所以有下面的问题产生了!
错误样例(使用UTL_HTTP发送http请求时,报出如下错误):
ORA-29273: HTTP 请求失败
ORA-06512: 在 "SYS.UTL_HTTP", line 1130
ORA-24247: 网络访问被访问控制列表 (ACL) 拒绝
ORA-06512: 在 "YGMM.P_SENDSMS_TEST", line 15
ORA-06512: 在 line 3
原因:
1、Oracle允许使用几个PL/SQL API(UTL_TCP, UTL_SMTP, UTL_MAIL, UTL_HTTP和 UTL_INADDR)访问外部网络服务,这些API都使用TCP协议。
2、在Oracle 10g是通过一个基于用户是否被授予执行某个包的许可的 on/off开关来实现的,Oracle 11g引入了细粒度访问网络服务.
3、通过在XML DB 数据库中使用访问控制列表(ACL)来实现,允许控制哪个用户能够访问哪个网络资源,而不关心包的授权。
解决方案主要有如下几个步骤:
1. 查看用户是否有网络权限
<span style="font-family:Comic Sans MS;">--查看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 any_path FROM resource_view WHERE any_path like '%/sys/acls/%.xml%';
</span>
2.假如没有需要添加网络权限
<span style="font-family:Comic Sans MS;">--添加http请求,以principal:用户/角色,DRVTRAINING为用户
BEGIN
dbms_network_acl_admin.create_acl (acl => 'ygmm_http_request.xml', -- 创建访问控制文件
DESCRIPTION => 'Normal Access' , -- 描述
principal => 'YGMM', -- 授权或取消授权的账号
is_grant => TRUE, -- 授权还是取消授权
PRIVILEGE => 'connect', -- 授权或取消授权的权限列表
start_date => NULL, -- 开始生效日期
end_date => NULL); -- 截止失效日期
END;
</span>
3.添加访问权限列表
<span style="font-family:Comic Sans MS;">begin
dbms_network_acl_admin.add_privilege ( -- 添加访问权限列表项
acl => 'ygmm_http_request.xml', -- 刚才创建的acl名称
principal => 'YGMM', -- 授权或取消授权用户
is_grant => TRUE, -- 与上同
privilege => 'resolve', -- 权限列表(解析)
start_date => null,
end_date => null
);
end;
</span>
<span style="font-family:Comic Sans MS;">--添加访问的地址,端口,DRVTRAINING为用户
begin
dbms_network_acl_admin.assign_acl (
acl => 'ygmm_http_request.xml',
host => '120.76.42.206', -- 访问主机
lower_port => 21110, -- 最小访问端口
upper_port => NULL); -- 最大访问端口
end;
</span>
5.测试访问是否OK
<span style="font-family:Comic Sans MS;">create or replace procedure pr_synch_sendsms(
p_businessType in varchar2,
p_operatorCode in varchar2,
p_mtSubID in varchar2,
err_code out integer,
ora_code out integer) is
s_request varchar2( 4000); --请求报文
s_respond varchar2( 4000); --响应报文
http_req utl_http.req; --请求包头
http_resp utl_http.resp; --响应包头
s_sysdate varchar2( 30); --发送时间
BEGIN
--取当前时间+1分钟
select to_char (sysdate, 'YYYY-MM-DD' )||' '|| to_char( sysdate + 1 / 1440, 'hh24:mi:ss')
INTO s_sysdate
FROM DUAL;
s_request := '{"businessType":"' ||p_businessType ||'","operatorCode":"'|| p_operatorCode||'","mtSubID":"' ||p_mtSubID ||'","sendtime":"'|| s_sysdate|| '"}';
---初始化REQUEST ]
http_req := utl_http.begin_request('http://120.25.68.86:21110/v2/oracle/synch/test',
'POST',
utl_http.HTTP_VERSION_1_1 /* 'HTTP/1.1'*/);
utl_http.set_body_charset('UTF-8' );--设置包体编码集
utl_http.set_header(http_req, 'Accept', '*/*');
utl_http.set_header(http_req,
'Content-Type',
'application/json;charset=UTF-8');
utl_http.set_header(http_req,
'User-Agent',
'Nimo Software HTTP Retriever 1.0');
utl_http.set_header(http_req, 'Content-Length', length (s_request ));
utl_http.set_header(http_req, 'Cache-Control', 'no-cache' );
utl_http.write_text(http_req, s_request);--如果有包体可以写入json数据,关键需要和Content-type相互对应
http_resp := utl_http.get_response (http_req ); --提交请求
if http_resp.status_code = utl_http.HTTP_OK then
--成功才读取响应消息
utl_http.read_text(http_resp, s_respond);
utl_http.end_response (http_resp ); --结束请求
s_respond := substr( s_respond, 1 , 4000); ---long 转成 varchar2
dbms_output.put_line (s_respond ); --打印响应消息
dbms_output.put_line (http_resp.reason_phrase ); --打印响应消息
else
err_code := http_resp.status_code ;
ora_code := sqlcode;
dbms_output.put_line (http_resp.reason_phrase ); --打印响应消息
end if;
exception
WHEN OTHERS THEN
ora_code := sqlcode;
END;
注意:oracle中的¶m表示一个变量的意思,所以在oracle中想使用&必须要&&才可以表示
</span>
说明:
如有博友觉得本人博文有需要更正的地方,还望能够指教一下!
我的邮箱:lvyongwenhouzi@qq.com
新浪微博:@lenny呂
QQ/微信号:854588035/Y-lenny
2016年3月23日
By lenny