我以以下方式使用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已耗尽。
[我认为您错过了整个“ REST思维方式”的要点。简短的答案:是的,您只能调用一次getEntity。您需要检查返回的HTTP状态,以了解应获取的实体。
在服务器端:
因此,现在您的服务器返回带有用户对象的“ 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);
}
注意:根据返回的状态码,此错误可能非常不同(因此需要非常不同的行为):
这种代码可用于管理响应中的错误消息或业务消息:
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));
}
}
如果无法更改服务器代码,则可以使用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;
}
}
限制是: