读书人

CXF施用笔记

发布时间: 2012-08-30 09:55:54 作者: rapoo

CXF使用笔记
第一次用CXF的服务端,写个简单的笔记。

●一、引用的包
直接上maven的pom,里面嵌套引用了好多jar,看起来不是那么爽。

<dependency>    <groupId>org.apache.cxf</groupId>    <artifactId>cxf-rt-frontend-jaxws</artifactId>    <version>2.6.0</version></dependency><dependency>    <groupId>org.apache.cxf</groupId>    <artifactId>cxf-rt-transports-http</artifactId>    <version>2.6.0</version></dependency>


●二、写个简单的服务类(不写接口,懒。。)。没什么特别的,只有一个@WebService注解。
@WebServicepublic class TestService{    public String doSomething(String msg){        System.out.println("有人来访问了,消息:" + msg);        return "谢谢惠顾,您的消息是:" + msg;    }}


●三、在Spring中配置服务(习惯使用spring了,这里不包括spring的其它配置)
<?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:p="http://www.springframework.org/schema/p"      xmlns:jaxws="http://cxf.apache.org/jaxws"      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd                          http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">    <description>WebService配置</description>    <jaxws:endpoint implementor="TestService" address="/test"/></beans>


●四、在web.xml中配置CXF的Servlet。(这里不包括spring的配置)
这里把servlet的路径配置成http://host:port/app/ws
<servlet>      <servlet-name>CXFServlet</servlet-name>      <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>      <load-on-startup>1</load-on-startup>  </servlet> <servlet-mapping>      <servlet-name>CXFServlet</servlet-name>      <url-pattern>/ws/*</url-pattern>  </servlet-mapping>


服务端完成。简单吧。
启动tomcat,访问http://host:port/app/ws,应该看到一个“Available SOAP services”的列表。如果不行,自己看看异常找找原因。。。

●五、用客户端来访问刚才的服务。还是用CXF,其它的不会用。先用CXF提供的wsdl2java工具(在CXF的bin目录下)生成客户端的代码。假设这些代码放在包test中,暂时存放于d:盘中。
CXF主目录/bin/wsdl2java -p test -d d: http://host:port/app/ws/test?wsdl

回车,稍等,在d:盘中生成了一个test目录,里面有几个类,有用的是以下四个:
TestService.javaDoSomething.javaDoSomethingResponse.javaObjectFactory.java

将这些类复制到客户端工程的test包下。

●六、在客户端配置spring(还是spring...)。
这个配置文件叫client-beans.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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">    <bean id="client" factory-method="create"/>    <bean id="clientFactory" value="test.TestService"/> <!-- 这个类是刚才生成的 -->        <property name="address" value="http://host:port/app/ws/test"/> <!-- 这个路径是服务器端配置的 --></bean></beans>


●七、编写客户端代码。在这之前应该像服务端那样引入了spring和cxf相关的包。
这些代码很明了,解释是多余的。难怪会喜欢用sping。
public class ClientTest {public static void main(String args[]) throws Exception {        ClassPathXmlApplicationContext context =         new ClassPathXmlApplicationContext(new String[] {"client-beans.xml"});        TestService client = context.getBean(TestService.class);        String res = client.doSomething("Hi, boy. I come!");        System.out.println(res);        System.exit(0);    }}

分别看看服务端和客户端的输出,体验一下两者大概是怎样交互的。

●八、以上已告一段落。下面要添加一点安全性,用最简单的“用户名-密码”方式。当然要先处理服务端。首先要引用两组新的依赖库:
<!-- WSS4J --><dependency>    <groupId>org.apache.ws.security</groupId>    <artifactId>wss4j</artifactId>    <version>1.6.5</version>    <scope>runtime</scope></dependency><dependency>    <groupId>org.apache.cxf</groupId>    <artifactId>cxf-rt-ws-security</artifactId>    <version>2.6.0</version></dependency>


●九、写一个验证用户名和密码的类
写最简单的,能表现出原理就行。类起名为PasswordCallback。假定提供的用户名是"user123",密码是"pwd123"。
import javax.security.auth.callback.Callback;import javax.security.auth.callback.CallbackHandler;public class PasswordCallback implements CallbackHandler {@Overridepublic void handle(Callback[] callbacks) throws Exception{for (Callback cb : callbacks){WSPasswordCallback pc = (WSPasswordCallback)cb;            if ("user123".equals(pc.getIdentifier())){                pc.setPassword("pwd123");            }}}}


●十、修改spring中的配置,加入拦截器
原本是这样的
<jaxws:endpoint implementor="TestService" address="/test"/>

修改后是
<jaxws:endpoint implementor="TestService" address="/test"><jaxws:inInterceptors><ref bean="wss4JInInterceptor"/></jaxws:inInterceptors></jaxws:endpoint><bean id="wss4JInInterceptor" value="UsernameToken"/><entry key="passwordType" value="PasswordDigest"/><entry key="passwordCallbackRef"><bean name="code">public class ClientPasswordCallback implements CallbackHandler {@Overridepublic void handle(Callback[] callbacks) throws Exception{for (Callback cb : callbacks){WSPasswordCallback pc = (WSPasswordCallback)cb;            pc.setPassword("pwd123");}}}

很简单,就直接将密码设置为pwd123而已。当然只是演示时才这样。至于用户名,是在配置文件中设置。

●十二、修改客户端的spring配置文件
定义一个拦截器,当然与服务端的WSS4JInInterceptor不同,客户端的拦截器是WSS4JOutInterceptor。
<bean id="wss4JOutInterceptor" value="UsernameToken" /> <!-- 要和服务端的配置一致 --><entry key="passwordType" value="PasswordDigest" /> <!-- 要和服务端的配置一致 --><entry key="user" value="user123" /> <!-- 用户名在这里设置 --><entry key="passwordCallbackRef"><bean name="code"><bean id="clientFactory" value="test.TestService"/><property name="address" value="http://host:port/app/ws/test"/><property name="outInterceptors"><list><ref bean="wss4JOutInterceptor"/></list></property></bean>

OK,配置完毕。看起来有点麻烦,其实也不算太复杂,对吧。

●十三、再次运行客户端代码,应该又可以看到正常的结果了。如果不行,自己看看异常找找原因。。。
有一个问题,如果客户端不用CXF,而是用Axis或其它,应该怎样通过安全验证呢,没试过。

读书人网 >软件架构设计

热点推荐