我有一个MessageBodyReader
,其中包含以下类:
@Provider
@Consumes(MediaType.APPLICATION_JSON)
public class TransactionMessageBodyReader implements MessageBodyReader<Transaction<Customer>>
boolean isReadable(Class<?> type,
Type genericType,
Annotation[] annotations,
MediaType mediaType)
我有以下REST端点:
@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Path("trans")
public Response checkStatus(Transaction<Customer> transaction) { ... }
在我的调试器中,我在isReadable
上有一个断点,它在调用checkStatus
方法之前命中断点。目前很好。我可以在调试器中看到genericType
说Transaction<Customer>
...换句话说,它知道类型信息。当Java类型擦除在运行时将其删除为Transaction
时,它怎么可能知道类型信息?我看到genericType
由ParameterizedType
组成,我认为它用于传递类型信息(以解决类型擦除问题)。但是,泽西岛如何自动填充genericType
?因为我从未指定类型信息,除了我在上面发布的方法标题中。
另外,第二个问题:如果泽西岛'自动'了解我的类型,为什么我需要一个MessageBodyReader
?是不是有一些更简单的方法来使用泛型与Jersey / REST端点并使其“正常工作”?
答案 0 :(得分:4)
查看javadoc。
genericType
- 要生成的实例类型。例如。如果要将邮件正文转换为方法参数,这将是Method.getGenericParameterTypes
返回的方法参数的正式类型。
类,方法和字段中的通用参数化保留在相应的.class
文件中。这显然是编译所必需的。如果不是这种情况,您将无法打包和使用Java类作为库。
Reflection公开了这种类型信息(以及更多)。
Jersey基本上会扫描您的类中的处理程序方法,使用@POST
注释的方法等,并检索相应的Method
个对象。一旦有了,就可以使用Method#getGenericParameterTypes()
返回表示形式参数的
Type
个对象数组 声明顺序的类型,由此表示的可执行文件 宾语。如果是底层可执行文件,则返回长度为0的数组 没有参数。如果形式参数类型是参数化类型,则为
Type
对象 返回它必须准确反映实际的类型参数 在源代码中使用。
换句话说,Type
必须表示参数的原始类型及其参数化(如果有)。
因此,Jersey会检索这些类型并将其输入您的MessageBodyReader
。期望您的实现应该能够处理genericType
。
我不太了解Jersey,但如果它遵循与Spring MVC相同的策略,它将简单地遍历已注册的所有MessageBodyReader
个实例。它实际上并不关心它的类型(例如你的TransactionMessageBodyReader
),这就是它依赖isReadable
的原因。从理论上讲,它可以保持类型到MessageBodyReader
实现的映射,但最终变得难以处理并且不够灵活。在任何情况下,应用程序通常不具有可以序列化的许多类型/格式,因此迭代一些对象并不是一件大事。
从Java 8开始,您还可以访问Executable#getParameters
(Method
是Executable
的子类型。)
以下是泽西岛可以做的一个例子
public class StackOverflow {
public static void main(String[] args) throws Exception {
Method method = StackOverflow.class.getDeclaredMethod("method", List.class);
Type[] parameterTypes = method.getGenericParameterTypes();
for (Type parameterType : parameterTypes) {
System.out.println(parameterType.getClass());
System.out.println(parameterType);
ParameterizedType parameterizedType = (ParameterizedType) parameterType;
System.out
.println(parameterizedType.getRawType().getTypeName() + "<" + parameterizedType.getActualTypeArguments()[0].getTypeName() + ">");
}
}
public String method(List<StackOverflow> parameter) {
return "example";
}
}
打印
class sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
java.util.List<com.example.StackOverflow>
java.util.List<com.example.StackOverflow>