Oracle发送http请求中文乱码问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shangshaohui2009/article/details/88556722

在日常开发中,可以需要使用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"?>
  <TXLife>
  <TXLifeRequest>
  <TransRefGUID>0066667626</TransRefGUID>
    <TransType tc="WLSCBS_BL_BK_0002">测试</TransType>
    <TransExeDate>2018-12-03</TransExeDate>
    <TransExeTime>10:12:30</TransExeTime>
    <Billcard>
      <CardType tc="166">单证类型</CardType>
      <BackType tc="14">单证回销类型值</BackType>
    </Billcard>
  </TXLifeRequest>
</TXLife>';
  
  --调用发送方法
  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. <br>
     */
    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"?>  <TXLife>  <TXLifeRequest>  <TransRefGUID>0066667626</TransRefGUID>    <TransType tc="WLSCBS_BL_BK_0002">娴嬭瘯</TransType>    <TransExeDate>2018-12-03</TransExeDate>    <TransExeTime>10:12:30</TransExeTime>    <Billcard>      <CardType tc="166">鍗曡瘉绫诲瀷</CardType>      <BackType tc="14">鍗曡瘉鍥為攢绫诲瀷鍊?</BackType>    </Billcard>  </TXLifeReque
出现这个问题需要改一下servlet的接收方法,改一句代码即可

将 InputStreamReader isr = new InputStreamReader(in);

改成InputStreamReader isr = new InputStreamReader(in, "utf-8");

再次测试,中文不乱码了,但报文不完整

oracle过来的xml数据:<?xml version="1.0" encoding="GBK"?>  <TXLife>  <TXLifeRequest>  <TransRefGUID>0066667626</TransRefGUID>    <TransType tc="WLSCBS_BL_BK_0002">测试</TransType>    <TransExeDate>2018-12-03</TransExeDate>    <TransExeTime>10:12:30</TransExeTime>    <Billcard>      <CardType tc="166">单证类型</CardType>      <BackType tc="14">单证回销类型值</BackType>    </Billcard>  </TXLifeReque

此时可以看到接收到的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的返回,也正常了

至此问题全部解决完毕!!!

猜你喜欢

转载自blog.csdn.net/shangshaohui2009/article/details/88556722