`
mj4d
  • 浏览: 302892 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

JAX-WS:背后的技术JAXB及传递Map

阅读更多

接上文JAX-WS:创建简单的webservice,JAX-WS对大部分复杂对象传递都能直接支持。在服务端传递了自定义的复杂对象Person:

public class Person implements Serializable {
    private static final long serialVersionUID = 8336803120311071811L;

    private String            username;
    private Date              birthday;
    private List<Address>     addresses;
//getter/setter

我们来看看根据wsimport生产的客户端中Person的定义:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "person", propOrder = {
    "addresses",
    "birthday",
    "username"
})
public class Person {

    @XmlElement(nillable = true)
    protected List<Address> addresses;
    @XmlSchemaType(name = "dateTime")
    protected XMLGregorianCalendar birthday;
    protected String username;
//getter/setter
}

在生产的客户端代码中多了很多annotation声明,在前面也说了JAX-WS是一种基于xml传递的webservice,也就是需要将传递的参数转化为xml文档,而这其中转化的过程就是我们见到的客户端对象中各种annotation声明,其背后的技术也就是前面说的JAXB(Java Architecture for XML Binding)简单地说就是一种将JAVA对象和XML互相转换的技术。包含在包
javax.jws
javax.xml.bind下提供了一系列解组、编组已经运行时绑定的API
javax.xml.bind.annotation 定义将 Java 程序元素定制成XML模式映射的注释
javax.xml.bind.annotation.adapters XmlAdapter 及其规范定义的子类允许任意 Java 类与 JAXB 一起使用

---------------------------------------- 

主要的接口或类:

HandlerChain 将 Web Service 与外部定义的处理程序链关联。
Oneway 指示给定 @WebMethod 只有一条输入消息并且没有输出。
WebMethod 定制一个公开为 Web Service 操作的方法。
WebParam 定制单个参数到 Web Service 消息部分和 XML 元素的映射关系。
WebResult 定制返回值到 WSDL 部分和 XML 元素的映射关系。
WebService 将 Java 类标记为实现 Web Service,或者将 Java 接口标记为定义 Web Service 接口。

 

Element 这是一个元素标记接口。
Marshaller Marshaller 类负责管理将 Java 内容树序列化回 XML 数据的过程。 
Unmarshaller Unmarshaller 类管理将 XML 数据反序列化为新创建的 Java 内容树的过程,并可在解组时有选择地验证 XML 数据。
UnmarshallerHandler 作为 SAX ContentHandler 实现的 Unmarshaller。
ValidationEvent此事件指示在执行解组操作期间验证传入的 XML 数据时、对 Java 内容树执行按需验证时或将 Java 内容树编组回 XML 数据时遇到问题。
DatatypeConverter可以使用 javaType 绑定声明来自定义 XML 模式数据类型到 Java 数据类型的绑定。
JAXBContext JAXBContext 类提供到 JAXB API 的客户端入口点。
XmlAdapter 修改 Java 类型以适应自定义编组

 

主要的Annotation

XmlAccessorOrder  控制类中字段和属性的排序。
XmlAccessorType  控制默认情况下是否对字段或 Javabean 属性进行系列化。
XmlAttribute   将 JavaBean 属性映射到 XML 属性。
XmlElement   将 JavaBean 属性映射到派生于属性名称的 XML 元素。
XmlElementWrapper  生成一个包装 XML 表示形式的包装器元素。
XmlList    用来将属性映射到列表简单类型。
XmlMimeType   关联控制属性 XML 表示形式的 MIME 类型。 
XmlRootElement   将类或枚举类型映射到 XML 元素。
XmlTransient   阻止将 JavaBean 属性映射到 XML 表示形式。
XmlType   将类或枚举类型映射到 XML 模式类型。
XmlValue   支持将类映射到带有 simpleContent 的 XML 模式复杂类型或 XML 模式简单类型。

 

1、如何解码转码

JAXBContext是JAXB API 的客户端入口,从java到xml的互相转换对应Marshaller和Unmarshaller。一个简单的例子是

JAXBContext jaxbContext = JAXBContext.newInstance(claszz);
Marshaller marshaller = jaxbContext.createMarshaller();

marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "utf-8");
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://sws.org/sample");

marshaller.marshal(t, System.out);
marshaller.marshal(t, new File("c:\\t.xml"));

 这里只是java转xml的例子。设置了格式化输出、encoding等属性、schema等信息,同时输出到控制台和指定文件路径 

 

2、常用annotation
常用的annotation用来绑定转换运行过程中的各种属性,如绑定属性、绑定的顺序、格式化处理等。下面介绍一些常用

@XmlRootElement(name="",namespace="")
标注此类作为xml的一个root节点,常用在顶层类或枚举类型。以下注释一起使用: XmlType、XmlEnum、XmlAccessorType、 XmlAccessorOrder。作为生产xml的root节点,名称可通过name来指定,默认会为该类名

@XmlAccessorType(XmlAccessType.FIELD)
控制对JavaBean的访问方式,一般有PROPERTY(getter/setter)、FIELD,PUBLIC_MEMBER(public getter/setter,fileds)、NONE可用于包,顶层类。若用于包表示该包下所有的类都照此处理,顶层类也即如果该类有其他的实体也将照此处理
默认为@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)

@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
指定序列化javabean的顺序

@XmlElement
@XmlElement 注释可以与以下程序元素一起使用: JavaBean 属性 ,非 static、非 transient 字段 ,XmlElements 中的程序元素

 @XmlElement(name = "firstName")
 private String name;
 private int age;

如果顶层类中标志了访问类型,如Filed。那么各个fileds的名称会被处理为xml中的节点,若按照上面的标注,此时节点名会是firstName

  <firstName>nico</firstName>
  <age>20</age>

@XmlTransient
@XmlTransient 注释对于解决 JavaBean 属性名称与字段名称之间的名称冲突,或者用于防止字段/属性的映射。

 @XmlTransient
 private String lastName;

则lastName不会被映射

@XmlList
@XmlList 来将属性映射到列表简单类型。比较两种序列方式:            

 List<String> data;       
<foo><data>aaaa</data><data>bbbb</data></foo>
            
@XmlList       
List<String> data;
<foo><data>aaaa bbbb</data></foo>

@XmlJavaTypeAdapter(class)
用来描述自定义的adapter,需要继承XmlAdapter,用来对自定义序列化的格式。如我们对时间的格式化输出

 

@XmlValue   
支持将类映射到带有 simpleContent 的 XML 模式复杂类型或 XML 模式简单类型。 简单说就是可以指定格式

<msg name="name">robin</msg>

 下面是一个Person的javabean,包含了一系列的声明:

@XmlRootElement(name = "per")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)
public class Person {
    @XmlElement(name = "firstName")
    private String         name;
    @XmlTransient
    private String         lastName;
    @XmlJavaTypeAdapter(value = DateXmlAdapter.class)
    private Date           birthDay;
    @XmlList
    private List<String>   lang;

    private List<KeyValue> msg;
//getter/setter
}

 其中DateXmlAdapter如下:

public class DateXmlAdapter extends XmlAdapter<String, Date> {

    @Override
    public String marshal(Date v) throws Exception {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 
        return format.format(v);
    }

    @Override
    public Date unmarshal(String v) throws Exception {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 
        return format.parse(v);
    }

}

 KeyValue:

@XmlAccessorType(XmlAccessType.FIELD)
public class KeyValue {

    @XmlAttribute
    private String name;
    @XmlValue
    private String value;

序列化结果为:

Person p = new Person();
p.setName("robin");
p.setLastName("yang");
p.setBirthDay(new Date());
List<String> lang = Arrays.asList(new String[] { "java", "javascript", "python" });
p.setLang(lang);
List<KeyValue> msg = new ArrayList<KeyValue>();
msg.add(new KeyValue("aa", "aaa-value"));
msg.add(new KeyValue("bbb", "bbb-value"));
p.setMsg(msg);
<per>
    <birthDay>2012-11-17</birthDay>
    <lang>java javascript python</lang>
    <msg name="aa">aaa-value</msg>
    <msg name="bbb">bbb-value</msg>
    <firstName>robin</firstName>
</per>

3、JAX-WS传递Map

前面在说到可以传递复杂对象时并没有指定Map,是因为并不支持原生的Map传递。如果需要传递我们需要做一个简单的包装,同时需要利用到上面说的XmlJavaTypeAdapter来对bean到xml转换转换。下面的例子是传递Map实例:

@WebService
public interface JaxWsMapService {

    @WebMethod
    public WrapperMapResult getPersonMap();

}

 WrapperMapResult 只是对Map的一个简单封装:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class WrapperMapResult {

    private String              message;
    private boolean             success;

    @XmlJavaTypeAdapter(value = MapAdapter.class)
    private Map<String, Person> map;

 其中最重要的是MapAdapter:

public class MapAdapter extends XmlAdapter<MapConvertor, Map<String, Person>> {

    @Override
    public Map<String, Person> unmarshal(MapConvertor convertor) throws Exception {
        List<MapEntry> entries = convertor.getEntries();
        if (entries != null && entries.size() > 0) {
            Map<String, Person> map = new HashMap<String, Person>();
            for (MapEntry mapEntry : entries) {
                map.put(mapEntry.getKey(), mapEntry.getValue());
            }
            return map;
        }
        return null;
    }

    @Override
    public MapConvertor marshal(Map<String, Person> map) throws Exception {
        MapConvertor convertor = new MapConvertor();
        for (Map.Entry<String, Person> entry : map.entrySet()) {
            convertor.addEntry(new MapConvertor.MapEntry(entry));
        }
        return convertor;
    }

}

这里声明了MapConvertor用来解析Map<String, Person>

@XmlType(name="MapConvertor")
@XmlAccessorType(XmlAccessType.FIELD)
public class MapConvertor {

    private List<MapEntry> entries = new ArrayList<MapConvertor.MapEntry>();

    public void addEntry(MapEntry entry) {
        entries.add(entry);
    }

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

    //结构依赖于需要Conver的Map,比如这里Map<String, Person>
    public static class MapEntry {
        private String key;
        private Person value;

        public MapEntry() {

        }

        public MapEntry(String key, Person person) {
            this.key = key;
            this.value = person;
        }

        public MapEntry(Map.Entry<String, Person> entry) {
            this.key = entry.getKey();
            this.value = entry.getValue();
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public Person getValue() {
            return value;
        }

        public void setValue(Person value) {
            this.value = value;
        }

    }

}

其他的步骤按照wsimport生产客户端代码调用即可,这样就完成了JAX-WS中map的传递

分享到:
评论

相关推荐

    jaxb-api.jar.jaxws-api.zip_ jaxb-api.jar_cxf_jax-ws.jar_jaxb-api

    标题提到的"jaxb-api.jar.jaxws-api.zip_ jaxb-api.jar_cxf_jax-ws.jar_jaxb-api",是针对这个问题提供的一组支持包。 **JAXB(Java Architecture for XML Binding)** 是Java平台的一个标准,它允许开发者将XML文...

    jax-rs jax-ws所需包,亲测可用

    与JAX-RS不同,JAX-WS通常涉及更复杂的配置和更多的协议层,但它的优势在于支持事务、安全性、可靠消息传递等高级特性。 **压缩包中的文件可能包含:** - `jaxws-api.jar`: JAX-WS规范的API,包含了`javax.xml.ws....

    Jax-ws所需要的JAR包

    2. **jaxb-api.jar**:Java Architecture for XML Binding (JAXB) API,用于XML和Java对象之间的转换,是JAX-WS的重要依赖。 3. **cxf-rt-frontend-jaxws.jar** 和 **cxf-rt-transports-http.jar**:Apache CXF是一...

    解决weblogic部署JAX-WS需要的配置文件

    在WebLogic服务器上部署JAX-WS服务时,可能会遇到一些配置问题。JAX-WS(Java API for XML Web Services)是Java平台上的一个标准,用于创建和部署Web服务。WebLogic作为一款强大的Java EE应用服务器,支持JAX-WS...

    jax-ws api jar包

    - **JAXB(Java Architecture for XML Binding)**:与JAX-WS配合使用,负责XML数据和Java对象之间的转换。当处理XML消息时,JAXB可以将XML数据解析成Java对象,反之亦然。 - **Service类**:JAX-WS提供的一个工具...

    JAX-WS所需Jar包

    标题提到的"JAX-WS所需Jar包"是指为了在Java环境中支持JAX-WS功能,开发者需要的一组核心库。这些库包含了运行和开发JAX-WS Web服务所必需的组件。下面将逐一解释这些库的作用: 1. **jaxb-xjc.jar**: 这是Java ...

    JAX-WS2.0 API

    5. **数据绑定:**JAX-WS使用JAXB(Java Architecture for XML Binding)进行数据绑定,将XML数据自动转换为Java对象和反之亦然。这使得处理XML消息变得更简单,减少了手动解析XML的必要。 6. **异常处理:**JAX-WS...

    JAX-WS 2.2 RI所有相关jar包

    JAX-WS 2.2 RI 所包含的JAR包集合,包含25个JAR包,列表如下: FastInoset.jar gmbal-api-only.jar ha-api.jar javax.annotation.jar javax.mail_1.4.jar jaxb-api.jar jaxb-impl.jar jaxb-xjc.jar jaxws-api...

    webservice之jax-ws

    JAX-WS通常与JAXB(Java Architecture for XML Binding)一起使用,用于自动序列化和反序列化Java对象到XML和反之。JAXB负责将Java对象转换成XML消息,反之亦然,使得数据交换变得简单。 7. **工具支持** 开发者...

    JAX-WS API, JAX-RS API

    **JAX-WS API** Java API for XML Web Services (JAX-WS) 是Java平台上的一个标准接口,用于创建和消费Web服务。它是Sun Microsystems在2004年推出的一个重要框架,旨在简化Web服务的开发,使得Java开发者能够更...

    JAX-WS规范

    JAX-WS通常与JAXB一起使用,以便在SOAP消息中序列化和反序列化Java对象。 ### 6. 实例分析 在提供的文档"web service.doc"中,可能会包含一个具体的JAX-WS服务示例,涵盖上述概念的实战应用。通过阅读该文档,读者...

    JAX-WS2.1用户指南

    通过提供强大的类型安全模型和与Java SE及Java EE平台的紧密集成,JAX-WS使得构建高效、可维护的Web服务成为可能。 2. **基本组件** - **服务端点接口(SEI)**: 定义了Web服务的操作,这些操作对应于SOAP消息中的...

    jax-ws webservice demo

    基于jax-ws 实现的web service client和server端的demo程序。 注:如果使用的是 myeclipse 时 server 部署到tomcat 启动的时候会报错 解决办法:找到myeclipse安装目录下的 plugins 目录里 查找 webservices-rt.jar,...

    metro-jax-ws-jaxws221x.zip

    【标题】"metro-jax-ws-jaxws221x.zip" 提供的是一个关于JAX-WS(Java API for XML Web Services)的开发示例,其中包含了JAX-WS 2.2.1版本的相关组件和库文件。这个压缩包是针对Java开发者设计的,用于帮助他们理解...

    一个包含jax-ws和jax-rs的例子(含服务端和客户端)

    标题中的“一个包含jax-ws和jax-rs的例子(含服务端和客户端)”是指这是一个示例项目,它演示了如何使用Java API for XML Web Services (JAX-WS)和Java API for RESTful Web Services (JAX-RS)来创建和消费Web服务。...

    如何基于JAX-WS开发一个WebService实例

    JAX-WS(Java API for XML Web Services)是Java平台上的一个标准,用于创建和消费Web服务。本篇将深入讲解如何基于JAX-WS开发一个WebService实例。 首先,让我们了解JAX-WS的基本概念。JAX-WS提供了一种简单的方式...

    jax-ws2.1.zip

    **标签:“jax-ws2.1”**表明这个压缩包与JAX-WS 2.1规范相关,该规范发布于2006年,是JAX-WS的早期版本,相对于后续的2.2及更高版本,可能会缺少一些特性或改进,但仍然广泛应用于许多现有的Java EE项目中。...

    学习JAX-WSWebService开发

    JAX-WS(Java API for XML Web Services)是Java平台上的一个标准,用于构建和部署Web服务。它提供了一种简单、类型安全的方式来创建、调用Web服务,并且与Java SE和Java EE环境紧密集成。在本教程中,我们将深入...

    设计与开发 JAX-WS 2.0 Web 服务

    - **数据绑定支持**:通过集成JAXB(Java Architecture for XML Binding),JAX-WS提供了强大的数据绑定功能,简化了XML数据与Java对象之间的转换过程。 - **SOAP消息处理**:集成SAAJ(SOAP with Attachments API ...

    jax-ws发布webservice

    在这个场景中,我们将深入探讨如何使用JDK 1.6及以上版本内置的JAX-WS来发布Web服务。 一、JAX-WS基础 1. **定义服务接口**:在JAX-WS中,我们首先定义一个Java接口,该接口声明了Web服务提供的操作。这些接口方法...

Global site tag (gtag.js) - Google Analytics