一个cxf使用例子

首先定义一个接口如下:

import java.util.Map;

import javax.jws.WebService;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@WebService
public interface HelloCXFServer {
	public String sayHi(String name);
	//@XmlJavaTypeAdapterMap使用该注解需要转换器
	@XmlJavaTypeAdapter(FKXmlAdapter.class) Map<String,Cat> getAllCats();
}
编写实现类如下:

import java.util.HashMap;
import java.util.Map;

import javax.jws.WebService;

import com.cxf.server.Cat;
import com.cxf.server.HelloCXFServer;
@WebService(serviceName="helloCXF",endpointInterface="com.cxf.server.HelloCXFServer")
public class HelloCXFServerImpl implements HelloCXFServer{

	@Override
	public String sayHi(String name) {
		return name+"你好!";
	}

	@Override
	public Map<String, Cat> getAllCats() {
		Map<String,Cat> cats=new HashMap<String,Cat>();
		cats.put("cat1", new Cat("cat1","red"));
		cats.put("cat2", new Cat("cat2","blue"));
		return cats;
	}

}
处理webservice无法转换的数据类型:

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.bind.annotation.adapters.XmlAdapter;

import com.cxf.server.StringCat.Entry;

//第二个泛型为无法处理的类型
//第一个为能够处理的类型
//改转换器负责完成类型转换
public class FKXmlAdapter extends XmlAdapter<StringCat, Map<String,Cat>>{

	@Override
	public Map<String, Cat> unmarshal(StringCat v) throws Exception {
		Map<String, Cat> map=new HashMap<String, Cat>();
		List<Entry> entries = v.getEntries();
		for (Entry entry : entries) {
			map.put(entry.getKey(), entry.getValue());
		}
		return map;
	}

	@Override
	public StringCat marshal(Map<String, Cat> v) throws Exception {
		StringCat stringCat=new StringCat();
		Iterator<String> it=v.keySet().iterator();
		while(it.hasNext()){
			String key=it.next();
			Cat value=v.get(key);
			stringCat.getEntries().add(new Entry(key,value));
		}
		return stringCat;
	}

}

public class Cat {
	private String name;
	private String color;
	
	public Cat() {
		super();
	}
	public Cat(String name, String color) {
		super();
		this.name = name;
		this.color = color;
	}
<span style="white-space:pre">	</span>...
	
}
定义一个封装map的类如下:
import java.util.ArrayList;
import java.util.List;

public class StringCat {
	 
	private List<Entry> entries=new ArrayList<Entry>();

	public List<Entry> getEntries() {
		return entries;
	}

	public void setEntries(List<Entry> entries) {
		this.entries = entries;
	}
	public static  class Entry{
		
		private String key;
		private Cat value;
		
		public Entry() {
		}
		public Entry(String key, Cat value) {
			this.key=key;
			this.value=value;
		}
		public String getKey() {
			return key;
		}
		public void setKey(String key) {
			this.key = key;
		}
		public Cat getValue() {
			return value;
		}
		public void setValue(Cat value) {
			this.value = value;
		}
	}
}
服务器端邀请客户端传入用户名和密码认证代码如下:

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

	public AuthInterceptro() {
		super(Phase.PRE_INVOKE);//改拦截器会在调用之前拦截soap消息
	}

	@Override
	public void handleMessage(SoapMessage message) throws Fault {
		//得到soap消息的所有header
		List<Header> headers=message.getHeaders();
		if(headers==null||headers.isEmpty()){
			throw new Fault(new IllegalArgumentException("没有header不能调用..."));
		}
		//假如邀请第一个header携带用户名和密码信息
		Header firstHeader=headers.get(0);
		Element ele=(Element)firstHeader.getObject();
		NodeList userIds=ele.getElementsByTagName("userId");
		NodeList userPasss=ele.getElementsByTagName("userPass");
		if(userIds.getLength()!=1){
			throw new Fault(new IllegalArgumentException("用户名格式不对..."));
		}
		if(userPasss.getLength()!=1){
			throw new Fault(new IllegalArgumentException("密码格式不对..."));
		}
		String userId=userIds.item(0).getTextContent();
		String userPass=userPasss.item(0).getTextContent();
		
		//检查数据中用户名密码是否被授权
		if(!userId.equals("chenjihong")||!userPass.equals("chen1989CHEN")){
			throw new Fault(new IllegalArgumentException("用户名密码不正确..."));
		}
		
	}

}

接下来发布webservice,这里有两种方式:
第一种代码如下:

import javax.xml.ws.Endpoint;

import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.jaxws.EndpointImpl;
import com.cxf.server.HelloCXFServer;
import com.cxf.server.impl.HelloCXFServerImpl;

public class ServerPublish {
	public static void main(String[] args) {
		HelloCXFServer implementor=new HelloCXFServerImpl();
		EndpointImpl ep = (EndpointImpl)Endpoint.create(implementor);
		ep.publish("http://localhost:8080/cxfServer");
		//这里使用in拦截器,即为每次请求进入服务器之前进行拦截
		ep.getInInterceptors().add(new AuthInterceptro());
		ep.getInInterceptors().add(new LoggingInInterceptor());//cxf自带的日志拦截器
	}
}

第二中在web应用中部署,这里我们采用使用了spring的web应用中部署:

首先在web.xml中配置spring的文件信息和cxf的请求处理信息如下:

<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value> /WEB-INF/config/applicationContext.xml</param-value>
	</context-param>
	<!-- cxf的处理servlet -->
	<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>/cxfService/*</url-pattern>
	</servlet-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:jaxws="http://cxf.apache.org/jaxws" 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
		http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

	<import resource="classpath:META-INF/cxf/cxf.xml" />
	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
	<!-- 对应发布接口的实现类 -->
	<bean id="helloService" class="com.cxf.server.impl.HelloCXFServerImpl" />
	<!-- #helloService应用了上面bean的依赖注入 -->
	<jaxws:endpoint id="helloWorld" implementor="#helloService"
		address="/HelloWorld" >
		<jaxws:inInterceptors>
			<bean class="com.cxf.server.AuthInterceptro"/>
			<bean class="org.apache.cxf.interceptor.LoggingInInterceptor" />
		</jaxws:inInterceptors>	
	</jaxws:endpoint>
</beans>
在浏览器中输入对应的发布地址即可访问wsdl文档。

客户端使用的两种方式:

可以先使用cxf的wsdl2java wsdl地址来生成客户端代码,之后

第一种代码如下:

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;
//客户端拦截器  改拦截器会自动在soap消息发送的时候调用,并且在头部生成一个认证xml片段插入到soap头部中
public class AuthHeaderInterceptor extends AbstractPhaseInterceptor<SoapMessage>{
	private String username;
	private String password;
	public AuthHeaderInterceptor(String username,String password) {
		super(Phase.PREPARE_SEND);//准备发送soap消息时调用拦截器
		this.username=username;
		this.password=password;
	}

	@Override
	public void handleMessage(SoapMessage message) throws Fault {
		List<Header> headers=message.getHeaders();//soap头
		Document doc=DOMUtils.createDocument();//创建xml文档
		Element ele=doc.createElement("authHeader");
		//此处的元素按照服务器要求
		Element userIdEle=doc.createElement("userId");
		userIdEle.setTextContent(username);
		Element userPassEle=doc.createElement("userPass");
		userPassEle.setTextContent(password);
		ele.appendChild(userIdEle);
		ele.appendChild(userPassEle);
		
		QName qname=new QName("test");
		Header header=new Header(qname, ele);
		headers.add(header);//将其添加到头集合中
	}

}
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;

import com.cxf.server.Entry;
import com.cxf.server.HelloCXFServer;
import com.cxf.server.StringCat;
import com.cxf.server.impl.HelloCXF;

public class CXFClient {
	public static void main(String[] args) {
		HelloCXF client=new HelloCXF();
		HelloCXFServer server=client.getHelloCXFServerImplPort();
		Client c=ClientProxy.getClient(server);
		//添加out拦截器 为客户端在发送消息的时候的拦截器
		c.getOutInterceptors().add(new AuthHeaderInterceptor("chenjihong","chen1989CHEN"));
		StringCat sc=server.getAllCats();
		List<Entry> ls=sc.getEntries();
		for (Entry entry : ls) {
			System.out.println(entry.getKey()+"[cat="+entry.getValue().getName()+","+entry.getValue().getColor()+"]");
		}
		System.out.println(server.sayHi("chenjihong"));
		
	}

}
第二种为web应用中集成了spring的整合,认证类都为同一个:

只需要在spring的配置文件中配置如下信息即可:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:jaxws="http://cxf.apache.org/jaxws" 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
		http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

	<import resource="classpath:META-INF/cxf/cxf.xml" />
	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
	<!-- 对应的接口类 通过<span style="font-family: Arial, Helvetica, sans-serif;">helloService即可得到对应的实例调用服务器端接口方法</span><span style="font-family: Arial, Helvetica, sans-serif;"> --></span>
	<jaxws:client id="helloService"
		serviceClass="com.cxf.server.HelloCXFServer"
		address="http://localhost:8080/cxf_spring/cxfService/HelloWorld"
	>
	<jaxws:outInterceptors>
		<bean class="com.cxf.server.AuthHeaderInterceptor">
			<constructor-arg value="xxxx"/>
			<constructor-arg value="xxxxx"/>
		</bean>
	</jaxws:outInterceptors>
	</jaxws:client>
	
</beans>
调用代码为:

public class ClientTest {
	private ApplicationContext ap;
	@Before
	public void init(){
		ap=new ClassPathXmlApplicationContext("file:D:/soft/common/workspace/cxf_client_spring/WebContent/WEB-INF/config/applicationContext.xml");
	}
	
	@Test
	public void test1(){
		HelloCXFServer service=ap.getBean("helloService", HelloCXFServer.class);
		StringCat sc=service.getAllCats();
		List<Entry> es=sc.getEntries();
		for (Entry entry : es) {
			System.out.println(entry.getKey()+"="+entry.getValue().getName());
		}
	}

}

下面是一组加了头的soap消息:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
	<soap:Header>
		<authHeader>
			<userId>xxxx</userId>
			<userPass>xxxxx</userPass>
		</authHeader>
	</soap:Header>
	<soap:Body>
		<ns2:sayHi xmlns:ns2="http://server.cxf.com/">
			<arg0>chenjihong</arg0>
		</ns2:sayHi>
	</soap:Body>
</soap:Envelope>














  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值