WebService-CXF 学习笔记
什么是CXF
Apache CXF = Celtix + Xfire
支持多种协议:
SOAP1.1,1.2
XML/HTTP
CORBA(Common Object Request Broker Architecture公共对象请求代理体系结构,早期语言使用的WS。C,c++,C#)
并可以与Spring进行快速无缝的整合
灵活的部署:可以运行在Tomcat,Jboss,Jetty(内置),IBMWS,BeaWL上面。
下载:
CXF的结构:
下载完成后将其解压到某个目录下:
安装CXF的其他支持项目
Ant
Tomcat
并设置以下环境变量:
JAVA_HOME
CXF_HOME
ANT_HOME
CATALINA_HOME
Path = %JAVA_HOME%\bin;%CXF_HOME%\bin;%CATALINA_HOME%\bin;%ANT_HOME%\bin
CLASSPATH=.;%CXF_HOME%\lib\cxf-manifest.jar;.\build\classes
用ANT来构造第一个CXF示例:
在cxf_home\samples\java_first_pojo目录下启动服务器:
在命令行模式下进入上述目录:
执行 以下命令 ant server
在同一目录下打开新命令行窗口运行:
ant client
查看它的源代码并修改运行:
用ANT将它发布到Tomcat服务器上:
1、执行ant clean清除以前生成的代码
2、执行ant war打包此应用。
3、执行ant deploy –Dtomcat=true将项目发布到tomcat的服务器上。
4、启动tomcat服务器
5、打开IE的地址栏输入:
http://localhost:9999/helloworld/services/hello_world?wsdl
或:http://localhost:9999/helloworld/services
6、在命令行执行:
ant client-servlet –Dbase.url=http://localhost:9999
或在MyEclipse的WebServiceExplorer中访问这个WebService
7、停止tomcat服务器。
8、卸载应用:ant undeploy –Dtomcat=true
9、清空项目:ant clean
在Eclipse中开发CXF的JavaSE应用:
导入CXF中的 所有jar文件。可以通过WACH_JARS来观察各jar文件的用途。
建立好之后的项目如
图所示:
CXF发布服务的类:
用两个不同的类发布应用:
ServerFactoryBean -- FacotryBean
JaxWsServerFactoryBean(建议使用此类)
服务与客户端类调用原则:
使用ServerFactoryBean发布服务:
使用ServerFactoryBean发布服务。
使用CXF发布一个服务,与JDK6发布一个服务完全不同
* 即使是不使用@WebService注解,一样可以发布成功
* 即使此类没有对外公布的方法一样可以发布成功
使用ClientProxyFactoryBean客户端调用:
使用ServerFactoryBean发布服务以后,在没有接口的情况下,可以使用wsimport生成的客户端代码调用成功。
但如果要使用ClientProxyFactoryBean客户端去调用服务器,则必须要先在服务器端创建一个接口。(一直以来,Spring都要求面向接口编程,而cxf与Spring能很好的整合,也就在此。),所以,必须要重写服务器端的代码。这将导致刚才使用wsimport生成的调用代码失效。
同时, ClientProxyFactoryBean由于要用到CXF环境,所以要导入CXF的所有包。
同时,如果是在本项目中调用,则可以直接使用本项目的接口。
如果在其他项目中调用,仍然需wsimport生成的类,但只需要一个接口。
使用JaxWsServerFactoryBean发布服务: (建议使用此类)
JaxWsServerFactoryBean是ServerFactoryBean的子类,也是功能扩展类。
但在CXF的API文档中没有提供此类API,请通过查看源代码的方式获取此类的帮助。
此类,必须要在被发布为服务的类上添加@WebService注解,如果不加注解,虽然不
出错,但也不会对外暴露任何方法。
使用此类生成的wsdl文件更加规范。
以下是从它的源代码中找到的对此类的说明。
使用CXF的类发布一个服务:
使用JaxWsProxyFactoryBean客户端调用
此调用过程与ClientProxyFactoryBean的要求一样,也必须要拥有一个接口。
此时,仍然可以使用wsimport生成接口,在其他项目的调用。
规范的做法应该是先书写一个接口,如下:
如果不是使用spring的配置文件发布,可以没有接口文件,但在任何情况下建议拥有接口文件。如果使用spring的配置文件发布,则必须要拥有接口类。
wsdl2java生成客户代码:
在cxf中,也提供了一个用于生成客户端调用代码的工具。它的功能就如同wsimport一样。
先让我们了解一下cxf的wsdl2java工具,可以生成一堆客户端调用的代码。
此工具位于cxf_home/bin目录下。参数与wsimport有所不同。
它包含以下参数:
-d参数,指定代码生成的目录。
-p参数,指定生成的新的包结构。
需要说明的是,由于wsdl2java是根据jdk1.7生成的本地代码,所以,需要对生成的代码做一点点修改。
在命令行执行:
wsdl2java –d . http://127.0.0.1:6666/helloworld?wsdl
调用端代码:
给服务添加消息拦截器:-这个非常有用:
LoggingInInterceptor – 信息输入时的拦截器 –请求
LoggingOutInterceptor –信息输出时的拦截器-响应
给服务器添加拦截器,类似于使用TCP/IP Monitor来捕获SOAP消息的过程。
使用JavaScript也可以访问WebServie:
jQuery访问WebService.
1、在本域准备jquery.js (由于jquery对跨域的请求做了限制,所以jquery仅限于在本域中使用。但为了快速解析XML文件,仍然可以使用jquery当成解析xml文件的工具。)。
2、通过js发起ajax请求。
总结:
如何通过ant发布第一个cxf应用。
手工建立一个java项目发布cxf的ws.
Java项目和js访问webService
加入消息拦截器
将服务端改为SOAP1.2实现
SOAP1.1与1.2
WebService-CXF-Spring基于web的cxf
开发cxf的web项目:
由于cxf的web项目已经集成了Spring所以,cxf的服务类都是在spring的配置文件中完成的。以下是步骤:
第一步:建立一个web项目。
第二步:准备所有jar包。将cxf_home\lib项目下的所有jar包全部copy到新项目的lib目录下,里面已经包含了spring3.0的jar包。
第三步:在web.xml中配置cxf的核心servlet,CXFServlet。
第四步:创建(最好是Copy)cxf-servlet.xml文件。这是一个spring的配置文件。
web.xml的配置如下:
Cxf-servlet.xml文件说明:
Cxf-servlet.xml文件,就是一个spring的配置文件。一个空的配置文件如下。
上面导入的三个配置文件都在cxf.jar的META文件夹中
在地址栏访问: -配置好空项目后,可以先测试是否可以启动成功:
http://localhost:9999/cxf_spring/ws
如果有WebService的存在,则会显示出来,如果没有,则会显示上而的信息。
如果有WebService的存在,则会显示出来,如果没有,则会显示上而的信息。
<?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"
xmlns:soap="http://cxf.apache.org/bindings/soap" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/bindings/soap
http://cxf.apache.org/schemas/configuration/soap.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd
">
<!-- 引入CXF Bean定义如下,早期的版本中使用 -->
<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" /> <!-- 方式一:简单发布,没有接口的发布方式 -->
<!--
id:当前服务的唯一标识 address:当前服务对应的请求url implementor:提供服务的类型
-->
<jaxws:endpoint id="helloService" address="/hello"
implementor="com.itheima.service.HelloService">
<!-- 添加客户端请求的消息拦截器 -->
<jaxws:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
</jaxws:inInterceptors>
<!-- 添加服务端响应的消息拦截器 -->
<jaxws:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</jaxws:outInterceptors>
</jaxws:endpoint> <!-- 方式二:带有接口的发布方式 -->
<!--
id:当前服务的唯一标识 address:当前服务对应的请求url serviceClass:接口类型
-->
<jaxws:server id="hiService" address="/hi"
serviceClass="com.itheima.service.IHiService">
<jaxws:serviceBean>
<bean class="com.itheima.service.HiServiceImpl" />
</jaxws:serviceBean>
<jaxws:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
</jaxws:inInterceptors>
<jaxws:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</jaxws:outInterceptors>
</jaxws:server> <!-- 发布一个Restful方式的WebService服务 -->
<bean id="personServiceImpl" class="com.itheima.service.PersonServiceImpl"></bean>
<jaxrs:server id="personService" address="/p">
<jaxrs:serviceBeans>
<ref bean="personServiceImpl" />
</jaxrs:serviceBeans>
<jaxrs:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
</jaxrs:inInterceptors>
<jaxrs:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</jaxrs:outInterceptors>
</jaxrs:server>
</beans>
cxf-servlet.xml
配置发布第一个ws : (jaxb)
发布带有接口的配置: (jax-ws)
必须要在声明为serviceClass的接口上声明@WebSerive注解
因为,要使用了接口,在接口上添加的注解才会有效。
配置说明:
CXFServlet类,通过读取config-location的配置项读取cxf-servlet.xml配置文件。并在内部读取自己的配置文件cxf.xml文件。
在CXFServlet读取配置文件后,将文件信息全部读取到ApplicationContext的Spring类中。
以下是它的源代码:
通过配置给服务添加消息拦截器:
LoggingInInterceptor
LogginOutInterceptor
在地址栏访问:
http://localhost:9999/cxf2.4_spring_web/ws
Java项目代码调用服务:
使用纯Java项目调用
1、根据客户端生成的代码来调用。(优选这种方式)
请先生成然后在任意的Java项目中调用 。
2、客户端只拥有一个接口,使用JaxWsProxyFactoryBean来调用。
因为以下使用了JaxWsProxyFactoryBean,所以,仍然需要CXF的环境,而使用此环境就会造成Jar文件的大量冗余,所以大家要谨慎选择。
在Spring项目中,通过配置文件调用:
以下是使用Spring的配置文件调用:
新建立一个Java项目,并加载cxf的所有包。
只需要生成的接口文件.
在classpath下新建立一个ClientBeans.xml文件.
优点与缺点:
此种情况,适合于一个Javaweb项目已经集成了Spring。并希望通过CXF配置的方式调用Web服务。
此种情况,仍然需要导入CXF的大量jar包。
这种情况也存在一定优点,如可以将外部的Web服务通过配置文件注入(DI)到Action类中。
建立好以后Java项目如下图
ClientBeans.xml文件的内容:
以下是调用代码:
关于web项目配置的说明1:
如果在项目中仅发布webservice,则可以只配置以下内容。
同时默认即是读取WEB-INF/cxf-servlet.xml文件,所以是否指定都可以。
关于web项目配置的说明2:
但一般情况下,一个web项目,在使用了Spring之后,往往会通过ApplicationContext获取一些服务,此时则必须注册Spring的监听器。即以下代码:
见备注处,是一个完整的web.xml的配置。
关于web项目配置的说明3:
在上页中出现的重复引入问题,可以修改cxf-servlet.xml文件。
修改后,CXFServlet类将不能自动加载cxf-servlet.xml文件,此时将导致名为cxf的bean加载不成功。
为解决此问题必须在重新命名的配置文件中加入以下代码,以启动CXF:
即:如果你是用contextConfigLocation加载的配置文件,则必须要加入以下代码。
关于web项目配置的说明4:
在增加了Spring的监听器之后,即可以使用以下代码在Servlet中获取Spring的配置 :
通过JS来调用WebService:
通过jQuery的ajax方法向服务器发送xml数据。
必须要先了解xml的数据格式,通过拦截器获取。
可以从LoggingInInterceptor中获取发出的数据格式。
可以从LoggingOutInterceptor中获取返回的数据。
导入jQuery1.5.js文件,放到js/jquery1.5.js
通过Ajax访问WebService
使用jQuery-本域
$.ajax({
url:..
type:’post’,
dataType:’xml’,
contentType:’application/soap+xml;charset=“UTF-”’
data:someXml,
Success:fun()…
})
在本域使用jquery访问: --查询所有用户:
课程回顾:
什么是WebService?
在Jdk6上使用Endpoint发布WebService。
使用wsimport生成客户端代码。及各种监控工具的使用。
CXF的安装。
wsdl2java工具的使用。
CXF与spring进行整合。*
使用Ajax直接发送SOAP请求。
Web服务为我们带来了什么:SOA
(这是一种思想,不是简单的代码实现)
开发基于CXF的RESTFul Webservice
开发基于CXF的 RESTful WebService .创建Web项目并导入CXF的jar
.在Web.xml中配置 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.创建实体类 Person
@XmlRootElement(name = "person")
public class Person implements Serializable {
private String id;
private String name;
private String description;
@XmlElement(name = "id")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@XmlElement(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlElement(name = "description")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
4.定义 PersonService 接口
//@Produces( { MediaType.APPLICATION_XML })
@Produces( { MediaType.APPLICATION_JSON })
public interface PersonService extends Serializable {
@GET
@Path("/persons")
public List<Person> getPersons(); @GET
@Path("/persons/{id}")
public Person getPerson(@PathParam("id") String id);
}
5.提供实现类 PersonServiceImpl
public class PersonServiceImpl implements PersonService {
private static final long serialVersionUID = 1L;
private static Map<String, Person> ps = new HashMap<String, Person>();
static {
Person info = new Person();
p1.setId("1");
p1.setName("zhangsan");
p1.setDescription("hello"); Person p1 = new Person();
p2.setId("2");
p2.setName("lisi");
p2.setDescription("lisi hehe"); ps.put(p1.getId(), p1);
ps.put(p2.getId(), p2);
} @Override
public Person getPerson(String id) {
return ps.get(id);
} @Override
public List<Person> getPersons() {
return new ArrayList(ps.values());
}
}
6.提供CXF 的配置文件 cxf-servlet.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:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://cxf.apache.org/jaxrs
http://cxf.apache.org/schemas/jaxrs.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<bean id="personService" class="cn.itcast.cxf.PersonServiceImpl" />
<jaxrs:server id="RestService" address="/v1">
<jaxrs:serviceBeans>
<ref bean="personService" />
</jaxrs:serviceBeans>
<jaxrs:inInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingInInterceptor"></bean>
</jaxrs:inInterceptors>
<jaxrs:outInterceptors>
<bean class="org.apache.cxf.interceptor.LoggingOutInterceptor"></bean>
</jaxrs:outInterceptors>
</jaxrs:server>
</beans>
7.访问CXFServlet:http://localhost/CXF_01/ws
8.通过 URLConnection 访问WebService服务:
URLConnection conn = new URL("http://localhost/CXF_01/ws/v1/persons").openConnection();
HttpURLConnection con = (HttpURLConnection) conn;
con.setRequestMethod("GET");
int code = con.getResponseCode();
System.out.println(code);
InputStream is = con.getInputStream();
int len = 0;
byte[] b = new byte[1024];
StringBuffer sb = new StringBuffer();
while((len = is.read(b)) != -1){
String s = new String(b,0,len,"UTF-8");
sb.append(s);
}
System.out.println(sb.toString());
con.disconnect();
开发基于CXF的RESTFul Webservice
WebService-CXF 学习笔记的更多相关文章
- WebService CXF学习:复杂对象传递(List,Map)
转自:https://blog.csdn.net/z69183787/article/details/35988335 第一步:创建存储复杂对象的类(因为WebServices的复杂对象的传递,一定要 ...
- webService cxf学习
1.首先去官网下载cxf包 http://archive.apache.org/dist/cxf/ 记住要选.zip结尾 大概40兆的样子 2.把上边的包都放项目里.如果你用的jeecg框架,那它自带 ...
- webservice系统学习笔记10-使用jax-ws创建基于tomcat类型的容器的ws服务
1.在web-info目录下新建目录wsdl 2.在1步的目录下 新建文件user.wsdl <?xml version="1.0" encoding="UTF-8 ...
- webservice系统学习笔记9-使用契约优先的方式的一个服务端demo(隐式传Header信息)
服务器端: 1.编写wsdl文件 <?xml version="1.0" encoding="UTF-8" standalone="no&quo ...
- webservice系统学习笔记7-使用handler实现过滤器/拦截器效果
handler可以作用于客户端,也可以作用了服务端 handler分为:1.LogicalHandler:只能获取到soap消息的body. 2.SOAPHandler:可以获取SOAPMessage ...
- webservice系统学习笔记5-手动构建/发送/解析SOAP消息
手动拼接SOAP消息调用webservice SOAP消息的组成: 1.创建需要发送的SOAP消息的XML(add方法为例子) /** * 创建访问add方法的SOAP消息的xml */ @Test ...
- webservice系统学习笔记4-使用工具查看SOAP消息
使用myeclipse的WTP java ee视图里的[web services Explorer]来测试查看webservice传输的SOAP消息 1. 2. 测试getUserByUsername ...
- webservice系统学习笔记2-使用jdk的命令生成本地代码
使用jdk自带的命令wsimport生成远程服务的本地代码 C:\Documents and Settings\Administrator>wsimport -d E:\mhWorkspace\ ...
- webservice系统学习笔记1-使用注解创建ws服务
简单入门之helloword,具体详细的在后面的章节详细介绍. 使用JDK自带的jax-ws创建并发布一个简单的webservice 在本地创建服务,然后本机访问 1.创建服务提供接口 IMyServ ...
- CXF学习笔记 之 “注解”
@WebService 1.serviceName: 对外发布的服务名,指定 Web Service 的服务名称:wsdl:service.缺省值为 Java 类的简单名称 + Service.(字符 ...
随机推荐
- 【DRF版本控制】
目录 使用内置的URLPathVersioning类 使用自定义的版本控制类 "首先,我们开发的项目会有多个版本. 其次,我们的项目版本会随着更新越来越多,我们不可能因出了新版本就不维护旧版 ...
- MBA 报考
1. 作者:MBA薛老师链接:https://www.zhihu.com/question/277811289/answer/397083199来源:知乎著作权归作者所有.商业转载请联系作者获得授 ...
- [PHP]新版的mongodb扩展安装和使用
旧版的mongo扩展已经不推荐使用了,在php7以上一般是安装和使用新版的mongodb扩展 ubuntu下 apt-get install php-mongodb 例如下面的代码进行了查询和插入集合 ...
- 被女朋友三番五次拉黑后,我用 Python 写了个“舔狗”必备神器
在一个阳光明媚的周日,我打开窗户呼吸了一口新鲜空气.阳光灿烂,岁月静好,又是一个约女朋友出去爬山吃饭看电影的好日子. 想到女朋友的大眼睛,我脸上不禁洋溢起了幸福的微笑.打开微信,给女朋友发出去一个美好 ...
- December 31st, Week 53rd Tuesday, 2019
Nothing comes from nothing. 天下没有免费的午餐. Nothing comes from nothing, and in some cases, even something ...
- JAVA(3)之关于运算符的优先级
关于运算符的优先级,我做了一个小测试,区别在于平常的运算思维和计算机思维 int result=2; result =(result=result*2)*6*(result=3+result); Sy ...
- 架设传奇时打开DBC数据库出错或读取DBC失败解决方法
架设传奇时打开DBC数据库出错或读取DBC失败解决方法 DBC右键-属性-高级-管理员身份运行 即可
- C语言:假定输入的字符串只包含字母和*号,fun函数:除了尾部的*号以外,将字符的其他*号进行全部删除,形参p已经指向字符串中最后一个字母。-利用折半查找整数m在有序数组中的位置,若找到,返回下标值,否则返回-1。
//假定输入的字符串只包含字母和*号,fun函数:除了尾部的*号以外,将字符的其他*号进行全部删除,形参p已经指向字符串中最后一个字母. #include <stdio.h> void f ...
- QWidget::setLayout: Attempting to set QLayout "" on xxx "", which already has a layout
QLayout是Qt应用开发中一个非常重要的组件,然而平时使用的时候不小心经常会发现控制台有类似如下的警告: QWidget::setLayout: Attempting to set QLayout ...
- Tornado项目简单创建
Tornado是使用Python编写的一个强大的.可扩展的Web服务器.它在处理严峻的网络流量时表现得足够强健,但却在创建和编写时有着足够的轻量级,并能够被用在大量的应用和工具中. tornado技术 ...