我有一个返回
List<Person>
的 Spring Boot 控制器,我想实现一个自定义 HttpMessageConverter
,它可以编写 Person
类型的集合。
我看到
AbstractHttpMessageConverter
,但是supports()
方法只接受一个类,所以我可以测试Collection,但没有办法(据我所知)测试Person类型的Collection。
我还看到
GenericHttpMessageConverter
和 AbstractGenericHttpMessageConverter
听起来很有希望,但我不知道如何正确实施。
我想我找到了解决方案。以下似乎有效...
@Component
static class PersonMessageConverter
extends AbstractGenericHttpMessageConverter<Collection<Person>> {
public PersonMessageConverter() {
super(MediaType.APPLICATION_JSON);
}
@Override
public boolean canWrite(Type type, Class<?> clazz, MediaType mediaType) {
TypeToken<Collection<Person>> personCollectionType = new com.google.common.reflect.TypeToken<>() {};
return canWrite(mediaType) && personCollectionType.isSupertypeOf(type);
}
@Override
protected void writeInternal(Collection<Person> persons, Type type, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
// do write...
}
// continue with read methods here
}
canWrite 是在 ResourceRegionHttpMessageConverter 中的 springs 代码中实现的。我建议使用它作为参考实现。
在你的情况下是:
@Override
public boolean canWrite(@Nullable Type type, @Nullable Class<?> clazz, @Nullable MediaType mediaType) {
if (!(type instanceof ParameterizedType parameterizedType)) {
return (type instanceof Class<?> c && Person.class.isAssignableFrom(c));
}
if (!(parameterizedType.getRawType() instanceof Class<?> rawType)) {
return false;
}
if (!(Collection.class.isAssignableFrom(rawType))) {
return false;
}
if (parameterizedType.getActualTypeArguments().length != 1) {
return false;
}
Type typeArgument = parameterizedType.getActualTypeArguments()[0];
if (!(typeArgument instanceof Class<?> typeArgumentClass)) {
return false;
}
return Person.class.isAssignableFrom(typeArgumentClass);
}
此解决方案不依赖于 guava 等其他第三方库。