使用Java向REST服务器发送POST请求时,无法发送ArrayList。

3
我是一名Java REST服务的新手,对于整个Java客户端服务器的概念也不是很了解。我正在尝试实现基本的客户端服务器设计。
从客户端方面来看,我正在尝试POST一个特定类(POJO)对象的ArrayList。以下是我的客户端代码:
public class TestClient1 {

    private static final String webServiceURI = "http://localhost:8080/IadssitHPCServer";
    private static URI serviceURI;
    private static WebTarget webTarget;
    private static ArrayList<ImageInput> imageList;

    public static void main(String[] args) {

        ClientConfig clientConfig = new ClientConfig();
        Client client   = ClientBuilder.newClient(clientConfig);
        serviceURI  = UriBuilder.fromUri(webServiceURI).build();
        webTarget   = client.target(serviceURI);
        webTarget   = webTarget.path("clientserver").path("restservice").path("analyze");

        imageList = new ArrayList<ImageInput>();

        /*
          Code to add objects in the Arraylist
        */  

        Session session= webTarget.request().accept(MediaType.APPLICATION_XML).
                post(Entity.entity(imageList, MediaType.APPLICATION_XML), Session .class);
    }
}

ImageInput(POJO)类:

@XmlRootElement
public class ImageInput implements Serializable {

    private String imageName;
    private String imageDirPath;

    public String getImageName() {
        return imageName;
    }
    public void setImageName(String imageName) {
        this.imageName = imageName;
    }
    public String getImageDirPath() {
        return imageDirPath;
    }
    public void setImageDirPath(String imageDirPath) {
        this.imageDirPath = imageDirPath;
    }
}

在服务器端:

@Path( "/hpcservice" )
@Consumes( MediaType.APPLICATION_XML )
@Produces( MediaType.APPLICATION_XML )
public class HpcService {

    @POST
    @Path( "/analyze" )
    public Session startAnalysing(ArrayList<ImageInput> clientInput){
        System.out.println( "Started Analyzing..." );
        return session;
    }
}

服务器返回一个类的对象Session,这又是一个POJO类。

当我执行代码时,在客户端会出现以下错误:

Oct 19, 2015 3:01:10 PM org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor aroundWriteTo
SEVERE: MessageBodyWriter not found for media type=application/xml, type=class java.util.ArrayList, genericType=class java.util.ArrayList.
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/xml, type=class java.util.ArrayList, genericType=class java.util.ArrayList.
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:247)
    at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:162)
    at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1154)
    at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:503)
    at org.glassfish.jersey.client.HttpUrlConnector._apply(HttpUrlConnector.java:315)
    at org.glassfish.jersey.client.HttpUrlConnector.apply(HttpUrlConnector.java:227)
    at org.glassfish.jersey.client.ClientRuntime.invoke(ClientRuntime.java:246)
    at org.glassfish.jersey.client.JerseyInvocation$2.call(JerseyInvocation.java:683)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:315)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:297)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:228)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:424)
    at org.glassfish.jersey.client.JerseyInvocation.invoke(JerseyInvocation.java:679)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.method(JerseyInvocation.java:435)
    at org.glassfish.jersey.client.JerseyInvocation$Builder.post(JerseyInvocation.java:338)
    at com.TestClient1.main(TestClient1.java:61)

我觉得可能是我发送和接收请求的类型有问题。这个MediaType.APPLICATION_..如何影响/变化与我发送的不同数据结构有关?

我知道我在这里问了一个非常基础的问题,但是无论我在Stack Overflow上找到什么在线解决方案,我都越来越困惑。


使用JSON表示ArrayList的内容。 - Abhishek Singh
REST API使用字符串进行通信...您应该以字符串表示形式表示您的对象。 - Lalit Mehra
@AbhishekSingh 我已经添加了ImageInput类的代码。我的ArrayList内容是这个类的对象。我该如何使用JSON表示这些对象?你能详细说明一下吗? - sandeep.ganage
我还建议您学习更多关于 JSON 的知识,这将对您以后的工作有所帮助。 - Abhishek Singh
3个回答

4

使用包装类

考虑将你的 ArrayList<ImageInput> 封装进一个类中,如下所示:

@XmlRootElement(name = "data")
@XmlAccessorType(XmlAccessType.FIELD)
public class ImageInputData {

    @XmlElement
    private ArrayList<ImageInput> images;

    // Getters and setters ommited
}

您的端点方法将如下所示:
@POST
@Path("/analyze")
public Session startAnalysing(ImageInputData inputData) {

    List<ImageInput> images = inputData.getImages();    
    // Do any processing...
    return session;
}

使用JSON

另外,您可以使用JSON而不是XML。要这样做,请从您的端点中删除以下注释:

@Consumes(MediaType.APPLICATION_XML)

并添加以下内容:

@Consumes(MediaType.APPLICATION_JSON)

如果您想支持XML和JSON格式,可以使用以下代码:
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })

MOXy

由于您使用了JAXB注释,有趣的是您可以使用JAXB注释通过Jersey生成JSON。

为此,您需要将MOXy依赖项添加到您的pom.xml中:

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>2.22.1</version>
</dependency>

如果您没有使用Maven,请确保在类路径中拥有所有所需的依赖项,这些依赖项在此链接中进行了描述。
Jackson 2.x提供了一个非常丰富的注释集,用于从POJOS生成JSON。
如果您更喜欢使用Jackson 2.x作为您的JSON提供者,则需要在您的pom.xml中添加以下依赖项:
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.22.1</version>
</dependency>

如果您没有使用Maven,请确保在类路径中拥有此link中描述的所有依赖项。

更多信息

要了解更多关于常见媒体类型表示的支持,请查看此link

1
在我的情况下,使用包装类是最优解。 - sandeep.ganage

2

在将ArrayList发送到服务器之前,您可能希望将其转换为JSON。使用gson jar可以完成相同的操作。

DataObject obj = new DataObject();
Gson gson = new Gson();

// convert java object to JSON format,
// and returned as JSON formatted string
String json = gson.toJson(obj);

将此字符串发送到服务器。在服务器上解析JSON表示以构建您的对象。

Gson gson = new Gson();
//convert the json string back to object
DataObject obj = gson.fromJson(br, DataObject.class);

DataObject 在你的情况下将会是 ArrayList

参考 http://www.mkyong.com/java/how-do-convert-java-object-to-from-json-format-gson-api/


1

JAXB(默认的Java XML解析器)无法处理ArrayList作为给定对象(因为它是匿名的等等)。尝试使用一个包装类,该类具有一个ArrayList字段,然后发送该类而不是直接发送ArrayList。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接