泽西岛客户请求中的多重返回类型

问题描述 投票:5回答:3

我以以下方式使用Jersey客户端API:-

User user = webRsrc.accept(MediaType.APPLICATION_XML).post(User.class, usr);

因此,我期望User类的对象得到响应,该对象是一个JAXB注释类。但是,有时我可能还会收到一个错误xml,为此我创建了一个JAXB类ErrorResponse。

现在的问题是,如果我的请求返回一个ErrorResponse对象而不是User,我该如何处理?

我尝试过这样-

ClientResponse response=null;
try {

        response = webRsrc.accept(MediaType.APPLICATION_XML).post(ClientResponse.class,usr);
        User usr = response.getEntity(User.class);    
    }catch(Exception exp)
    {
       ErrorResponse err = response.getEntity(ErrorResponse.class);    
    }

但是当我尝试在catch块中使用getEntity()时,它将引发以下异常

[org.xml.sax.SAXParseException: Premature end of file.]
at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.readFrom(AbstractRootElementProvider.java:107)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:532)
at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:491) .....

似乎就像一次调用getEntity()之后,inputstream已耗尽。

web-services rest client jersey
3个回答
10
投票

[我认为您错过了整个“ REST思维方式”的要点。简短的答案:是的,您只能调用一次getEntity。您需要检查返回的HTTP状态,以了解应获取的实体。

在服务器端:

  1. [设计REST API时,对于appropriate status codes,应始终使用HTTP RFC
  2. 为此,请考虑使用the ExceptionMapper interface(这里是example with a "NotFoundException"

因此,现在您的服务器返回带有用户对象的“ HTTP状态正常-200”,或带有错误对象的错误状态。

在客户端:

您需要检查返回状态并根据API规范调整您的行为。这是一个快速而肮脏的代码示例:

ClientResponse response=null;

response = webRsrc.accept(MediaType.APPLICATION_XML).post(ClientResponse.class,usr);

int status = response.getStatus();

if (Response.Status.OK.getStatusCode() == status) {

  // normal case, you receive your User object
  User usr = response.getEntity(User.class);

} else {

  ErrorResponse err = response.getEntity(ErrorResponse.class);
}

注意:根据返回的状态码,此错误可能非常不同(因此需要非常不同的行为):

  • 客户端错误40X:您的客户端请求有误
  • 服务器错误500:服务器端发生意外错误

2
投票

这种代码可用于管理响应中的错误消息或业务消息:

protected <T> T call(String uri, Class<T> c) throws  BusinessException {


    WebResource res = new Client().create().resource(url);
    ClientResponse cresp = res.get(ClientResponse.class);
    InputStream respIS = cresp.getEntityInputStream();


    try {
        // Managing business or error response
        JAXBContext jCtx = JAXBContext.newInstance(c, BeanError.class);
        Object entity = jCtx.createUnmarshaller().unmarshal(respIS);

        // If the response is an error, throw an exception
        if(entity instanceof  BeanError) {
            BeanError error = (BeanError) entity;
            throw new  BusinessException(error);

        // If this not an error, this is the business response
        } else {
            return (T) entity;
        }

    } catch (JAXBException e) {

        throw(new BusinessException(e));
    }



}

0
投票

如果无法更改服务器代码,则可以使用ReaderInterceptor。这确实有一些限制,但是您至少将能够获取错误响应对象的内容。


我使用的是JSON,但适用相同的原则:

public class MyException extends RuntimeException {

    private final ErrorResponse content;

    public MyException(ErrorResponse content) {
        this.content = content;
    }

    public ErrorResponse getContent() {
        return content;
    }
}

public class ErrorResultInterceptor implements ReaderInterceptor {

    private static final ObjectReader JSON = new ObjectMapper().readerFor(ErrorResponse.class);

    @Override
    public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
    byte[] buffer = context.getInputStream().readAllBytes();
    context.setInputStream(new ByteArrayInputStream(buffer));
        try {
            return context.proceed();
        } catch (UnrecognizedPropertyException ex) {
            try {
                throw new MyException(JSON.readValue(buffer));
            } catch (IOException errorProcessingEx) {
                // Log errorProcessingEx using your preferred framework
                throw ex;
            }
        }
    }
}

然后将其用作调用的一部分:

client.register(ErrorResultInterceptor.class);
// Oher client setup
try {
    // Make the client call
    // Handle OK case
} catch (ResponseProcessingException ex) {
    if (ex.getCause() instanceof MyException) {
        ErrorResponse respone = ((MyException)ex.getCause()).getContent();
        // Handle error response
    } else {
        throw ex;
    }
}

限制是:

  • 响应必须被缓冲,这可能是内存开销
  • 获取错误结果的客户端调用非常笨拙
© www.soinside.com 2019 - 2024. All rights reserved.