您的位置:首页 > 运维架构 > Apache

Web Service应用之CXF开发

2018-02-18 15:21 381 查看

Web Service应用之CXF开发

web service应用之JAX-WS开发链接:http://blog.csdn.net/sinat_32366329/article/details/79085602

简介

Apache CXF =Celtix + XFire,开始叫 Apache CeltiXfire,后来更名为 Apache CXF 了,以下简称为 CXF。CXF 继承了 Celtix 和 XFire 两大开源项目的精华,提供了对 JAX-WS 全面的支持,并且提供了多种 Binding 、DataBinding、Transport 以及各种 Format 的支持,并且可以根据实际项目的需要,采用代码优先(Code First,根据已经存在的代码进行约定、描述服务)或者 WSDL 优先(WSDL First,以wsdl等描述服务,从头开始构建实现服务)来轻松地实现 Web Services 的发布和使用。官网地址:http://cxf.apache.org
Apache CXF 是一个开源的Services 框架,像JAX-WS。它的特点:
l 支持多种协议SOAP1.1,1,2、Http
l 可以与Spring进行快速无缝整合部署灵活
l 可以运行在Tomcat,Jboss,Jetty(内置),IBMWS,BeaWS上面

技术支持

1.jax-ws的支持

CXF实现了jax-ws 的API使得构建web服务更加简单。jax-ws包含许多不同的领域。例如:1)从Java类生成WSDL和从WSDL生成Java类。2)提供的API允许创建简单的消息接收服务器端点。3)允许发送原始的XML格式消息服务器端点等。

2.spring的支持

CXF支持了Spirng 2.0的XML语法,使得更加容易与Spring整合注入项目。可以通过Spring的配置文件发布接口。

3.RESTful服务

CXF通过使用HTTP绑定的注释支持rest式服务的开发。使用URL模板和注解,可以将服务绑定到URL或者VERB组合中。例如可以使用@Get@HttpResource("/customers/{id}")来注解自定义方法。CXF将监听URL上的GET请求,使用{id}位置的参数作为服务器参数。

4.WS-*的支持

CXF还支持多种的web service协议包括:1)WS-Addressing。2)WS-Policy。3)WS-ReliableMessaging。4)WS-Security。

5.支持模块一览













CXF应用

1.   服务端



2.wsdl2java

在cxf中,也提供了一个用于生成客户端调用代码的工具wsdl2java。它的功能和wsimport一样,都可以生成客户端代码。常用的参数有:
 
-d 生成的代码所在目录,不指定则为当前目录
-p 生成的代码所在包
-h 查看帮助
 
【注意】该工具在cxf的bin目录下,如果想在其它目录中使用则需要设置cxf的bin目录在环境变量中。

2.1.wsdl2java安装与配置

下载“apache-cxf-x.x.x.zip”包,解压后包括如下文件:



bin:批处理执行文件,是 CXF 框架中所提供的代码生成、校验、管理控制台等
docs:api文档
etc:配置信息文件
lib:cxf与使用到的依赖包;WHICH_JARS文件中有详细说明。
licenses:授权说明
samples:示例
 
【配置】若使用cxf提供的代码生成工具,需要配置cxf的bin目录到系统环境变量path中。


3.客户端

利用wsdl2java生成客户端代码:
wsdl2java-p com.rabbit.ws.client.hello http://127.0.0.1:9085/ws/hello?wsdl
客户端代码调用:



1.   总结

使用cxf与jax-ws一样可以发布Web Service服务,步骤如下:
1、编写服务实现类并添加@WebService注解;
2、使用cxf自带的客户端代码生成工具wsdl2java,生成客户端代码;
3、利用客户端代码调用服务

2.   拦截器

Cxf有2种拦截器,InInterceptor、OutInterceptor,顾名思义,InInterceptor可以处理soap请求消息,OutInterceptor可以处理soap响应消息。
所有的拦截器都继承自AbstractPhaseInterceptor<?>,此抽象拦截器实现了Interceptor接口!这个类可以指定继承它的拦截器在什么阶段被启用,阶段属性可以通过org.apache.cxf.phase.Phase 中的常量指定值。CXF通过在Interceptor中对消息进行特殊处理,实现了很多重要功能模块,例如:日志记录,Soap消息处理,消息的压缩处理。
Cxf的拦截器是可以在客户端和服务端都可以使用的,in/out都是soap消息相对于客户端或服务器端而言。



日志拦截器
LoggingInInterceptor 信息输入时的拦截器(请求);LoggingOutInterceptor信息输出时的拦截器(响应)。可以在客户端和服务器端都添加这两个拦截器;查看在请求和响应时的消息。
 

服务端添加日志拦截器:



客户端添加日志拦截器:



自定义拦截器

一般拦截器可以用于鉴权,在客户端发送消息之前对soap消息添加头部信息(包含权限信息);然后在服务器端接收到消息后对头部信息进行权限判断是否正确,如果对则调用服务,否则返回失败信息。以此;需要在服务器端添加输入拦截器,而在客户端添加输出拦截器。
服务端输入拦截器在服务器端的输入拦截器主要在调用方法之前,校验soap消息的头部是否存在约定的权限相关信息。
鉴权输入拦截器:

package com.rabbit.ws.cxf.interceptor;

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 AuthInInterceptor extends AbstractPhaseInterceptor<SoapMessage> {

private String uid;
private String psw;

public AuthInInterceptor(String uid, String psw) {
//在调用服务类中的方法之前进行拦截
super(Phase.PRE_INVOKE);

this.uid = uid;
this.psw = psw;
}

@Override
public void handleMessage(SoapMessage soapMessage) throws Fault {
List<Header> headers = soapMessage.getHeaders();

if(headers == null || headers.size() < 1){
throw new Fault(new IllegalArgumentException("没有鉴权消息。"));
}

Header header = headers.get(0);

//获取auth标签
Element authElement = (Element)header.getObject();
//获取uid标签
NodeList uidList = authElement.getElementsByTagName("uid");
String uid = uidList.item(0).getTextContent();

//获取psw标签
NodeList pswList = authElement.getElementsByTagName("psw");
String psw = pswList.item(0).getTextContent();

if(!(this.uid.equals(uid) && this.psw.equals(psw))){
throw new Fault(new IllegalArgumentException("鉴权失败。"));
}

}

}
在发布时添加鉴权输入拦截器:

客户端输出拦截器在客户端的输出拦截器主要是在发送soap请求前,自动的为soap消息头部添加权限相关信息。
鉴权输出拦截器:
Package com.rabbit.ws.client.interceptor;

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 AuthOutInterceptor extends AbstractPhaseInterceptor<SoapMessage> {

private String uid;
private String psw;

public AuthOutInterceptor(String uid, String psw) {
//准备发送时拦截
super(Phase.PREPARE_SEND);
this.uid = uid;
this.psw = psw;
}

@Override
public void handleMessage(SoapMessage soapMessage) throws Fault {

//对soap消息添加头部信息,添加如下信息:
/**
* <auth>
*    <uid>liao</uid>
*    <psw>123456</psw>
* </auth>
*/
List<Header> headers = soapMessage.getHeaders();

//创建document文档对象
Document document = DOMUtils.createDocument();
Element authEle = document.createElement("auth");

Element uidEle = document.createElement("uid");
uidEle.setTextContent(this.uid);
Element pswEle = document.createElement("psw");
pswEle.setTextContent(this.psw);

//添加节点
authEle.appendChild(uidEle);
authEle.appendChild(pswEle);

headers.add(new Header(new QName(""),authEle));
}

}
在发送消息之前添加鉴权输出拦截器:

Spring整合CXF核心配置         

服务端

服务类

@WebService
public interface IHelloWeb {

public String sayHello(String name);
}
public class HelloWebImpl implements IHelloWeb {

@Override
public String sayHello(String name) {
return "Hello Spring,"+name;
}

}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:cxf="http://cxf.apache.org/core" 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-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> 
<!-- 引入cxf配置
<import resource="classpath:META-INF/cxf/cxf.xml" />-->

<!-- 配置ws的服务端 -->
<jaxws:server id="springID" serviceClass="com.rabbit.ws.IHelloWeb"
address="/spring">
<jaxws:serviceBean>
<!-- 服务端类实现类 -->
<bean class=" com.rabbit.ws.impl.HelloWebImpl"></bean>
</jaxws:serviceBean>
</jaxws:server>

</beans>
使用tomcat部署项目启动,然后访问项目wsdl看是否正常显示。例如:http://127.0.0.1:8080/ws-spring-cxf-server/services/spring?wsdl

Web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<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>/services/*</url-pattern>
</servlet-mapping>
</web-app>

客户端

生成客户端代码:

wsdl2java –p com.rabbit.ws.client.byehttp://127.0.0.1:8080/ws-spring-cxf-server/ws/spring?wsdl

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jaxws="http://cxf.apache.org/jaxws" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns:cxf="http://cxf.apache.org/core" 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-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"> 
<jaxws:client id="helloClient"
serviceClass="com.rabbit.ws.IHelloWeb" //具体类路径
address="http://localhost:8080/server/services/spring"></jaxws:client>

</beans>

测试

public class Demo {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("/applicationContext.xml");
IHelloWeb helloWeb = (IHelloWeb)ac.getBean("helloClient");
System.out.println(helloWeb.sayHello("eric"));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息