Web services Jersey客户端请求中的多个返回类型

Web services Jersey客户端请求中的多个返回类型,web-services,rest,client,jersey,Web Services,Rest,Client,Jersey,我以以下方式使用Jersey客户端API:- User user = webRsrc.accept(MediaType.APPLICATION_XML).post(User.class, usr); 因此,我期望用户类的对象中出现响应,这是一个JAXB注释类。 然而,有时我也会得到一个错误xml,为此我创建了一个JAXB类ErrorResponse 现在的问题是,如果我的请求返回一个ErrorResponse对象而不是User,我该如何处理 我试过这样- ClientResponse resp

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

User user = webRsrc.accept(MediaType.APPLICATION_XML).post(User.class, usr);
因此,我期望用户类的对象中出现响应,这是一个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就耗尽了。

我认为您在整个“休息思维方式”中遗漏了一点。
简短回答:是的,您只能调用getEntity一次。您需要检查返回的HTTP状态,以了解应该获得哪个实体

在服务器端:

  • 在设计REST API时,应始终使用以下内容: 对于这件事,请考虑使用(这里是< < /LI>) 因此,现在您的服务器返回带有用户对象的“HTTP状态OK-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:服务器端发生意外错误

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

    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));
        }
    
    
    
    }
    
    protectedt调用(字符串uri,类c)引发BusinessException{
    WebResource res=new Client().create().resource(url);
    ClientResponse cresp=res.get(ClientResponse.class);
    InputStream respIS=cresp.getEntityInputStream();
    试一试{
    //管理业务或错误响应
    JAXBContext jCtx=JAXBContext.newInstance(c,BeanError.class);
    对象实体=jCtx.createUnmarshaller().unmarshal(respIS);
    //如果响应是错误,则引发异常
    if(实体实例的BeanError){
    BeanError=(BeanError)实体;
    抛出新的BusinessException(错误);
    //如果这不是错误,则这是业务响应
    }否则{
    返回(T)实体;
    }
    }捕获(JAXBEException e){
    抛出(新业务异常(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;
        }
    }
    

    限制是:

    • 必须缓冲响应,这可能是内存开销
    • 获取错误结果的客户端调用非常笨拙

    是的,你说得对,Brian m8,谢谢:)不幸的是,设计我正在访问的服务的人似乎没有遵循这些原则。但是每当我设计自己的服务时,你的信息都会非常有用。再次感谢:)