2

我目前正在尝试使用 CXF 2.6.4 为 REST 应用程序开发一个简单的概念证明。我正在采用非弹簧方法。我使用 JBoss AS 7.1.1 Final 作为我的 Web 服务器。

以下是我的网络服务类:

package restful.webservice;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import restful.entity.ControllerVersion;

@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class WebServiceRest implements WebServiceInterface
{

    @Override
    @POST
    @GET
    @Path("/getVersion")
    public ControllerVersion getVersion(String deviceID, String[] macAddresses)
    {

        return new ControllerVersion();
    }
}

控制器版本类:

package restful.entity;

@XmlRootElement(name = "ControllerVersion")
public class ControllerVersion {

    private String version="R1.1.0.0";

    public String getVersion() {
        return version;
    }

}

现在,当我尝试对我的 Web 服务进行 REST 调用时,我在服务器端收到以下异常:

18:51:52,913 WARNING [org.apache.cxf.jaxrs.utils.JAXRSUtils] (http--0.0.0.0-8080-1) No message body reader has been found for request class String[], ContentType : application/json.
18:51:52,927 WARNING [org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper] (http--0.0.0.0-8080-1) javax.ws.rs.WebApplicationException
        at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java:1054)
        at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:614)
        at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:578)
        at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:238)
        at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:89)
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
        at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
        at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:236)
        at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:209)
        at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:154)
        at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:130)
        at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:225)
        at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:145)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
        at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:201)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
        at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930)
        at java.lang.Thread.run(Thread.java:662)

我在 WEB-INF/lib 下拥有的库是:

cxf-api-2.6.4.jar
cxf-bundle-2.6.4.jar
cxf-rt-frontend-jaxrs-2.6.4.jar
cxf-rt-frontend-jaxrs.jar
cxf-rt-transports-http-2.6.4.jar
geronimo-servlet.jar
jaxb-api-2.2.5.jar
jaxb-impl-2.2.5.1.jar
jaxb-xjc-2.2.5.1.jar
jettison-1.3.4.jar
log4j-1.2.16.jar
neethi-3.0.2.jar
xmlschema-core-2.0.3.jar

有趣的是我尝试做另一个项目,但是这次在我的 Web 服务方法的签名中,我包含了一个自定义类。我在阅读自定义类实例的内容时没有问题,在将其返回给我的客户时也没有问题。

我错过了什么吗?

更新: 我尝试将以下内容添加到我的 web.xml:

<init-param>
  <param-name>jaxrs.providers</param-name>
  <param-value>
      org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider
      (writeXsiType=false)
  </param-value> 
</init-param>

并添加了以下依赖项:

jackson-jaxrs-1.9.2.jar
jackson-mapper-asl-1.9.2.jar
jackson-xc-1.9.2.jar

现在我收到以下异常:

19:22:29,762 WARNING [org.apache.cxf.jaxrs.impl.WebApplicationExceptionMapper] (http--0.0.0.0-8080-1) javax.ws.rs.WebApplicationException: java.io.IOException: Stream closed
        at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:243)
        at org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:89)
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:262)
        at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
        at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:236)
        at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:209)
        at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:154)
        at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:130)
        at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:225)
        at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:145)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
        at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:201)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161)
        at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368)
        at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877)
        at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671)
        at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930)
        at java.lang.Thread.run(Thread.java:662)
Caused by: java.io.IOException: Stream closed
        at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:377)
        at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:193)
        at java.io.FilterInputStream.read(FilterInputStream.java:116)
        at org.codehaus.jackson.impl.ByteSourceBootstrapper.ensureLoaded(ByteSourceBootstrapper.java:507)
        at org.codehaus.jackson.impl.ByteSourceBootstrapper.detectEncoding(ByteSourceBootstrapper.java:129)
        at org.codehaus.jackson.impl.ByteSourceBootstrapper.constructParser(ByteSourceBootstrapper.java:224)
        at org.codehaus.jackson.JsonFactory._createJsonParser(JsonFactory.java:785)
        at org.codehaus.jackson.JsonFactory.createJsonParser(JsonFactory.java:561)
        at org.codehaus.jackson.jaxrs.JacksonJsonProvider.readFrom(JacksonJsonProvider.java:414)
        at org.apache.cxf.jaxrs.utils.JAXRSUtils.readFromMessageBody(JAXRSUtils.java:1038)
        at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameter(JAXRSUtils.java:614)
        at org.apache.cxf.jaxrs.utils.JAXRSUtils.processParameters(JAXRSUtils.java:578)

更新 2: 我尝试实现一个具有不同签名的方法,而这一次,我从方法中省略了 String 数组:

public ControllerVersion getVersion(String deviceID)

没有字符串数组,一切都运行良好。你觉得我应该怎么做?

4

3 回答 3

1

我显然误解了 REST 的工作原理。我为最终解决问题所做的工作如下:

1-更改了我的网络服务签名:

@POST
@Path("/getVersion")
@Produces(MediaType.APPLICATION_JSON)
@Consumes({"application/xml", "application/json", "application/x-www-form-urlencoded"})
public ControllerVersion getVersion(@FormParam("deviceID") String deviceID,@FormParam("macAddresses") String macAddresses)

2- 现在,确保客户端正在发送内容类型(application/x-www-form-urlencoded)的请求,并且客户端正确添加了与您在@FormParam 注释中定义的相同的表单参数。

3- 现在,您可以使用 FlexJson 等库从 JSon 字符串中反序列化您的参数。例如,我现在将 macAddresses 作为 JSon String: ["mac1","mac2"] 从客户端发送。在服务器端,我使用以下方法将此 JSON 字符串转换为 String[]:

public static String[] parseStringArrayFromJSONArray(String jsonArray)
{
    String[] stringArray = null;
    try
    {
        JSONArray array = new JSONArray(jsonArray);
        if (array != null)
        {
            stringArray = new String[array.length()];

            for (int i = 0; i < array.length(); i++)
            {
                stringArray[i] = array.getString(i);
            }
        }
    } catch (Exception e)
    {
        stringArray = null;
    }

    return stringArray;
}

我希望这会帮助那里的人。

于 2013-10-22T11:20:11.127 回答
0

cxf 默认使用 jettison。为什么有@GET 和@POST 注释?但它说

 java.io.IOException: Stream closed

所以很可能有一个输入流没有被关闭。

于 2013-10-16T17:33:14.593 回答
0

你正在使用@Consumes(MediaType.APPLICATION_JSON). 您需要添加jackson-core(可能还有更多jackson依赖项)才能使转换生效。

于 2013-10-16T16:14:53.480 回答