加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

WebService框架WebService-CXF (二) --参考传智播客视频

发布时间:2020-12-17 00:54:06 所属栏目:安全 来源:网络整理
导读:1??????:WebService框架WebService-CXF ? 1.1????简介: 1.1.1??什么是CXF l? Apache CXF = Celtix + Xfire ?:结合 Celtix + Xfire的优点; l? 支持多种协议: ???? SOAP1.1,1,2 ???? XML/HTTP ???? CORBA(Common Object Request Broker Architecture公共

1??????:WebService框架WebService-CXF

?

1.1????简介:

1.1.1??什么是CXF

l? Apache CXF = Celtix + Xfire?:结合Celtix + Xfire的优点;

l? 支持多种协议:

???? SOAP1.1,1,2

???? XML/HTTP

???? CORBA(Common Object Request Broker Architecture公共对象请求代理体系结构,早期语言使用的WS。C,c++,C#)

???? 并可以与Spring进行快速无缝的整合

???? 灵活的部署:可以运行在Tomcat,Jboss,Jetty(内置),IBMWS,BeaWL上面。

?

?

?

?

?

?

?

?

??????????????????????????????????????????????????????????????????

?

?

?

1.1.2?CXF的结构:

?

?

1.1.2.1?Bus CXF框架的支撑

Bus是CXF框架的支撑.CXF Bus由spring配置文件构成(cxf.xml),在servlet初始化时

通过SpringBusFactory加载,它为所有终端定义了公共的上下文.它织入了所有运行

时的结构组件并提供了一个公共的应用上下文.SpringBusFactory扫描并加载类路径

下的META-INF/cxf目录并从以下文件构建上下文.

META-INF/cxf/cxf.xml

META-INF/cxf/cxf-extension.xml

META-INF/cxf/cxf-property-editors.xml

XML文件是安装CXF类库的一部分.CXF内部使用Spring配置.cxf.xml文件中bus定义如

下:

<bean id="cxf"class="org.apache.cxf.bus.CXFBusImpl" />

核心bus组件是CXFBusImpl,该类更多扮演拦截器供应商的角色对于终端出入的请求.

这些拦截器一旦应用,即可用于上下文中所有的终端.cxf.xml文件也定义了其他的组

件,比如BindingFactoryManager,ConduitFactoryManager等等.这些组件可用于bus

的扩展.可以使用getExtension()方法这些组件.注册这些组件以用于获取或更新服

务终端级别参数如服务绑定,传输协议,中转等等.

--------------

1.1.2.2Frontend-前端:

Frontend

CXF提供了前端建模的概念,可以使用不同的前端API创建ws.这些API使用简单工厂

bean和JAX-WS实现创建ws.可以创建动态ws客户端.CXF支持的前端主要是JAX-WS.

---------

1.1.2.3Message and intercetpors: 消息和拦截器

CXF框架中重要的组件之一是拦截器组件.拦截器拦截客户端和服务器间的消息.在

CXF,这通过拦截器链的概念实现.拦截器链是CXF运行时的核心功能.链中的每个拦截

器是可配的,用户可以控制他的执行.

框架的核心的是拦截器接口,它定义了两个方法handleMessage和handleFault,都携

带Message类型作为参数.

拦截器通常分组成各阶段.每个阶段执行特定的消息处理,每个阶段又被添加到拦截

器链中,因此,链有时有序的拦截器阶段的列表.典型的ws终端有三个连接器链:

Inbound messages chain(入消息链)

Outbound messages chain(出消息链)

Error messages chain(错误消息链)

内置拦截器如日志,安全,也可以自定义拦截器.

-----

1.1.2.4Service Model-主要用于生成wsdl文件的各个元素。

建模service,创建各种WSDL元素如操作,绑定,终端,schema等等.

如下显示了服务模型中的各个组件:

-------

1.1.2.5?Data binding

数据绑定是ws开发的关键.它意味着java对象和xml元素之间的映射.数据绑定组件执

行这一工作.CXF最新版本使用JAXB2.1.JAXB使用注解定义java对象和XML之间的映射.如下:

@XmlRootElement(name="processOrder",

?????????????????? ?????? namespace="http://localhost/orderprocess")

@XmlAccessorType(XmlAccessType.FIELD)

@XmlType(name="processOrder",namespace="http://localhost/orderprocess")

public class OrderProcess {

???????? @XmlElement(name="arg0",namespace="")

???????? privateorder.Order arg0;

???????? //Gettterand Setter

???????? …

}

-----------

协议绑定:protocol bindings

CXF支持以下形式的绑定:

SOAP1.1

SOAP1.2

CORBA

Pure XML

--

数据传输——transport

CXF支持以下数据传输方式:

HTTP

CORBA

JMS

LOCAL

?

下载完成后将其解压到某个目录下

?

1.2????Ant +CXF+java环境搭建

l? Ant

l? Tomcat

l? 并设置以下环境变量:

???? JAVA_HOME?

???? CXF_HOME

???? ANT_HOME

???? CATALINA_HOME? (tomcat_hone)

???? Path =%JAVA_HOME%bin;%CXF_HOME%bin;%CATALINA_HOME%bin;%ANT_HOME%bin

???? CLASSPATH=.;%CXF_HOME%libcxf-manifest.jar;.buildclasses

?

1.2.1?1、为什么要用到ant这个工具呢?

Ant做为一种工具已经广泛被使用,并且历史悠久。使用ant的内置命令,可以编译java源文件(javac),运行java文件(java),给class文件打包(jar、war、ear),也可以创建(mkdir)、删除(del)、拷贝(copy),甚至可以使用ant执行sql文件。由于ant是用xml语言写成的文件,并取默认名为build.xml文件。所以,今后大家应该在见到名为build.xml文件时知道这是一个ant的文件。

2、默认在Eclipse和MyEclipse的对ant有内建的支持。大家可以在MyEclipse中任意项目中建立一个文件叫build.xml文件,你会发现它有不同的图标(上面有个小蚂蚁)。

?

?

1.2.2?用ANT来构造第一个CXF示例:

l? 在cxf_homesamplesjava_first_pojo目录下启动服务器:

???? 在命令行模式下进入上述目录:

???? 执行 以下命令 ant server?? (server不是固定的_这里使用server)

l? 在同一目录下打开新命令行窗口运行:

???? ant client

l? 上面的代码,其实就是通过ant工具对源代码进行编译和运行。

l? 如果能编译通过,将会显示buildsuccess.

???? ?

1.2.3?用ANT来构造第一个CXF示例:

查看它的源代码并修改运行:

?

1.2.3.1用ANT将它发布到Tomcat服务器上:

l? 1、执行ant clean清除以前生成的代码

l? 2、执行ant war打包此应用。

l? 3、执行ant deploy –Dtomcat=true将项目发布到tomcat的服务器上。

l? 4、启动tomcat服务器

l? 5、打开IE的地址栏输入:

http://localhost:9999/helloworld/services/hello_world?wsdl

或:http://localhost:9999/helloworld/services

l? 6、在命令行执行:

???? ant client-servlet –Dbase.url=http://localhost:9999

???? 或在MyEclipse的WebServiceExplorer中访问这个WebService

l? 7、停止tomcat服务器。

l? 8、卸载应用:ant undeploy –Dtomcat=true

l? 9、清空项目:ant clean

?

?

?

1.3????Eclipse中开发CXF的JavaSE应用:

l? 导入CXF中的 所有jar文件。可以通过WACH_JARS来观察各jar文件的用途。

l? 建立好之后的项目如

??????右图所示:

?

?

?

CXF发布服务的类:

l? 用两个不同的类发布应用:

l? ServerFactoryBean?? --FacotryBean

l? JaxWsServerFactoryBean(建议使用此类)

?

1.3.1??使用ServerFactoryBean发布服务:(不建议使用)

l? 使用ServerFactoryBean发布服务。

l? 使用CXF发布一个服务,与JDK6发布一个服务完全不同

???? * 即使是不使用@WebService注解,一样可以发布成功

???? * 即使此类没有对外公布的方法一样可以发布成功

?

?

package cn.itcast.cxf1;

import java.util.Date;

import org.apache.cxf.frontend.ServerFactoryBean;

/**

?* 使用ServerFactoryBean发布服务

?* 使用CXF发布一个服务,与JDK6发布一个服务完全不同

?* 即使是不使用@WebService注解,一样可以发布成功

?* 即使此类没有对外公布的方法一样可以发布成功

?*/

public class CxfOneServer {

???????? public String sayHi(){

?????????????????? return "Hello:"+new Date();

???????? }

???????? public static void main(String[] args) {

?????????????????? ServerFactoryBean bean = //声明实例

??????????????????????????? new ServerFactoryBean();

?????????????????? //绑定到发布地址的端口

?????????????????? bean.setAddress("http://127.0.0.1:9999/one");

?????????????????? //设置服务接口,如果没有接口,则为本类

?????????????????? bean.setServiceClass(CxfOneServer.class);

?????????????????? //设置接口实现类,即服务类

?????????????????? bean.setServiceBean(new CxfOneServer());

?????????????????? bean.create();//发布服务

?????????????????? System.err.println("启动成功");

???????? }

}

?

1.3.2??使用JaxWsServerFactoryBean发布服务:(建议使用此类)

?

l? JaxWsServerFactoryBean是ServerFactoryBean的子类,也是功能扩展类。

l? 但在CXF的API文档中没有提供此类API,请通过查看源代码的方式获取此类的帮助。

l? 此类,必须要在被发布为服务的类上添加@WebService注解,如果不加注解,虽然不

出错,但也不会对外暴露任何方法。

使用此类生成的wsdl文件更加规范。

l? 以下是从它的源代码中找到的对此类的说明。

?

?

package cn.leaf.one;

import javax.jws.WebService;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

@WebService

public class OneService {

???????? public String sayHi(){

?????????????????? return "Good";

???????? }

???????? public static void main(String[] args) throws Exception {

?????????????????? JaxWsServerFactoryBean bean? //使用jaxWs对其进行发布

?????????????????? ? = new JaxWsServerFactoryBean();

?????????????????? bean.setServiceBean(new OneService());

?????????????????? bean.setServiceClass(OneService.class);

?????????????????? bean.setAddress("http://localhost:4444/one");

?????????????????? bean.create();

?????????????????? System.err.println("服务启动成功。。");

?????????????????? //Thread.sleep(1000*60*60);

?????????????????? //System.exit(0);

???????? }

}

?

?

?

?

?

1.3.3?使用ClientProxyFactoryBean客户端调用

在同一个项目中调用

package cn.itcast.cxf1;

import org.apache.cxf.frontend.ClientProxyFactoryBean;

public class Client {

????? public static void main(String[] args) {

??????????????? ClientProxyFactoryBean bean = //创建客户端类

???????????????????????? new ClientProxyFactoryBean();

??????????????? //设置访问地址

??????????????? bean.setAddress("http://localhost:9999/one");

??????????????? //设置服务接口,直接使用本项目中的接口

??????????????? bean.setServiceClass(CxfOne.class);

??????????????? //通过create方法返回接口实例

??????????????? CxfOne s =?? (CxfOne) bean.create();

??????????????? String str = s.sayHi();//调用

??????????????? System.err.println(str);

????? }

}

?

?

在不同的项目中调用

????? public static void main(String[] args) {

??????????????? ClientProxyFactoryBean bean = //创建客户端类

???????????????????????? new ClientProxyFactoryBean();

??????????????? //设置访问地址

??????????????? bean.setAddress("http://localhost:9999/one");

??????????????? //设置服务接口,直接使用本项目中的接口

??????????????? bean.setServiceClass(CxfOnePortType.class);

??????????????? //通过create方法返回接口实例

??????????????? CxfOnePortType one =?? (CxfOnePortType) bean.create();

??????????????? String s = s.sayHi();//调用

??????????????? System.err.println(s);

????? }

?

?

?

1.4????CXF的实践

1.4.1??使用CXF的类发布一个服务:

?

packagecn.leaf.one;

import javax.jws.WebService;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

@WebService

publicclassOneService {

?? publicString sayHi(){

????? return"Good";

?? }

?? publicstaticvoidmain(String[] args)throwsException {

????? JaxWsServerFactoryBeanbean//使用jaxWs对其进行发布

????? ? = new JaxWsServerFactoryBean();

????? bean.setServiceBean(new OneService());

????? bean.setServiceClass(OneService.class);

????? bean.setAddress("http://localhost:4444/one");

????? bean.create();

????? System.err.println("服务启动成功。。");

????? //Thread.sleep(1000*60*60);

????? //System.exit(0);

?? }

}

?

?

1.4.2??使用JaxWsProxyFactoryBean客户端调用

?

packagecn.itcast.cxf2;

importorg.apache.cxf.jaxws.JaxWsProxyFactoryBean;

publicclassA {

publicstaticvoid main(String[] args) {

JaxWsProxyFactoryBean bean =

newJaxWsProxyFactoryBean();

bean.setAddress("http://localhost:9999/two");

//此外注册的必须是一个接口,否则将抛出异常信息

bean.setServiceClass(Cxf2Server.class);

Cxf2Server s = (Cxf2Server) bean.create();

System.err.println(s.sayHello());

}

}

?

?

1、在使用CXF发布服务时,需要首先写一个接口,用以声明服务类型。这有点类似于Spring中的服务层的实现。

package cn.test;

?

import javax.jws.WebService;

import javax.xml.ws.BindingType;

import javax.xml.ws.soap.SOAPBinding;

?

@WebService

@BindingType(value=SOAPBinding.SOAP12HTTP_BINDING)

?

publicinterface IHelloService {

?

?? public String sayHello(String name);

}

?

?

1.4.2.1wsdl2java生成客户代码

l? 在cxf中,也提供了一个用于生成客户端调用代码的工具。它的功能就如同wsimport一样。

l? 先让我们了解一下cxf的wsdl2java工具,可以生成一堆客户端调用的代码。

l? 此工具位于cxf_home/bin目录下。参数与wsimport有所不同。

l? 它包含以下参数:

???? -d参数,指定代码生成的目录。

???? -p参数,指定生成的新的包结构。

l? 需要说明的是,由于wsdl2java是根据jdk1.7生成的本地代码,所以,需要对生成的代码做一点点修改。

l? 在命令行执行:

???????? wsdl2java–d . http://127.0.0.1:6666/helloworld?wsdl

?

1、注意:由于使用的是apache-cxf-2.4.0版本,它是支持jdk1.7的。所以,对于生成的Service要进行稍微的修改。

?? 在jdk1.6中的javax.xml.ws.Service的构造方法接收二个参数为:(String url,QName qname);

在jdk1.7中的javax.xml.ws.Service的构造方法中接收三个参数为:(String url,QName qname,features);

2、将生成的代码,拷贝到项目目录,然后使用以前相同方法调用。

??? 注意:如果你对@WebMethod设置了header=true参数,将会在调用时多传递一个参数。它参数可以直接传null值。

????????????对于这种情况,可以将header=true修改成header=false然后再重要获取客户端源代码。

3、大家可能发现了,使用cxf生成的客户端代码与wsimport差不多,甚至是一样,那为什么还要使用cxf呢?

它较好的发布方式、较容易的与其他服务器集成、及与Spring的完美结合都不得不让我们使用cxf。

?

调用端代码:

1、必须已经使用wsimport或wsdl2java生成了客户端代码。

以下是源代码:

packagecom.run;

importcom.itcast.cxfserver.javaclient.IHelloWorld;

importcom.itcast.cxfserver.javaclient.IHelloWorldPortType;

/**

?* 使用java6来调用cxf生成的客户端类的服务

?* 不管是用wsimport还是用wsdl2java生成的类基本上是完全一样的

?*/

publicclassCxfServerJava6Client {

?? publicstaticvoid main(String[] args) {

????? //调用使用wsimport生成的代码

????? IHelloWorldPortType hello = newIHelloWorld().getIHelloWorldPort();

????? String str = hello.sayHello("小王");

????? System.err.println(str);

?????

????? //调用使用wsdl2java生成的代码(一样)

????? com.itcast.cxfserver2.javaclient.IHelloWorldPortType client =

????? ?? newcom.itcast.cxfserver2.javaclient.IHelloWorld().getIHelloWorldPort();

????? String str2 = client.sayHello("CXF");

????? System.err.println(str2);

?? }

}

?

3、要想研究更多程序请见:cxf2.4_ws服务项目和cxf2.4_java6client客户端项目。

?

?

?

1.4.3?给服务添加消息拦截器:-这个非常有用:

在服务发布之前添加拦截器:

l? LoggingInInterceptor – 信息输入时的拦截器 –请求

l? LoggingOutInterceptor –信息输出时的拦截器-响应

?

???????? server.getInInterceptors().add(new LoggingInInterceptor());

???????? server.getOutInterceptors().add(new LoggingOutInterceptor());

?

给服务器添加拦截器,类似于使用TCP/IP Monitor来捕获SOAP消息的过程。

?

package cn.itcast.cxf;

?

import org.apache.cxf.interceptor.LoggingInInterceptor;

import org.apache.cxf.interceptor.LoggingOutInterceptor;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

?

/**

?*

?* 使用JaxWsServerFactoryBean发布CXFWeb服务

?* 必须加入WebService注解,如果不加,虽然不报错,但是所有的方法都暴露不出来

?*/

?

public class Server {

?

??? public static void main(String[] args) {

??????? JaxWsServerFactoryBean bean = new JaxWsServerFactoryBean();

??????? bean.setAddress("http://192.168.1.100:7788/hello");

??????? //提供服务的类的类型或接口类型

??????? bean.setServiceClass(IHelloService.class);

??????? bean.setServiceBean(new HelloServiceImpl());

??????? //可以多次针对不同的对象在(srping)中配置

??????? //加入请求的消息拦截器

??????? bean.getInInterceptors().add(new LoggingInInterceptor());

??????? //加入请求的消息拦截器

??????? bean.getOutInterceptors().add(new LoggingOutInterceptor());

???????

??????? bean.create();

??????? System.out.println("Hello Service ready...");

??? }

}

?

1.4.4?使用JavaScript也可以访问WebServie:

l? jQuery访问WebService.

???? 1、在本域准备jquery.js (由于jquery对跨域的请求做了限制,所以jquery仅限于在本域中使用。但为了快速解析XML文件,仍然可以使用jquery当成解析xml文件的工具。)。

???? 2、通过js发起ajax请求。

<%@pagelanguage="java"import="java.util.*"pageEncoding="UTF-8"%>

????? <%@ tagliburi="http://java.sun.com/jsp/jstl/core" prefix="c" %>

????? <html>

????? <head>

???????? <script type="text/javascript" src="<c:url value='/js/jquery-1.6.2.js'/>"></script>

????? </head>

????? <body>

????? <p>用js来控制的客户端</p>

???????? <button id="all">显示所有</button><br/>

???????? <hr/>

???????? Name:<input type="text" id="_name">,Age:<input type="text" id="_age">

???????? <button id="add">增加一个</button><br/>

???????? <table id="tb" width="70%" border="1">

??????????? <tr>

??????????????? <th>学生姓名</th>

??????????????? <th>学生年龄</th>

??????????? </tr>

???????? </table>

????? </body>

????? <script type="text/javascript">

???????? ?$(function(){

??????????? ?var url = "http://localhost:7777/xcxf3_ss/ws/studQuery";

??????????? ?$("#all").click(function(){

??????????????? //查询时必须向服务器发以下xml文件

??????????????? ?var xml = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'+

????????????????????? '<soap:Body><ns2:query xmlns:ns2="http://service.stud.cn/"/>'+

????????????????????? '</soap:Body></soap:Envelope>';

??????????????? ?$.ajax({

?????????????????? ?url:url,

?????????????????? ?type:'post',

?????????????????? ?dataType:'xml',

?????????????????? ?contentType:'application/soap+xml;charset=UTF-8',

?????????????????? ?data:xml,

?????????????????? ?success:function(data){

????????????????????? ?$("#tb tr:gt(0)").remove();//删除所有列?

????????????????????? //遍历data

????????????????????? ?$(data).find("return").each(function(){

???????????????????????? ?var name = $(this).find("name").text();

???????????????????????? ?var age? = $(this).find("age").text();

???????????????????????? ?var tr = $('<tr><td>'+name+'</td><td>'+age+'</td></tr>');

???????????????????????? ?tr.appendTo("#tb");

????????????????????? ?});

?????????????????? ?}

??????????????? ?});

??????????????? //以下是增加

??????????????? ?$("#add").click(function(){

?????????????????? ?var nm = $("#_name").val();

?????????????????? ?var age = $("#_age").val();

?????????????????? if($.trim(nm)=="" || $.trim(age)==""){

?? ?????????????????? alert('姓名和年龄必须输入');?

?????????????????? ?}

?????????????????? //以下是保存服务的xml

?????????????????? ?var xml = '<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'

???????????????????????? ?? +'<soap:Body><ns2:add xmlns:ns2="http://service.stud.cn/">'

???????????????????????? ?? +'<arg0><age>'+age+'</age><name>'+nm+'</name></arg0></ns2:add>'

???????????????????????? ?? +'</soap:Body></soap:Envelope>';

?????????????????? ?$.ajax({

????????????????????? ?url:url,

????????????????????? ?type:'post',

????????????????????? ?dataType:'xml',

????????????????????? ?contentType:'application/soap+xml;charset=UTF-8',

????????????????????? ?data:xml,

????????????????????? ?success:function(){

???????????????????????? alert('保存成功');? ?????????????????

????????????????????? ?}

?????????????????? ?});

??????????????? ?});

??????????? ?});

???????? ?});

????? </script>

????? </html>

?

?

l? 如何通过ant发布第一个cxf应用。

l? 手工建立一个java项目发布cxf的ws.

l? Java项目和js访问webService

l? 加入消息拦截器

l? 将服务端改为SOAP1.2实现

l? SOAP1.1与1.2

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读