4.2. WebService请求深入分析
1). 分析WebService的WSDL文档结构
1.1). 实例截图
<definitions>
<types>
<schema>
<element>
<message>
<portType>
<operation>
<input>
<output>
<binding>
<operation>
<input>
<output>
<service>
<port>
binding属性
<address>
1.2). 文档结构
<definitions>
<types>
<schema>
<element>
</types>
<message>
<part>
</message>
<portType>
<operation>
<input>
<output>
</portType>
<binding>
<operation>
<input>
<output>
</binding>
<service>
<port>
<address>
</service>
</definitions>
1.3). 文档结构图
1.4). 重要标签的说明
-
types - 数据类型(标签)定义的容器,里面使用schema
- 定义了一些标签结构供message引用
- 定义了一些标签结构供message引用
-
message - 通信消息的数据结构的抽象类型化定义。
-
引用types中定义的标签
-
引用types中定义的标签
-
operation - 对服务中所支持的操作的抽象描述,
- 一个operation描述了一个访问入口的请求消息与响应消息对。
- 一个operation描述了一个访问入口的请求消息与响应消息对。
-
portType - 对于某个访问入口点类型所支持的操作的抽象集合,
-
这些操作可以由一个或多个服务访问点来支持。
-
这些操作可以由一个或多个服务访问点来支持。
-
binding - 特定端口类型的具体协议和数据格式规范的绑定。
-
service- 相关服务访问点的集合
- port - 定义为协议/数据格式绑定与具体Web访问地址组合的单个服务访问点。
2). 测试CXF支持的数据类型
- 基本类型
– int,float,boolean等
- 引用类型
– String
– 集合:数组,List, Set, Map
– 自定义类型 Student
Jdk:不支持 map.
3). 一次Web service请求的流程
一次web service请求的本质:
1)客户端向服务器端发送了一个soap消息(http请求+xml片断)
2) 服务器端处理完请求后, 向客户端返回一个soap消息
那么它的流程是怎样的呢?
4.3. CXF框架的深入使用
1).CXF的拦截器
1.1) 理解
- 为什么设计拦截器?
- 为了在webservice请求过程中,能动态操作请求和响应数据, CXF设计了拦截器.
- 拦截器分类:
- 按所处的位置分:服务器端拦截器,客户端拦截器
- 按消息的方向分:入拦截器,出拦截器
- 按定义者分:系统拦截器,自定义拦截器
- 拦截器API
Interceptor(拦截器接口)
AbstractPhaseInterceptor(自定义拦截器从此继承)
LoggingInInterceptor(系统日志入拦截器类)
LoggingOutInterceptor(系统日志出拦截器类)
1.2) 编码实现拦截器
- 使用日志拦截器,实现日志记录
– LoggingInInterceptor
– LoggingOutInterceptor
- 使用自定义拦截器,实现用户名与密码的检验
– 服务器端的in拦截器
– 客户端的out拦截器
1 服务端: 2 public class CheckUserInterceptor extends AbstractPhaseInterceptor<SoapMessage> { 3 4 public CheckUserInterceptor() { 5 super(Phase.PRE_PROTOCOL); 6 } 7 8 @Override 9 public void handleMessage(SoapMessage msg) throws Fault { 10 Header header = msg.getHeader(new QName("thecheck")); 11 if(header != null){ 12 Element chenkEle = (Element) header.getObject(); 13 String username = chenkEle.getElementsByTagName("username").item(0).getTextContent(); 14 String password = chenkEle.getElementsByTagName("password").item(0).getTextContent(); 15 16 if("ymmm".equals(username) && "123456".equals(password)){ 17 System.out.println("Client de "+username+" 通过了 服务器的检查"); 18 return; 19 } 20 } 21 System.out.println("client 没有通过拦截器检查"); 22 23 throw new Fault(new RuntimeException("请输入正确的用户名和密码!!!")); 24 25 } 26 27 } 28 29 30 客户端: 31 public class AddUserInterceptor extends AbstractPhaseInterceptor<SoapMessage> { 32 private String username; 33 private String password; 34 35 public AddUserInterceptor(String username , String password) { 36 super(Phase.PRE_PROTOCOL); 37 this.username = username; 38 this.password = password; 39 } 40 /* 41 <Envelope> 42 <head> 43 <chenkEle> 44 <name>xfzhang</name> 45 <password>123456</password> 46 </chenkEle> 47 <chenkEle2> 48 <name>xfzhang</name> 49 <password>123456</password> 50 </chenkEle2> 51 <head> 52 <Body> 53 <sayHello> 54 <arg0>BOB</arg0> 55 <sayHello> 56 </Body> 57 </Envelope> 58 */ 59 60 @Override 61 public void handleMessage(SoapMessage msg) throws Fault { 62 List<Header> list = msg.getHeaders(); 63 64 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 65 Document document; 66 try { 67 document = factory.newDocumentBuilder().newDocument(); 68 69 Element chenkEle = document.createElement("thecheck"); 70 71 Element usernameEle = document.createElement("username"); 72 usernameEle.setTextContent(username); 73 chenkEle.appendChild(usernameEle); 74 75 Element passwordEle = document.createElement("password"); 76 passwordEle.setTextContent(password); 77 chenkEle.appendChild(passwordEle); 78 79 list.add(new Header(new QName("thecheck"), chenkEle)); 80 } catch (ParserConfigurationException e) { 81 // TODO Auto-generated catch block 82 e.printStackTrace(); 83 } 84 } 85 }