如何配置由spring-hateoas注册的MappingJackson2HttpMessageConverter

And*_*ken 16 java spring json spring-mvc spring-hateoas

我喜欢在我的项目中使用spring-hateoas并配置它@EnableHypermediaSupport.现在的问题是,这个神奇的配置注释会注册它自己MappingJackson2HttpMessageConverter,我的自定义转换器将被忽略.

背景:我在项目中添加了一些Jackson模块(比如JodaModule),我希望它们能够使用objectMapper.findAndRegisterModules();.这是通过覆盖完成configureMessageConverters(List<HttpMessageConverter<?>> converters)WebMvcConfigurationSupportWebMvcConfigurer.

我当前的配置如下所示:

@Configuration
@EnableHypermediaSupport(type = HAL)
public class WebMvcConfiguration extends WebMvcConfigurationSupport {

  @Override
  protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    final MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.getObjectMapper().findAndRegisterModules();

    converters.add(converter);
  }
}
Run Code Online (Sandbox Code Playgroud)

是否有自定义的方式MappingJackson2HttpMessageConverterObjectMapper所使用的弹簧HATEOAS?

And*_*ken 0

我为我的问题找到了一个丑陋的解决方案:

我使用 BeanPostProcessor 和大量反射魔法,用我自己的内部 ConversionService 替换 Spring HATEOAS 的内部 ConversionService,该服务之前已添加到 Spring 上下文中。这样我可以确保 Spring HATEOAS 使用与 Spring MVC 完全相同的 ConversionService。

/**
 * This is a HACK to work around a not yet implemented feature. At the moment Spring Hateoas uses a
 * {@link ConversionService}, which is hold in a private static final field and hence cannot be accessed to add more
 * Converters<br/>
 *
 * <ul>
 *   <li><a href="https://github.com/spring-projects/spring-hateoas/issues/118">Spring Hateoas Issue</a></li>
 *   <li><a
 *     href="http://stackoverflow.com/questions/22240155/converter-from-pathvariable-domainobject-to-string-using-controllerlinkbuilde">
 *     Solution on Stackoverflow</a></li>
 * </ul>
 */
public static class HateoasConversionServicePostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(final Object bean, final String beanName) throws BeansException {
        if (bean instanceof ConversionService) {
            try {
                Class<?> clazz = Class.forName(
                        "org.springframework.hateoas.mvc.AnnotatedParametersParameterAccessor$BoundMethodParameter");
                Field field = clazz.getDeclaredField("CONVERSION_SERVICE");
                field.setAccessible(true);

                Field modifiersField = Field.class.getDeclaredField("modifiers");
                modifiersField.setAccessible(true);
                modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

                field.set(null, bean);

                modifiersField.setInt(field, field.getModifiers() & Modifier.FINAL);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        }

        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException {
        return bean;
    }
}
Run Code Online (Sandbox Code Playgroud)