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"));
}
}
知春秋
认证博客专家
博客专家
Java高级研发
不忘初心,方得始终。初心易得,始终难守。