下载:WebService学习笔记.txt
Web Service
不是框架 ,也不是一种技术.
而是一种跨平台,跨语言的规范.
集中解决
远程调用
跨平台调用
跨语言调用
实际案例
同一公司,新旧系统的整合
不公司的业务整合
内容整合
CXF
Axis (Apache) -> Axis2 XFire -> XFire + Celtrix = XFC ->CXF | | | | | ---(ESB框架) | --(Web Service 框架)
SOA(面向服务的框架)
Service1,Service2,Service3 所有的组件都是"即插即用"的.
提倡的SOA架构: 希望以"组装台式电脑"的方式来开发软件.
1.各种提供服务的组件. (Web Service)
2.企业服务总线(Enterprise Service Bus , ESB)
CXF号称是SOA框架
--------------------------------
使用CXF开发Web Service服务器端
1.开发WebService业务接口
@WebService <- javax.jws. java公司提供了规范, CXF提供了框架 public interface Hello { public String sayHello(String str); }
2.开发业务的实现类
@WebService( endpointInterface = "com.memorycat.testwebservice.service.Hello", serviceName = "HelloWorld") public class HelloWorld implements Hello { @Override public String sayHello(String str) { // TODO Auto-generated method stub System.out.println("HelloWorld - sayHello"); return str + "hiiiiiiiiiiiiii"; } }
3.发布
public static void main(String[] args) { Endpoint.publish("http://127.0.0.1:70/hello", new HelloWorld()); System.out.println("发布完成"); }
4.浏览器打开
http://127.0.0.1:70/hello?wsd
------------------
使用CXF开发Web Service客户端
1.调用CXF提供的wsdl2java工具,根据wsdl文档生成响应的java代码
wsdl-Web Service Definition Language
D:\workspace_default\TestWebServiceClient\src>wsdl2java http://127.0.0.1:70/hello?wsdl
等几下,就会自动生成一堆文件
那玩意在cxf下载的zip解压后的D:\jar\cxf\apache-cxf-2.7.14\bin里,,(把这加入path就好了)
2.编写测试代码
public class Tester { public static void main(String[] args) { // TODO Auto-generated method stub HelloWorld factory=new HelloWorld(); //注意,他是个工厂. Hello hello = factory.getHelloWorldPort();//调用的他的get**Port(),返回远程WebServie的代理方法 System.out.println(hello.sayHello("MCat")); } }
-----------
参数,返回值类型
1.当形参,返回值是String,基本数据类型时,CXF可以轻松处理.
2.当形参,返回值是JavaBean式的复合类,List集合,数组等时,
CXF也可以很好的处理.
3.但有一些像Map,非JavaBean式的复合类,CXF是处理不了的.
------------
WebService的三个技术基础
WebService的三个技术基础 1.WSDL Web Service Difinition Language - Web Service 定义语言 WebService接口 1.types(标准的Schema) 2.2N的message 3.porttype --N个operation WebService实现 1.binding元素 --N个更详细的operation 2.service --指定WebService的服务器地址 2.SOAP Header(可选) 一般添加一些自定义信息,如帐号密码之类的 Body(默认) 当WebService交互正确时,Body元素里的内容由WSDL控制. 当WebService交互出错时,Body元素里的内容将是Fault子元素. 3.UDDI
-------
xml里的2个属性
targetNamespace --> java的package
targetNamespace="http://impl.service.testwebserviceserver.memorycat.com/"
xmlns --> java中的import
---------
本质
1.客户端把调用方法参数,转换生成xml文档片段(SOAP消息)
该文档必须符合wsdl定义的格式
2.通过网络把xml文档重传给服务器
3.服务器收到xml文档片段
4.服务器解释xml文档片段,提取其中的数据.
并把数据转调用WebService所需的数据的参数值
5.服务器执行
6.服务器执行方法的返回值,再次转换生成为xml文档片段
该文档必须符合wsdl定义的格式
7.通过网络把xml文档重传给客户端
8.客户端接收到xml文档片段
9.客户端解释xml文档片段,提取其中的数据.
并把数据转调用WebService所需的返回值
-------------
拦截器
服务器端
实现Interceptor接口,但是一般继承AbstractPhaseInterceptor EndpointImpl publish = (EndpointImpl) Endpoint.publish("http://127.0.0.1:70/hello", new HelloWorld()); publish.getInInterceptors().add(new LoggingInInterceptor()); 传入信封 <?xml version="1.0" ?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns2:sayHello xmlns:ns2="http://service.testwebserviceserver.memorycat.com/"> <arg0>MCat</arg0> </ns2:sayHello> </S:Body> </S:Envelope> 传出信封 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <ns2:sayHelloResponse xmlns:ns2="http://service.testwebserviceserver.memorycat.com/"> <return>MCathiiiiiiiiiiiiii</return> </ns2:sayHelloResponse> </soap:Body> </soap:Envelope>
public static void main(String[] args) { HelloWorld factory=new HelloWorld(); Hello hello = factory.getHelloWorldPort(); Client client = ClientProxy.getClient(hello); client.getInInterceptors().add(new LoggingInInterceptor()); client.getOutInterceptors().add(new LoggingOutInterceptor()); System.out.println(hello.sayHello("MCat")); } 传出信封 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <ns2:sayHello xmlns:ns2="http://service.testwebserviceserver.memorycat.com/"> <arg0>MCat</arg0> </ns2:sayHello> </soap:Body> </soap:Envelope> 传入信封 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <ns2:sayHelloResponse xmlns:ns2="http://service.testwebserviceserver.memorycat.com/"> <return>MCathiiiiiiiiiiiiii</return> </ns2:sayHelloResponse> </soap:Body> </soap:Envelope>
自定义拦截器
服务端 package com.memorycat.testwebserviceserver.service.test; import java.util.List; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.headers.Header; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.w3c.dom.Element; import org.w3c.dom.NodeList; public class MyAuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> { public MyAuthInterceptor(){ super(Phase.INVOKE); // TODO Auto-generated constructor stub } @Override public void handleMessage(SoapMessage smsg) throws Fault { // TODO Auto-generated method stub System.out.println(">>>" + smsg); List<Header> headers = smsg.getHeaders(); if (headers.size() > 0) { Header header = headers.get(0); Element element = (Element) header.getObject(); NodeList name = element.getElementsByTagName("username"); NodeList psw = element.getElementsByTagName("userpsw"); if (name.getLength() > 0 || psw.getLength() > 0) { String username = name.item(0).getTextContent(); String userpsw = psw.item(0).getTextContent(); if (username.equals("asd") && userpsw.equals("qwe")) { System.out.println("身份合法:" + username + "\t" + userpsw); } else { throw new Fault(new IllegalAccessError("身份不合法")); } } else { throw new Fault(new IllegalAccessError("缺少username或userpsw元素")); } } else { throw new Fault(new IllegalAccessError("请求参数不正确哟")); } } } 客户端 package com.memorycat.testwebserviceserver.service; import java.util.List; import javax.xml.namespace.QName; import org.apache.cxf.binding.soap.SoapMessage; import org.apache.cxf.headers.Header; import org.apache.cxf.helpers.DOMUtils; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.w3c.dom.Document; import org.w3c.dom.Element; public class MyClientAuthInterceptor extends AbstractPhaseInterceptor<SoapMessage> { public MyClientAuthInterceptor(){ super(Phase.PREPARE_SEND); // TODO Auto-generated constructor stub } @Override public void handleMessage(SoapMessage smsg) throws Fault { // TODO Auto-generated method stub List<Header> headers = smsg.getHeaders(); Document document = DOMUtils.createDocument(); Element elementAuth = document.createElement("auth"); Element elementUserName = document.createElement("username"); elementUserName.setTextContent("asd"); Element elementuserPsw = document.createElement("userpsw"); elementuserPsw.setTextContent("qwe"); elementAuth.appendChild(elementUserName); elementAuth.appendChild(elementuserPsw); /* * <auth> * <username>asd</username> * <userpsw>qwe</userpsw> * </auth> * */ headers.add(new Header(new QName("MemoryCat"), elementAuth)); } }
---------------------
CXF与Spring整合发布
1.导入CXF的Jar包 2.在web.xml配置CXF的核心控制器 CXFServlet <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>/ws/*</url-pattern> </servlet-mapping> 3.在Spring配置文件beans.xml中导入CXF的Schema,xml配置文件 <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> 注意此处的 xmlns:jaxws="http://cxf.apache.org/jaxws" http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd 还要导入一些配置 <import resource="classpath:META-INF/cxf/cxf.xml" /> <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" /> <import resource="classpath:META-INF/cxf/cxf-servlet.xml" /> 关于classpath问题 classpath 指向 WEB-INF/classes/ 还有 WEB-INF/lib/ 且优先级 lib>classes classpath 和 classpath* 区别: classpath:只会到你的class路径中查找找文件; classpath*:不仅包含class路径,还包括jar文件中(class路径)进行查找. 4.在Spring配置文件中使用jaxws:endpoint元素来暴露WebService <jaxws:endpoint address="/hello" implementor="com.memorycat.testwebserviceserver.service.impl.HelloWorld"> <!-- 如果是想引用spring中bean.这里加一个#号,如#userWebService --> </jaxws:endpoint> 5.添加拦截器 <jaxws:endpoint address="/hello" implementor="com.memorycat.testwebserviceserver.service.impl.HelloWorld"> <jaxws:inInterceptors> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor" /> <bean class="com.memorycat.testwebserviceserver.interceptor.MyAuthInterceptor" /> </jaxws:inInterceptors> <jaxws:outInterceptors> <bean class="org.apache.cxf.interceptor.LoggingOutInterceptor" /> </jaxws:outInterceptors> </jaxws:endpoint>
--------------
服务端和客户端的配置区别
服务端,其Bean是实现类 <jaxws:endpoint address="/hello" implementor="com.memorycat.testwebserviceserver.service.impl.HelloWorld"> </jaxws:endpoint> 客户端,其Bean是接口 <jaxws:client id="wsHello" serviceClass="com.memorycat.testwebserviceserver.service.Hello" address="http://127.0.0.1:8080/MySpringMVCWithWebService/ws/hello"> </jaxws:client> 调用代码 WebApplicationContext context = WebApplicationContextUtils .getWebApplicationContext(request.getSession() .getServletContext()); Hello hello = (Hello) context.getBean("wsHello"); response.getWriter().println(hello.sayHello(who)); ------- 可以注入式 @Resource(name="wsHello") Hello hello ;
工程例子,,但不含jar包 webservice例子.rar
包含2个例子
1.普通java工程整合webservice
2. springmvc整合webservice