使用javax创建webservice服务

 

什么是WebServices?
    它是一种构建应用程序的普遍模型,可以在任何支持网络通信的操作系统中实施运行;它是一种新的web应用程序分支,是自包含、自描述、模块化的应用,可以发布、定位、通过web调用。Web Service是一个应用组件,它逻辑性的为其他应用程序提供数据与服务.各应用程序通过网络协议和规定的一些标准数据格式(Http,XML,Soap)来访问Web Service,通过Web Service内部执行得到所需结果.Web Service可以执行从简单的请求到复杂商务处理的任何功能。一旦部署以后,其他Web Service应用程序可以发现并调用它部署的服务。
关键的技术和规则
   在构建和使用Web Service时,主要用到以下几个关键的技术和规则:
  1.XML:描述数据的标准方法.
  2.SOAP:表示信息交换的协议.
  3.WSDL:Web服务描述语言.
   4.UDDI:通用描述、发现与集成,它是一种独立于平台的,基于XML语言的用于在互联网上描述商务的协议。
   XML
   可扩展的标记语言(XML)是Web service平台中表示数据的基本格式。除了易于建立和易于分析外,XML主要的优点在于它既是平台无关的,又是厂商无关的。无关性是比技术优越性更重要的:软件厂商是不会选择一个由竞争对手所发明的技术的。
   SOAP
   SOAP是web service的标准通信协议,SOAP为simple object access protocoll的缩写,简单对象访问协议. 它是一种标准化的传输消息的XML消息格式。
   WSDL
   WSDL的全称是web service Description Language,是一种基于XML格式的关于web服务的描述语言。其主要目的在于web service的提供者将自己的web服务的所有相关内容,如所提供的服务的传输方式,服务方法接口,接口参数,服务路径等,生成相应的完全文档,发布给使用者。使用者可以通过这个WSDL文档,创建相应的SOAP请求消息,通过HTTP传递给webservice提供者;web服务在完成服务请求后,将SOAP返回消息传回请求者,服务请求者再根据WSDL文档将SOAP返回消息解析成自己能够理解的内容。
   UDDI
   将web service进行UDDI注册发布,UDDI是一种创建注册表服务的规范,以便大家将自己的web service进行注册发布供使用者查找.然而当服务提供者想将自己的web service向全世界公布,以便外部找到其服务时,那么服务提供者可以将自己的web service注册到相应的UDDI商用注册网站,目前全球有IBM等4家UDDI商用注册网站。因为WSDL文件中已经给定了web service的地址URI,外部可以直接通过WSDL提供的URI进行相应的web service调用。所以UDDI并不是一个必需的web service组件,服务方完全可以不进行UDDI的注册。
签于webservice开发C/S或B/S结构中的重要性,一直在研究其原理。本章主要讲述使用JDK自带的javax扩展包创建webservice服务的过程。我们创建通用性高的web服务接口时一般采取java基础类型来作为参数传递和返回,比如string,byte[],int等。string多采用XML格式来进行规范化交互,byte[]常用来进行二进制的处理,这样使用web service可以做很多设计了。
我们提供一个范式的服务器端代码:
import  javax.annotation.Resource;
import  javax.jws.WebMethod;
import  javax.jws.WebParam;
import  javax.jws.WebResult;
import  javax.jws.WebService;
import  javax.jws.soap.SOAPBinding;
import  javax.xml.ws.WebServiceContext;
 
import  com.sun.net.httpserver.HttpExchange;
import  com.ue.dto.CrackBean;
import  com.ue.server.CrackControl;
import  com.ue.util.ConvertUtils;
@WebService  (name =  "client"   , targetNamespace =  "http://ws.ue.com" , serviceName =  "client"   )
@SOAPBinding  (style =  SOAPBinding   .Style.  RPC )
public   class   CrackClientImp  implements  CrackClient
{
         @Resource
         private  WebServiceContext  wsContext   ;
 
         private  String getIp()
      {
            HttpExchange exchange = (HttpExchange)  wsContext  .getMessageContext().get( "com.sun.xml.internal.ws.http.exchange"   );
            String remortAddress = exchange.getRemoteAddress().getAddress().getHostAddress();
               return  remortAddress;
      }
         // 获得破解开
         @WebMethod  (operationName =  "getCrack"   , action =  "getCrack" , exclude =  false  )
         @WebResult  (name =  "returnWord"   )
         public   byte   [] getCrack ()
      {
               byte  [] defaultvalue =  ""   .getBytes();
               byte  [] code =  null ;
            
            CrackControl c = CrackControl. getInstance();
            CrackBean bean = c.take();
               if  (bean !=  null )
            {
                     byte  [] name = bean.getTypeName().getBytes();
                     byte  [] pack = ConvertUtils.intToBytes4(name.   length  );
                     byte  [] content = bean.getContent();
                  code =  new   byte   [content.  length  + pack.   length  + name. length  ];
                  System. arraycopy(pack, 0, code, 0, pack.  length );
                  System. arraycopy(name, 0, code, pack.  length , name. length  );
                  System. arraycopy(content, 0, code, pack.  length  + name. length  , content. length   );
            }
               if  (code==  null ){
                     //throw new RuntimeException("Exception in getCrack()");
                  code = defaultvalue;                
            }
               return  code;
      }
         // 获得破解开
         @WebMethod  (operationName =  "crack"   , action =  "crack" , exclude =  false  )
         public   void   crack ( @WebParam   (partName =  "id" )
      String id,  @WebParam  (partName =  "crackValue"   )
      String crackValue)
      {
            CrackControl c = CrackControl. getInstance();
            c.setCrackCode(id, crackValue);
      }
         // 获得破解开
         @WebMethod  (operationName =  "unCrack"   , action =  "unCrack" , exclude =  false  )
         public   void   unCrack ( @WebParam   (partName =  "id" )
      String id)
      {
            CrackControl c = CrackControl. getInstance();
            c.unCrack(id);
      }
         @WebMethod  (operationName =  "getPackLength"   , action =  "getPackLength"   , exclude =  false )
         @WebResult  (name =  "returnWord"   )
         public   int   getPackLength ( @WebParam   (partName =  "p" )
         byte  [] p)
      {
               int  value = 0;
               if  (p. length   >= 4)
            {
                     byte  [] bytes =  new   byte [4];
                  System. arraycopy(p, 0, bytes, 0, 4);
                  value = ConvertUtils. byteToInt(bytes);
            }
               return  value;
      }
}
public   class   Server
{
         public   static   void  main(String[] args)  throws  IOException   {             
            CrackServerImp server =  new  CrackServerImp();
               /*
             * 发布Web Service
             */
            String ip = InetAddress. getLocalHost().getHostAddress();
            Endpoint clientEndpoint = Endpoint. publish(  "http://"  + ip +  ":7000/client"   , server   );
            Binding clientBinding = clientEndpoint.getBinding();
            List<Handler> clientHandlerChain =  new  LinkedList<Handler>();
            clientHandlerChain.add(   new  ClientTraceHandler());
            clientBinding. setHandlerChain(clientHandlerChain);
 }
}
Annotation 1:@WebService(name="client", targetNamespace="http://ws.ue.com", serviceName="client")
@WebService标签主要将类暴露为WebService,其中targetNamespace属性定义了自己的命名空间,serviceName则定义了< definitions >标签和<service>标签的name属性。
 
Annotation 2:@SOAPBinding(style=SOAPBinding.Style.RPC)
@SOAPBinding标签定义了WSDL文档中SOAP的消息协议,其中style属性对应SOAP的文档类型,可选的有RPC和DOCUMENT
 
Annotation 3:@WebMethod(operationName="getCrack",action="getCrack",exclude=false)
@WebMethod定义Web Service运作的方法,
属性action 对应操作的活动 ,如<soap:operation soapAction="getCrack" />
属性operationName匹配的wsdl:operation 的名称,如<operation name="getCrack" parameterOrder="userName">
属性exclude 用于阻止将某一继承方法公开为web服务,默认为false
 
Annotation 4:@WebResult(name="returnWord")
@ WebResult定义方法返回值得名称,如<part name="returnWord" type="xsd:string" />
在产生的WSDL文档中,message元素反映了这个变化:
 
<message name="getTimeAsString"/>
<message name="getTimeAsStringResponse">
    <part name="time_response" type="xsd:string"/>
</message>
<message name="getTimeAsElased"/>
<message name="getTimeAsElasedResponse">
    <part name="time_response" type="xsd:long"/>
</message>
 
没有添加@WebResult注解之前,WSDL文档中,message元素是这样的:
 
<message name="getTimeAsString"/>
<message name="getTimeAsStringResponse">
    <part name="return" type="xsd:string"/>
</message>
<message name="getTimeAsElased"/>
<message name="getTimeAsElasedResponse">
    <part name="return" type="xsd:long"/>
</message> 
两个message元素对比,我们可以看出,return标签被换成了time_response,也就是@WebResult注解定义的。在从web服务返回的SOAP消息中也同样反映出了这点变化,以调用getTimeAsString服务方法为例: 
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns2:getTimeAsStringResponse xmlns:ns2="http://ts.ch01/">
            <time_response>Mon Mar 17 10:41:13 CST 2014</time_response>
        </ns2:getTimeAsStringResponse>
    </S:Body>
</S:Envelope>
没有添加@WebResult注解时,SOAP消息返回是这样的: 
<?xml version="1.0" ?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns2:getTimeAsStringResponse xmlns:ns2="http://ts.ch01/">
            <return>Mon Mar 17 10:46:30 CST 2014</return>
        </ns2:getTimeAsStringResponse>
    </S:Body>
</S:Envelope> 
从SOAP消息对比中,我们也可以看到,return标签也相应地被替换成了time_response标签。假设我们只对getTimeAsString增加@WebResult注解,那么返回的SOAP消息中针对该服务操作使用time_response标签,而针对getTimeAsElapsed服务操作所返回的SOAP消息中仍然使用默认的return标签。
Annotation 5:@WebParam(partName="person", mode=Mode.IN
@WebParam定义方法的参数名称,如<part name="person" type="tns:person" />,其中mode属性表示参数的流向,可选值有IN / OUT / INOUT
 
我们提供一个范式的客户器端代码:
import  java.net.MalformedURLException;
import  java.net.URL;
import  javax.xml.namespace.QName;
import  javax.xml.ws.Service;
import  javax.xml.ws.WebEndpoint;
import  javax.xml.ws.WebServiceClient;
 
@WebServiceClient  (name =  "client"   , targetNamespace =  "http://ws.ue.com" , wsdlLocation =  "http://10.0.108.194:7000/client?wsdl"   )
public   class   ClientService  extends  Service
{
 
         private   final   static  URL  CLIENT_WSDL_LOCATION ;
 
         static
      {
            URL url =  null  ;
               try
            {
                  url =  new  URL( "http://10.0.108.194:7000/client?wsdl"   );
            }
               catch  (MalformedURLException e)
            {
                  e.printStackTrace();
            }
               CLIENT_WSDL_LOCATION   = url;
      }
 
         public  ClientService(URL wsdlLocation, QName serviceName)
      {
               super  (wsdlLocation, serviceName);
      }
 
         public  ClientService()
      {
               super  (  CLIENT_WSDL_LOCATION ,  new  QName(   "http://ws.ue.com"  ,  "client"  ));
      }
 
         /**
        *
        *   @return   returns   Client
        */
         @WebEndpoint  (name =  "clientPort"   )
         public  Client getClientPort()
      {
               return  (Client)  super .getPort(  new  QName(   "http://ws.ue.com"  ,  "clientPort"  ), Client.  class );
      }
}
 
import  javax.jws.WebMethod;
import  javax.jws.WebParam;
import  javax.jws.WebResult;
import  javax.jws.WebService;
import  javax.jws.soap.SOAPBinding;
 
 
@WebService  (name =  "client"   , targetNamespace =  "http://ws.ue.com" , serviceName =  "client"   )
@SOAPBinding  (style =  SOAPBinding   .Style.  RPC )
public   interface   Client
{
         // 获得破解开
         @WebMethod   (operationName =  "getCrack" , action =  "getCrack"  , exclude =  false  )
         @WebResult  (name =  "returnWord"   )
         public   byte   [] getCrack();
 
         // 获得破解开
         @WebMethod   (operationName =  "crack" , action =  "crack"  , exclude =  false  )
         public   void   crack(  @WebParam (partName =  "id"  )
      String id,  @WebParam  (partName =  "crackValue"   )
      String crackValue);
 
         @WebMethod   (operationName =  "getPackLength" , action =  "getPackLength"   , exclude =  false )
         @WebResult  (name =  "returnWord"   )
         public   int   getPackLength(  @WebParam (partName =  "p"  )
         byte  [] p);
 
         // 不填了
         @WebMethod   (operationName =  "unCrack" , action =  "unCrack"  , exclude =  false  )
         public   void   unCrack(  @WebParam (partName =  "id"  )
      String id);
}
 
import  com.ue.dto.CrackBean;
import  com.ue.ws.client.Client;
import  com.ue.ws.client.ClientService;
import  com.ue.ws.client.HandlerResolverImp;
 
public   class   TestClient
{
         public   static   void  main(String[] args)
      {
            ClientService cs =  new  ClientService();
            HandlerResolver hr =  new  HandlerResolverImp( "ue"   ,  "ue123456"  );
            cs.setHandlerResolver(hr);
            Client c = cs.getClientPort();              
               byte  [] bytes = c.getCrack();
               byte  [] p =  new   byte [4];
            System. arraycopy(bytes, 0, p, 0, 4);
            
               int  cl = c.getPackLength(p);       
               byte  [] typeName =  new   byte [cl];
            System. arraycopy(bytes, 4, typeName, 0, cl);             
            
               byte  [] content =  new   byte [bytes.   length  -cl-4];
            System. arraycopy(bytes, cl+4, content, 0, content.   length  );
            
            CrackBean cb =  new  CrackBean(  new  String(typeName),content);
            System.   out  .println(cb.getTypeName());
      }
}
 
当然我们完全可以使用Xfire搭建基于B/S架构的web service,这个在之前的文章中已经有讲述。javax的好处是完全脱离servlet容器的支持,我们就可以搭建非web体系的服务,有时候我们选择这样做或许更好。

 

你可能感兴趣的:(webservice)