解决:Apache CXF无法自动转换JSON数据

来源:互联网 发布:淘宝高仿nike鞋店推荐 编辑:程序博客网 时间:2024/04/30 11:41

问题描述

  Apache CXF是一个比较成熟的Java版Web Service框架,我们当前的项目中正在使用。它当然支持RESTful风格的Web Service,也支持JSON的数据格式。但是,在最新的3.0.4版本中,却无法自动将数据转换为JSON格式。
  像下面这样发布一个HelloWorld服务的话,是可以成功的。但是对于需要转换JSON数据的场景(通过JAXB方式或其他),它会报出错误。

package com.tech4j.demo;import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;import com.tech4j.demo.webservice.HelloWorld;import com.tech4j.demo.webservice.HelloWorldImpl;public class CxfJsonProviderDemo {    public static void main(String[] args) {        HelloWorld hello = new HelloWorldImpl();        JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();        factory.setResourceClasses(HelloWorld.class);        factory.setResourceProvider(HelloWorld.class,                new SingletonResourceProvider(hello));        String address = "http://localhost:9000/MyService";        factory.setAddress(address);        factory.create();    }}

  在这段代码中,HelloWorld接口定义了一个getPerson()方法,它返回一个Person类型的对象,并且使用@Produces注解声明其为JSON格式的数据。具体接口和实现类的代码略。
  如果通过浏览器访问地址http://localhost:9000/MyService/HelloWorld/getPerson,页面会提示说“No message body writer has been found for class com.tech4j.demo.webservice.Person, ContentType: application/json”。虽然服务发布成功,但是却无法将Person类型的对象转换为JSON数据。

解决方案

  这是由于新版本的CXF中已经不再提供默认的JSON Provider了,我们需要自己找一个第三方的Provider,设置给CXF框架,它才能够自动调用该Provider完成转换操作。
  我们需要在发布服务的时候,为CXF的服务factory设置这个第三方的Provider,例如Jackson。代码如下:

JacksonJaxbJsonProvider jaxbProvider = new JacksonJaxbJsonProvider();factory.setProvider(jaxbProvider);

  这样一来,CXF就会自动调用这个Provider来完成符合JAXB标准的对象与JSON格式的转换工作。

Maven信息

Apache CXF

  CXF框架当前最新的Maven构建信息如下(可根据实际需要扩充或修改):

<dependency>    <groupId>org.apache.cxf</groupId>    <artifactId>cxf-rt-frontend-jaxws</artifactId>    <version>3.0.4</version></dependency><dependency>    <groupId>org.apache.cxf</groupId>    <artifactId>cxf-rt-frontend-jaxrs</artifactId>    <version>3.0.4</version></dependency><dependency>    <groupId>org.apache.cxf</groupId>    <artifactId>cxf-rt-transports-http</artifactId>    <version>3.0.4</version></dependency><dependency>    <groupId>org.apache.cxf</groupId>    <artifactId>cxf-rt-transports-http-jetty</artifactId>    <version>3.0.4</version></dependency>

SLF4J-Log4j

  CXF默认不含有日志记录的组件,需要手动再引入SLF4J和/或Log4j的Maven依赖。如下所示:

<dependency>    <groupId>org.slf4j</groupId>    <artifactId>slf4j-log4j12</artifactId>    <version>1.7.10</version></dependency>

JacksonJsonProvider

  Jackson专门针对JAX-RS标准提供了JSON Provider,其Maven信息如下:

<dependency>    <groupId>com.fasterxml.jackson.jaxrs</groupId>    <artifactId>jackson-jaxrs-json-provider</artifactId>    <version>2.5.2</version></dependency>

参考代码

HelloWorld.java

package com.tech4j.demo.webservice;import javax.ws.rs.GET;import javax.ws.rs.Path;import javax.ws.rs.Produces;import javax.ws.rs.core.MediaType;@Path("/HelloWorld")public interface HelloWorld {    @GET    @Path("/getPerson")    @Produces(MediaType.APPLICATION_JSON)    public Person getPerson();}

HelloWorldImpl.java

package com.tech4j.demo.webservice;public class HelloWorldImpl implements HelloWorld {    @Override    public Person getPerson() {        return new Person("JavaHuan", 24);    }}

Person.java

package com.tech4j.demo.webservice;import javax.xml.bind.annotation.XmlRootElement;@XmlRootElementpublic class Person {    private String name;    private Integer age;    public Person() {    }    public Person(String name, Integer age) {        super();        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public Integer getAge() {        return age;    }    public void setAge(Integer age) {        this.age = age;    }}

  Person类中含有JAXB的注解配置,如@XmlRootElement。还可以添加其他的JAXB注解。

0 0
原创粉丝点击