首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何配置spring- MappingJackson2HttpMessageConverter注册的hateoas

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

Stack Overflow用户
提问于 2014-07-11 17:30:33
回答 3查看 9K关注 0票数 16

我喜欢在我的项目中使用spring-hateoas,并用@EnableHypermediaSupport对其进行了配置。现在的问题是,这个神奇的配置注释注册了自己的MappingJackson2HttpMessageConverter,而我自己定制的转换器将被忽略。

背景:我在我的项目中添加了一些杰克逊模块(比如JodaModule),我想让它们使用objectMapper.findAndRegisterModules();进行注册。这是通过在WebMvcConfigurationSupportWebMvcConfigurer中覆盖configureMessageConverters(List<HttpMessageConverter<?>> converters)来完成的。

我当前的配置如下所示:

代码语言:javascript
复制
@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);
  }
}

有没有办法定制spring-hateoas使用的MappingJackson2HttpMessageConverterObjectMapper

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-11-22 00:49:56

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

我使用了一个BeanPostProcessor和很多反射魔法,用我自己的ConversionService替换了Spring HATEOAS的内部a,它以前已经添加到了Spring上下文中。这样,我可以确保Spring HATEOAS使用与Spring MVC完全相同的ConversionService。

代码语言:javascript
复制
/**
 * 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;
    }
}
票数 0
EN

Stack Overflow用户

发布于 2014-11-06 02:38:10

我不得不做同样的事情。有了HATEOAS .16,我就能让这款working..but变得非常非常丑陋。

关键在于,在HypermediaSupportBeanDefinitionRegistrar中,寄存器HAL转换器的部分在尝试添加另一个之前检查是否已经存在一个HAL转换器。所以我自己在WebMVCConfig::configureMessageConverters中添加了一个HAL转换器。

类似于:

代码语言:javascript
复制
private static final String DELEGATING_REL_PROVIDER_BEAN_NAME = "_relProvider";
private static final String LINK_DISCOVERER_REGISTRY_BEAN_NAME = "_linkDiscovererRegistry";
private static final String HAL_OBJECT_MAPPER_BEAN_NAME = "_halObjectMapper";

@Autowired
private ListableBeanFactory beanFactory;

private static CurieProvider getCurieProvider(BeanFactory factory) {

    try {
        return factory.getBean(CurieProvider.class);
    } catch (NoSuchBeanDefinitionException e) {
        return null;
    }
}

@Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        List<HttpMessageConverter<?>> baseConverters = new ArrayList<HttpMessageConverter<?>>();
        super.configureMessageConverters(baseConverters);

        //Need to override some behaviour in the HAL Serializer...so let's make our own
        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 TypeConstrainedMappingJackson2HttpMessageConverter(
            ResourceSupport.class);
        halConverter.setSupportedMediaTypes(Arrays.asList(HAL_JSON));
        halConverter.setObjectMapper(halObjectMapper);

        converters.add(halConverter);
    }

这显然是依赖于实现的,使用了实现细节,并且确实不允许修改@EnableHyperMediaSupport为you....but构建的版本。

票数 1
EN

Stack Overflow用户

发布于 2014-07-20 19:08:38

我使用以下方法

代码语言:javascript
复制
@Configuration
@EnableHypermediaSupport(type = HypermediaType.HAL)
public class MvcConfig {    

  @Bean
  public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24694493

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档