gpt4 book ai didi

java - 接受列表作为使用多部分内容类型的 Jersey Web 服务的参数

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:57:10 24 4
gpt4 key购买 nike

我有一个现有的 Jersey web 服务方法,它通过 Http POST 方法接受许多参数,该方法旨在处理标准表单数据,内容类型为应用程序/x-www-form-urlencoded;这些参数之一是字符串列表。下面是我拥有的方法签名的示例。

@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 参数传入时,Jersey 正确生成列表并将其传入方法。

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

@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)

在 Jersey 代码中放置了一些断点,在堆栈跟踪中确定的一些点上,它似乎已经确定了要调用的正确方法,但在它试图传递给它的参数列表中, 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 代替 param,但得到了相同的结果。

在此先致谢,如有任何帮助,我们将不胜感激。

最佳答案

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

 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;
}

因此,当它看到参数类型是 List 或 Collection 时,如果泛型类型不是 FormDataBodyPart 或 FormDataContentDisposition,它将忽略它。

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

关于java - 接受列表作为使用多部分内容类型的 Jersey Web 服务的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11020427/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com