已在最新版本中修复
不确定何时解决
1.1.8.RELEASE此问题,但是由于使用,此问题不再存在
ClassUtils.isAssignablevalue。此处保留原始答案仅供参考。
这里似乎存在多个问题,因此我将总结我的发现作为答案。我仍然没有真正解决我要解决的问题的方法,但是我将与Spring
Boot的人员进行交谈,以了解发生的事情是否是有意的。
为什么扩展时现有的转换器会被覆盖MappingJackson2HttpMessageConverter
?
这适用于
1.1.4.RELEASESpring Boot 版本;我还没有检查其他版本。
HttpMessageConverters该类的构造函数如下:
public HttpMessageConverters(Collection<HttpMessageConverter<?>> additionalConverters) { List<HttpMessageConverter<?>> converters = new ArrayList<HttpMessageConverter<?>>(); List<HttpMessageConverter<?>> defaultConverters = getDefaultConverters(); for (HttpMessageConverter<?> converter : additionalConverters) { int defaultConverterIndex = indexOfItemClass(defaultConverters, converter); if (defaultConverterIndex == -1) { converters.add(converter); } else { defaultConverters.set(defaultConverterIndex, converter); } } converters.addAll(defaultConverters); this.converters = Collections.unmodifiableList(converters);}在
for循环内。请注意,它通过调用
indexOfItemClass方法确定列表中的索引。该方法如下所示:
private <E> int indexOfItemClass(List<E> list, E item) { Class<? extends Object> itemClass = item.getClass(); for (int i = 0; i < list.size(); i++) { if (list.get(i).getClass().isAssignableFrom(itemClass)) { return i; } } return -1;}由于我的课程扩展
MappingJackson2HttpMessageConverter了该
if语句的返回值
true。这意味着在构造函数中,我们有一个有效的索引。然后,Spring
Boot 用 新实例 替换 现有实例,这 正是 我所看到的。
这是理想的行为吗?
我不知道。它不 似乎 是,似乎很奇怪,我。
在Spring Boot文档中的任何地方都明确指出了这一点吗?
有点。看这里。它说:
HttpMessageConverter bean上下文中存在的任何内容都将添加到转换器列表中。您也可以通过这种方式覆盖默认转换器。
但是,仅仅因为转换器是现有转换器的子类型而对其进行覆盖似乎并不有用。
Spring HATEOAS如何解决这个Spring Boot问题?
Spring HATEOAS的生命周期与Spring Boot分开。Spring HATEOAS
application/hal+json在
HyperMediaSupportBeanDefinitionRegistrar类中为媒体类型注册其处理程序。相关方法是:
private List<HttpMessageConverter<?>> potentiallyRegisterModule(List<HttpMessageConverter<?>> converters) { for (HttpMessageConverter<?> converter : converters) { if (converter instanceof MappingJackson2HttpMessageConverter) { MappingJackson2HttpMessageConverter halConverterCandidate = (MappingJackson2HttpMessageConverter) converter; ObjectMapper objectMapper = halConverterCandidate.getObjectMapper(); if (Jackson2HalModule.isAlreadyRegisteredIn(objectMapper)) { return converters; } } } CurieProvider curieProvider = getCurieProvider(beanFactory); RelProvider relProvider = beanFactory.getBean(DELEGATING_REL_PROVIDER_BEAN_NAME, RelProvider.class); ObjectMapper halObjectMapper = beanFactory.getBean(HAL_OBJECT_MAPPER_BEAN_NAME, ObjectMapper.class); halObjectMapper.registerModule(new Jackson2HalModule()); halObjectMapper.setHandlerInstantiator(new Jackson2HalModule.HalHandlerInstantiator(relProvider, curieProvider)); MappingJackson2HttpMessageConverter halConverter = new MappingJackson2HttpMessageConverter(); halConverter.setSupportedMediaTypes(Arrays.asList(HAL_JSON)); //HAL_JSON is just a MediaType instance for application/hal+json halConverter.setObjectMapper(halObjectMapper); List<HttpMessageConverter<?>> result = new ArrayList<HttpMessageConverter<?>>(converters.size()); result.add(halConverter); result.addAll(converters); return result;}该
converters参数通过从这个片段传入的
postProcessBeforeInitialization从相同类的方法。相关代码段为:
if (bean instanceof RequestMappingHandlerAdapter) { RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter) bean; adapter.setMessageConverters(potentiallyRegisterModule(adapter.getMessageConverters()));}什么是创建自定义媒体类型转换器的正确方法,该转换器表示基本上仍为JSON(因此可以通过进行序列化和反序列化)的语义媒体类型
MappingJackson2HttpMessageConverter?
我不确定。子分类
ExtensibleMappingJackson2HttpMessageConverter<T>(在问题中显示)暂时有效。另一个选择可能是
MappingJackson2HttpMessageConverter在自定义转换器内部创建一个私有实例,然后简单地委托给它。无论哪种方式,我都将在Spring
Boot项目中打开一个问题,并从中获得一些反馈。然后,我将使用任何新信息为答案进行更新。



