CXF集成Spring

最近调研了对webservice实现比较好的框架,觉得Apache的CXF不错.
做了一个简单的技术预研,其中主要包括2方面:1.与Spring的集成,2.安全性方面即WS-Security
首先与Spring的集成可以通过ContextLoaderListener去装配bean
在WS-Security方面可以与WSS4J集成
WSS4J支持多种模式:
XML Security:1.XML Signature 2.XML Encryption
Tokens:1.Username Tokens 2.Timestamps 3.SAML Tokens

做个了小的集成demo项目,项目的包结构如下:

 

CXF集成Spring_第1张图片

 

服务端部分

1. 下面是web.xml的配置,主要配置cxf核心cxfServlet以及Spring的ContextLoaderListener

<?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"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID"
version="2.5">
  <display-name>CXF_Spring_INTG_Test</display-name>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
   classpath:cxf.xml
 </param-value>
  </context-param>
  <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>
  <listener>
    <listener-class>
   org.springframework.web.util.Log4jConfigListener
 </listener-class>
  </listener>
  <!-- configuration unique Web app root for log4j -->
  <context-param> 
      <param-name>webAppRootKey</param-name> 
      <param-value>cxf.root</param-value> 
  </context-param> 
</web-app>

 

2. cxf.xml配置

主要包括两部分:wss4j安全验证及webservice的管理

<?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:jaxws="http://cxf.apache.org/jaxws"
 xsi:schemaLocation="
  http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans.xsd
  http://cxf.apache.org/jaxws
  http://cxf.apache.org/schemas/jaxws.xsd">
 <bean id="saaj" class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />
 
 <bean id="wss4j" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor" >
  <constructor-arg>
   <map>
    <entry key="action" value="UsernameToken" />
    <entry key="passwordType" value="PasswordText" />
    <entry key="passwordCallbackClass" value="com.test.ws.handler.ServerWsAuthHandler" />
   </map>
  </constructor-arg>
 </bean>
 <jaxws:endpoint implementor="com.test.service.ITestWSImpl" address="/TestWS">
  <jaxws:inInterceptors>
   <ref bean="saaj" />
   <ref bean="wss4j" />
  </jaxws:inInterceptors>
 </jaxws:endpoint>
</beans>

 

3. Server端进行WSS4J处理的Handler ServerWsAuthHandler,做了一个简单的密码为明文的验证

public class ServerWsAuthHandler implements CallbackHandler {
 private String passwd = "test";
 
 @Override
 public void handle(Callback[] callbacks) throws IOException,
   UnsupportedCallbackException {
  for (int i = 0; i < callbacks.length; i++) {
   WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];  
   pc.setPassword(passwd);
  }
 }
}

 

4. WebService的接口ITestWS.java

package com.test.service;
import javax.jws.WebService;
@WebService
public interface ITestWS {
 public String sayHello(String name);
}

 

5.  WebService的实现类ITestWSImpl.java

package com.test.service;
import javax.jws.WebService;
@WebService(endpointInterface="com.test.service.ITestWS"
 ,serviceName="ITestWS")
public class ITestWSImpl implements ITestWS{

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

 

客户端部分

1. Client端进行WSS4J处理的Handler ClientWsAuthHandler.java

package com.test.ws.handler;
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 ClientWsAuthHandler implements CallbackHandler {
 private String passwd = "test";
 @Override
 public void handle(Callback[] callbacks) throws IOException,
   UnsupportedCallbackException {
  for (int i = 0; i < callbacks.length; i++) {
   WSPasswordCallback pc = (WSPasswordCallback) callbacks[i];
   pc.setPassword(passwd);
  }
 }
}

2. Client端进行调用的测试类ClientTest

public class ClientTest {
private static List list = new ArrayList(); 
 static{
  Map<String, Object> outProps = new HashMap<String, Object>();
  outProps.put(WSHandlerConstants.ACTION,WSHandlerConstants.USERNAME_TOKEN);
  outProps.put(WSHandlerConstants.USER, "admin");
  //密码类型明文测试使用,还有很多如WSConstants.PASSWORD_DIGEST
  outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
  //outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PASSWORD_DIGEST);
  // 指定在调用远程ws之前触发的回调函数ClientWsAuthHandler,其实类似于一个拦截器
  outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS,ClientWsAuthHandler.class.getName());
  // 添加cxf安全验证拦截器
  list.add(new SAAJOutInterceptor());
  list.add(new WSS4JOutInterceptor(outProps));
 }
 
 public static void main(String[] args){
     //客户端采用动态创建及调用的方式
  JaxWsDynamicClientFactory  factory = JaxWsDynamicClientFactory.newInstance();
     Client client =factory.createClient("http://localhost:8080/Spring_CXF/ws/TestWS?wsdl");
     client.getOutInterceptors().addAll(list);
     try {
   String name = "Tom";
      Object[] param = new Object[]{name};
      Object[] obj =client.invoke("sayHello",param);
      String rtnStr = (String) obj[0];
      System.out.println(rtnStr);
     } catch (Exception e) {
      e.printStackTrace();
     }
 }
}

 

你可能感兴趣的:(spring,webservice,CXF)