webservice:学习总结

Table of Contents

一、webservice定义

二、wsdl 解析

三、webservice服务端发布

1 通过jdk自带的发布

2 通过工具cxf 发布

1 ServerFactoryBean 发布服务

2 JaxWsServerFactoryBean 发布

四、webservice 客户端调用  

1 wsimport 调用

2 URLConnection

3  client 调用

4 ajax 调用

五、wsimport 和cxf生成客户端代码

方式一:wsimport

方式二:  cxf


一、webservice定义

就是基于Web的服务。它使用Web(HTTP)方式,接收和响应外部系统的某种请求。从而实现远程调用.

 

名词1:XML. Extensible Markup Language -扩展性标记语言 XML,用于传输格式化的数据,是Web服务的基础。 namespace-命名空间。 xmlns=“http://itcast.cn” 使用默认命名空间。 xmlns:itcast=“http://itcast.cn”使用指定名称的命名空间。

名词2:WSDL – WebService Description Language – Web服务描述语言。 通过XML形式说明服务在什么地方-地址。 通过XML形式说明服务提供什么样的方法 – 如何调用。

名词3:SOAP-Simple Object Access Protocol(简单对象访问协议) SOAP作为一个基于XML语言的协议用于有网上传输数据。 SOAP = 在HTTP的基础上+XML数据。 SOAP是基于HTTP的。 SOAP的组成如下: Envelope – 必须的部分。以XML的根元素出现。 Headers – 可选的。 Body – 必须的。在body部分,包含要执行的服务器的方法。和发送到服务器的数据。

WebService的特点 WebService通过HTTP POST方式接受客户的请求 WebService与客户端之间一般使用SOAP协议传输XML数据. 它本身就是为了跨平台或跨语言而设计的。

 

WebService的注解包括:

@WebService-定义服务   --类上

@WebMethod-定义方法   - 方法

@WebResult-定义返回值 – 返回值

@WebParam-定义参数 – 参数

*************************************************************************************************************************************************

二、wsdl 解析

targetNamespace:相当于是java中的包。有些可以有import就是因为这个不痛
xmlns:命名空间
types元素:该元素就是标准的schema文档,一个方法有2个message:一个请求一个返回
portType :包含wsdl:operation 的就是方法

binding :包含了operation子元素。
service :service包含port子元素,绑定的地址和服务名

简单理解:

service:类

binding:接口

portType:方法

message:参数  fault是属于抛出的异常

 

wsdl:说明服务在哪里,如何调用,其实就是一个使用说明书:

 理解WSDL文档的意义

 

soap:请求数据 

soap响应数据 

*************************************************************************************************************************************************

三、webservice服务端发布

***添加拦截器

//        Endpoint.publish("http://192.168.1.113:6789/hello",new HelloServer());
        EndpointImpl publish = (EndpointImpl) Endpoint.publish("http://192.168.71.1:6789/hello", new HelloServer());
        publish.getOutInterceptors().add(new LoggingOutInterceptor(new PrintWriter(new FileWriter("out.txt"))));
        publish.getInInterceptors().add(new LoggingInInterceptor(new PrintWriter(new FileWriter("in.txt"))));
        System.out.println("添加拦截器成功");

 

1 通过jdk自带的发布

       在类上添加@WebService注解。

       这是jdk1.6提供的一个注解。它位于:javax.jws.*包中。

   @BindingType(value = SOAPBinding.SOAP12HTTP_BINDING)  jdk默认支持soap1.1,加上注解可以支持soap1.2

      通过EndPoint(端点服务)发布一个webService。

       Endpoint也是jdk提供的一个专门用于发布服务的类,它的publish方法接收两个参数,一个是本地的服务地址,二是提供服务的类。它位于javax.xml.ws.*包中。 static Endpoint.publish(String address, Object implementor) 在给定地址处针对指定的实现者对象创建并发布端点。

       stop方法用于停止服务。

       EndPoint发布完成服务以后,将会独立的线程运行。所以,publish之后的代码,可以正常执行。

      其他注意事项: 给类添加上@WebService注解后,类中所有的非静态方法都将会对外公布。 不支持静态方法,final方法。

   如果希望某个方法(非static,非final)不对外公开,可以在方法上添加@WebMethod(exclude=true),阻止对外公开。 如果一个类  上,被添加了@WebService注解,则必须此类至少有一个可以公开的方法,否则将会启动失败。

 

WebService只采用HTTP POST方式传输数据,不使用GET方式;  -- 握手,WSDL-get,

普通http post的contentType为 application/x-www-form-urlencoded

WebService的contentType为-即在Http的基础上发SOAP协议 text/xml 这是基于soap1.1协议。 application/soap+xml 这是基于soap1.2协议。

SOAP1.1和SOAP1.2的 namespace不一样。可以通过查看类 javax.xml.ws.soap.SOAPBinding来查看里面的常量 默认情况下,Jdk1.6只支持soap1.1 即:@BindingType(value=javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING)


import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;

/**

 使用JDK发布方式
 * @version:
 */

@WebService(serviceName = "HelloServer",targetNamespace = "http://server.yubin.com.cn/")
public class HelloServer {

    @WebMethod(operationName = "sayHello")
    @WebResult(name = "myreturn")
    public String sayHello(@WebParam(name = "argNum1") String name) {
        System.out.println("helloServer...sayHello()");
        return "hello:"+name;
    }

    public String sayHello2(String name) {
        System.out.println("helloServer...sayHello2()");
        return "hello2:"+name;
    }

    public static void main(String[] args) {
        System.out.println("发布服务:http://192.168.1.113:6789/hello.wsdl");
        //        Endpoint.publish("http://192.168.1.113:6789/hello",new HelloServer());
        EndpointImpl publish = (EndpointImpl) Endpoint.publish("http://192.168.71.1:6789/hello", new HelloServer());
        publish.getOutInterceptors().add(new LoggingOutInterceptor(new PrintWriter(new FileWriter("out.txt"))));
        publish.getInInterceptors().add(new LoggingInInterceptor(new PrintWriter(new FileWriter("in.txt"))));
        System.out.println("添加拦截器成功");
    }

}

 

2 通过工具cxf 发布

用两个不同的类发布应用:

ServerFactoryBean   --FacotryBean

JaxWsServerFactoryBean(建议使用此类)

 

        使用ServerFactoryBean发布服务。 使用CXF发布一个服务,与JDK6发布一个服务完全不同 * 即使是不使用@WebService注解,一样可以发布成功 * 即使此类没有对外公布的方法一样可以发布成功

          JaxWsServerFactoryBean是ServerFactoryBean的子类,也是功能扩展类。 但在CXF的API文档中没有提供此类API,请通过查看源代码的方式获取此类的帮助。 此类,必须要在被发布为服务的类上添加@WebService注解,如果不加注解,虽然不 出错,但也不会对外暴露任何方法。       使用此类生成的wsdl文件更加规范。 以下是从它的源代码中找到的对此类的说明。

使用ServerFactoryBean发布服务以后,在没有接口的情况下,可以使用wsimport生成的客户端代码调用成功。 但如果要使用ClientProxyFactoryBean客户端去调用服务器,则必须要先在服务器端创建一个接口。(一直以来,Spring都要求面向接口编程,而cxf与Spring能很好的整合,也就在此。),所以,必须要重写服务器端的代码。这将导致刚才使用wsimport生成的调用代码失效。 同时, ClientProxyFactoryBean由于要用到CXF环境,所以要导入CXF的所有包。 同时,如果是在本项目中调用,则可以直接使用本项目的接口。 如果在其他项目中调用,仍然需wsimport生成的类,但只需要一个接口。 

 

 

1 ServerFactoryBean 发布服务

public interface IHelloServerCXF {
    public String sayHello(String name);
}



/**
 ServerFactoryBean

 使用ServerFactoryBean发布CXF的Web服务


 规范的做法应该是先书写一个接口
 bean.setServiceBean(new HiService()); 这里提供服务的类型如果是接口@WebService那么注解就应该用在接口上
 */

public class HelloServerCXF implements IHelloServerCXF {

    public String sayHello(String name){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(sdf.format(new Date()) +"sayHello()... name:" + name);
        return sdf.format(new Date()) + " hello " + name;
    }

    //使用ServerFactoryBean发布CXF的Web服务
    public static void main(String[] args) {
        ServerFactoryBean bean = new ServerFactoryBean();

        bean.getInInterceptors().add(new LoggingInInterceptor());
        bean.getOutInterceptors().add(new LoggingOutInterceptor());

        //服务的发布地址
//        bean.setAddress("http://192.168.1.113:6789/hello");
        bean.setAddress("http://192.168.0.213:6789/hello");
        //提供服务的类的类型
        bean.setServiceClass(IHelloServerCXF.class);
        //提供服务的实例
        bean.setServiceBean(new HelloServerCXF());
        //发布服务  publish()...
        bean.create();
        System.out.println("server ready...");

    }

}

调用ClientProxyFactoryBean

&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

 

 

2 JaxWsServerFactoryBean 发布

@WebService
public interface IHelloServerCXFJaxWs {
    public String sayHi(String name);
}


/**
 ** 使用JaxWsServerFactoryBean发布CXF的Web服务
 *  * 必须加入WebService注解,如果不加,虽然不报错,但是所有的方法都暴露不出来
 */


public class HelloServerCXFJaxWS implements IHelloServerCXFJaxWs{

    public String sayHi(String name){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("sayHi()... name:" + name);
        return sdf.format(new Date()) + " hi " + name;
    }

    public static void main(String[] args) {
        JaxWsServerFactoryBean bean = new JaxWsServerFactoryBean();
        //服务的地址
        bean.setAddress("http://192.168.1.113:6786/hi");
        //提供服务的类的类型
        bean.setServiceClass(HelloServerCXFJaxWS.class);
        //提供服务的实例
        bean.setServiceBean(new HelloServerCXFJaxWS());
        //发布服务  publish()...
        bean.create();
        System.out.println("server ready...");
    }
}

 

 调用:JaxWsProxyFactoryBean

 

*************************************************************************************************************************************************

 

四、webservice 客户端调用  

1 wsimport 调用

调用的就是看wsdl描述文档:wsdl:service name="HelloServer"  ,
 就需要去找客户端生成的代码中哪个是继承server类的,然后new出来,调用其中的getxxxPort方法返回一个接口类( name="HelloServer")

//客户端添加拦截器
Client client = ClientProxy.getClient(port);
client.getOutInterceptors().add(new LoggingOutInterceptor());
client.getInInterceptors().add(new LoggingInInterceptor());

 

 

/**
*调用的就是看wsdl描述文档:wsdl:service name="HelloServer"  ,
 *就需要去找客户端生成的代码中哪个是继承server类的,然后new出来,调用其中的getxxxPort方法**返回一个接口类( name="HelloServer")
*/
public class Application_Client {

    public static void main(String[] args) {
        HelloServerService helloServerService = new HelloServerService();
        HelloServer port = helloServerService.getHelloServerPort();

        //客户端添加拦截器
        Client client = ClientProxy.getClient(port);
        client.getOutInterceptors().add(new LoggingOutInterceptor());
        client.getInInterceptors().add(new LoggingInInterceptor());

        String s = port.sayHello("张三");
        System.out.println(s);
    }
}

2 URLConnection

 

public static void main(String[] args) throws Exception {
        //获取服务地址
        URL url = new URL("http://192.168.1.113:6789/hello");

        //
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        connection.setDoInput(true);
        connection.setDoOutput(true);
        connection.setRequestProperty("Content-Type","text/xml;charset=UTF-8");
        connection.setRequestMethod("POST");
        OutputStream stream = connection.getOutputStream();

        String soap ="<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ser=\"http://server.yubin.com/\">"+
                "<soapenv:Header/><soapenv:Body> <ser:sayHello> <arg0>aaa</arg0></ser:sayHello></soapenv:Body></soapenv:Envelope>";
        stream.write(soap.getBytes());

        InputStream inputStream = connection.getInputStream();

        byte[] b = new byte[1024];
        int len = 0;
        String s = "";
        while((len = inputStream.read(b)) != -1) {
            String ss =  new String(b,0,len,"UTF-8");
            s += ss;

        }

        System.out.println(s);
        inputStream.close();
        stream.close();
        connection.disconnect();



    }

3  client 调用

public static void main(String[] args) throws Exception {

        URL url = new URL("http://192.168.1.113:6789/hello?wsdl");
        Service s = Service.create(url,new QName("http://server.yubin.com/","HelloServerService"));
        HelloServer server = s.getPort(new QName("http://server.yubin.com/", "HelloServerPort"), HelloServer.class);

        String res = server.sayHello("ceshi");
        System.out.println(res);
    }

4 ajax 调用

var xhr = null;
			if(window.XMLHttpRequest) {
				xhr = new XMLHttpRequest();
			}else {
				xhr = new ActiveXObject("Microsoft.XMLHTTP");
			}
			
		
			function sendMsg(){
				var name = document.getElementById('name').value;
			
				var wsUrl = 'http://192.168.1.113:6789/hello';
				
				
				var soap = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://server.yubin.com/">' + 
									 '<soapenv:Header/><soapenv:Body> <ser:sayHello> <arg0>'+name+'</arg0></ser:sayHello></soapenv:Body></soapenv:Envelope>';
						
					
				
				xhr.open('POST',wsUrl,true);
				
	
				xhr.setRequestHeader("Content-Type","text/xml;charset=UTF-8");
				
				
				xhr.onreadystatechange = _back;
				
				
				xhr.send(soap);
			}
			
			function _back(){
				if(xhr.readyState == 4){
					if(xhr.status == 200){
							
							var ret = xhr.responseXML;
							var msg = ret.getElementsByTagName('return')[0];
							document.getElementById('showInfo').innerHTML = msg.text;
							
						}
				}
			}

 

 

 

 

五、wsimport 和cxf生成客户端代码

方式一:wsimport

获取webservice的wsdl文件
输入命令:wsimport unifiedOrder.wsdl -keep -p wy.soap.order -s d:/mytest就可以生成代码到mytest目录下

-keep		keepgenerated files

-p 		生成的包名

-s		指定产生代码所在的目录

或者直接从url生成
wsimport -d generated http://esample.org/sock?wskl


-b:	指定绑定文件或者附加模式
-B:	将此选项传递给jaxb模式编辑器
-catalog:	指定用于解析外部实体引用的目录文件
-encoding	指定源文件所使用的字符编码
-extension	允许供应商扩展,不按照规范指定功能,使用扩展可能会导致程序不可移植或无法实现其他进行互相
-help		显示帮助
-keep		保留生成的文件
-p		指定目标程序包
-quiet		隐藏wsimport输出
-httpproxy:<host>:<port> 指定http代码服务器,端口默认8080



***********************************
用法: wsimport [options] <WSDL_URI>

\其中 [options] 包括:
  -b <path>                 指定 jaxws/jaxb 绑定文件或附加模式
                            (每个 <path> 都必须具有自己的 -b)
  -B<jaxbOption>            将此选项传递给 JAXB 模式编译器
  -catalog <file>           指定用于解析外部实体引用的目录文件
                            支持 TR9401, XCatalog 和 OASIS XML 目录格式。
  -d <directory>            指定放置生成的输出文件的位置  只有class文件
  -encoding <encoding>      指定源文件所使用的字符编码
  -extension                允许供应商扩展 - 不按规范
                            指定功能。使用扩展可能会
                            导致应用程序不可移植或
                            无法与其他实现进行互操作
  -help                     显示帮助
  -httpproxy:<host>:<port>  指定 HTTP 代理服务器 (端口默认为 8080)
  -keep                     保留生成的文件
  -p <pkg>                  指定目标程序包
  -quiet                    隐藏 wsimport 输出
  -s <directory>            指定放置生成的源文件的位置
  -target <version>         按给定的 JAXWS 规范版本生成代码
                            默认为 2.2, 接受的值为 2.0, 2.1 和 2.2
                            例如, 2.0 将为 JAXWS 2.0 规范生成兼容的代码
  -verbose                  有关编译器在执行什么操作的输出消息
  -version                  输出版本信息
  -wsdllocation <location>  @WebServiceClient.wsdlLocation 值
  -clientjar <jarfile>      创建生成的 Artifact 的 jar 文件以及
                            调用 Web 服务所需的 WSDL 元数据。
  -generateJWS              生成存根 JWS 实现文件
  -implDestDir <directory>  指定生成 JWS 实现文件的位置
  -implServiceName <name>   生成的 JWS 实现的服务名的本地部分
  -implPortName <name>      生成的 JWS 实现的端口名的本地部分

\扩展:
  -XadditionalHeaders              映射标头不绑定到请求或响应消息不绑定到
                                   Java 方法参数
  -Xauthfile                       用于传送以下格式的授权信息的文件:
                                   http://username:password@example.org/stock?wsdl
  -Xdebug                          输出调试信息
  -Xno-addressing-databinding      允许 W3C EndpointReferenceType 到 Java 的绑定
  -Xnocompile                      不编译生成的 Java 文件
  -XdisableAuthenticator           禁用由 JAX-WS RI 使用的验证程序,
                                   将忽略 -Xauthfile 选项 (如果设置)
  -XdisableSSLHostnameVerification 在提取 wsdl 时禁用 SSL 主机名
                                   验证

\示例:
  wsimport stock.wsdl -b stock.xml -b stock.xjb
  wsimport -d generated http://example.org/stock?wsdl

 

 

方式二:  cxf

生成客户端程序。利用cxf插件直接生成wsdl2java命令
wsdl2java -p com -d src -encoding utf-8 -all wsdl

-p:指定wsdl命名空间,也就是要生成的包名

-d:指定要产生代码所在的目录

-client:生成客户端测试web service代码

-server:生成服务器启动web service代码

-impl:生成web service的实现代码

-ant: 生成build.xml文件

-all: 生成所有有开始端点代码

-b:	指定绑定文件或者附加模式

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值