一个cxf使用例子

来源:互联网 发布:测试淘宝标题 编辑:程序博客网 时间:2024/06/05 02:34

首先定义一个接口如下:

import java.util.Map;import javax.jws.WebService;import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;@WebServicepublic 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{@Overridepublic String sayHi(String name) {return name+"你好!";}@Overridepublic 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>>{@Overridepublic 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;}@Overridepublic 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消息}@Overridepublic void handleMessage(SoapMessage message) throws Fault {//得到soap消息的所有headerList<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.xsdhttp://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;}@Overridepublic 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.xsdhttp://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;@Beforepublic void init(){ap=new ClassPathXmlApplicationContext("file:D:/soft/common/workspace/cxf_client_spring/WebContent/WEB-INF/config/applicationContext.xml");}@Testpublic 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
原创粉丝点击