CXF有多种数据绑定方式,如:Aegis Databinding,JAXB,MTOM Attachments . 其中JAXB(JavaTM Architecture for XML Binding)是其默认的数据绑定方式。JAXB是一套自动映射XML和Java实例的开发接口和工具。
如果web Service发布的接口为:
String sayUserHello(User user);
List<User> findUsers();
且传入参数类型是类,而且返回的为List ,String 等,这样,发布web service与普通java的没有区别,是因为JAXB都能支持。
但JAXB不能将一些 Java 类型自然映射到 XML 表示形式,例如,HashMap 或其他非 JavaBean 类。如参数类型为接口,以及Map ,这需要特殊的XmlAdapter类进行处理. 例如:
1、 编写要发布的web service 接口和实现
import javax.jws.WebService; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @WebService public interface HelloWorld { String sayHello(String text); String sayUserHello(User user); List<User> findUsers(); @XmlJavaTypeAdapter(UserMapAdapter.class) Map<Integer, User> getMapUsers(); } import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import javax.jws.WebService; @WebService(endpointInterface = "test.HelloWorld", serviceName = "HelloWorld") public class HelloWorldImpl implements HelloWorld { public String sayHello(String text) { return "Hello " + text; } public String sayUserHello(User user) { return "Hello " + (user!=null?user.getUsername():"guest"); } public List<User> findUsers() { ArrayList<User> list = new ArrayList<User>(); list.add(new UserImpl("aa","bb")); list.add(new UserImpl("aa1","bb")); list.add(new UserImpl("aa2","bb")); list.add(new UserImpl("aa3","bb")); return list; } public Map<Integer,User> getMapUsers() { Map<Integer, User> users = new LinkedHashMap<Integer, User>(); users.put(1, new UserImpl("aa","bb")); users.put(2, new UserImpl("sss","sss")); return users; } } import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlJavaTypeAdapter(UserAdapter.class) public interface User { String getPassword(); String getUsername(); void setUsername(String username); void setPassword(String password); void setUserId(Integer userId); Integer getUserId(); } @XmlType(name = "User") public class UserImpl implements User { private Integer userId; private String username; private String password; public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public UserImpl(String username, String password) { super(); this.username = username; this.password = password; } public UserImpl() { } public UserImpl(String username) { this.username = username; } public UserImpl(Integer userId, String username, String password) { this.userId = userId; this.username = username; this.password = password; } }
2、 编写适配器
因为JAXB不支持将HashMap 或其他非 JavaBean 类 自然映射到xml表示形式,这样就要定义一个适配器使用java类型适应自定义编组.一般有两步:
1>. 编写一个类继承XmlAdapter,以实现此抽象类的适配器。
2>. 安装使用注释 XmlJavaTypeAdapter 的适配器。
类XmlAdapter的说明:
类 XmlAdapter<ValueType,BoundType>
BoundType - JAXB 不知道如何处理的一些类型。编写一个适配器,以便允许通过 ValueType 将此类型用作内存表示形式。
ValueType - JAXB 无需其他操作便知道如何处理的类型。
其两个抽象方法:
marshal(...):编组过程中,JAXB 绑定框架调用 XmlAdapter.marshal(..) 将 bound 类型修改为 value 类型,然后将 value 类型编组为 XML 表示形式。
unmarshal(...):解组过程中,JAXB 绑定框架首先将 XML 表示形式解组为 value 类型,然后调用 XmlAdapter.unmarshal(..) 将 value 类型修改为 bound 类型。
常用的几个注释说明:
a.@XmlJavaTypeAdapter 注释可以与下列编程元素一起使用: JavaBean 属性 、字段、参数 、包 、XmlJavaTypeAdapters 内部的元素 。用来表示使用实现 XmlAdapter 的适配器,告诉其如何如何转换。
b. @XmlType 注释可以与以下程序元素一起使用:顶层类、枚举类型 。表示将类或枚举类型映射到 XML 模式类型。
c. @XmlAccessorType 注释可以与以下程序元素一起使用:包、顶层类。表示控制默认情况下是否对字段或 Javabean 属性进行序列化。
@XmlAccessorType(XmlAccessType.FIELD)
FIELD :JAXB 绑定类中的每个非静态、非瞬态字段将会自动绑定到 XML,除非由 XmlTransient 注释。
d. @XmlElement 注释可以与以下程序元素一起使用: JavaBean 属性、非 static、非 transient 字段 、XmlElements 中的程序元素 。表示将 JavaBean 属性映射到派生于属性名称的 XML 元素。
如:将User接口转化的适配器类:UserAdapter:
import javax.xml.bind.annotation.adapters.XmlAdapter; /*XmlAdapter<ValueType,BoundType> * BoundType - JAXB 不知道如何处理的一些类型。编写一个适配器,以便允许通过 ValueType 将此类型用作内存表示形式。 ValueType - JAXB 无需其他操作便知道如何处理的类型。 */ public class UserAdapter extends XmlAdapter<UserImpl, User> { /*marshal表示要将user类型编组为UserImpl类型*/ public UserImpl marshal(User v) throws Exception { if (v instanceof UserImpl) { return (UserImpl)v; } return new UserImpl(v.getUsername(),v.getPassword()); } /*marshal表示要将UserImpl类型解组为具体的类User*/ public User unmarshal(UserImpl v) throws Exception { return v; } } 将Map转化的适配器类:UserMapAdapter.java 和UserMap.java @XmlType(name = "UserMap") @XmlAccessorType(XmlAccessType.FIELD) public class UserMap { @XmlElement(nillable = false, name = "entry") List<UserEntry> entries = new ArrayList<UserEntry>(); /** * @return the entries */ public List<UserEntry> getEntries() { return entries; } @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "IdentifiedUser") static class UserEntry { //Map keys cannot be null @XmlElement(required = true, nillable = false) Integer id; User user; public void setId(Integer k) { id = k; } public Integer getId() { return id; } public void setUser(User u) { user = u; } public User getUser() { return user; } } } public class UserMapAdapter extends XmlAdapter<UserMap,Map<Integer,User>> { @Override public UserMap marshal(Map<Integer, User> v) throws Exception { UserMap userMap=new UserMap(); for (Map.Entry<Integer, User> e : v.entrySet()) { UserMap.UserEntry iue = new UserMap.UserEntry(); iue.setUser(e.getValue()); iue.setId(e.getKey()); userMap.getEntries().add(iue); } return userMap; } @Override public Map<Integer, User> unmarshal(UserMap v) throws Exception { Map<Integer, User> map = new LinkedHashMap<Integer, User>(); for (UserMap.UserEntry e : v.getEntries()) { map.put(e.getId(), e.getUser()); } return map; } }
3、 发布web service
public class Server { protected Server() throws Exception { System.out.println("Starting Server"); HelloWorldImpl implementor = new HelloWorldImpl(); String address = "http://localhost:9000/helloWorld"; Endpoint.publish(address, implementor); } public static void main(String args[]) throws Exception { new Server(); System.out.println("Server ready..."); Thread.sleep(5 * 60 * 1000); System.out.println("Server exiting"); System.exit(0); } } 运行后,在浏览器中输入http://localhost:9000/helloWorld?wsdl将显示这个web service的wsdl.说明web service发布成功。
4、 生成客户端代码
下面就开始创建一个客户端程序,访问这个web service, 同样新建java project ,并加入apache-cxf-2.0.7/lib所有包,由于CXF已经提供wsdl转化成java 的命令工具,所以创建一个build.xml,用来生成客户端程序。Bulid.xml内容如下:
<?xml version="1.0"?> <project name="cxf wsdl2java" basedir="."> <property name="cxf.home" location ="${basedir}/WebRoot/WEB-INF/"/> <path id="cxf.classpath"> <fileset dir="${cxf.home}/lib"> <include name="*.jar"/> </fileset> </path> <target name="cxfWSDLToJava"> <java classname="org.apache.cxf.tools.wsdlto.WSDLToJava" fork="true"> <arg value="-client"/> <arg value="-d"/> <arg value="src"/> <arg value="http://localhost:9000/helloWorld?wsdl"/> <classpath> <path refid="cxf.classpath"/> </classpath> </java> </target> </project>
或者:配置环境变量%CXF_HOME%=E:/WebService/CXF/apache-cxf-2.1.1/apache-cxf-2.1.1(以我的目录为例),并在PATH后加上;%CXF_HOME%/bin
在cmd命令行中输入wsdl2java如果显示其用法表示配置好了。
输入:wsdl2java -d src - client http://localhost:9000/helloWorld?wsdl
其作用上面的build.xml作用一样。
附加:wsdl2java用法:
wsdl2java -p com -d src -all aa.wsdl
-p 指定其wsdl的命名空间,也就是要生成代码的包名:
-d 指定要产生代码所在目录
-client 生成客户端测试web service的代码
-server 生成服务器启动web service的代码
-impl 生成web service的实现代码
-ant 生成build.xml文件
-all 生成所有开始端点代码:types,service proxy,,service interface, server mainline, client mainline, implementation object, and an Ant build.xml file.
详细用法见:http://cwiki.apache.org/CXF20DOC/wsdl-to-java.html
5、 调用web service
import demo.hw.server.HelloWorld; import demo.hw.server.HelloWorld_Service; import demo.hw.server.IdentifiedUser; import demo.hw.server.User; import demo.hw.server.UserMap; public class MyClient { public static void main(String[] argv) { HelloWorld hello = new HelloWorld_Service().getHelloWorldImplPort(); User user = new User(); user.setUsername("11111111111111"); System.out.println(hello.sayUserHello(user)); List<User> list = hello.findUsers(); Iterator<User> i = list.iterator(); while (i.hasNext()) { User u = i.next(); System.out.println(u.getUsername()); } UserMap map = hello.getMapUsers(); for (IdentifiedUser e : map.getEntry()) { System.out.println(e.getId()); System.out.println(e.getUser().getUsername()); } } }
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/pengchua/archive/2008/07/30/2740578.aspx