找不到媒体类型的球衣客户端 MessageBodyWriter=application/x-www-form-urlencoded
jersey-client MessageBodyWriter not found for media type=application/x-www-form-urlencoded
使用 org.glassfish.jersey.core.jersey-客户端版本 2.16,似乎无法发出简单的 POST 请求:
MessageBodyProviderNotFoundException:找不到媒体类型的 MessageBodyWriter=application/x-www-form-urlencoded
客户端
String response = ClientBuilder.newClient().target("http://0.0.0.0:8080")
.path("/get")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(getForm(), MediaType.APPLICATION_FORM_URLENCODED_TYPE), String.class);
private Form getForm()
{
return new Form() {{ this.param("whatever", "whatever"); }};
}
服务器
@Path("/get")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String postForToken(@FormParam("whatever") final String whatever) {...}
根据 this post 注册 MultiPartFeature 没有任何区别。
config.register(MultiPartFeature.class);
好的,所以线索在完整的异常消息中(上面没有发布)。
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/x-www-form-urlencoded, type=class com.blah.AcceptanceTest, genericType=class com.blah.AcceptanceTest.
$1 表示它正在尝试解析某种内部 class - 这使我找到了 Form 的匿名子 class。将上面的内容更改为以下内容可以正常工作:
private Form getForm()
{
final Form form = new Form();
form.param("whatever", "whatever");
return form;
}
Jersey 使用 Entity Providers 序列化和反序列化 Java 个对象——它使用 MessageBodyWriter
序列化和 MessageBodyReader
反序列化。一些实体提供程序是开箱即用的,包括 FormProvider
,它处理媒体类型 application/x-www-form-urlencoded
的 Form
对象的读取和写入。
Jersey 文档的 Section 8.3 概述了在决定使用哪个注册提供者时使用的算法。第 5 步是这样说的:
- Iterate through the sorted MessageBodyWriter providers and,
utilizing the isWriteable method of each until you find a
MessageBodyWriter that returns true.
问题是 FormProvider
中的 implementation of isWriteable()
检查对象的运行时类型是否 完全 等于 Form.class
-- 子classes,包括匿名classes,不合格,所以方法returns false
和FormProvider
不用于序列化。然后,没有找到其他匹配的提供者,结果是 MessageBodyProviderNotFoundException
.
简单的解决方案:
简单的解决方案是只使用实际的 Form
class。
硬解:
对于任何真正想要使用 Form
的子classes 的人来说,困难的解决方案是重新实现 FormProvider
(标记为 final
,因此您可以不只是 subclass 它),用下面的代码代替 isWriteable()
方法:
public boolean isWriteable(...) {
return Form.class.isAssignableFrom(type);
}
然后您必须在使用前向 Client
注册您的自定义 FormProvider:
Client client = ClientBuilder.newClient().register(MyFormProvider.class);
使用 org.glassfish.jersey.core.jersey-客户端版本 2.16,似乎无法发出简单的 POST 请求:
MessageBodyProviderNotFoundException:找不到媒体类型的 MessageBodyWriter=application/x-www-form-urlencoded
客户端
String response = ClientBuilder.newClient().target("http://0.0.0.0:8080")
.path("/get")
.request(MediaType.APPLICATION_JSON_TYPE)
.post(Entity.entity(getForm(), MediaType.APPLICATION_FORM_URLENCODED_TYPE), String.class);
private Form getForm()
{
return new Form() {{ this.param("whatever", "whatever"); }};
}
服务器
@Path("/get")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String postForToken(@FormParam("whatever") final String whatever) {...}
根据 this post 注册 MultiPartFeature 没有任何区别。
config.register(MultiPartFeature.class);
好的,所以线索在完整的异常消息中(上面没有发布)。
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/x-www-form-urlencoded, type=class com.blah.AcceptanceTest, genericType=class com.blah.AcceptanceTest.
$1 表示它正在尝试解析某种内部 class - 这使我找到了 Form 的匿名子 class。将上面的内容更改为以下内容可以正常工作:
private Form getForm()
{
final Form form = new Form();
form.param("whatever", "whatever");
return form;
}
Jersey 使用 Entity Providers 序列化和反序列化 Java 个对象——它使用 MessageBodyWriter
序列化和 MessageBodyReader
反序列化。一些实体提供程序是开箱即用的,包括 FormProvider
,它处理媒体类型 application/x-www-form-urlencoded
的 Form
对象的读取和写入。
Section 8.3 概述了在决定使用哪个注册提供者时使用的算法。第 5 步是这样说的:
- Iterate through the sorted MessageBodyWriter providers and, utilizing the isWriteable method of each until you find a MessageBodyWriter that returns true.
问题是 FormProvider
中的 implementation of isWriteable()
检查对象的运行时类型是否 完全 等于 Form.class
-- 子classes,包括匿名classes,不合格,所以方法returns false
和FormProvider
不用于序列化。然后,没有找到其他匹配的提供者,结果是 MessageBodyProviderNotFoundException
.
简单的解决方案:
简单的解决方案是只使用实际的 Form
class。
硬解:
对于任何真正想要使用 Form
的子classes 的人来说,困难的解决方案是重新实现 FormProvider
(标记为 final
,因此您可以不只是 subclass 它),用下面的代码代替 isWriteable()
方法:
public boolean isWriteable(...) {
return Form.class.isAssignableFrom(type);
}
然后您必须在使用前向 Client
注册您的自定义 FormProvider:
Client client = ClientBuilder.newClient().register(MyFormProvider.class);