您的位置:首页 > 其它

CXF+Web Service入门实例展示

2014-06-23 16:15 495 查看
Web Service的三个基本技术:

1.SOAP -- web Service的基本通信协议,是一种规范,用来定义SOAP消息的xml格式

2.WSDL -- 是一个用来描述Web服务和说明如何与Web服务通信的XML语言,

WSDL是Web Service的描述语言,用于描述Web Service的服务,接口绑定等,为用户提供详细的接口说明书

3.UUID -- 即统一描述,发现和集成协议,UUID实现了一组可公开访问的接口,通过这些接口,网络服务可以

以向服务信息库注册其服务信息,服务需求者可以找到分散在世界各地的网络服

(二)代理工厂,安全验证,数据绑定

代理工厂

1.服务端:ServerFactoryBean,JaxWsServerFactoryBean 用于服务端调用.前者针对POJO,后者针对JAX-WS,他们用于生成服务端的EndPoint,暴露出服务接口

2.客户端:ClientProxyFactoryBean,JaxWsProxyFactoryBean 用于客户端调用.前者针对POJO,后者针对JAX-WS,他用于在客户端生成Web Service的代理proxy

3.除了这些Factory,CXF客户端还有ClientFactoryBean,JaxWsClientFactoryBean,这两个Factory生成的不是Web Service的代理,而是一个Endpoint,提供一些更该机的功能.

安全验证

Apache WSS4J(WebService Security For Java) 实现了java语言的 WS-Security.WSS4J依赖于SAAJ.CXF中使用拦截器机制完成WSS4J功能的支持.只需要初始化WSS4JInInterceptor(对应还有一个WSS4JOutInterceptor)实例并添加相关信息即可.CXF2.1.x之后的版本可以完成SAAJInInterceptor(对应的一个SAAJOutInterceptor)拦截器的自动注册,否则需要再注册一下SAAJ拦截器.

1.在spring.xml中配置WSS4J输入拦截器

Xml代码


<span style="font-family: YouYuan,幼圆,tahoma,arial,helvetica,sans-serif;"><bean id="wss4jInInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
<map>
<entry key="xx" value="xx"/>
</map>
</bean>
</span>

在接口服务里面加入关系

Xml代码


<span style="font-family: YouYuan,幼圆,tahoma,arial,helvetica,sans-serif;"><jaxws:inInterceptors>
<ref bean="wss4jInInterceptor" />
</jaxws:inInterceptors>
</span>

下面是服务器端具体密码回调处理类,它负责接收并处理客户端提交的用户名和密码,这个方法没有返回值,显示,如果验证失败,抛出异常表示.

Java代码


<span style="font-family: YouYuan,幼圆,tahoma,arial,helvetica,sans-serif;">import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSecurityException;

public class ServerPasswordCallbackHandler implements CallbackHandler {

public final static String USER = "liu";
public final static String PASSWORD = "lius";//设置用户名密码
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
WSPasswordCallback wspassCallback = (WSPasswordCallback) callbacks[0];
System.out.println(wspassCallback.getIdentifier() + "\t"
+ wspassCallback.getPassword());

if(WSConstants.PASSWORD_TEXT.equals(wspassCallback.getPasswordType())){
if (wspassCallback.getIdentifier().equals(USER)
&& wspassCallback.getPassword().equals(PASSWORD)) {
System.out.println(".................验证通过!");
System.out.println(".................identifier = " + USER);
System.out.println(".................password = " + PASSWORD);
} else {
throw new WSSecurityException("............未通过验证!");
}
} else {
//密码使用MD5密文发送
System.out.println(wspassCallback.getIdentifier());
wspassCallback.setPassword(PASSWORD);
}
}
}
</span>

2.客户端实现:在spring.xml中配置WSS4J输出拦截器

Xml代码


<span style="font-family: YouYuan,幼圆,tahoma,arial,helvetica,sans-serif;"><bean id="wss4jOutInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor">
<map>
<entry key="xx" value="xx"/>
</map>
</bean></span>

在服务接口里加入关系

Xml代码


<span style="font-family: YouYuan,幼圆,tahoma,arial,helvetica,sans-serif;"><jaxws:outInterceptors>
<ref bean="wss4jOutInterceptor" />
</jaxws:outInterceptors</span>

这里使用了WSS4J输出拦截器,因为要将用户名和密码输出到服务器进行验证处理.另外与服务端不同的是多了一个user参数初始化WSS4J的输出拦截器,用于初始化用户名,这是一个必选,稍后将在下面的客户端密码回调处理类进行重新设定值

Java代码


<span style="font-family: YouYuan,幼圆,tahoma,arial,helvetica,sans-serif;">import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;

public class ClientPasswordCallbackHandler implements CallbackHandler{
public final static String USER = "liu";
public final static String PASSWORD = "lius";//设置用户名密码
public void handle(Callback[] callbacks) throws IOException,
UnsupportedCallbackException {
WSPasswordCallback wspassCallback = (WSPasswordCallback)callbacks[0];
wspassCallback.setIdentifier(USER);
wspassCallback.setPassword(PASSWORD);
}
}
</span>

然后我们访问这个web服务,从控制台查看日志,可以看到在SOAP信封的Header中包装了<wsse:Security...等元素,元素包括了WS-Security 的一些信息和设置的用户名和密码.如果使用MD5加密,则密码显示为null,只能显示用户名.如果客户端和服务端的用户名或者密码不对应,则登陆不上,会显示"...为通过验证!".

数据绑定

1.JAXB绑定.JAXB是一套自动映射XML和JAVA 实例的开发接口和工具.如果Web Service发布的接口的参数类型时类,而且返回的类型是List,String等,这样发布的Web Service 与普通的java没区别,因为JAXB都支持.但是JAXB不能将一些java类型自然映射到XML表现形式,例如HashMap,或其他非JavaBean之类,例如接口,Map,这样就要定义一个适配器,使java类型自动适应.一般可以编写一个类继承XmlAdapter,以实现此抽象类的适配器,另外可以安装使用注释XmlJavaTypeAdapter的适配器

2.Aegis Databingding.Aegis是一个快速,基于STAX的数据绑定,他能使采用代码优先方式发布Web Service的情况更简单.Aegis支持接口,集合类,MAP和各种数据类型.也不需要注释,也不需要写适配器

(三)HelloWorld

准备工作

eclipse 3.6

tomcat 6

jdk 1.7

cxf 相关架包,spring相关架包,jdbc相关架包

创建一个工程,把架包添加到lib中



写一个接口

Java代码


package com.cxf.test;

import javax.jws.WebParam;

import javax.jws.WebService;

@WebService

public interface HelloWorld {

String zhuce(String username, String password);

}

写一个实现

Java代码


package com.cxf.test;

import javax.jws.WebService;

/**

* @ WebService:申明为webservice的注解

* endpointInterface:要暴露的接口类

* serviceName : 服务名

*/

@WebService(endpointInterface ="com.cxf.test.HelloWorld",

serviceName = "HelloWorld")

public class HelloWorldImpl implements HelloWorld {

public String zhuce(String username, String password) {

String result = "";

if(username.equals("admin")){

result = "用户名已经存在";

}

else if (password.length() != 6) {

result = "请输入6位数密码";

}

return result;

}

}

发布web service

Java代码


package com.cxf.test;

import javax.xml.ws.Endpoint;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

public class service {

public static void startService() throws Exception{

//通过CXF内置的Jetty应用服务器发布

//方法1:用CXF的JaxWsServerFactoryBean类进行发布。(需要CXF相关包)

HelloWorldImpl hw = new HelloWorldImpl();

JaxWsServerFactoryBean factoryBean = new JaxWsServerFactoryBean();

factoryBean.setAddress("http://localhost:8080/cxf/HelloWorld");

factoryBean.setServiceClass(HelloWorld.class);

factoryBean.setServiceBean(hw);

factoryBean.create();

System.out.println("方法1");

//方法2:使用Sun JAX-WS 2中Endpoint.publish进行发布

/*Endpoint endpoint = Endpoint.publish("http://localhost:10080/cxf/HelloWorld", new HelloWorldImpl());

System.out.println("方法2");*/

}

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

startService();

System.out.println("Web Service 发布成功");

}

}

在浏览器里面输入http://localhost:10080/cxf/HelloWorld?wsdl,就可以看见XML文件了,控制台打印 发布成功.

cxf+web service(四)cxf+spring集成

客户端

Java代码


public class Client {

private Client(){}

public static void main(String[] args) {

ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext-client.xml");

HelloWorld hw = (HelloWorld) context.getBean("client");

String response = hw.zhuce("piter", "123456");

System.out.println(response);

}

}

客户端配置文件,这里面配置代理工厂,地址,暴露的服务接口.这里也可以直接在客户端代码里面使用JaxWsProxyFactoryBean来发布

Java代码


<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"/>

<bean id="client" class="com.cxf.test.HelloWorld" factory-bean="clientFactory" factory-method="create" />

<bean id="clientFactory" class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">

<property name="serviceClass" value="com.cxf.test.HelloWorld" />

<property name="address" value="http://localhost:8080/cxf/ws/HelloWorld" />

</bean>

然后在spring.xml中加入接口的配置

Java代码


<!-- Import Apache CXF Bean Definition -->

<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"/>

<jaxws:endpoint id="helloWorld"

implementor="com.cxf.test.HelloWorldImpl"

address="/HelloWorld"/>

OK,最后在浏览器输入http://localhost:8080/cxf/ws,如下图,发布成功!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: