Tuscany SCA案例分析

Tuscany SCA案例分析(一)(连载中...)

给了好久的承诺 , 前些日子一直在学习一些 SOA 方面相关的资料 , 包括 Web Service 基础 --WSDL SOAP UDDI , 这些是经典的 Web service 规范 , 同时学习了些相关的 XML-RPC 以及 WS-BPEL 等相关的内容,其中发现要看明白这些东西必须要先学好 XML 以及 XML Schema 的基础知识 , 然后又开始学习了 , 发现可以看明白一些东西了 , 当然还看了些 SOA 设计方面的原则的资料了 , 这些会在学习以及后续的分析整理出来 . 现在有了高层的设计指导 , 当然需要具体的编码技术支持了 , 否则再好的设计也无法实现了 , 所以开始了对 Tuscany SCA 的编码学习 . 为了让读者更有思路跟上节奏 , 以后的连载文章都将按照如下顺序介绍 :1  解析设计图  2 具体编码  3 分析以及总结

       为了让编码更容易,Java编程怎么能缺少Javadoc,否则无法查看帮助文档是很郁闷的事情,于是我先安装了maven2.0.5,这个在本人翻译的 <如何进入Java SCA软件的开发>文章中提到了,高于Maven2.0.5版本可能会出现错误,下面就配置maven2.0.5,下载maven2.0.5,直接解压(我这里是解压到d盘了)

下面配置maven的可执行文件到Path

然后进入tuscany源代码的解压文件夹,

-apache-tuscany-sca-1.0.1-incubating-src

 |-- sca

     |-- demos         SCA 演示应用程序

     |-- distribution     SCA 发布程序

     |-- itest           SCA 集成测试

     |-- modules       SCA 实现的各个模块 (core, runtimes, contribution, extensions                                 等等)

     |-- samples       SCA 样例程序

     |-- tools          SCA 工具 (Eclipse插件, wsdl2java, java2wsdl等等)

这是我环境的结构,在dos窗口中进入sca目录,然后直接使用mvn命令

mvn javadoc:javadoc

来生成Javadoc,经过一段时间,就会在modules里面的每个相应目录下的target文件夹下生成site文件夹,里面就是javaAPIdoc了,我们需要的就是这些javadoc,因为我们后面的编程会用到,用得比较多的是modules/domain-api/target/site/apidocs里的帮助信息了。

里面有SCADomainFactorySCADomain类的相关信息。

好的,万事具备,只欠东风了。我们开始我们的编码旅程吧。顺便说下,为了方便编辑.composite文件,我根据网上的<Eclipse开发Apache Tuscany上的SCA应用>文章下载了个eclipse插件,这里就不多说了。

开始了,我们先从最简单的calculator开始,先解析下设计图,如下:

在这个案例中,运行环境是每个组件都在一个node上,前台的CalculatorServiceComponent组件分别引用到了AddServiceComponentSubstractServiceComponentMultiplyServiceComponent以及DivideServiceComponent四个组件。他们之间的引用关系由SCA运行时自动注入。可以认为后面的四个具体的服务是“原子服务”(它完全由自己实现),而前台的CalculatorServiceComponent组件则是组合出来的服务,虽然它只是简单的做了个功能代理而已,但它完全可以加入自己的附加功能。

       好了,设计图的分析到此为止,我们可以开始进行编码了,来学习学习如何用SCA javaAPI来实现。打开eclipse,新建一个普通的java project,在建工程的时候可以加入Junit3的库和MyTuscany用户库(该库的设置在我的< Tuscany初探>的附录中给出了设置方法)

我设置了target文件夹为默认的输出路径,这里无所谓的。下一步建立组件的逻辑功能代码。我这里为了保持一致,建立了calculator包,在该包下分别建立加、减、乘、除的服务接口文件AddService.javaSubtractService.javaMultiplyService.javaDivideService.java。这四个Java接口都是本地的。

AddService.java内容如下:

package calculator;

 

/**

 * The Add service interface

 */

public interface AddService {

 

    double add(double n1, double n2);

 

}

SubtractService.java内容如下:

package calculator;

/**

 * The interface for the multiply service

 */

public interface SubtractService {

    double subtract(double n1, double n2);

}

MultiplyService.java内容如下:

package calculator;

/**

 * The interface for the multiply service

 */

public interface MultiplyService {

    double multiply(double n1, double n2);

}

DivideService.java内容如下:

package calculator;

/**

 * The divide service interface

 */

public interface DivideService {

    double divide(double n1, double n2);

}

后面的实现很简单的,就是利用double类型的+ - * /号来进行运算,这里就不给出具体实现了,仅给出java文件名,我的命名规则是在相应的Service后面加上Impl就成了实现的java代码文件名。再给出前台服务组件的CalculatorService.java的接口代码如下:

package calculator;

/**

 * The Calculator service interface.

 */

public interface CalculatorService {

    double add(double n1, double n2);

    double subtract(double n1, double n2);

    double multiply(double n1, double n2);

    double divide(double n1, double n2);

}

CalculatorServiceImpl.java内容如下:

package calculator;

import org.osoa.sca.annotations.Reference;

/**

 * An implementation of the Calculator service.

 */

public class CalculatorServiceImpl implements CalculatorService {

    private AddService addService;

    private SubtractService subtractService;

    private MultiplyService multiplyService;

    private DivideService divideService;

    @Reference

    public void setAddService(AddService addService) {

        this.addService = addService;

    }

    @Reference

    public void setSubtractService(SubtractService subtractService) {

        this.subtractService = subtractService;

    }

    @Reference

    public void setDivideService(DivideService divideService) {

        this.divideService = divideService;

    }

    @Reference

    public void setMultiplyService(MultiplyService multiplyService) {

        this.multiplyService = multiplyService;

    }

    public double add(double n1, double n2) {

        return addService.add(n1, n2);

    }

    public double subtract(double n1, double n2) {

        return subtractService.subtract(n1, n2);

    }

    public double multiply(double n1, double n2) {

        return multiplyService.multiply(n1, n2);

    }

    public double divide(double n1, double n2) {

        return divideService.divide(n1, n2);

    }

}

该类中有相应引用的服务接口,并且在这些接口实例setter函数注入时,都有@Reference注解。不用担心,tuscany SCA运行时会自动注入的。

    到目前为止,所有的服务组件逻辑业务功能都用Java实现了。该是时候给出.composite文件了,该文件展示了各个服务组件之间的引用关系以及构件与组件的组合关系。直接在src下建立Calculator.composite文件,这个文件名可以自己取,不一定要和我的一致。

其内容如下:

<?xml version="1.0" encoding="UTF-8"?>

<composite xmlns="http://www.osoa.org/xmlns/sca/1.0"

    xmlns:t="http://tuscany.apache.org/xmlns/sca/1.0"

    xmlns:c="http://Calculator" name="Calculator">

<!-- 这里的name就是composite的名字,其中默认名称空间与"http://www.osoa.org/xmlns/sca/1.0"相关

       用插件生成的composite文件会在composite元素头标签给出一个c名称空间,其与"http://Calculator"关联

    -->

    <component name="CalculatorServiceComponent">

       <implementation.java class="calculator.CalculatorServiceImpl"/>

       <reference name="addService" target="AddServiceComponent" />

        <reference name="subtractService" target="SubtractServiceComponent" />

        <reference name="multiplyService" target="MultiplyServiceComponent" />

        <reference name="divideService" target="DivideServiceComponent" />

    </component>

    <component name="AddServiceComponent">

       <implementation.java class="calculator.AddServiceImpl"/>

    </component>

    <component name="SubtractServiceComponent">

       <implementation.java class="calculator.SubtractServiceImpl"/>

    </component>

    <component name="MultiplyServiceComponent">

       <implementation.java class="calculator.MultiplyServiceImpl"/>

    </component>

    <component name="DivideServiceComponent">

       <implementation.java class="calculator.DivideServiceImpl"></implementation.java>

    </component>

</composite>

    名叫"Calculator"的构件中含有五个组件CalculatorServiceComponentAddServiceComponent SubtractServiceComponent、MultiplyServiceComponentDivideServiceComponent其中CalculatorServiceComponent引用到其他四个组件每个组件都是用java实现的<implementation.java具体的class类个不相同。这里要注意的是CalculatorServiceComponent的引用书写,例如<referencename="addService" target="AddServiceComponent" />referencename要是该实现类里需要注入的属性名,这里是CalculatorServiceImpl类代码体的private AddService addService;代码行的addServicetarget就是后面的component名字<component name="AddServiceComponent">

        好了现在服务的业务逻辑实现和装配都给出来了,那么如何才能让SCA运行时运行起来,装配出服务,并向外界提供服务呢?客户又如何实现调用服务呢?这里给出的代码只是给出了与服务方运行在同一个JVM里的客户程序。其代码实现如下: 

package calculator;

 import org.apache.tuscany.sca.host.embedded.SCADomain;

 /**

 * This client program shows how to create an SCA runtime, start it,

 * and locate and invoke a SCA component

 */

public class CalculatorClient {

    public static void main(String[] args) throws Exception {

        SCADomain scaDomain = SCADomain.newInstance("Calculator.composite");

        CalculatorService calculatorService =

            scaDomain.getService(CalculatorService.class,"CalculatorServiceComponent");

        // Calculate

        System.out.println("3 + 2=" + calculatorService.add(3, 2));

        System.out.println("3 - 2=" + calculatorService.subtract(3, 2));

        System.out.println("3 * 2=" + calculatorService.multiply(3, 2));

        System.out.println("3 / 2=" + calculatorService.divide(3, 2));

        scaDomain.close();

    }

}

现在要用到前面的javadoc了,这里的main函数中用了SCADomain类的newInstance,传入了composite文件的路径,这里 是相对路径。eclipse中会到src中找Calculator.composite文件。然后利用scaDomaingetService方法得到 CalculatorService接口的实例,这个其实有点象Spring 了,spring也是一开始先得到applicationContext,这里会传入applicationContext.xml配置文件路径地址,然 后通过applicationContext实例用getBean获得bean。如果说spring是类的装配和生产工厂,那么就可以说Tuscany 服务的装配和生产工厂。接着就可以使用calculatorService的加、减、乘、除功能了。最后关闭SCADomain对象就可以了。

你可能感兴趣的:(SCA,tuscany,案例分析)