`
zym_nanako
  • 浏览: 83362 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java Web Service之JSE实现梗概

阅读更多

在Java中创建、使用Web Service主要是通过JAX-RPC来进行的。
JAX-RPC Service Endpoint(JSE)和EJB Endpoint是Java Web Service的服务器端两种主要实现方式。而Java Web Service的客户端主要有:

  1. 生成的stub,它是最常用的,最接近Java RMI的语义;
  2. 动态代理;
  3. 动态调用接口

Java Web Service的服务器端实现
JSE是通过Servlet(下称JAX-RPC Servlet)响应来自客户端的SOAP消息的,JAX-RPC Servlet负责把SOAP消息转换为Java的方法调用,并调用响应的JSE。
实现一个JSE通常需要定义一个endpoint接口和相应的实现。接口中定义了作为web service的方法,该接口需要继承java.rmi.Remote,其所有方法必须抛java.rmi.RemoteException。
在Java中创建、使用Web Service主要是通过JAX-RPC来进行的。
JAX-RPC Service Endpoint(JSE)和EJB Endpoint是Java Web Service的服务器端两种主要实现方式。而Java Web Service的客户端主要有:
  1. 生成的stub,它是最常用的,最接近Java RMI的语义;
  2. 动态代理;
  3. 动态调用接口

Java Web Service的服务器端实现
JSE是通过Servlet(下称JAX-RPC Servlet)响应来自客户端的SOAP消息的,JAX-RPC Servlet负责把SOAP消息转换为Java的方法调用,并调用响应的JSE。
实现一个JSE通常需要定义一个endpoint接口和相应的实现。接口中定义了作为web service的方法,该接口需要继承java.rmi.Remote,其所有方法必须抛java.rmi.RemoteException。示例如下:
package some.dot.com;

public interface BookQuote extends java.rmi.Remote {
  public float getBookPrice(String isbn) throws java.rmi.RemoteException;
}

在J2EE环境下可以通过以多种式实现endpoint接口,一般都是先通过JNDI找到相关的资源,然后调用资源上的相应的方法。典型的实现有:
1.通过JDBC访问数据库
public class BookQuote_Impl_2 implements BookQuote {
  public float getBookPrice(String isbn){
    java.sql.Connection jdbcConnection = null;
    java.sql.Statement sqlStatement = null;
    java.sql.ResultSet resultSet;
    try {
      javax.naming.InitialContext jndiEnc =
                               new javax.naming.InitialContext();
      javax.sql.DataSource dataSource = (javax.sql.DataSource)
                  jndiEnc.lookup("java:comp/env/jdbc/DataSource");
      jdbcConnection = dataSource.getConnection();
      sqlStatement = jdbcConnection.createStatement();
      resultSet = sqlStatement.executeQuery(
        "SELECT wholesale FROM CATALOG WHERE isbn = \'"+isbn+"\'");

      if(resultSet.next()){
        float price = resultSet.getFloat("wholesale");
        return price;
      }
      return 0;// zero means it's not stocked.
    }catch (java.sql.SQLException se) {
      throw new RuntimeException("JDBC access failed");
    }catch (javax.naming.NamingException ne){
      throw new RuntimeException("JNDI ENC access failed");
    }
  }
}


2.调用EJB
public class BookQuote_Impl_3 implements BookQuote {
  public float getBookPrice(String isbn){
    try {
      javax.naming.InitialContext jndiEnc =
                    new javax.naming.InitialContext();
      BookHomeLocal bookHome =(BookHomeLocal)
                    jndiEnc.lookup("java:comp/env/ejb/BookHomeLocal");
      BookLocal book = bookHome.findByPrimaryKey(isbn);
      return book.getWholesalePrice();
    }catch(javax.naming.NamingException ne){
      throw new RuntimeException("JNDI ENC access failed");
    }catch(java.rmi.RemoteException re){
      throw new RuntimeException("Problem invoking operation on Book EJB");
    }catch(javax.ejb.FinderException fe){
      throw new RuntimeException("Cannot find Book EJB");
    }
  }
}


3.使用JAX-RPC生成Stub调用其它的web service
public class BookQuote_Impl_4 implements BookQuote {
  public float getBookPrice(String isbn){
    try {
      javax.naming.InitialContext jndiEnc = new javax.naming.InitialContext();
      ImsCatalogService webService =(ImsCatalogService)
               jndiEnc.lookup("java:comp/env/service/ImsCatalogService");
      CatalogPort catalog = webService.getCatalogPort();
      return catalog.getWholesalePrice(isbn);
    }catch (javax.xml.rpc.ServiceException se) {
            throw new RuntimeException("JAX-RPC ServiceException thrown");
    }catch (javax.xml.rpc.JAXRPCException je) {
            throw new RuntimeException("JAXRPCException thrown");
    }catch (java.rmi.RemoteException re){
            throw new RuntimeException("RemoteException thrown");
    }catch (javax.naming.NamingException ne){
            throw new RuntimeException("NamingException thrown");
    }
  }
}


4.调用JCA等

为 方便JSE得到ServletContext和原始的SOAP消息等元信息,JAX-RPC定义了ServletEndpointContext,它是这 些元信息载体,并通过让JSE实现ServiceLifecycle来传递ServletEndpointContext。
ServiceLifeCyle定义如下:
package javax.xml.rpc.server;
import javax.xml.rpc.ServiceException;

public interface ServiceLifecycle {
    public void init(Object context) throws ServiceException;
    public void destroy();
}

其中,init方法用来传递ServletEndpoinContext,destroy方法用来给JSE释放资源。
ServletEndpointContext定义如下:
package javax.xml.rpc.server;
public interface ServletEndpointContext {
    public java.security.Principal getUserPrincipal();
    public boolean isUserInRole(String role);
    public javax.xml.rpc.handler.MessageContext getMessageContext();
    public javax.Servlet.http.HttpSession getHttpSession()
      throws javax.xml.rpc.JAXRPCException;
    public javax.Servlet.ServletContext getServletContext();
}

方 法getUserPrincipal,isUserInRole得到JAX-RPC Servlet的UserPrincipal, isUserInRole,这些方法仅适用于Web Service使用了HTTP Basic Authentication或HTTPS的情形。方法getHttpSession用于得到HttpSession。当在JSE中需要显式地处理 SOAP消息(如处理SOAP 消息头)时,可以调用方法getMessageContext得到MessageContext。
JSE支持单线程模式和多线程模式,但偏向于后者。所以,实现JSE时要注意对类成员变量访问的并发控制,或则让JSE变为无状态的。

可发Java Web Service也可以从web service定义本身入手,定义好WSDL。然后用工具生成endpoint的接口和实现的框架。为了增强不同平台的互操作性,定义WSDL的SOAP绑定时应尽量避免使用encoded。
分享到:
评论
1 楼 sojune 2007-11-02  
,不错

相关推荐

Global site tag (gtag.js) - Google Analytics