Web 服务客户端的服务定位器:设计详细信息

此解决方案通过作为 Web 服务应用程序客户端的 Java[TM] 2 Platform, Enterprise Edition(J2EE[TM] 平台)组件进行演示,该客户端应用程序位于 java.net 中的 bpcatalog 项目下。该应用程序说明了 J2EE 组件如何调用 Web 服务。它是通过将服务定位器模式应用于其设计中得到增强的。此应用程序显示了一个 Servlet 组件,该组件用于访问已部署为其他应用程序一部分的 Web 服务。对于任何需要访问 Web 服务的 J2EE 组件(Servlet、JSP[TM] 页、EJB[TM] 组件),其概念基本相同。

此应用程序的关键部分是:
此应用程序访问部署的 Web 服务(另一个应用程序)。因为此客户端是 J2EE 应用程序,在本例中为 Web 应用程序 war 文件,所以必须在其 web.xml 文件中指定服务引用。以下是 web.xml 的代码片段:

<service-ref>
  <description>Schema defined Purchase Order Service Client</description>
  <service-ref-name>service/SchemaDefinedPurchaseOrderService</service-ref-name>
  <service-interface>
 com.sun.j2ee.blueprints.docoriented.client.objectposervice.SchemaDefinedPurchaseOrderService 
  </service-interface>
  <wsdl-file>WEB-INF/wsdl/SchemaDefinedPurchaseOrderService.wsdl</wsdl-file>
 <jaxrpc-mapping-file>WEB-INF/schemadefinedpurchaseorderservice-mapping.xml</jaxrpc-mapping-file>
  <service-qname xmlns:servicens="urn:SchemaDefinedPurchaseOrderService">servicens:SchemaDefinedPurchaseOrderService</service-qname>
</service-ref> 


代码示例 1:web.xml 部署描述符中的服务引用

除了包含服务引用外,应用程序还需在部署时将该服务引用绑定到 JNDI 名称,便于客户端代码进行查找。现在,让我们来看一些使用和实现服务定位器模式的键类。

SchemaPOServiceBD.java

首先让我们来看 SchemaPOServiceBD.java 类的代码。此类使用服务定位器。此类仅有一种方法,该方法将被调用并充当访问 Web 服务的代理。此类实现业务委托模式。此 submitPO 方法的关键之处在于它使用了服务定位器。它使用服务定位器获取对 Web 服务的引用,然后调用该 Web 服务。

public class SchemaPOServiceBD {
  private ServiceLocator serviceLocator;

  public SchemaPOServiceBD(){    
        serviceLocator = new ServiceLocator();  
    }

  public String submitPO(com.sun.j2ee.blueprints.docoriented.client.PurchaseOrder po) throws RequestHandlerException {
       
    try {      
      SchemaDefinedPurchaseOrderServiceSEI port = (SchemaDefinedPurchaseOrderServiceSEI)         
      serviceLocator.getServicePort(JNDINames.SCHEMA_SERVICE_REF, SchemaDefinedPurchaseOrderServiceSEI.class);
                     
      //convert po object into object for service type of order
      // that is to be sent to the endpoint
      ...    

      String ret = port.submitPO(order);
      return ret;
    } catch ...
     ....
  }
}

ServiceLocator.java

现在让我们来看 ServiceLocator.java 类。正如您所看到的,该实现就像一个用于其他资源的服务定位器,仅在这种情况下,我们添加了对获取 Web 服务引用的支持。由于服务定位器包含获取服务引用的所有查找代码,因此类可以使用此服务定位器,从而避免将此查找代码复制并粘贴到许多不同位置。这有助于清理应用程序中的代码。

import javax.naming.*;
import java.rmi.Remote;
import javax.xml.rpc.*;

/**
 * Implements Service Locator pattern for Web services
 */
public class ServiceLocator {
   
    private transient InitialContext ic;

    public ServiceLocator() throws ServiceLocatorException  {
        try {
            setInitialContext();
        } catch (Exception e) {
            throw new ServiceLocatorException(e);
        }
    }

    private void setInitialContext() throws javax.naming.NamingException {
      ic = new InitialContext();
    }

    /**
     * Service class acts as a factory of the Dynamic proxy for the target service endpoint.
     * @see java.xml.rpc.Service.java
     * @return the Service instance
     */
    public Remote getServicePort(String jndiName, Class className) throws ServiceLocatorException {
        try {
            if (ic == null) setInitialContext();
            Service service = (Service) ic.lookup(jndiName);
            return service.getPort(className);
        } catch (Exception e) {
            throw new ServiceLocatorException("ServiceLocator can not lookup jndiName=" + jndiName + " and className=" + className,  e);
        }
    } 
}

ServiceLocatorException.java

现在让我们来看 ServiceLocatorException.java 类。请注意,我们选择此异常扩展 RuntimeException。由于在命名目录中查找资源时出现异常对用户来说是一种无法恢复的异常,因此我们选择将此异常视为未检查的系统异常。另请注意,我们还使用了异常链。在使用服务定位器的 J2EE 客户端示例应用程序中,主 Servlet 使用 web.xml 中的 Servlet 错误页映射机制,将此异常和所有运行时异常映射到输出系统错误消息的 JSP 错误页。

package com.sun.j2ee.blueprints.docoriented.client;

public class ServiceLocatorException extends RuntimeException {
    public ServiceLocatorException() {}
    public ServiceLocatorException(String msg) { super(msg); }
    public ServiceLocatorException(String msg, Throwable cause) { super(msg, cause); }
    public ServiceLocatorException(Throwable cause) { super(cause); }
}


© Sun Microsystems 2005。Java BluePrints Solutions Catalog 中的所有内容受版权保护,未经 Sun Microsystems 的明确书面许可,不得在其他产品中发布。