使用Apache CXF通过REST解析String 请求参数

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

以下是我的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(); } } 

ControllerVersion类:

 package restful.entity; @XmlRootElement(name = "ControllerVersion") public class ControllerVersion { private String version="R1.1.0.0"; public String getVersion() { return version; } } 

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

 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:

  jaxrs.providers  org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider (writeXsiType=false)   

并添加了以下依赖项:

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

现在我收到以下exception:

 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) 

没有String数组,一切都很完美。 你觉得我应该怎么做?

我显然误解了REST是如何工作的。 我最终解决问题的方法如下:

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

 @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-现在,确保客户端正在发送带有content-type(application / x-www-form-urlencoded)的请求,并且客户端正确添加了与@FormParam注释中定义的表单参数相同的表单参数。

3-现在,您可以使用FlexJson等库来从JSon String中反序列化参数。 例如,我现在从客户端发送macAddresses作为JSon字符串:[“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; } 

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

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

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

  java.io.IOException: Stream closed 

所以最有可能的输入流没有被关闭。