3

我正在将 RestTemplate 用于 android 客户端。我在服务器端使用带有 JaxB 注释的简单 XML 注释对象和相同的 java 对象。我成功发送/接收字符串和其他原始类型,但字节数组有问题。当我在服务器的 JaxB 端看到时,我从 Simple XML 发送的字节数组被转换为其他内容。下面是代码..

REST 服务器上的 JaxB 注释对象

import java.io.Serializable;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Device implements Serializable
{
    private final static long serialVersionUID = 1L;
    protected byte[] imageRef;

    public Device() {
        super();
    }

    public byte[] getImageRef() {
        return imageRef;
    }

    public void setImageRef(byte[] imageRef) {
        this.imageRef = imageRef;
    }
}

这是 Rest 服务器的样子。我为此使用 Apache CXF。

<bean id="xmlBeanProvider" class="org.apache.cxf.jaxrs.provider.XMLBeansElementProvider"/>
    <bean id="jacksonJsonProvider" class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>

    <jaxrs:server id="dataRESTService" address="/">
         <jaxrs:serviceBeans>
            <ref bean="MyDataRESTService"/>
        </jaxrs:serviceBeans>
        <jaxrs:providers>
            <ref bean="xmlBeanProvider"/>
            <ref bean="jacksonJsonProvider"/>
        </jaxrs:providers>
    </jaxrs:server>
    <context:component-scan base-package="com.xxx.restservices" />

和控制器

@Path("/mydata")
@Produces(MediaType.APPLICATION_XML)
@Consumes(MediaType.APPLICATION_XML)
@Service
public class MyDataRESTService 
{   
    @POST
    @Path("/testpost")
    public String testPost(Device device)
    {
        //device.getImageRef() returns [-41, 109, -8] for the bytes
    }
}

这是 Android 客户端的外观

Android 上的简单 XML 注释对象

import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;

@Root
public class Device implements Serializable
{
    private final static long serialVersionUID = 1L;
    @Element
    protected byte[] imageRef;

    public Device() {
        super();
    }

    public byte[] getImageRef() {
        return imageRef;
    }

    public void setImageRef(byte[] imageRef) {
        this.imageRef = imageRef;
    }   
}

带有简单 XML 转换器的 RestTemplate 客户端

public void testPost() 
 {

          RestTemplate restTemplate = new RestTemplate();
          Serializer serializer = new Persister();
      restTemplate.getMessageConverters().add(new          SimpleXmlHttpMessageConverter(serializer));
       restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
       restTemplate.getMessageConverters().add(new FormHttpMessageConverter());

       Device device = new Device();
       device.setImageRef(new byte[]{1,2,3,4,5});
       String response =  restTemplate.postForObject("http://10.0.0.3:8080/rest/mydata/testpost", device, String.class);
        assertNotNull(response);

 }

所以基本上当我在服务器上发送byte[]{1,2,3,4,5}的字节数组时,我得到了这个字节数组 [-41, 109, -8]。我尝试在服务器端使用 Base64 进行解码,认为可能是简单的 xml 正在对其进行编码,但无法弄清楚发生了什么?

同样,如果我执行 Get 操作而不是 Post,那么我会在 android 客户端中得到 NumberFormat 异常。org.springframework.http.converter.HttpMessageNotReadableException lang.Integer.invalidInt(Integer.java:138) 在 java.lang.Integer.parse(Integer.java:375) 在 java.lang.Integer.parseInt(Integer.java:366) 在 java.lang.Byte.parseByte (Byte.java:214) 在 java.lang.Byte.parseByte(Byte.java:195) 在 java.lang.Byte.valueOf(Byte.java:264) 在 org.simpleframework.xml.transform.ByteTransform.read( ByteTransform.java:55)

任何帮助将不胜感激。

4

3 回答 3

1

我跟进了@Blaise Doughan 的建议,编写了一个自定义转换器。我在简单 XML 方面写了一篇。但是,它仅适用于向服务器发送数据,但接收它不起作用。这是转换器的外观。我认为这可能是一个简单的 XML 问题,因此这篇文章的答案是我们必须编写一个自定义转换器。我为 Simple XML 的人发布了一个后续问题,看看为什么当我们将 xml 序列化回对象时没有调用 read 方法?请参阅此处的问题,用于简单 xml 的自定义转换器无法正常工作

我在 read 方法中设置了一个断点,看起来它从未被调用过。简单的 XML 解析器在此异常之前失败org.springframework.http.converter.HttpMessageNotReadableException:无法读取 [class cs.core.mobile.database.JaxBResponse]; 嵌套异常是 java.lang.NumberFormatException: Invalid int: "AAECAwQ="

import org.restlet.engine.util.Base64;
import org.simpleframework.xml.convert.Converter;
import org.simpleframework.xml.stream.InputNode;
import org.simpleframework.xml.stream.OutputNode;

public class ByteArrayConverter implements Converter<byte[]>
{

    @Override
    public byte[] read(InputNode node) throws Exception 
    {
        String value = node.getValue();
        return Base64.decode(value);
    }

    @Override
    public void write(OutputNode node, byte[] byteArray) throws Exception 
    {       
        node.setValue(Base64.encode(byteArray, false));     
    }



}
于 2013-07-10T15:45:44.783 回答
1

耶...我让它工作了。唷.. 所以我用简单的 xml 写了这个ByteArrayConverter。我围绕 byte[] 创建了一个名为 ByteArrayWrapper 的包装类,并将 Converter 替换为 Converter

public class ByteArrayConverter implements Converter<ByteArrayWrapper>
{
    @Override
    public ByteArrayWrapper read(InputNode node) throws Exception 
    {
        InputNode nextnode = node.getNext();
        return new ByteArrayWrapper(Base64.decode(nextnode.getValue()));
    }

    public void write(OutputNode node, ByteArrayWrapper byteArray) throws Exception 
    {       
        OutputNode byteArrayNode = node.getChild("byteArray");
        byteArrayNode.setValue(Base64.encode(byteArray.getByteArray(), false));     
    }

}

这是我的简单 ByteArrayWrapper 类

@Root
public class ByteArrayWrapper
{
    @Element
    protected byte[] byteArray;

    public ByteArrayWrapper()
    {
        super();
    }

    getters..
        setters..
}

这是 Device 类的外观

@Root
public class Device implements Serializable
{
    private final static long serialVersionUID = 1L;
    @Element
    @Convert(ByteArrayConverter.class)
    private ByteArrayWrapper imageRef;

    public Device() {
        super();
    }

    public ByteArrayWrapper getImageRef() {
        return imageRef;
    }

    public void setImageRefByteArrayWrapper imageRef) {
        this.imageRef = imageRef;
    }   
}

最后是 RestTemplate 客户端

public void testPost() 
 {

      RestTemplate restTemplate = new RestTemplate();          
      Strategy strategy = new AnnotationStrategy();
      Serializer serializer = new Persister(strategy);
      restTemplate.getMessageConverters().add(new     SimpleXmlHttpMessageConverter(serializer));
       restTemplate.getMessageConverters().add(new StringHttpMessageConverter());


       Device device = new Device();
       device.setImageRef(new byte[]{1,2,3,4,5});
       String response =  restTemplate.postForObject("http://10.0.0.3:8080/rest/mydata/testpost", device, String.class);
        assertNotNull(response);
 }

一切都很好!感谢@Blaise Doughan 的指点。

于 2013-07-11T14:54:28.533 回答
0

JAXB 实现将期望 a在 XMLbyte[]中表示。base64Binary根据您的评论,简单 XML 具有以下表示形式byte[]

<imageRef length="5">1, 2, 3, 4, 5</imageRef>

您将需要选择是要使用base64Binary来自 JAXB 的表示还是来自 Simple XML 的专有表示,并为对方使用适配器/转换器以使其理解您选择的表示。

于 2013-07-09T16:31:56.193 回答