接受一个列表作为参数传递给web服务新泽西消耗多部分的内容类型(Accepting a List a

2019-09-18 02:04发布

我不得不接受若干经由HTTP POST方法参数,其被设计为处理一个标准形式的数据,应用程序/ x-WWW窗体-urlencoded内容类型的现有泽西web服务方法; 其中一个参数是一个字符串列表。 下面是该方法的签名我的一个例子。

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

这是正常工作和当多个P3参数在列表被传递正确由新泽西产生并传递到方法。

我现在需要让这个方法会接受一个多部分请求,这样一个文件也可以与现有的参数上传沿的替代版本。 因此,我创建一个非常类似的方法签名消耗如下所示的多部分请求的例子。

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response createItemWithFile(
        @FormDataParam("p1") long p1,
        @FormDataParam("p2") String p2,
        @FormDataParam("p3") List<String> 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)

说完就把一些破发点到新泽西州的代码,在一些堆栈跟踪中标识的点,它似乎已经确定调用正确的方法,但在它试图传递给它的参数列表,省略P3 。

是否有不同的东西需要做,以支持接受一个列表作为输入与多部分数据处理时? 鉴于这是一个可选参数,我希望它应该有可能无论如何忽略它,这是与原始方法的情况。

在测试中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的时候,却得到相同的结果我也试过。

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

Answer 1:

通过一些更多的球衣代码具有台阶,我的结论是使用多部分的时候,我不能有类型列表的参数上我的方法。 在过程中的一个点泽西遍历的方法找到一个注射每个参数设置为读取每个参数的值(对不起也许不是一个伟大的交代,但我调试,我需要尽可能多),这个类的com.sun内在getInjectables方法.jersey.multipart.impl.FormDataMultiPartDispatchProvider是以下代码:

 private List<Injectable> getInjectables(AbstractResourceMethod method) {
    List<Injectable> list = new ArrayList<Injectable>(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;
}

那么,它看到的参数类型列表或集合中会忽略它在泛型类型以外的任何其他FormDataBodyPart或FormDataContentDisposition。

为了避开这个问题我刚才已经改变了我的方法接受P3逗号分隔的字符串代替名单。



Answer 2:

我碰到另一种解决方案这可能是不必手动处理逗号分隔发布姗姗来迟列表等版本,以帮助其他人发现这个帖子更好(更简单)。

更改从多参数:

@FormDataParam("p3") List<String> p3,

@FormDataParam("p3") List<FormDataBodyPart> p3,

然后你有你在P3列表,你可以得到的参数值对每个FormDataBodyPart使用元素getValue()

来源: 接收阵列-从外形元件与-平针织



文章来源: Accepting a List as a parameter to a Jersey webservice that consumes a content type of multi-part