欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

oracle执行存储过程调用http请求

程序员文章站 2024-01-22 21:22:58
...

前言:
公司的消息推送功能需要用到
技术难点:公司代码封闭 无法改动 能改动的只有存储过程 公司说没办法调用其他的服务
导致操作完系统没办法做消息推送给其他公司 我在网上看到有oracle调用http请求的文章
所以自己实践一下 查看到百度很多的博客都不大全面 所以做一下记录
还有几个要完善的问题 在文章结尾我会记录下来 处理完了我再更新此博客

第一步 开启Oracle ACL权限

begin
  dbms_network_acl_admin.create_acl (       -- 创建访问控制文件(ACL)
    acl         => 'utl_http.xml',          -- 文件名称
    description => 'HTTP Access',           -- 描述
    principal   => 'ZLHIS',                 -- 授权或者取消授权账号,大小写敏感
    is_grant    => TRUE,                    -- 授权还是取消授权
    privilege   => 'connect',               -- 授权或者取消授权的权限列表
    start_date  => null,                    -- 起始日期
    end_date    => null                     -- 结束日期
  );
 --添加访问权限列表项
  dbms_network_acl_admin.add_privilege (    -- 添加访问权限列表项
    acl        => 'utl_http.xml',           -- 刚才创建的acl名称 
    principal  => 'ZLHIS',                    -- 授权或取消授权用户
    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 => 9005,                     -- 允许访问的起始端口号
    upper_port => Null                      -- 允许访问的截止端口号
  );
end;

特别注明一下我碰到的坑:
principal => ‘ZLHIS’, – 授权或者取消授权账号,大小写敏感
1: 这个要填写plsql登录的账户 随便填写会报下面的错:
oracle执行存储过程调用http请求
2: 执行成功后不能重复执行 否则会报错 原因 utl_http.xml已经存在 具体utl_http.xml做什么用的不详
oracle执行存储过程调用http请求
第二步 写调用http的存储过程

Create Or Replace Procedure Zl_Send_Mes(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:9005/hospital/common/push/notice';
Begin
	Begin
		Req := Utl_Http.Begin_Request(r_Url, 'POST');
		Utl_Http.Set_Header(Req, 'Content-Type', 'application/json; 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 Zl_Send_Mes;

这个存储过程是由几篇博客自己优化过来的
执行完我没出现过问题
如有其他问题可以联系我解决完并且补充这篇博客

第三步 执行存储过程看能否请求到你的服务

执行语句:call ZL_SEND_MES('{"patientCode": "1","type": 1002,"content": "门诊待缴费通知"}');
在存储过程中我设置的请求头为json格式 所以这边传json格式的参数作为存储过程的入参
oracle执行存储过程调用http请求
执行存储过程完成 服务出现问题

JSON parse error: Unexpected end-of-input in VALUE_STRING; nested exception is com.fasterxml.jackson.core.io.JsonEOFException: Unexpected end-of-input in VALUE_STRING
 at [Source: (PushbackInputStream); line: 1, column: 123] 

无效字符集:应该是传过来的编码问题 这个我已经在存储过程里面设置了字符集 但是还是有问题 这个问题待完善,不传中文是没问题的。

不传中文的语句:

call ZL_SEND_MES('{"patientCode": "1","type": 1002,"content": "aaa"}');

执行成功
oracle执行存储过程调用http请求
服务调用成功

oracle执行存储过程调用http请求
剩余问题:
1:字符集没办法传中文问题(这个问题比较鸡肋 因为平常应该不会传中文)
2:重点问题: 当服务停用掉的时候 存储过程将卡死 报错如下:
oracle执行存储过程调用http请求
因为我这个存储过程要嵌套在其他存储过程里面 所以我要将这个过程做成异步的 执行此过程成功不成功都不要对其他的业务产生影响 等待更新。

相关标签: emmm 数据库