在日常开发中,可以需要使用Oracle存储过程进行http请求发送,有时会遇到,客户端接收的xml中文乱码,还有报文格式不完整,以及接收返回报文中文乱码问题,下面就为大家举例,并提供解决方法。
发送例子:
一、Oracle存储过程部分:
1、调用发送方法的存储过程
create or replace procedure CallHttpRequest(
pi_URL in varchar2, --发送的Http URL
po_ReMsg out varchar2 --返回信息
) is
obj_xmldoc sys.xmltype; --响应报文xml对象
ro_xmlContent varchar2(10000); --请求报文
begin
--要发送的报文
ro_xmlContent:='<?xml version="1.0" encoding="GBK"?>
0066667626
测试
2018-12-03
10:12:30
单证类型
单证回销类型值
';
--调用发送方法
SqlHttpRequest(pi_URL, ro_xmlContent, po_ReMsg, obj_xmldoc);
end CallHttpRequest;
2、具体的发送存储过程
create or replace procedure SqlHttpRequest(
pi_URL in varchar2, --发送的Http URL
pi_Content in varchar2, --发送的报文内容
po_ReMsg out varchar2, --错误内容
po_xmltype out xmltype --响应报文内容
)
as
obj_http_req UTL_HTTP.REQ; --http请求对象
obj_http_resp UTL_HTTP.RESP; --http响应对象
v_req_clob varchar2(32767); --请求报文
v_resp_clob clob; --响应报文
v_buffer_text varchar2(32767); --缓存
TIMEOUT INTEGER DEFAULT 3600;
begin
v_req_clob:=pi_Content;
-- 初始化晌应CLOB.
DBMS_LOB.createtemporary(v_resp_clob, FALSE);
-- 初始化HTTP请求参数.
UTL_HTTP.SET_TRANSFER_TIMEOUT(TIMEOUT);
obj_http_req := UTL_HTTP.BEGIN_REQUEST (pi_URL, 'POST');
UTL_HTTP.SET_HEADER (obj_http_req,'Content-Type','text/xml;chartset=utf-8');
v_req_clob:=utl_url.escape(v_req_clob,true,'UTF8');--进行url编码
UTL_HTTP.SET_HEADER (obj_http_req,'Content-Length',lengthb(v_req_clob));
UTL_HTTP.SET_BODY_CHARSET(obj_http_req,'UTF-8');
--发送HTTP请求
UTL_HTTP.WRITE_TEXT (obj_http_req,v_req_clob);
--接收响应
obj_http_resp := UTL_HTTP.GET_RESPONSE(obj_http_req);
BEGIN
LOOP
UTL_HTTP.READ_TEXT(obj_http_resp, v_buffer_text, 32767);
DBMS_LOB.WRITEAPPEND(v_resp_clob, length(v_buffer_text), v_buffer_text);
END LOOP;
--关闭HTTP连接
UTL_HTTP.END_RESPONSE(obj_http_resp);
EXCEPTION
WHEN UTL_HTTP.REQUEST_FAILED THEN
UTL_HTTP.END_RESPONSE(obj_http_resp);
DBMS_LOB.freetemporary(v_resp_clob);
po_ReMsg := 'HTTP请求失败:' || 'DBS' || to_char(SQLCODE) || ':' || substr(SQLERRM,1,128);
WHEN UTL_HTTP.TRANSFER_TIMEOUT THEN
UTL_HTTP.END_RESPONSE(obj_http_resp);
DBMS_LOB.freetemporary(v_resp_clob);
po_ReMsg := 'HTTP请求超时失败:' || 'DBS' || to_char(SQLCODE) || ':' || substr(SQLERRM,1,128);
WHEN UTL_HTTP.END_OF_BODY THEN
UTL_HTTP.END_RESPONSE(obj_http_resp);
WHEN OTHERS THEN
UTL_HTTP.END_RESPONSE(obj_http_resp);
DBMS_LOB.freetemporary(v_resp_clob);
po_ReMsg := 'HTTP请求错误:' || 'DBS' || to_char(SQLCODE) || ':' || substr(SQLERRM,1,128);
END;
dbms_output.put_line('返回-------------->'||v_resp_clob);
--创建XMLTYPE对象
po_xmltype:=sys.XMLTYPE(v_resp_clob);
--释放clob
DBMS_LOB.freetemporary(v_resp_clob);
po_ReMsg := '请求成功!';
EXCEPTION
WHEN OTHERS THEN
UTL_HTTP.END_RESPONSE(obj_http_resp);
DBMS_LOB.freetemporary(v_resp_clob);
po_ReMsg := 'XML内容错误:' || 'DBS' || to_char(SQLCODE) || ':' || substr(SQLERRM,1,128);
end SqlHttpRequest;
二、Java部分
1、一个接收oracle存储过程发送请求的servlet
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
public class OracleHttpResponse extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = -6824462722279265976L;
/**
* Destruction of the servlet.
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 设置接收的内容编码
request.setCharacterEncoding("utf-8");
// 接收请求的输入流数据
String sendMessage = null;
try {
InputStream in = request.getInputStream();
InputStreamReader isr = new InputStreamReader(in);
BufferedReader br = new BufferedReader(isr);
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = br.readLine()) != null) {
buffer.append(line);
}
sendMessage = buffer.toString();
} catch (InterruptedIOException e) {
e.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (NullPointerException npe) {
npe.printStackTrace();
}
System.out.println("oracle过来的xml数据:" + sendMessage);
OutputStream url_out = null;
String xmlData = CreateResponseData();
response.setContentType("text/xml;charset=utf-8");
response.reset();
url_out = response.getOutputStream();
url_out.write(xmlData.getBytes("utf-8"), 0, xmlData.getBytes("utf-8").length);
url_out.flush();
url_out.close();
}
private String CreateResponseData() {
Document document = DocumentHelper.createDocument();
// 增加根节点
Element TXLife = document.addElement("TXLife");
Element TXLifeResponse = TXLife.addElement("TXLifeResponse");
Element TransRefGUID = TXLifeResponse.addElement("TransRefGUID");
TransRefGUID.setText("1000000000");
Element TransType = TXLifeResponse.addElement("TransType");
TransType.setText("测试同步交易");
TransType.addAttribute("tc", "WLSCBS_QY_BL_0001");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr = dateFormat.format(new Date());
Element TransExeDate = TXLifeResponse.addElement("TransExeDate");
TransExeDate.setText(dateStr.split(" ")[0]);
Element TransExeTime = TXLifeResponse.addElement("TransExeTime");
TransExeTime.setText(dateStr.split(" ")[1]);
Element TransResult = TXLifeResponse.addElement("TransResult");
Element ResultCode = TransResult.addElement("ResultCode");
ResultCode.setText("测试成功");
ResultCode.addAttribute("tc", "1");
return document.asXML();
}
public void init() throws ServletException {
// Put your code here
}
三、测试
1、右键存储过程callhttprequest,选择Test,进入测试界面,输入前面我定义的servlet的访问路径
2、查看servlet接收的报文
首先是乱码:
oracle过来的xml数据:<?xml version="1.0" encoding="GBK"?> 0066667626 娴嬭瘯 2018-12-03 10:12:30 鍗曡瘉绫诲瀷 鍗曡瘉鍥為攢绫诲瀷鍊?
出现这个问题需要改一下servlet的接收方法,改一句代码即可
将 InputStreamReader isr = new InputStreamReader(in);
改成InputStreamReader isr = new InputStreamReader(in, "utf-8");
再次测试,中文不乱码了,但报文不完整
oracle过来的xml数据:<?xml version="1.0" encoding="GBK"?> 0066667626 测试 2018-12-03 10:12:30 单证类型 单证回销类型值
此时可以看到接收到的xml没有完整结束。原因是因为Oracle发送过来的xml中有中文导致的。
而且Oracle这里接收到的返回报文还是乱码
四、解决方法
就是进行url编码
1、Oracle存储过程发送xml报文前进行url编码
v_req_clob:=utl_url.escape(v_req_clob,true,'UTF-8');--进行url编码
具体位置:
2、servlet接收时,进行url解码
sendMessage = java.net.URLDecoder.decode(sendMessage,"utf-8");
具体位置:
3、返回给oracle报文前,进行url编码
xmlData = java.net.URLEncoder.encode(xmlData,"utf-8").replaceAll("\\+", "%20");
具体位置:
4、Oracle存储过程在接收到servlet返回时,进行url解码
v_resp_clob := utl_url.unescape(v_resp_clob, 'utf-8');--进行url解码
具体位置
五、再次进行测试
1、servle端接收到的xml报文完整了,而且格式还保持了
2、Oracle接收到servlet的返回,也正常了
至此问题全部解决完毕!!!