接受List作为Jersey Web服务的参数,该Web服务使用多部分的内容类型

我有一个现有的Jersey webservice方法,它通过Http POST方法接受许多参数,该方法用于处理标准表单数据,application / x-www-form-urlencoded的内容类型; 其中一个参数是字符串列表。 下面是我拥有的方法签名的示例。

@POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response createItem( @FormParam("p1") long p1, @FormParam("p2") String p2, @FormParam("p3") List p3, @FormParam("p4") String p4, @Context UriInfo uriInfo ) throws SQLException { 

这是正常工作,当在List中传递多个p3参数时,Jersey正确生成并传递给方法。

我现在需要制作一个可以接受多部分请求的方法的替代版本,这样文件也可以与现有参数一起上传。 所以我创建了一个非常相似的方法签名来使用多部分请求,如下所示。

 @POST @Consumes(MediaType.MULTIPART_FORM_DATA) public Response createItemWithFile( @FormDataParam("p1") long p1, @FormDataParam("p2") String p2, @FormDataParam("p3") List p3, @FormDataParam("p4") String p4, @FormDataParam("file") InputStream inputStream, @Context UriInfo uriInfo ) throws SQLException { 

我将FormParam注释更改为FormDataParam,因为我认为在使用多部分数据时需要这样做。 我一直试图从使用RESTAssured的JUnit测试中调用此方法来进行调用(与原始方法相同)但我得到以下错误。

 java.lang.IllegalArgumentException: wrong number of arguments at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60) at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:205) at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75) at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:288) 

在Jersey代码中添加了一些断点,在堆栈跟踪中标识的某些点上,似乎已经识别出要调用的正确方法,但是在尝试传递给它的参数列表中,省略了p3 。

在处理多部分数据时,是否需要采取不同的措施来支持接受List作为输入? 鉴于这是一个可选参数,我预计无论如何都应该可以省略它,这是原始方法的情况。

用于调用该方法的测试中的RESTAssured代码如下。

 Response response = given() .header("my_header", "xyz") .param("p1", "8000040") .param("p2", "sample string") .param("p3", "first_value") .param("p4", "abcde") .multiPart("file", myFile1, inputStream) .expect() 

我也尝试在RESTAssured测试代码中使用formParam代替param,但得到相同的结果。

在此先感谢,任何帮助将不胜感激。

在介绍了更多的jersey代码后,我的结论是,在使用多部分时,我的方法上不能有List类型的参数。 在进程中的某一点,Jersey循环遍历方法上的每个参数,找到一个Injectable来读取每个参数的值(抱歉可能不是一个很好的解释,但我已经调试了尽可能多的内容),在com.sun类中getInjectables方法中的.jersey.multipart.impl.FormDataMultiPartDispatchProvider是以下代码:

  private List getInjectables(AbstractResourceMethod method) { List list = new ArrayList(method.getParameters().size()); for (int i = 0; i < method.getParameters().size(); i++) { Parameter p = method.getParameters().get(i); if (Parameter.Source.ENTITY == p.getSource()) { if (FormDataMultiPart.class.isAssignableFrom(p.getParameterClass())) { list.add(new FormDataMultiPartInjectable()); } else { list.add(null); } } else if (p.getAnnotation().annotationType() == FormDataParam.class) { if (Collection.class == p.getParameterClass() || List.class == p.getParameterClass()) { Class c = ReflectionHelper.getGenericClass(p.getParameterType()); if (FormDataBodyPart.class == c) { list.add(new ListFormDataBodyPartMultiPartInjectable(p.getSourceName())); } else if (FormDataContentDisposition.class == c) { list.add(new ListFormDataContentDispositionMultiPartInjectable(p.getSourceName())); } } else if (FormDataBodyPart.class == p.getParameterClass()) { list.add(new FormDataBodyPartMultiPartInjectable(p.getSourceName())); } else if (FormDataContentDisposition.class == p.getParameterClass()) { list.add(new FormDataContentDispositionMultiPartInjectable(p.getSourceName())); } else { list.add(new FormDataMultiPartParamInjectable(p)); } } else { Injectable injectable = getInjectableProviderContext().getInjectable(p, ComponentScope.PerRequest); list.add(injectable); } } return list; } 

因此,当它看到参数类型是List或Collection时,它将忽略它,其中generics类型不是FormDataBodyPart或FormDataContentDisposition。

为了解决这个问题,我刚刚改变了我的方法,接受p3的逗号分隔字符串代替List。