先看一下tuscany簡介,簡單瞭解一下tuscany是什麼
SCA 的基本概念以及 SCA 規範的具體內容並不在本文的範疇之內,有興趣的讀者可以通過一些相關文檔瞭解相關內容,這也是閱讀本文的基礎。下面本文首先對 Tuscany 架構做一定的介紹。
Tuscany 是 Apache 的開源項目,它是 IBM、Oracle、SAP 等廠商聯合成立的 SOA 標準化組織 -OSOA 支援下開發出的 SCA 架構,它既是開源界 SCA 的試金石,也是當前開源界最成熟的 SCA 架構之一。
tuscany是一套開源的sca架構模型,是做soa的基礎架構
SCA是什嗎?
SCA為構建基於SOA的應用和解決方案提供了編程模型。它基於這樣的理念:將業務功能作為一系列的服務而提供,並由這一系列的服務組裝起來的解決方案來滿足特定業務需求。這些組合的應用既包括為應用而新建立的特定服務,也包括源自已已存在系統和應用的商務邏輯,這些商務邏輯作為組合構件的一部分被複用。SCA既為服務的組合也為服務構件的建立提供了模型,包括對SCA組組合構件中對已存在應用功能的複用。
SCA的基礎工件就是component,它是SCA的構成單元。構件(component)由一個實現的可配置(implementation)執行個體所組成。在該構件中,實現是提供業務功能的程式碼片段。該業務功能作為服務(service)而提供,為其他構件所使用。實現也許依賴於由其他構件所提供的服務,這些依賴被稱作”引用”(reference)。實現可以有一個可設定的屬性(properties),該屬性是可以影響業務功能操作的資料值。構件通過提供屬性值和連線(wire)到由其他構件提供服務的引用來配置實現。
還是通過執行個體來看一下SCA到底實現了什麼樣的功能吧!
看一下發布一個基本的加減乘除的樣本,這個是tuscany的官方樣本
定義一個介面實現基本的計算機功能
定義介面CalculatorService,實現基本的加減乘除
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);}
實作類別分別調用對應的介面AddService,DivideService,MultiplyService,SubtractService
在CalculatorServiceImpl中分別調用對應的介面
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); }}
通過@Reference進行注入,看一下每個介面的功能定義
AddService
public interface AddService { double add(double n1, double n2);}
AddServiceImpl
public class AddServiceImpl implements AddService { public double add(double n1, double n2) { Logger logger = Logger.getLogger("calculator"); logger.log(Level.FINEST, "Adding " + n1 + " and " + n2); return n1 + n2; }}
DivideService
public interface DivideService { double divide(double n1, double n2);}
DivideServiceImpl
public class DivideServiceImpl implements DivideService { public double divide(double n1, double n2) { Logger logger = Logger.getLogger("calculator"); logger.log(Level.FINEST, "Dividing " + n1 + " with " + n2); return n1 / n2; }}
MultiplyService
public interface MultiplyService { double multiply(double n1, double n2);}
MultiplyServiceImpl
public class MultiplyServiceImpl implements MultiplyService { public double multiply(double n1, double n2) { Logger logger = Logger.getLogger("calculator"); logger.log(Level.FINEST, "Multiplying " + n1 + " with " + n2); return n1 * n2; }}
SubtractService
public interface SubtractService { double subtract(double n1, double n2);}
SubtractServiceImpl
public class SubtractServiceImpl implements SubtractService { public double subtract(double n1, double n2) { Logger logger = Logger.getLogger("calculator"); logger.log(Level.FINEST, "Subtracting " + n1 + " from " + n2); return n1 - n2; }}
看用戶端調用的代碼
SCANodeFactory factory = SCANodeFactory.newInstance(); SCANode node = factory.createSCANodeFromClassLoader("Calculator.composite", CalculatorClient.class.getClassLoader()); node.start(); CalculatorService calculatorService = ((SCAClient)node).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)); node.stop();
程式中讀取Calculator.composite設定檔,這個是核心設定檔實現的功能是對外發布服務
再看一下設定檔中的定義
<composite xmlns="http://www.osoa.org/xmlns/sca/1.0" targetNamespace="http://sample" xmlns:sample="http://sample" name="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"/> </component></composite>
發布的服務名為CalculatorServiceComponent
通過用戶端的調用程式可以找到對應的服務名
CalculatorService calculatorService = ((SCAClient)node).getService(CalculatorService.class, "CalculatorServiceComponent");
然後調用相應的方法
程式執行結果如下:
2011-10-31 15:44:14 org.apache.tuscany.sca.node.impl.NodeImpl <init>資訊: Creating node: Calculator.composite2011-10-31 15:44:16 org.apache.tuscany.sca.node.impl.NodeImpl configureNode資訊: Loading contribution: file:/D:/Java/workspace/sca/calculator/target/classes/2011-10-31 15:44:18 org.apache.tuscany.sca.node.impl.NodeImpl start資訊: Starting node: Calculator.composite3 + 2=5.02011-10-31 15:44:18 org.apache.tuscany.sca.node.impl.NodeImpl stop資訊: Stopping node: Calculator.composite3 - 2=1.03 * 2=6.03 / 2=1.5
也可以使用CORBA方式調用遠端的實現,對應的服務端的配置,尋找本地的5080連接埠發布的服務
<component name="CalculatorServiceComponent"><implementation.java class="calculator.CalculatorServiceImpl"/><reference name="addService"> <tuscany:binding.corba uri="corbaname::localhost:5080#CalculatorCORBAService"/></reference> <reference name="subtractService"> <tuscany:binding.corba uri="corbaname::localhost:5080#CalculatorCORBAService"/> </reference> <reference name="multiplyService"> <tuscany:binding.corba uri="corbaname::localhost:5080#CalculatorCORBAService"/> </reference> <reference name="divideService"> <tuscany:binding.corba uri="corbaname::localhost:5080#CalculatorCORBAService"/> </reference> </component>
測試案例中的代碼實現如下:
public class CalculatorCORBAReferenceTestCase extends TestCase { private SCADomain scaDomain; private CalculatorService calculatorService; private TransientNameServer server; private void bindObject(String name, org.omg.CORBA.Object object) throws Exception { ORB orb = server.getORB(); org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); NamingContext ncRef = NamingContextHelper.narrow(objRef); NameComponent nc = new NameComponent(name, ""); NameComponent path[] = {nc}; ncRef.rebind(path, object); } @BeforeClass protected void setUp() throws Exception { // create name service server = new TransientNameServer("localhost", 5080, TransientNameService.DEFAULT_SERVICE_NAME); Thread t = server.start(); if (t == null) { Assert.fail("The naming server cannot be started"); } else { // create CORBA object which will be accessible by SCA CORBA binding bindObject("CalculatorCORBAService", new CalculatorCORBAServant()); scaDomain = SCADomain.newInstance("CalculatorCORBAReference.composite"); calculatorService = scaDomain.getService(CalculatorService.class, "CalculatorServiceComponent"); } } @AfterClass protected void tearDown() throws Exception { scaDomain.close(); server.stop(); } @Test public void testCalculator() throws Exception { assertEquals(5.0, calculatorService.add(3, 2)); assertEquals(1.0, calculatorService.subtract(3, 2)); assertEquals(6.0, calculatorService.multiply(3, 2)); assertEquals(1.5, calculatorService.divide(3, 2)); }}
服務是SOA的核心,它們代表了那些可以被結合在一起成為應用程式或商務程序的可工作,可重用的代碼單元。
OSGI明確地把Java作為目標平台,提供用於建立組件的模組化架構,以及用來運行這些組件的運行時容器。OSGI本身並不提供可直接用於SOA服務所需的功能特性。
利用SCA,你可以用不同的程式設計語言構建功能單元或組件,然後將他們通過SOAP、JMS、RMI、REST或其它協議暴露為服務。
不僅如此,這些組件可以在內部被連在一起形成到時候進階別的服務或組合。服務可以以分布式的方式運行,並作為虛擬雲來管理。