GlassFish 4 中EclipseLink MOXY实现REST应用简介(1)
GlassFish 4 中EclipseLink MOXY实现REST应用简介(1)
最近,随着JAVA EE 7 标准的最终落地,其中Oracle 还发布了GlassFish 4服务器,它可以说是JAVA EE 7标准的一种参考实现。 其中,Eclipse旗下的EclipseLink开源项目向JAVE EE 7中贡献了不少力量,其中包括JPA 2.1 (JSR-338)的实现,另外一个贡献是本文向大家介绍的EclipseLink MOXy项目,它是JAVE EE 7中JAX-RS(REST标准)的一个默认的JSON Provider。
首先简单介绍下Eclipse旗下的EclipseLink开源项目,它主要用来实现快速将JAVA中的对象转化为各种类型的XML,该项目主要有如下的特性:
- 支持JAXB中最多的注解
- 同时支持XML和JSON
- 支持最新的JPA 2.1
对JPA-RS的增强支持
MOXY有十分强大的将各类JAVA对象 序列化为XML以及XML反序列化为JAVA对象的能力。这在REST架构的应用中,MOXY可以用来实现JAX-RS标准中的各种转换,下面以一个REST的例子进行讲解。如果读者对REST和JAX-RS标准有不清楚的地方,请参考相关的资料。
我们设计一个最简单的Hello World的REST Webservice。其中Customer对象是一个简单的POJO对象,代码如下:
- package org.example.service;
- import javax.ejb.*;
- import javax.ws.rs.*;
- import javax.ws.rs.core.MediaType;
- import org.example.model.*;
- @Stateless
- @LocalBean
- @Path("/customers")
- public class CustomerService {
- @GET
- @Produces({
- MediaType.APPLICATION_XML,
- MediaType.APPLICATION_JSON
- })
- @Path("{id}")
- public Customer read(@PathParam("id") int id) {
- Customer customer = new Customer();
- customer.setId(id);
- customer.setName("Jane Doe");
- PhoneNumber pn = new PhoneNumber();
- pn.setType("work");
- pn.setValue("5551111");
- customer.getPhoneNumbers().add(pn);
- return customer;
- }
- }
可以看到,Customer对象中有一个PhoneNumber的表示电话号码的Pojo。代码中的注解都是遵守JAX-RS标准的REST相关的注解。其中,用注解
@ MediaType.APPLICATION_XML和@ MediaType.APPLICATION_JSON,分别指出该REST会同时以XML和JSON的形式对外发布。而在JAX-RS标准中,用如下的方式,就可以实现REST的对外发布部署:
- package org.example.service;
- import javax.ws.rs.ApplicationPath;
- import javax.ws.rs.core.Application;
- @ApplicationPath("rest/*")
- public class CustomerApplication extends Application {
- }
其中,@ApplicationPath 注解指定所有服务的相对基址,如果为空字符串,则直接使用上下文根路径。上面表示这个REST服务将以如http://localhost/rest/xxx的形式对外发布,应该的根为rest。
接下来我们具体看Customer这个POJO,代码如下:
- package org.example.model;
- import java.util.*;
- import javax.xml.bind.annotation.*;
- @XmlRootElement
- public class Customer {
- private int id;
- private String name;
- private List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();
- public int getId() {
- return id;
- }
- public void setId(int id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- @XmlElementWrapper
- @XmlElement(name="phoneNumber")
- public List<PhoneNumber> getPhoneNumbers() {
- return phoneNumbers;
- }
- }
在这个Customer对象中,其中保持了对另外一个对象phoneNumber的引用。使用@XmlElementWrapper,其目的是为了在XML中通过单独设置名为phoneNumber的别名标签去
更清晰的输出。
接下来请看PhoneNumber类,代码如下:
- package org.example.model;
- import javax.xml.bind.annotation.*;
- public class PhoneNumber {
- private String type;
- private String value;
- @XmlAttribute
- public String getType() {
- return type;
- }
- public void setType(String type) {
- this.type = type;
- }
- @XmlValue
- public String getValue() {
- return value;
- }
- public void setValue(String value) {
- this.value = value;
- }
- }
注意,其中使用了注解@XmlAttribute,将type设置为转换后XML中的一个属性,而@XmlValue则将字段value直接序列为值,即如下的样子:
用户点评