1、什么是webservice
先来考虑一个问题,如果我们要在自己的程序里面展示天气预报,那怎么弄?正确的做法是我们发送一个请求到一个系统,他会给我们返回来天气情况。这个就是一个webservice。天气预报系统就相当于webservice的服务端,我们的系统就相当于客户端。如http://www.webxml.com.cn这个网站上面就列举了多个webservice服务站点
2、JAVA中如何调用别人发布的webservice
2.1、获取webservice的wsdl文档
2.11、什么是wsdl文档
wsdl跟java一样,也是一种语言,是通过xml的形式说明该webservice如何调用。
2.12、如何获取wsdl文档
通过在webservice的url后面加?wsdl的方式,比如天气预报的的就是http://ws.webxml.com.cn/WebServices/WeatherWS.asmx?wsdl
2.13、WSDL解析
Wsdl文档从下往上读
Types - 数据类型定义的容器,它使用某种类型系统(一般地使用XML Schema中的类型系统)。(入参和出参的数据类型)
Message - 通信消息的数据结构的抽象类型化定义。使用Types所定义的类型来定义整个消息的数据结构(入参和出参)。
Operation - 对服务中所支持的操作的抽象描述,一般单个Operation描述了一个访问入口的请求/响应消息对(方法)。
PortType - 对于某个访问入口点类型所支持的操作的抽象集合,这些操作可以由一个或多个服务访问点来支持(服务类)。
Binding - 特定服务访问点与具体服务类的绑定(不看内容,看关系)。
Port - 定义为webservice单个服务访问点。
Service- 相关服务访问点的集合。
2.2、通过wsdl文档生成客户端调用代码
2.21、使用jdk自带的命令生成
配置java环境变量后在命令窗口中输入wsimport –s . http://xxxx.xx.xx/xxx?wsdl即可生成java代码
注意:-s不能分开,-s后面有个小点,用于指定源代码生成的目录。点即当前目录。如果使用了-s参数则会在目录下生成两份代码,一份为.class代码。一份为.java代码。.class代码,可以经过打包以后使用。.java代码可以直接Copy到我们的项目中运行
2.3、生成代码后如何调用
先把生成的代码复制到项目中,然后通过读wsdl文档来调用
//wsdl文档中service的name
SayHelloIntefaceService ss = new SayHelloIntefaceService();
//wsdl文档中portType的name
SayHelloInteface shf=ss.getSayHelloIntefacePort();
//wdl文档中complexType的name
String str=shf.sayhellow("lisi");
//str即为webservice的服务端返回的信息
System.out.println(str);
3、如何发布一个webservice
Endpoint.publish("http://127.0.0.1:8080/sayHello", new SayHellowIntefaceImpl());
注意:用Jdk1.6.0_21以后的版本发布一个WebService服务.与Web服务相关的类,都位于javax.xml.ws.*包中。
主要类有:
a) @WebService - 它是一个注解,用在类上指定将此类发布成一个webservice服务.
b) Endpoint – 此类为端点服务类,它的方法publish用于将一个已经添加了@WebService注解对象绑定到一个地址的端口上。Endpoint是jdk提供的一个专门用于发布服务的类,它的publish方法接收两个参数,一个是本地的服务地址,二是提供服务的类。它位于javax.xml.ws.*包中。
static Endpoint.publish(String address, Object implementor) 在给定地址处针对指定的实现者对象创建并发布端点。stop方法用于停止服务。
其他注意事项:
1) 给类添加上@WebService注解后,类中所有的非静态方法都将会对外公布。不支持静态方法,final方法。
2) 如果希望某个方法(非static,非final)不对外公开,可以在方法上添加@WebMethod(exclude=true),阻止对外公开。
3) 如果一个类上,被添加了@WebService注解,则必须此类至少有一个可以公开的方法,否则将会启动失败。
4) 服务类中不能没有方法
5) @WebMethod(exclude=true)屏蔽方法
4、其他调用webservice的方式
4.11、 使用ajax调用
var xhr;
function invoke(){
if(window.ActiveXObject){
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}else{
xhr = new XMLHttpRequest();
}
//指定请求地址
var url = "http://127.0.0.1:7777/hello?wsdl";
//定义请求类型和地址和异步
xhr.open("POST", url, true);
//设置Content-Type
xhr.setRequestHeader("Content-Type", "text/xml;charset=UTF-8");
//指定回调方法
xhr.onreadystatechange = back;
var textVal = document.getElementById("mytext").value;
//组装消息体的数据
var data = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://server.hm.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
+'<soapenv:Body>'
+'<q0:sayHello>'
+'<arg0>'+textVal+'</arg0>'
+'</q0:sayHello>'
+'</soapenv:Body>'
+'</soapenv:Envelope>';
xhr.send(data);
}
function back(){
if(xhr.readyState == 4){
if(xhr.status == 200){
var doc = xhr.responseXML;
alert(doc);
alert(xhr.responseText);
var tag = doc.getElementsByTagName("return")[0];
alert(tag)
}
}
}
4.12、通过URLConnection调用
//创建url地址
URL url = new URL("http://192.168.1.104:8080/hello");
//打开连接
URLConnection conn = url.openConnection();
//转换成HttpURL
HttpURLConnection httpConn = (HttpURLConnection) conn;
//打开输入输出的开关
httpConn.setDoInput(true);
httpConn.setDoOutput(true);
//设置请求方式
httpConn.setRequestMethod("POST");
//设置请求的头信息
httpConn.setRequestProperty("Content-type", "text/xml;charset=UTF-8");
//拼接请求消息
String data = "<soapenv:Envelope xmlns:soapenv=" +
"\"http://schemas.xmlsoap.org/soap/envelope/\" " +
"xmlns:q0=\"http://server.rl.com/\" " +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">"
+"<soapenv:Body>"
+"<q0:sayHello>"
+"<arg0>renliang</arg0> "
+"</q0:sayHello>"
+"</soapenv:Body>"
+"</soapenv:Envelope>";
//获得输出流
OutputStream out = httpConn.getOutputStream();
//发送数据
out.write(data.getBytes());
//判断请求成功
if(httpConn.getResponseCode() == 200){
//获得输入流
InputStream in = httpConn.getInputStream();
//使用输入流的缓冲区
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuffer sb = new StringBuffer();
String line = null;
//读取输入流
while((line = reader.readLine()) != null){
sb.append(line);
}
//创建sax的读取器
SAXReader saxReader = new SAXReader();
//创建文档对象
Document doc = saxReader.read(new StringReader(sb.toString()));
//获得请求响应return元素
List<Element> eles = doc.selectNodes("//return");
for(Element ele : eles){
System.out.println(ele.getText());
}
}
4.13、使用jquery调用cxf
$(function(){
$("#mybutton").click(function(){
var data = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://server.web.cxf.rl.com/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">'
+'<soapenv:Body>'
+'<q0:sayHello>'
+' <arg0>sss</arg0>'
+' </q0:sayHello>'
+'</soapenv:Body>'
+'</soapenv:Envelope>';
$.ajax({
url:'http://localhost:8080/cxf-web-server/services/hello',
type:'post',
dataType:'xml',
contentType:'text/xml;charset=UTF-8',
data:data,
success:function(responseText){
alert($(responseText).find('return').text());
},
error:function(){
alert("error");
}
})
})
})
5、wsdl文档元素名称修改
自动生成的文档的名字有时不规范,可以手动进行修改。
@WebService(
portName=”myHelloService”,修改端口名字
serviceName=”HelloServices”,修改服务访问点集合名字
name=”HelloService”,修改服务类的名字
targetNamespace=”hello.rl.com” 修改命名空间名字
)
@WebResult(name=”sirHello”)修改返回值的元素的父标签名字
@WebParam(name=”sir”)修改传入参数的元素的父标签名字
6、CXF使用详解
说到webservice那么cxf是不得不说的一个东西
1、什么是cxf
可以理解为使用webservice的一种框架,用了cxf,可以让发布和调用更加简单并且功能丰富
2、cxf目录详解(了解)
Apache CXF = Celtix + Xfire
支持多种协议:
a) SOAP1.1,1,2
b) HTTP
c) CORBA(Common Object Request Broker Architecture公共对象请求代理体系结构,早期语言使用的WS。C,c++,C#)
d) 并可以与Spring进行快速无缝的整合
e) 灵活的部署:可以运行有Tomcat,Jboss,Jetty(内置),IBMWS,BeaWS上面。
bin(目录)
bin 目录中是 CXF 框架中所提供的代码生成、校验、管理控制台工具(可执行命令)
docs(目录)
CXF 所有类(class)对应的 API 文档,为开发者使用 CXF 完成应用开发提供应有的帮助。
etc(目录)
包含一个基本的 Service 暴露所需要的 web.xml 文件,及其它的配置文件。
lib(目录)
lib 目录中包含 CXF 及其运行时所需要的和可选的第三方支持类包(.jar 文件),可以根据不同项目所需的 CXF 特性选择所需要的支持类包。如果不想一一去区分的话,可
以直接在 Web 项目中包含所有的 CXF 及其运行时所需要的第三方支持类包(.jar 文件)即可。
其中 cxf-2.0.2-incubator.jar 是 CXF 框架的二进制包文件,包含了全部的模块(modules),cxf-manifest-incubator.jar 是列表清单文件 manifest jar 。
以下的 jar 包是所有 CXF 项目所必需的:
cxf.jar
commons-logging.jar
geronimo-activation.jar (Or the Sun equivalent)
geronimo-annotation.jar (Or the Sun equivalent)
geronimo-javamail.jar (Or the Sun equivalent)
neethi.jar
jaxb-api.jar
jaxb-impl.jar
stax-api.jar
XmlSchema.jar
wstx-asl.jar
xml-resolver.jar
对于 Java2WSDL 和 WSDL2Java,除了必需的之外,还需要再增加如下 jar 包:
jaxb-xjc.jar
veliocity.jar
velocity-dep.jar
为了支持 JAX-WS ,除了必需的之外,还需要再增加如下 jar 包:
jaxws-api.jar
saaj-api.jar
saaj-impl.jar
asm.jar (可选的,但是可以提升包装类型的性能)
为了支持 XML 配置,除了必需的之外,还需要再增加如下 jar 包:aopalliance.jar
spring-beans.jar
spring-context.jar
spring-core.jar
spring.web.jar
为了独立的 HTTP 服务支持,除了必需的之外,还需要再增加如下 jar 包:geronimo-servlet.jar
jetty.jar
jetty-sslengine.jar
jetty-util.jar
sl4j.jar & sl4j-jdk14.jar (可选的,但是可以提升日志 logging)
为了支持 Aegis ,除了必需的之外,还需要再增加如下 jar 包:
jaxen.jar
jdom.jar
stax-utils.jar
为了支持 WS-Security ,除了必需的之外,还需要再增加如下 jar 包:bcprov-jdk14.jar
wss4j.jar
xalan.jar
xmlsec.jar
为了支持 HTTP Binding ,除了必需的之外,还需要再增加如下 jar 包:jra.jar
jettison.jar (仅为 JSON 服务所需的)
licenses(目录)
列表了引用第三方 jar 包的相关许可协议。
modules(目录)
modules 目录中包含了 CXF 框架根据不同特性分开进行编译的二进制包文件。发布基于 CXF 框架的 Web 项目时,可以选择使用该目录下的所有 .jar 文件,也可以选择 lib 目 录中的 cxf-2.0.2-incubator.jar 文件。
samples(目录)
samples 目录中包含了所有随 CXF 二进制包发布的示例,包含这些示例的源代码和相关 Web 应用配置文件,可以方便地用 Ant 来编译运行测试这些示例,来了解 CXF 的开发和
使用的方法。可以通过 samples 目录和它各个子目录下的 README.txt 的文件来详细了解示例的编译与运行的步骤。
3、使用cxf发布webservice
1、把cxf目录下lib下面的包全部加入到项目中
2、编写代码
1、创建接口
@WebService
@BindingType(value=javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING)
public interface SayHelloInteface {
public String sayhellow(String name);
}
2、创建实现类
@WebService
public class SayHellowIntefaceImpl implements SayHelloInteface {
@Override
public String sayhellow(String name) {
return name+"hello world";
}
}
3、使用cxf类发布
public static void main(String[] args) {
//运行
JaxWsServerFactoryBean jwsf=new JaxWsServerFactoryBean();
//CXF拦截器
jwsf.getInInterceptors().add(new LoggingInInterceptor());
jwsf.getOutInterceptors().add(new LoggingOutInterceptor());
jwsf.setAddress("http://127.0.0.1:8080/sayHello");
jwsf.setServiceClass(SayHelloInteface.class);
jwsf.setServiceBean(new SayHellowIntefaceImpl());
jwsf.create();
}
4、使用cxf的wsdl2java命令生成客户端代码
wsdl2java –d . http://127.0.0.1:6666/helloworld?wsdl
5、调用
调用方式不变
SayHelloIntefaceService ss = new SayHelloIntefaceService();
SayHelloInteface shf=ss.getSayHelloIntefacePort();
String str=shf.sayhellow("lisi");
System.out.println(str);
6、在web项目中发布webservice
- 创建服务接口在接口上加@webservice
- 创建服务接口的实现类
在web.xml中配置CXFServlet
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>cxf</servlet-name> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>cxf</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> <session-config> <session-timeout>60</session-timeout> </session-config> </web-app>
配置cxf-servlet.xml
<jaxws:server id="bye" address="/bye" serviceClass="com.rl.cxf.web.inter.ByeInter"> <jaxws:serviceBean> <bean class="com.rl.cxf.web.inter.ByeInterImpl"></bean> </jaxws:serviceBean> <jaxws:outInterceptors> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean> </jaxws:outInterceptors> <jaxws:inInterceptors> <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean> </jaxws:inInterceptors> </jaxws:server>
- 使用wsdl2java生成客户端代码
- 调用webservice