日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
淺談Spring2.5集合WebService

使用JAX-RPC暴露基于servlet的web服務(wù)

Spring為JAX-RPC servlet的端點實現(xiàn)提供了一個方便的基類 - ServletEndpointSupport. 未來暴露我們的 AccountService我們擴展Spring的ServletEndpointSupport類并在這里實現(xiàn)了我們的業(yè)務(wù)邏輯,通常將調(diào)用交給業(yè)務(wù)層。

 
 
 
  1. /**
  2. * JAX-RPC compliant RemoteAccountService implementation that simply delegates
  3. * to the AccountService implementation in the root web application context.
  4. *
  5. * This wrapper class is necessary because JAX-RPC requires working with dedicated
  6. * endpoint classes. If an existing service needs to be exported, a wrapper that
  7. * extends ServletEndpointSupport for simple application context access is
  8. * the simplest JAX-RPC compliant way.
  9. *
  10. * This is the class registered with the server-side JAX-RPC implementation.
  11. * In the case of Axis, this happens in "server-config.wsdd" respectively via
  12. * deployment calls. The web service engine manages the lifecycle of instances
  13. * of this class: A Spring application context can just be accessed here.
  14. */import org.springframework.remoting.jaxrpc.ServletEndpointSupport;
  15. public class AccountServiceEndpoint extends ServletEndpointSupport implements RemoteAccountService {
  16.     
  17.     private AccountService biz;
  18.     protected void onInit() {
  19.         this.biz = (AccountService) getWebApplicationContext().getBean("accountService");
  20.     }
  21.     public void insertAccount(Account acc) throws RemoteException {
  22.         biz.insertAccount(acc);
  23.     }
  24.     public Account[] getAccounts(String name) throws RemoteException {
  25.         return biz.getAccounts(name);
  26.     }
  27. }

AccountServletEndpoint需要在Spring中同一個上下文的web應(yīng)用里運行,以獲得對Spring的訪問能力。如果使用Axis,把AxisServlet定義復(fù)制到你的'web.xml'中,并且在'server-config.wsdd'中設(shè)置端點(或使用發(fā)布工具)。參看JPetStore這個例子中OrderService是如何用Axis發(fā)布成一個Web服務(wù)的。

使用JAX-RPC訪問web服務(wù)

Spring提供了兩個工廠bean用來創(chuàng)建Web服務(wù)代理,LocalJaxRpcServiceFactoryBean 和 JaxRpcPortProxyFactoryBean。前者只返回一個JAX-RPC服務(wù)類供我們使用。后者是一個全功能的版本,可以返回一個實現(xiàn)我們業(yè)務(wù)服務(wù)接口的代理。本例中,我們使用后者來為前面段落中暴露的AccountService端點創(chuàng)建一個代理。你將看到Spring對Web服務(wù)提供了極好的支持,只需要很少的代碼 - 大多數(shù)都是通過類似下面的Spring配置文件:

 
 
 
  1.  id="accountWebService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
  2.      name="serviceInterface" value="example.RemoteAccountService"/>
  3.      name="wsdlDocumentUrl" value="http://localhost:8080/account/services/accountService?WSDL"/>
  4.      name="namespaceUri" value="http://localhost:8080/account/services/accountService"/>
  5.      name="serviceName" value="AccountService"/>
  6.      name="portName" value="AccountPort"/>

serviceInterface是我們客戶端將使用的遠程業(yè)務(wù)接口。 wsdlDocumentUrl是WSDL文件的URL. Spring需要用它作為啟動點來創(chuàng)建JAX-RPC服務(wù)。 namespaceUri對應(yīng).wsdl文件中的targetNamespace。 serviceName 對應(yīng).wsdl文件中的服務(wù)名。 portName 對應(yīng).wsdl文件中的端口號。

現(xiàn)在我們可以很方便的訪問web服務(wù),因為我們有一個可以將它暴露為RemoteAccountService接口的bean工廠。我們可以在Spring中這樣使用:

 
 
 
  1.  id="client" class="example.AccountClientImpl">
  2.     ...
  3.      name="service" ref="accountWebService"/>

從客戶端代碼上看,除了它拋出RemoteException,我們可以把這個web服務(wù)當成一個普通的類進行訪,。

 
 
 
  1. public class AccountClientImpl {
  2.     private RemoteAccountService service;
  3.     
  4.     public void setService(RemoteAccountService service) {
  5.         this.service = service;
  6.     }
  7.     
  8.     public void foo() {
  9.         try {
  10.             service.insertAccount(...);
  11.         }
  12.         catch (RemoteException ex) {
  13.             // ouch
  14.         }
  15.     }
  16. }

我們可以不檢查受控異常RemoteException,因為Spring將它自動轉(zhuǎn)換成相應(yīng)的非受控異常RemoteException。這也需要我們提供一個非RMI的接口。現(xiàn)在配置文件如下:

 
 
 
  1.  id="accountWebService" class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
  2.      name="serviceInterface" value="example.AccountService"/>
  3.      name="portInterface" value="example.RemoteAccountService"/>

我們的serviceInterface變成了非RMI接口。我們的RMI接口現(xiàn)在使用portInterface屬性來定義。我們的客戶端代碼可以避免處理異常java.rmi.RemoteException:

 
 
 
  1. public class AccountClientImpl {
  2.     private AccountService service;
  3.     
  4.     public void setService(AccountService service) {
  5.         this.service = service;
  6.     }
  7.     
  8.     public void foo() {
  9.         service.insertAccount(...);
  10.     }
  11. }

請注意你也可以去掉"portInterface"部分并指定一個普通業(yè)務(wù)接口作為"serviceInterface"。這樣JaxRpcPortProxyFactoryBean將自動切換到JAX-RPC "動態(tài)調(diào)用接口", 不使用固定端口存根來進行動態(tài)調(diào)用。這樣做的好處是你甚至不需要使用一個RMI相關(guān)的Java接口(比如在非Java的目標web服務(wù)中);你只需要一個匹配的業(yè)務(wù)接口。查看JaxRpcPortProxyFactoryBean的javadoc來了解運行時實行的細節(jié)。

注冊JAX-RPC Bean映射

T為了傳遞類似Account等復(fù)雜對象,我們必須在客戶端注冊bean映射。

注意

在服務(wù)器端通常在'server-config.wsdd'中使用Axis進行bean映射注冊。

我們將使用Axis在客戶端注冊bean映射。為此,我們需要通過程序注冊這個bean映射:

 
 
 
  1. public class AxisPortProxyFactoryBean extends JaxRpcPortProxyFactoryBean {
  2.     protected void postProcessJaxRpcService(Service service) {
  3.         TypeMappingRegistry registry = service.getTypeMappingRegistry();
  4.         TypeMapping mapping = registry.createTypeMapping();
  5.         registerBeanMapping(mapping, Account.class, "Account");
  6.         registry.register("http://schemas.xmlsoap.org/soap/encoding/", mapping);
  7.     }
  8.     protected void registerBeanMapping(TypeMapping mapping, Class type, String name) {
  9.         QName qName = new QName("http://localhost:8080/account/services/accountService", name);
  10.         mapping.register(type, qName,
  11.                 new BeanSerializerFactory(type, qName),
  12.                 new BeanDeserializerFactory(type, qName));
  13.     }
  14. }

注冊自己的JAX-RPC 處理器

本節(jié)中,我們將注冊自己的javax.rpc.xml.handler.Handler 到Web服務(wù)代理,這樣我們可以在SOAP消息被發(fā)送前執(zhí)行定制的代碼。Handler是一個回調(diào)接口。jaxrpc.jar中有個方便的基類javax.rpc.xml.handler.GenericHandler供我們繼承使用:

 
 
 
  1. public class AccountHandler extends GenericHandler {
  2.     public QName[] getHeaders() {
  3.         return null;
  4.     }
  5.     public boolean handleRequest(MessageContext context) {
  6.         SOAPMessageContext smc = (SOAPMessageContext) context;
  7.         SOAPMessage msg = smc.getMessage();
  8.         try {
  9.             SOAPEnvelope envelope = msg.getSOAPPart().getEnvelope();
  10.             SOAPHeader header = envelope.getHeader();
  11.             ...
  12.         }
  13.         catch (SOAPException ex) {
  14.             throw new JAXRPCException(ex);
  15.         }
  16.         return true;
  17.     }
  18. }

我們現(xiàn)在要做的就是把AccountHandler注冊到JAX-RPC服務(wù),這樣它可以在消息被發(fā)送前調(diào)用 handleRequest(..)。Spring目前對注冊處理方法還不提供聲明式支持,所以我們必須使用編程方式。但是Spring中這很容易實現(xiàn),我們只需覆寫專門為此設(shè)計的 postProcessJaxRpcService(..) 方法:

 
 
 
  1. public class AccountHandlerJaxRpcPortProxyFactoryBean extends JaxRpcPortProxyFactoryBean {
  2.     protected void postProcessJaxRpcService(Service service) {
  3.         QName port = new QName(this.getNamespaceUri(), this.getPortName());
  4.         List list = service.getHandlerRegistry().getHandlerChain(port);
  5.         list.add(new HandlerInfo(AccountHandler.class, null, null));
  6.         logger.info("Registered JAX-RPC AccountHandler on port " + port);
  7.     }
  8. }

***,我們要記得更改Spring配置文件來使用我們的工廠bean:

 
 
 
  1.  id="accountWebService" class="example.AccountHandlerJaxRpcPortProxyFactoryBean">
  2.     ...

使用JAX-WS暴露基于servlet的web服務(wù)
Spring為JAX-WS servlet端點實現(xiàn)提供了一個方便的基類 - SpringBeanAutowiringSupport。要暴露我們的AccountService接口,我們可以擴展Spring的SpringBeanAutowiringSupport類并實現(xiàn)我們的業(yè)務(wù)邏輯,通常把調(diào)用交給業(yè)務(wù)層。我們將簡單的使用Spring 2.5的@Autowired注解來聲明依賴于Spring管理的bean。

 
 
 
  1. /**
  2. * JAX-WS compliant AccountService implementation that simply delegates
  3. * to the AccountService implementation in the root web application context.
  4. *
  5. * This wrapper class is necessary because JAX-WS requires working with dedicated
  6. * endpoint classes. If an existing service needs to be exported, a wrapper that
  7. * extends SpringBeanAutowiringSupport for simple Spring bean autowiring (through
  8. * the @Autowired annotation) is the simplest JAX-WS compliant way.
  9. *
  10. * This is the class registered with the server-side JAX-WS implementation.
  11. * In the case of a Java EE 5 server, this would simply be defined as a servlet
  12. * in web.xml, with the server detecting that this is a JAX-WS endpoint and reacting
  13. * accordingly. The servlet name usually needs to match the specified WS service name.
  14. *
  15. * The web service engine manages the lifecycle of instances of this class.
  16. * Spring bean references will just be wired in here.
  17. */import org.springframework.web.context.support.SpringBeanAutowiringSupport;
  18. @WebService(serviceName="AccountService")
  19. public class AccountServiceEndpoint extends SpringBeanAutowiringSupport {
  20.     @Autowired
  21.     private AccountService biz;
  22.     @WebMethod
  23.     public void insertAccount(Account acc) {
  24.        biz.insertAccount(acc);
  25.     }
  26.     @WebMethod
  27.     public Account[] getAccounts(String name) {
  28.        return biz.getAccounts(name);
  29.     }
  30. }

為了能夠讓Spring上下文使用Spring設(shè)施,我們的AccountServletEndpoint類需要運行在同一個web應(yīng)用中。在Java EE 5環(huán)境中這是默認的情況,它使用JAX-WS servlet端點安裝標準契約。詳情請參閱Java EE 5 web服務(wù)教程。

使用JAX-WS暴露單獨web服務(wù)
Sun JDK 1.6提供的內(nèi)置JAX-WS provider 使用內(nèi)置的HTTP服務(wù)器來暴露web服務(wù)。Spring的SimpleJaxWsServiceExporter類檢測所有在Spring應(yīng)用上下文中配置的l@WebService 注解bean,然后通過默認的JAX-WS服務(wù)器(JDK 1.6 HTTP服務(wù)器)來暴露它們。

在這種場景下,端點實例將被作為Spring bean來定義和管理。它們將使用JAX-WS來注冊,但其生命周期將一直跟隨Spring應(yīng)用上下文。這意味著Spring的顯示依賴注入可用于端點實例。當然通過@Autowired來進行注解驅(qū)動的注入也可以正常工作。

 
 
 
  1.  class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter">
  2.      name="baseAddress" value="http://localhost:9999/"/>
  3.  id="accountServiceEndpoint" class="example.AccountServiceEndpoint">
  4.     ...
  5. ...

AccountServiceEndpoint類可能源自Spring的 SpringBeanAutowiringSupport類,也可能不是。因為這里的端點是由Spring完全管理的bean。這意味著端點實現(xiàn)可能像下面這樣沒有任何父類定義 - 而且Spring的@Autowired配置注解仍然能夠使用:

 
 
 
  1. @WebService(serviceName="AccountService")
  2. public class AccountServiceEndpoint {
  3.     @Autowired
  4.     private AccountService biz;
  5.     @WebMethod
  6.     public void insertAccount(Account acc) {
  7.        biz.insertAccount(acc);
  8.     }
  9.     @WebMethod
  10.     public Account[] getAccounts(String name) {
  11.        return biz.getAccounts(name);
  12.     }
  13. }

使用Spring支持的JAX-WS RI來暴露服務(wù)

Sun的JAX-WS RI被作為GlassFish項目的一部分來開發(fā),它使用了Spring支持來作為JAX-WS Commons項目的一部分。這允許把JAX-WS端點作為Spring管理的bean來定義。這與前面章節(jié)討論的單獨模式類似 - 但這次是在Servlet環(huán)境中。注意這在Java EE 5環(huán)境中是不可遷移的,建議在沒有EE的web應(yīng)用環(huán)境如Tomcat中嵌入JAX-WS RI。

與標準的暴露基于servlet的端點方式不同之處在于端點實例的生命周期將被Spring管理。這里在web.xml將只有一個JAX-WS servlet定義。在標準的Java EE 5風(fēng)格中(如上所示),你將對每個服務(wù)端點定義一個servlet,每個服務(wù)端點都代理到Spring bean (通過使用@Autowired,如上所示)。

使用JAX-WS訪問web服務(wù)
類似JAX-RPC支持,Spring提供了2個工廠bean來創(chuàng)建JAX-WS web服務(wù)代理,它們是LocalJaxWsServiceFactoryBean和JaxWsPortProxyFactoryBean。前一個只能返回一個JAX-WS服務(wù)對象來讓我們使用。后面的是可以返回我們業(yè)務(wù)服務(wù)接口的代理實現(xiàn)的完整版本。這個例子中我們使用后者來為AccountService端點再創(chuàng)建一個代理:

 
 
 
  1.  id="accountWebService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
  2.      name="serviceInterface" value="example.AccountService"/>
  3.      name="wsdlDocumentUrl" value="http://localhost:8080/account/services/accountService?WSDL"/>
  4.      name="namespaceUri" value="http://localhost:8080/account/services/accountService"/>
  5.      name="serviceName" value="AccountService"/>
  6.      name="portName" value="AccountPort"/>

serviceInterface是我們客戶端將使用的遠程業(yè)務(wù)接口。 wsdlDocumentUrl是WSDL文件的URL. Spring需要用它作為啟動點來創(chuàng)建JAX-RPC服務(wù)。 namespaceUri對應(yīng).wsdl文件中的targetNamespace。 serviceName 對應(yīng).wsdl文件中的服務(wù)名。 portName 對應(yīng).wsdl文件中的端口號。

現(xiàn)在我們可以很方便的訪問web服務(wù),因為我們有一個可以將它暴露為AccountService接口的bean工廠。我們可以在Spring中這樣使用:

 
 
 
  1.  id="client" class="example.AccountClientImpl">
  2.     ...
  3.      name="service" ref="accountWebService"/>

從客戶端代碼上我們可以把這個web服務(wù)當成一個普通的類進行訪問:

 
 
 
  1. public class AccountClientImpl {
  2.     private AccountService service;
  3.     public void setService(AccountService service) {
  4.         this.service = service;
  5.     }
  6.     public void foo() {
  7.         service.insertAccount(...);
  8.     }
  9. }

注意: 上面被稍微簡化了,因為JAX-WS需要端點接口及實現(xiàn)類來使用@WebService, @SOAPBinding等注解。 這意味著你不能簡單的使用普通的Java接口和實現(xiàn)來作為JAX-WS端點,你需要首先對它們進行相應(yīng)的注解。這些需求詳情請查閱JAX-WS文檔。

使用XFire來暴露Web服務(wù)

XFire是一個Codehaus提供的輕量級SOAP庫。暴露XFire是通過XFire自帶的context,這個context將和RemoteExporter風(fēng)格的bean相結(jié)合,后者需要被加入到在你的WebApplicationContext中。對于所有讓你來暴露服務(wù)的方法,你需要創(chuàng)建一個DispatcherServlet類并有相應(yīng)的WebApplicationContext來封裝你將要暴露的服務(wù):

 
 
 
  1.     xfire
  2.     org.springframework.web.servlet.DispatcherServlet

你還必須鏈接XFire配置。這是通過增加一個context文件到由ContextLoaderListener(或者ContextLoaderServlet)加載的 contextConfigLocations 參數(shù)中。

 
 
 
  1.     contextConfigLocation
  2.     classpath:org/codehaus/xfire/spring/xfire.xml
  3.     org.springframework.web.context.ContextLoaderListener

在你加入一個Servlet映射后(映射/*到上面定義的XFire Servlet),你只需要增加一個額外的bean來使用XFire暴露服務(wù)。例如,在 'xfire-servlet.xml' 中增加如下配置:

 
 
 
  1.      name="/Echo" class="org.codehaus.xfire.spring.remoting.XFireExporter">
  2.          name="serviceInterface" value="org.codehaus.xfire.spring.Echo"/>
  3.          name="serviceBean">
  4.              class="org.codehaus.xfire.spring.EchoImpl"/>
  5.         
  6.         
  7.          name="xfire" ref="xfire"/>

XFire處理了其他的事情。它檢查你的服務(wù)接口并產(chǎn)生一個WSDL文件。這里的部分文檔來自XFire網(wǎng)站,要了解更多有關(guān)XFire Spring的集成請訪問 docs.codehaus.org/display/XFIRE/Spring。


本文標題:淺談Spring2.5集合WebService
本文URL:http://www.dlmjj.cn/article/dhcpedc.html