zoukankan      html  css  js  c++  java
  • WebService开发指南

    WebServiceInAurora

    Web Service

    Web Service是一种面向服务的架构的技术,通过标准的Web协议提供服务,目的是保证不同平台的应用服务可以互操作。在Aurora框架中可以方便的提供Web Service服务及调用由他人发布的Web Service。

    在Aurora中发布Web Service


    1. 从
    Aurora-framework上下载最新的aurora.jar
    2. 添加web service监听器。打开
    WEB-HOMEWEB-INFaurora.featureservice-listener.config,在 <participant-list category="service"> 节点下,添加 <participant class="aurora.service.ws.SOAPServiceInterpreter"/> 子节点。
    3. 取消此svc的登录校验。在系统注册svc文件时,设置不需要登录的权限。对于webservice作为一个独立部署的工程,可以取消service-procedure.config配置文件,这样所有的文件都不需要登录校验。
    4. 撰写svc文件,提供给他人调用即可。


    简单例子

    我们提供一个svc,此svc把请求的数据插入到一个数据库表中。


    1. create table account_test(ACCOUNT_ID number,ACCOUNT_OTHER_CODE varchar2(100)); 新建一个对应的结果表 
    2. 建立一个此表的bm:

     
    <?xml version="1.0" encoding="UTF-8"?>
    <!--
    $Author: linjinxiao 
    $Date: 2011-11-9 上午10:42:34 
    $Revision: 1.0 
    $Purpose: 
    -->
    <bm:model xmlns:bm="http://www.aurora-framework.org/schema/bm" alias="t1" baseTable="ACCOUNT_TEST">
      <bm:fields>
        <bm:field name="ACCOUNT_ID" databaseType="NUMBER" datatype="java.lang.Long" 
    physicalName="ACCOUNT_ID" prompt="ACOUNT_TEST.ACCOUNT_ID"/>
        <bm:field name="ACCOUNT_OTHER_CODE" databaseType="VARCHAR2" 
    datatype="java.lang.String" physicalName="ACCOUNT_OTHER_CODE" prompt="ACOUNT_TEST.ACCOUNT_OTHER_CODE"/>
      </bm:fields>
    </bm:model>
    


    3. 在modules/sys目录下新建ws_test.svc文件,并输入以下内容

    <?xml version="1.0" encoding="UTF-8"?>
    <a:service xmlns:a="http://www.aurora-framework.org/application">
        <a:init-procedure>
            <a:model-insert model="fnd.account_test"/>
        </a:init-procedure>
        <a:service-output output="/parameter"/>
    </a:service>
    


     以上内容就完成了服务器的编写,下面提供客户端的调用代码示例
    4. 使用开源框架axis2为例

    public class LowLevelClient {
    	public static void main(String[] args) throws AxisFault {
    			ServiceClient client = new ServiceClient();
    			Options options = new Options();
    			options.setTo(new EndpointReference(
    							"http://127.0.0.1:8080/newhec/modules/sys/ws_test.svc"));//修正为实际工程的URL
    			client.setOptions(options);
    			OMElement request = makeRequest();
    			OMElement response = client.sendReceive(request);
    			System.out.println("ok:"+response.toString());
    	}
    	private static OMElement makeRequest() {
    			OMFactory factory = OMAbstractFactory.getOMFactory();
    			OMElement request = factory.createOMElement(new QName(
    							"", "parameter"));
    			request.addAttribute("ACCOUNT_ID", "123", null);
    			request.addAttribute("ACCOUNT_OTHER_CODE", "test", null);
    			return request;
    	}
    


    5. 查看插入数据库记录是否成功和控制台的结果是否正确。

    复杂例子

    这个例子处理有头行结构的例子。譬如,调用方发送过来的请求是如下格式

    <requestHead seqNo="1"/>
      <requestBody>
        <records>
           <record ACCOUNT_ID="22" ACCOUNT_OTHER_CODE="test"/>
           <record ACCOUNT_ID="33" ACCOUNT_OTHER_CODE="test2"/>
        </records>
      </requestBody>
    

    返回的结构要求是如下格式

    <responseHead xmlns="http://aurora.org" seqNo="1" />
    <requestBody responsedate="3008900">
        <records>
          <record ACCOUNT_ID="22" ACCOUNT_OTHER_CODE="test" REQUEST_RESULT="successful"  />
           <record ACCOUNT_ID="33" ACCOUNT_OTHER_CODE="test2" REQUEST_RESULT="successful" />
        </records>
    </requestBody>
    


    1. 我们创建一个pkg:

     
    create or replace package ACCOUNT_TEST_PKG is
      procedure insert_account_test(p_account_id         number,
                                    p_account_other_code varchar2,
                                    p_request_result     out varchar2);
    end ACCOUNT_TEST_PKG;
    
    create or replace package body "ACCOUNT_TEST_PKG" is
      procedure insert_account_test(p_account_id         number,
                                    p_account_other_code varchar2,
                                    p_request_result     out varchar2) is
      begin
      
        insert into account_test
          (account_id, account_other_code)
        values
          (p_account_id, p_account_other_code);
        p_request_result := 'successful';
      
      end;
    end ACCOUNT_TEST_PKG;
    /
    


    2. 在bm中调用此pkg:

     
    <bm:operations>
            <bm:operation name="insert">
                <bm:update-sql><![CDATA[
                begin
                  ACCOUNT_TEST_PKG.insert_account_test        
                    (
                      p_account_id => ${@ACCOUNT_ID},
                      p_account_other_code => ${@ACCOUNT_OTHER_CODE}, 
                      p_request_result => ${@REQUEST_RESULT}
                     ); 
                end;               
    		</bm:update-sql>
                <bm:parameters>
                    <bm:parameter name="ACCOUNT_ID"/>
                    <bm:parameter name="ACCOUNT_OTHER_CODE"/>
                    <bm:parameter name="REQUEST_RESULT" output="true" outputPath="@REQUEST_RESULT"/>
                </bm:parameters>
            </bm:operation>
        </bm:operations>
    


    3. 撰写svc如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <a:service xmlns:a="http://www.aurora-framework.org/application" 
    xmlns:p="uncertain.proc">
        <a:init-procedure>
            <p:echo/>
            <!-- 对数据进行循环操作-->
            <batch-apply sourcepath="/parameter/requestBody/records">
               <a:model-insert model="fnd.account_test"/> 
            </batch-apply>
            <!--更改节点的名称和namespace-->
            <p:set-element target="/parameter/requestHead" name="responseHead" namespace="http://aurora.org" />
             <!-- 获得当前的时间--> 
             <a:model-query fetchAll="true" fethOneRecord="true" model="ccic.systest"
     rootPath="/parameter/requestBody"/>
         </a:init-procedure>
        <a:service-output output="/parameter/"/>
    </a:service>
    


    4. 撰写客户端调用代码,同样是利用开源框架axis2:

    private static OMElement makeRequest2() {
     OMFactory factory = OMAbstractFactory.getOMFactory();
     OMElement request = factory.createOMElement(new QName("soap:Body"));
     OMElement requestHead = factory.createOMElement(new QName("requestHead"));
     requestHead.addAttribute("seqNo", "1", null);
     OMElement requestBody = factory.createOMElement(new QName("requestBody "));
    
     OMElement records = factory.createOMElement(new QName("records "));
     OMElement record = factory.createOMElement(new QName("record "));
     record.addAttribute("ACCOUNT_ID", "11", null);
     record.addAttribute("ACCOUNT_OTHER_CODE", "test", null);
    
     records.addChild(record);
     requestBody.addChild(records);
     request.addChild(requestHead);
     request.addChild(requestBody);
       
     return request;
    }
    


    5. 执行此客户端,并查询数据库记录和返回结果是否正确。


    调用WebService

    假设服务端要求提交的格式如下:

    <axis2ns1:cancat xmlns:axis2ns1="http://www.aurora.org/simple/">
                <s1>abc</s1>
                <s2>def</s2>
     </axis2ns1:cancat>
    

    返回的格式如下:

    <ns1:syncAccResponse xmlns:ns1=http://service.test.com>
            <ns1:out>
                    <ns2:Account xmlns:ns2=http://dto.test.com>
                            <ACCOUNT_ID xmlns=http://dto.test.com>1681</ACCOUNT_ID>
                            <ACCOUNT_OTHER_CODE xmlns=http://dto.test.com></ACCOUNT_OTHER_CODE>
                    </ns2:Account>
                    <ns2:Account xmlns:ns2=http://dto.test.com>
                            <ACCOUNT_ID xmlns=http://dto.test.com>1682</ACCOUNT_ID>
                            <ACCOUNT_OTHER_CODE xmlns=http://dto.test.com></ACCOUNT_OTHER_CODE>
                    </ns2:Account>
            </ns1:out>
    </ns1:syncAccResponse>
    


    1. 模拟第三方发布服务,以axis2为例
      1. 下载
    axis2
      2.  把
    simpleWebService部署到
    AXIS2_HOME/repository/services下,然后启动服务
    2. 编写客户端代码
      1. 编写systest.bm文件

    <?xml version="1.0" encoding="UTF-8"?>
    <bm:model xmlns:bm="http://www.aurora-framework.org/schema/bm">
        <bm:operations>
            <bm:operation name="query">
                <bm:query-sql><![CDATA[select '3008900' exp_report_number,
                                      '222222222' employee_code,
                                      '测试'  name,
                                      'MAS'  unit_code,
                                      'test@hand-china.com' email,
                                                                      '0' type
                              from dual
    </bm:query-sql>
            </bm:operation>
        </bm:operations>
    </bm:model>
    


      2. 编写svc文件

    <?xml version="1.0" encoding="UTF-8"?>
    <a:service xmlns:a="http://www.aurora-framework.org/application"
     xmlns:p="uncertain.proc" xmlns:rs="aurora.database.rsconsumer" >
        <a:init-procedure>
            <!-- 构建符合的请求的格式-->
            <a:model-query fetchAll="true" prefix="ns1"
     nameSpace="http://www.aurora.org/simple" localName="cancat" model="sys.systest" rootPath="/model/result1"/>
            <a:model-query fetchAll="true" model="sys.systest" localName="s1" 
    attribAsCdata="true" attribAsCdataList="unit_code"rootPath="/model/result1/cancat"/>
            <a:model-query fetchAll="true" model="sys.systest" localName="s2" 
    attribAsCdata="true" attribAsCdataList="employee_code" rootPath="/model/result1/cancat"/>
            <!-- 请求WebService-->
            <a:ws-invoker raiseExceptionOnError="false" url="http://localhost:8080/axis2/services/simple" 
    inputPath="/model/result1/cancat" returnPath="/model/syncAccResponse"/>
            <!--把子节点中cdata的内容整合成父节点中的一个属性 -->
           <p:method-invoke className="uncertain.composite.CompositeUtil" methodName="collapse">
                <p:arguments>
                    <p:argument path="/model/syncAccResponse/out" type="uncertain.composite.CompositeMap"/>
                </p:arguments>
          </p:method-invoke>
          <as:SetParameterParsed />
          <!--循环处理子节点 -->
          <batch-apply sourcepath="/model/syncAccResponse/out">
             <a:model-insert model="fnd.account_test"/> 
          </batch-apply>
        </a:init-procedure>
     <a:service-output output="/parameter/"/>
    


      3. 调用此svc,并查看日志和数据库记录是否正确。

    svc常用功能简介


    最基本的四个功能:model-query,model-insert,model-update,model-delete
    把单条记录查询结果返回的属性直接更新到指定的节点上: fetchOneRecord="true" 。例子:

    <a:model-query fetchAll="true" fetchOneRecord="true" model="sys.systest" rootPath="/model/result1/cancat"/>
    


    如果不加此属性,返回的结果是

    <model>
      <result1>
        <concat>
          <record employee_cod="test"/>
        </concat>
      </result1>
    </model> 
    


    加了此属性后,返回结果就是:

    <model>
      <result1>
        <concat employee_cod="test"/>
       </result1>
    </model> 
    


    注意:此属性仅对返回单条记录有效。
    批量循环处理:batch-apply 。例子:

    <batch-apply sourcepath="/model/syncAccResponse/out">
       <a:model-insert model="fnd.account_test"/>   
    </batch-apply>
    


    表示对/model/syncAccResponse/out下面的所有子节点执行model-insert操作。
    更改查询返回的数据格式。例子:

    <a:model-query fetchAll="true" model="sys.systest" localName="s2" attribAsCdata="true" 
    attribAsCdataList="employee_code" prefix="ns1" 
    nameSpace="http://www.aurora.org/simple" rootPath="/model/result1/cancat"/>
    </a:model-query>
    


    如果不加localName="s2"...nameSpace="http://www.aurora.org/simple" 那段,那么原本的返回结果可能是

    <model>
      <result1>
        <concat>
          <record employee_cod="test"/>
        </concat>
      </result1>
    </model>
    


    经过处理后,就变成

    <model>
      <result1>
        <concat>
          <ns1:s2 xmlns:ns1="http://www.aurora.org/simple">test</ns1:s2>
        </concat>
      </result1>
    </model>
    


    把cdata的内容变成父节点的一个属性,例子:

    <p:method-invoke className="uncertain.composite.CompositeUtil" methodName="collapse">
          <p:arguments>
             <p:argument path="/model/syncAccResponse/out" type="uncertain.composite.CompositeMap"/>
          </p:arguments>
    </p:method-invoke>
    


    原先的数据格式可能是这样的:

    <model>
      <syncAccResponse>
        <out>
          <s1>yes</s1>
          <s2>test</s2>
        </out>
      </syncAccResponse1>
    </model>
    


    处理后的格式就是这样的

    <model>
      <syncAccResponse>
        <out s1="yes" s2="test"/>
      </syncAccResponse1>
    </model>
    


    复制元素属性,例子

     <p:method-invoke className="uncertain.composite.CompositeUtil" methodName="copyAttributes" >
         <p:arguments>
            <p:argument path="/model/result4" type="java.util.Map"/>
            <p:argument path="/parameter" type="java.util.Map"/>
        </p:arguments>
    </p:method-invoke>
    


    原先的格式可能是这样的

    <model>
      <result4 s1="yes" s2="test"/>
    </model>
    <parameter s3="aurora" />
    


    执行后就变成这个效果

    <model>
      <result4 s1="yes" s2="test"/>
    </model>
    <parameter s1="yes" s2="test" s3="aurora" />
    


    更改元素名称、namespace和前缀:set-element。
    例子

    <p:set-element target="/model/syncAccResponse/out" name="ok" prefix="right"
     namespace="http://aurora.org" childLevel="0"/>
    


    原先的格式可能是这样的:

    <model>
      <syncAccResponse>
        <out>
          <s1>yes</s1>
          <s2>test</s2>
        </out>
      </syncAccResponse1>
    </model>
    


    执行后变成:

     <model>
      <syncAccResponse>
        <right:ok xmlns:right="http://aurora.org">
          <s1>yes</s1>
          <s2>test</s2>
        </right:ok>
      </syncAccResponse1>
    </model>
    


    其中childLevel表示子节点的层次,如果是0,代表本节点,如果是1,表示下一级子节点。假设把上面的childLevel改成1,然后结果会变成:

    <model>
      <syncAccResponse>
        <out>
          <right:ok xmlns:right="http://aurora.org" >yes</right:o>
          <right:ok xmlns:right="http://aurora.org">test</right:o>
        </out>
      </syncAccResponse1>
    </model>
  • 相关阅读:
    【LeetCode每天一题】Symmetric Tree(对称树)
    【LeetCode每天一题】Same Tree(相同的树)
    【Go】并发
    【LeetCode每天一题】Validate Binary Search Tree(有效的二叉搜索树)
    【LeetCode每天一题】 Unique Binary Search Trees(唯一二叉搜索树)
    【LeetCode每天一题】Binary Tree Inorder Traversal(二叉树的中序遍历)
    【LeetCode每天一题】Reverse Linked List II(旋转链表II)
    【LeetCode每天一题】Subsets II(子集合II)
    【LeetCode每天一题】Partition List(分区链表)
    【Go】面向对象
  • 原文地址:https://www.cnblogs.com/wanghang/p/6299143.html
Copyright © 2011-2022 走看看