【问题标题】:REST call returning blank XMLREST 调用返回空白 XML
【发布时间】:2014-11-28 03:36:04
【问题描述】:

我对 REST 编程很陌生。

下面是我的类,它旨在返回 XML/JSON,但我很难让它返回正确的值。我尝试返回我的POJO 类的响应、JsonArray 和对象,但它不起作用。我查看了几个线程,但无法弄清楚到底是什么问题。

资源类:

public class UserService {

    UserDBHandler userDBHandler; 
    Friend f;

    @GET
    @Path("users/{userId}/friends")
//  @Produces(MediaType.TEXT_PLAIN)
    @Produces({ MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
    public Friend  getFriends(@PathParam("userId") String userId) throws SQLException, ClassNotFoundException
    {
        System.out.println("userId : " +userId);
        userDBHandler =  new UserDBHandler();
        f = new Friend();



        ArrayList<String> userList = userDBHandler.fetchUsers(userId);

        System.out.println("Array size: "+userList.size());
        Iterator<String> iterator = userList.iterator();

        while(iterator.hasNext())
        {
            f.setUri(iterator.next());
            System.out.println(f.getUri());
        }

        //JsonObject  object = Json.createObjectBuilder().add("frienduri",f.getUri()).build();
        //ResponseBuilder response = Response.ok(f);

        //return Json.createArrayBuilder().add(object).build()
        //return response.build();
        return f;
    }
}

POJO 类:

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;

@XmlRootElement
public class Friend{

    private String friendURI;
    private String event;
    private String uri;

    String getUri() {
        return uri;
    }
    void setUri(String uri) {
        this.uri = uri;
    }
    String getFriendURI() {
        return friendURI;
    }
    void setFriendURI(String friendURI) {
        this.friendURI = friendURI;
    }
    String getEvent() {
        return event;
    }
    void setEvent(String event) {
        this.event = event;
    }
}

这是我返回 ResponseFriend 对象时得到的结果:

**<?xml version="1.0" encoding="UTF-8" standalone="yes"?><friend/>**

当返回 JsonArray 时,我得到的是:

[{"frienduri":{"string":"b@b.com","chars":"b@b.com","valueType":"STRING"}}]

我面临的另一个问题是:如果我创建一个构造函数,我会得到以下错误:

一个 MultiException 有 1 个异常。他们是: 1.java.lang.NoSuchMethodException:在repository.resources.UserService class中找不到合适的构造函数。

我的开发环境是 Tomcat 8、JDK 1.8、Eclipse Luna。

我没有使用 Maven 或 web.xml,而是有一个 Application 类。

我正在使用 jaxrs-ri-2.13 和杰克逊罐子:

  • jackson-core-asl-1.9.2
  • 杰克逊-jaxrs-1.9.2
  • jackson-mapper-asl-1.9.2
  • jackson-xc-1.9.2

Json 罐子

  • javax.json-api-1.0
  • javax.json-1.0.4

谢谢

【问题讨论】:

  • 这不是一个完整的问题。您为 xml 显示的结果将 not 是您显示的代码的结果。顶部元素是&lt;friend&gt;,而不是&lt;f&gt;。你不说你想要什么。我不知道您为什么要尝试返回 JSONArray 和 Friend (它们绝对没有关系)。 Maven 也与web.xml/Application 完全无关。还要发布您正在使用的 JAX-RS 实现以及您拥有的 jar。你需要的不仅仅是标准的 jars 来支持 JSON。
  • 确实是 ,我丢失了输出,所以手动编写了它。对于那个很抱歉。我提到 Maven 只是因为之前我收到了一些 MessageWriter 错误,并且一些线程建议在 maven 中添加一些依赖项。对于 messagewriter 错误,我导入了几个 jackson jars。我将编辑问题以列出罐子。

标签: java json rest jersey jax-rs


【解决方案1】:

首先你应该明白 JAX-RS 是一个规范,而你拥有的 jaxrs-ri-2.13 的 jar 是来自 Jersey 的一个实现(实际上是参考实现)。了解实施对于帮助解决您的问题很重要。所以你应该在你的帖子中提到这一点(通过标签或明确)。

其次,对于序列化,JAX-RS 需要MessageBodyReaders 和MessageBodyWriters。 Jersey 发行版已经支持 xml,但是对于 JSON,我们需要添加一个模块来支持。 Jackson 本身对此提供支持。我们需要一个像jersey-media-jason-jackson 这样的提供者模块。使用 Maven 是获取此模块的最简单方法,因为它依赖于其他 jar。如果我创建一个新的 Maven 项目,只有这个依赖项,这是模块所依赖的工件的完整列表

Jersey 发行版已经包含其中的一些工件。我不确定它们是否都包含在捆绑 jar 中,但基于主要(未捆绑的)Jersey 发行版,不包含未着色的 jar

您将需要去寻找那些 jar 并将它们添加到您的项目中。就像我说的,我不知道 Jersey Bundle jar 是否与其他包一起提供,但是您可以获得使用单个 jar 的完整发行版here。如果使用单个 jar 不起作用,我会考虑使用单独的 jar(所有这些)。

添加这些 jar 包应该可以为您提供 Friend 以支持 JSON。


&lt;?xml version="1.0" encoding="UTF-8" standalone="yes"?&gt;&lt;friend/&gt;

您需要将Friend 访问器方法设为public。作者找不到getXxx 方法,因为它不在同一个包中。您还应该公开 setXxx 方法。


我面临的另一个问题是:如果我创建一个构造函数,我会得到以下错误:

A MultiException has 1 exceptions. They are: 1. java.lang.NoSuchMethodException: Could not find a suitable constructor in repository.resources.UserService class

是的。资源类由 Jersey 创建,它处理我们的请求范围资源类的生命周期,并且需要一个 no-arg 构造函数。添加带参数的构造函数,取消隐式无参数构造函数。但是,即使您创建了一个无参数构造函数并且您创建了其他 arg 构造函数,arg 构造函数也永远不会被调用,除非您将资源类的实例显式创建为单例。


更新

关于 singelton 实例,我在教程中没有找到相同的实例。你能告诉我这样做的方法吗?

当您扩展 Application 时,您可以覆盖 getClasses()(它将是容器管理的请求范围资源类)和 getSingletons,它将成为整个应用程序的单个实例

@ApplicationPath("..")
public class MyApplication extends Application {
    private Set<Class<?>> classes = new HashSet<>();
    private Set<Object> singletons = new HashSet<>();

    public MyApplication() {
        singletons.add(new UserResource(new UserDBHandler()));
    }

    @Override
    public Set<Class<?>> getClasses() {
        return classes;
    }
  
    @Override
    public Set<Object> getSingletons() {
        return singletons;
    }
}

但我不确定你是否真的希望UserResource 成为单身人士。这意味着您希望此资源对于整个应用程序是有状态的,这可能不是我们所希望的。相反,您可以使用 Jersey 支持的注入框架,以便将 UserDBHandler 注入 UserResource 类。类似的东西

@Path("...")
public class UserResource {
    @Inject
    private UserDBHandler handler;
}

@ApplicationPath("..")
public class MyApplication extends Application {
    private Set<Class<?>> classes = new HashSet<>();

    public MyApplication() {
        classes.add(UserResource.class);
        singletons.add(new AppBinder());
    }

    @Override
    public Set<Class<?>> getClasses() {
        return classes;
    }

    class AppBinder extends org.glassfish.hk2.utilities.binding.AbstractBinder {
        @Override
        public void configure() {
            bind(UserDBHandler.class).to(UserDBHandler.class);
        }
    }
}

Custom Injection 上查看更多信息。此外,我刚刚使用单个 jaxrs-rs jar 对此进行了测试,但它没有附带所需的类。您将需要下载单独的 Jersey 发行版(上面提到过)将所有单个 jars,并将所有这些 jars 添加到您的项目中,以使其正常工作,或者至少包括 hk jars,这也是 Jackson 所需的无论如何提供者。

【讨论】:

  • 感谢您的全面回答。让 getter 和 setter 完成了这项工作。现在,获取正确的 XML。也将测试 Json。关于单例实例,我在教程中没有找到相同的。你能告诉我这样做的方法吗?谢谢。
  • 请看我的更新
  • 添加其他jackson jars没有其他效果,输出仍然是[{"friendid":{"string":"b@b.com","chars":"b@b.com ","valueType":"STRING"}}] 但是在响应对象中返回 json 工作正常。
  • 对 JSON 的支持不同。如果您使用JsonArray,那么您正在尝试使用 Java 的 JSONP API。这与使用杰克逊不同。使用 Jackson 允许我们从您的域对象中获取 JSON。使用 JSONP,我们需要使用 API 的 JsonObjectJsonArray 等自己创建 JSON 结构。使用 Jackson,我们可以简单地返回常规 Java 对象,如 FriendList&lt;Friend&gt; 而不是 JsonObject 或 @987654354 @。无论您返回Response 还是Friend,结果都是一样的(有条件)。我更喜欢返回Response
  • ... 这样做,Jersey 将永远不会尝试创建 UserResource,因为我们自己创建它。如果我们让 Jersey 创建它,我们就隐含地说该类应该是一个单例,在这种情况下,Jersey 将为每个请求创建一个新实例。与单例一样,每个请求都将使用相同的实例,这可能不是我们所希望的,具体取决于应用程序语义
猜你喜欢
  • 2017-06-11
  • 2017-01-29
  • 2018-03-06
  • 2020-03-11
  • 1970-01-01
  • 2018-03-28
  • 1970-01-01
  • 1970-01-01
  • 2018-12-23
相关资源
最近更新 更多