WebService 及 CXF 的进阶讲解
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 - 通信消息的数据结构的抽象类型化定义。
- 引用types中定义的标签
- 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拦截器
服务端:
public class CheckUserInterceptor extends AbstractPhaseInterceptor<SoapMessage> { public CheckUserInterceptor() {
super(Phase.PRE_PROTOCOL);
} @Override
public void handleMessage(SoapMessage msg) throws Fault {
Header header = msg.getHeader(new QName("thecheck"));
if(header != null){
Element chenkEle = (Element) header.getObject();
String username = chenkEle.getElementsByTagName("username").item(0).getTextContent();
String password = chenkEle.getElementsByTagName("password").item(0).getTextContent(); if("ymmm".equals(username) && "123456".equals(password)){
System.out.println("Client de "+username+" 通过了 服务器的检查");
return;
}
}
System.out.println("client 没有通过拦截器检查"); throw new Fault(new RuntimeException("请输入正确的用户名和密码!!!")); } } 客户端:
public class AddUserInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
private String username;
private String password; public AddUserInterceptor(String username , String password) {
super(Phase.PRE_PROTOCOL);
this.username = username;
this.password = password;
}
/*
<Envelope>
<head>
<chenkEle>
<name>xfzhang</name>
<password>123456</password>
</chenkEle>
<chenkEle2>
<name>xfzhang</name>
<password>123456</password>
</chenkEle2>
<head>
<Body>
<sayHello>
<arg0>BOB</arg0>
<sayHello>
</Body>
</Envelope>
*/ @Override
public void handleMessage(SoapMessage msg) throws Fault {
List<Header> list = msg.getHeaders(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document document;
try {
document = factory.newDocumentBuilder().newDocument(); Element chenkEle = document.createElement("thecheck"); Element usernameEle = document.createElement("username");
usernameEle.setTextContent(username);
chenkEle.appendChild(usernameEle); Element passwordEle = document.createElement("password");
passwordEle.setTextContent(password);
chenkEle.appendChild(passwordEle); list.add(new Header(new QName("thecheck"), chenkEle));
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
MyInterceptor
public class TestService2 { public static void main(String[] args) {
String address = "http://192.168.1.102:8787/webService_02_sayService/hellows";
Endpoint publish = Endpoint.publish(address, new HelloWsImpl());
EndpointImpl endImpl = (EndpointImpl) publish; //添加日志入拦截器拦截器
List<Interceptor<? extends Message>> inList = endImpl.getInInterceptors();
inList.add(new LoggingInInterceptor());
inList.add(new CheckUserInterceptor()); //添加日志出拦截器
List<Interceptor<? extends Message>> outIplm = endImpl.getOutInterceptors();
outIplm.add(new LoggingOutInterceptor()); System.out.println("发布 webService_01_cxf_sayService 成功");
}
}
Service
public class Test2 { public static void main(String[] args) {
HelloWsImplService factory = new HelloWsImplService();
HelloWs helloWs = factory.getHelloWsImplPort(); Client client = ClientProxy.getClient(helloWs); List<Interceptor<? extends Message>> outList = client.getOutInterceptors();
outList.add(new AddUserInterceptor("ymmm", "123456")); String string = helloWs.sayHello("cxf-client3 yyy");
System.out.println(string);
}
}
Client
2). 用CXF编写基于spring的web service
2.1). 编码实现
- Server端
– 创建spring的配置文件beans.xml,在其中配置SEI
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<!-- 如果是低版本,还要引入更多文件 -->
<import resource="classpath:META-INF/cxf/cxf.xml" />
<!-- 配置终端 -->
<jaxws:endpoint
id="orderWS"
implementor="com.ittest.servcie_02_cxf_.ws.OrderWsImpl"
address="/orderws" >
<!-- 配置拦截器 -->
<jaxws:inInterceptors>
<bean class="com.ittest.ws.interceptor.CheckUserInterceptor"></bean>
</jaxws:inInterceptors> </jaxws:endpoint>
</beans>
applicationContext.xml
– 在web.xml中,配置上CXF的一些核心组件
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param> <listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener> <servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
web.xml
注意:各种cxf版本在配置xml的时候有区别( 在Cxf的高版本中要引入的其它文件较少 ).
- Client端
– 生成客户端代码
– 创建客户端的spring配置文件beans-client.xml,并配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> <jaxws:client id="orderClient" serviceClass="com.ittest.servcie_02_cxf_.ws.OrderWs"
address="http://localhost:8080/webService_02_cxf_sayService_spring/orderws" > <!-- 添加拦截器 -->
<jaxws:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"/>
<bean class="com.ittest.ws.client.intercepter.AddUserInterceptor">
<constructor-arg name="username" value="ymmm"/>
<constructor-arg name="password" value="123456"/>
</bean>
</jaxws:outInterceptors> </jaxws:client> </beans>
Client-bean.xml
– 编写测试类请求web service
public class Test1 { public static void main(String[] args) {
String path = "classpath:applicationContext.xml";
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(path); OrderWs orderWs = (OrderWs) applicationContext.getBean("orderClient");
Order order = orderWs.getOrder(3);
System.out.println(order);
}
}
Test
2.2). 添加自定义拦截器
- Server端
– 在beans.xml中,在endpoint中配置上入拦截器 (同上)
- Client端
– 通过Client对象设置出拦截器 (同上)
4.4. 其它调用WebService的方式
1). Ajax调用webService
跨域请求问题:
1. 什么是跨域请求? (jquery还要求都是 localhost)
1. sina.com--=->baidu.com/xxx.jsp
2. localhost----à192.168.42.165
2. 解决ajax跨域请求webservice的问题?
在客户端应用中使用java编码去请求webservice, 在页面中去请求自己的后台
2). Jquery调用WebService
3). HttpURLConnection调用WebService
以上三个的代码(一起):
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="jquery-1.8.3.js" ></script>
<script type="text/javascript"> $(document).ready(function(){ $("#btn2").click(function(){
var name = document.getElementById("name").value;
$.post(
"HttpURLConnectionServlet",
"name="+name,
function(msg){
var $Result = $(msg);
var value = $Result.find("return").text();
alert(value);
},
"xml"
);
}); $("#btn1").click(function(){ var name = document.getElementById("name").value;
var date = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Header><thecheck><username>ymmm</username><password>123456</password></thecheck></soap:Header><soap:Body><ns2:getOrder xmlns:ns2="http://ws.servcie_02_cxf_.ittest.com/"><arg0>3</arg0></ns2:getOrder></soap:Body></soap:Envelope>';
alert(name+" "+date);
$.ajax({
type : "POST",
url : "http://localhost:8080/webService_02_cxf_sayService_spring/orderws",
data : date,
success : function(msg){
alert("------");
var $Result = $(msg);
var value = $Result.find("return").text();
alert(value);
},
error : function(msg) {
//alert("-----"+msg);
},
dataType : "xml"
});
});
}); function reqWebService() { var name = document.getElementById("name").value;
var date = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHello xmlns:ns2="http://service.ws.ittest.com/"><arg0>'
+ name + '</arg0></ns2:sayHello></soap:Body></soap:Envelope>'; var xmlhttp = getRequest();
alert("---");
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
alert("前");
var result = xmlhttp.responseXML;
alert("后");
var returnEle = result.getElementsByTagName("return")[0];
var vale = returnEle.firstChild.data;
alert(vale); }
}; xmlhttp.open("POST",
"http://192.168.1.102:8787/webService_02_sayService/hellows"); xmlhttp.setRequestHeader("Content-type",
"application/x-www-form-urlencoded"); xmlhttp.send(date); } function getRequest() {
var xmlhttp = null;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
return xmlhttp;
}
</script> </head>
<body>
用户名:
<input type="text" id="name" name="username" />
<br />
<div>
<button onclick="reqWebService()">使用Ajax连接 webservice</button></div>
<button id="btn1">使用JQuery链接webService</button>
<button id="btn2">使用Connection链接webService</button> </body>
</html>
insex.jsp
package com.ittest.servcie_02_cxf_.web; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection; import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.apache.jasper.tagplugins.jstl.core.Url; import com.sun.jndi.toolkit.url.Uri; /**
* Servlet implementation class HttpURLConnectionServlet
*/
@WebServlet("/HttpURLConnectionServlet")
public class HttpURLConnectionServlet extends HttpServlet {
private static final long serialVersionUID = 1L; /**
* 跨域请求webService
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String name = request.getParameter("name"); String path = "http://192.168.1.102:8787/webService_02_sayService/hellows";
String data = "<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'><soap:Body><ns2:sayHello xmlns:ns2='http://service.ws.ittest.com/'><arg0>"
+ name + "</arg0></ns2:sayHello></soap:Body></soap:Envelope>"; URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestProperty("Content-Type", "text/xml;charset=utf-8"); OutputStream os = connection.getOutputStream();
os.write(data.getBytes("utf-8"));
os.flush(); int code = connection.getResponseCode();
if(code==200){
InputStream is = connection.getInputStream(); response.setContentType("text/xml;charset=utf-8");
ServletOutputStream outputStream = response.getOutputStream(); int len=0;
byte[] buff = new byte[1024]; while((len = is.read(buff))>0){
outputStream.write(buff,0,len);
} outputStream.flush();
outputStream.close();
}
}
}
HttpURLConnectionServlet
4.5. 通过注解修改wsdl文档
1). JDK中的相关注解
1.1). @WebService
l 作用在具体类上。而不是接口。 l 一个类只有添加了此注解才可以通过Endpoint发布为一个web服务。 l 一个添加了此注解的类,必须要至少包含一个实例方法。静态方法和final方法不能被发布为服务方法。 l WebService注解包含以下参数: |
1.2). @WebMethod
l 此注解用在方法上,用于修改对外暴露的方法。 |
1.3). @WebResult
用于定制返回值到WSDL的映射 |
1.4). @WebParam
用于定义WSDL中的参数映射 |
1.5). @XmlElement
用于定义实体类的属性到WSDL中的映射(get/set方法上) |
2). 说明
即使是没有修改源代码,只修改了注解,客户端的代码也必须要重新生成, 否则调用将会失败。 |
WebService 及 CXF 的进阶讲解的更多相关文章
- WebService之CXF注解报错(一)
WebService之CXF注解 1.详细报错例如以下 usage: java org.apache.catalina.startup.Catalina [ -config {pathname} ] ...
- WebService它CXF注释错误(两)
WebService它CXF注解 1.详细报错例如以下 五月 04, 2014 11:24:12 下午 org.apache.cxf.wsdl.service.factory.ReflectionSe ...
- WebService之CXF注解报错(三)
WebService之CXF注解 1.具体错误如下 五月 04, 2014 11:29:28 下午 org.apache.cxf.wsdl.service.factory.ReflectionServ ...
- WebService之CXF注解报错(二)
WebService之CXF注解 1.具体报错如下 五月 04, 2014 11:24:12 下午 org.apache.cxf.wsdl.service.factory.ReflectionServ ...
- 转载 WebService 的CXF框架 WS方式Spring开发
WebService 的CXF框架 WS方式Spring开发 1.建项目,导包. 1 <project xmlns="http://maven.apache.org/POM/4.0 ...
- 【WebService】WebService之CXF和Spring整合(六)
前面介绍了WebService与CXF的使用,项目中我们经常用到Spring,这里介绍CXF与Spring整合 步骤 1.创建一个Maven Web项目,可以参照:[Maven]Eclipse 使用M ...
- 转-JAVA webservice之CXF 范例--http://cxshun.iteye.com/blog/1275408
JAVA webservice之CXF 博客分类: j2ee相关 昨天我们一起学习了一下xfire,今天我们来看一下CXF,为什么学完那个接着学这个呢.因为CXF是在xfire的基础上实现 的,所以我 ...
- Webservice与CXF框架快速入门
1. Webservice Webservice是一套远程调用技术规范 远程调用RPC, 实现了系统与系统进程间的远程通信.java领域有很多可实现远程通讯的技术,如:RMI(Socket + 序列化 ...
- WebService之CXF框架
本文主要包括以下内容 ant工具的使用 利用cxf实现webservice cxf与spring整合 ajax访问webservice ant 工具 1.为什么要用到ant这个工具呢? Ant做为一种 ...
随机推荐
- 解决mybatis generator警告Cannot obtain primary key information from the database, generated objects may be incomplete
使用 mybatis generator 生成pojo.dao.mapper时 经常出现 Cannot obtain primary key information from the database ...
- java中的缓冲流!
package cn.zhozuohou; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; impor ...
- Oracle minus用法详解及应用实例
本文转载:https://blog.csdn.net/jhon_03/article/details/78321937 Oracle minus用法 “minus”直接翻译为中文是“减”的意思,在Or ...
- Lodop输出页面input文本框的最新值
默认使用Lodop打印页面上的文本框等,会发现虽然页面上文本框输入了值,打印预览却是空的,这是由于没有把最新的值传入Lodop. 如图,演示的是Lodop如何输出文本框内的新值,这里整个页面只有inp ...
- How to remove unwant Internet Explorer Context Menu
HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt
- Vue插件plugins的基本操作
前面的话 本文将详细介绍Vue插件plugins的基本操作 开发插件 插件通常会为 Vue 添加全局功能.插件的范围没有限制——一般有下面几种: 1.添加全局方法或者属性,如: vue-custom- ...
- Power Spectral Density
对于一个特定的信号来说,有时域与频域两个表达形式,时域表现的是信号随时间的变化,频域表现的是信号在不同频率上的分量.在信号处理中,通常会对信号进行傅里叶变换得到该信号的频域表示,从而得到信号在频域上的 ...
- GLSL 变量属性
1. attribute变量为这个attribute变量指定一个位置(用无符号值表示):glBindAttribLocation利用这个“位置”来指定需要传给shader里的attribue变量的数据 ...
- mosquitto发布消息
./mosquitto_pub -t '$SYS/broker/clients/status/online' -m 1
- python 机械学习之sklearn的数据正规化
from sklearn import preprocessing #导入sklearn的处理函数用于处理一些大值数据 x_train, x_test, y_train, y_test = tr ...