记录 Oracle 远程调用 HTTP 接口

前言

如果你有了解过PL/SQL, 那么下面的内容将会一目了然;当然对于没接触过PL/SQL的朋友来说,Copy/Paste 也不会影响使用。某天自己想到一个奇怪的功能需要使用Oracle调用自己的接口,于是查了些资料完成了一个Demo放过来,以便下次方便Copy。

1. 演示接口

@RestController
@RequestMapping("aboutTriggerController")
public class AboutTriggerController {
	@RequestMapping("inputUpdateData")
	public Object inputUpdateData(HttpServletRequest request) {
		Object content= request.getParameter("content");
		return content;
	}
}

2. 开启Oracle ACL权限

存储过程,需要在SQL窗口中执行(使用超级管理员用户执行)。根据自己的需求对里面的内容进行修改。
principal 变量是授权的账号,根据自己的情况进行配置。

begin
  dbms_network_acl_admin.create_acl (       -- 创建访问控制文件(ACL)
    acl         => 'utl_http.xml',          -- 文件名称
    description => 'HTTP Access',           -- 描述
    principal   => 'DEMO',                   -- 授权或者取消授权账号,大小写敏感
    is_grant    => TRUE,                    -- 授权还是取消授权
    privilege   => 'connect',               -- 授权或者取消授权的权限列表
    start_date  => null,                    -- 起始日期
    end_date    => null                     -- 结束日期
  );
 --添加访问权限列表项
  dbms_network_acl_admin.add_privilege (    -- 添加访问权限列表项
    acl        => 'utl_http.xml',           -- 刚才创建的acl名称 
    principal  => 'DEMO',                    -- 授权或取消授权用户
    is_grant   => TRUE,                     -- 与上同 
    privilege  => 'resolve',                -- 权限列表
    start_date => null,                     
    end_date   => null
  );
 --配置对应ip地址及端口
  dbms_network_acl_admin.assign_acl (       -- 该段命令意思是允许访问acl名为utl_http.xml下授权的用户,使用oracle网络访问包,所允许访问的目的主机,及其端口范围。
    acl        => 'utl_http.xml',
    host       => '127.0.0.1',              -- ip地址或者域名,填写http://localhost:9000/hello与http://localhost:9000/是会报host无效的
                                            -- 且建议使用ip地址或者使用域名,若用localhost,当oracle不是安装在本机上的情况下,会出现问题
    lower_port => 9102,                     -- 允许访问的起始端口号
    upper_port => Null                      -- 允许访问的截止端口号
  );
end;

3. 配置HTTP连接

存储过程,需要在SQL窗口中执行。r_url varchar2 变量是要调用的 URL, 需要自行配置。

CREATE OR REPLACE PROCEDURE remote_call(r_content in varchar2) IS
  req  UTL_HTTP.REQ;
  resp UTL_HTTP.RESP;
  message  varchar2(10000);
  xmlstr  varchar2(30000);
	r_url varchar2(1000) := 'http://127.0.0.1:9102/xx-web/aboutTriggerController/inputUpdateData.do?content='||r_content;
begin
    begin
      req  := UTL_HTTP.BEGIN_REQUEST(r_url);
      utl_http.set_header(req, 'Content-Type', 'text/html; charset=utf-8');
      utl_http.write_text(req,xmlstr); --通过body发送消息
      xmlstr:=r_content; 
      utl_http.set_header(req, 'Content-Length',lengthb(xmlstr));
      utl_http.write_text(req,xmlstr);
      resp := UTL_HTTP.GET_RESPONSE(req);  
      LOOP
        UTL_HTTP.read_line(resp,message, TRUE);
        dbms_output.put_line(message);
      END LOOP;
 
      utl_http.end_request(req);
      utl_http.end_response(resp);
    EXCEPTION
      WHEN utl_http.end_of_body THEN
        utl_http.end_response(resp);
        WHEN OTHERS THEN
      utl_http.end_response(resp);
      utl_http.end_request(req);
    end;
END remote_call;

调用

调用的方式有很多种,可以自行百度关键词: 如何调用存储过程;我这里直接在SQL命令行中使用 call 方法调用。

call remote_call('hello,rpc!');

结果:
在这里插入图片描述

4. 可能会使用到

修改ACL文件

如果需要扩展访问权限列表项的端口或是想修改主机地址,可以使用以下存储过程来处理。

begin
  dbms_network_acl_admin.assign_acl (       -- 该段命令意思是允许访问acl名为utl_http.xml下授权的用户,使用oracle网络访问包,所允许访问的目的主机,及其端口范围。
    acl        => 'utl_http.xml',
    host       => '127.0.0.1',              -- ip地址或者域名,错误示例:http://127.0.0.1:80
                                            -- 且建议使用ip地址或者使用域名,若用localhost,当oracle不是安装在本机上的情况下,会出现问题
    lower_port => 80,                     -- 允许访问的起始端口号
    upper_port => Null                      -- 允许访问的截止端口号
  );
  commit;
end;

如果开启 ACL 权限的时候提示说 ACL 文件已经存在,则将 acl 参数的值简单修改一下,这样会覆盖掉原来的数据。

查询ACL文件是否存在

select * from dba_network_acl_privileges ;

遇到的问题

网络访问被访问控制列表 (ACL) 拒绝

ORA-06512: 在 "SYS.UTL_HTTP", line 368
ORA-06512: 在 "SYS.UTL_HTTP", line 1118
ORA-29273: HTTP 请求失败
ORA-24247: 网络访问被访问控制列表 (ACL) 拒绝

如果用户并未指定 ACL 权限(访问控制列表)的话不能直接访问互联网,需要执行第 2 步开启 ACL 权限。

ACL 无效:无法解析的主用户

ORA-444416: ACL 无效: 无法解析的主用户 'xxx'
ORA-06512: 在 "SYS.DBMS_NETWORK_ACL_ADMIN", line 252
ORA-06512: 在 line2

在第 2 步 principal 指定的用户名为小写就会出现这个问题,改为大写。

编码问题

一直传入英文字符和数字,某天突然传入中文参数时既没有调用接口也没有抛异常,首先想到的就是编码,在服务端(也就是接口中)对中文进行转码是没有效果的。所以只能在 Oracle 中进行转码,参考相关资料解决方法如下:

CREATE OR REPLACE FUNCTION url_encode(urlEncode IN VARCHAR2)
  RETURN VARCHAR2 AS
BEGIN
  RETURN utl_url.escape(urlEncode, TRUE, 'utf-8');
END;

执行这个脚本后,在存储过程中使用这个函数将中文参数进行转码即可。

提供参考

UTL_HTTP 的使用

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值