Spring Data Rest:自定义 JsonDeserializer 中的 @Autowire

Posted

技术标签:

【中文标题】Spring Data Rest:自定义 JsonDeserializer 中的 @Autowire【英文标题】:Spring Data Rest: @Autowire in Custom JsonDeserializer 【发布时间】:2019-12-18 20:42:48 【问题描述】:

我正在尝试将组件自动装配到自定义 JsonDeserializer 中,但即使我找到了以下建议,也无法正确完成:

Autowiring in JsonDeserializer: SpringBeanAutowiringSupport vs HandlerInstantiator Right way to write JSON deserializer in Spring or extend it How to customise the Jackson JSON mapper implicitly used by Spring Boot? Spring Boot Autowiring of JsonDeserializer in Integration test

我的最终目标是接受不同微服务中资源的 URL,并仅在本地存储资源的 ID。但我不想只从 URL 中提取 ID,还要验证 URL 的其余部分是否正确。

我已经尝试了很多东西,但我对我尝试过的东西有点迷失了,但我相信我尝试了上面链接中提到的所有东西。我为 SpringHandlerInstantiator、Jackson2ObjectMapperBuilder、MappingJackson2HttpMessageConverter、RestTemplate 等创建了大量的 bean,还尝试在 RepositoryRestConfigurer#configureJacksonObjectMapper 中设置 SpringHandlerInstantiator。

我正在使用 Spring Boot 2.1.6.RELEASE,这让我觉得有些东西可能已经改变了,因为一些链接的线程已经很老了。

这是我的最后一次尝试:

@Configuration
public class JacksonConfig 

    @Bean
    public HandlerInstantiator handlerInstantiator(ApplicationContext applicationContext) 
        return new SpringHandlerInstantiator(applicationContext.getAutowireCapableBeanFactory());
    


@Configuration
public class RestConfiguration implements RepositoryRestConfigurer 

    @Autowired
    private Validator validator;

    @Autowired
    private HandlerInstantiator handlerInstantiator;

    @Override
    public void configureValidatingRepositoryEventListener(ValidatingRepositoryEventListener validatingListener) 
        validatingListener.addValidator("beforeCreate", validator);
        validatingListener.addValidator("beforeSave", validator);
    

    @Override
    public void configureJacksonObjectMapper(ObjectMapper objectMapper) 
        objectMapper.setHandlerInstantiator(handlerInstantiator);
    


@Component
public class RestResourceURLSerializer extends JsonDeserializer<Long> 

    @Autowired
    private MyConfig config;

    @Override
    public Long deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException 
        ServiceConfig serviceConfig = config.getServices().get("identity");
        URI serviceUri = serviceConfig.getExternalUrl();
        String servicePath = serviceUri.getPath();

        URL givenUrl = p.readValueAs(URL.class);
        String givenPath = givenUrl.getPath();

        if (servicePath.equals(givenPath)) 
            return Long.parseLong(givenPath.substring(givenPath.lastIndexOf('/') + 1));
        

        return null;
    


我不断收到 NullPointerException POST 到 API 端点的信息,该端点使用上面的 JsonDeserializer 反序列化。

【问题讨论】:

【参考方案1】:

我能够通过将我的反序列化器构造函数标记为接受一个参数(并因此删除空构造函数)并将构造函数标记为@Autowired 来解决类似的问题。

 public class MyDeserializer extends JsonDeserializer<MyEntity>     
    private final MyBean bean;

    // no default constructor
    @Autowired
    public MyDeserializer(MyBean bean)
        this.bean = bean
    
    ...
 

@JsonDeserialize(using = MyDeserializer.class)
public class MyEntity...

我的实体标有 @JsonDeserialize 注释,因此我不必使用 ObjectMapper 显式注册它。

【讨论】:

以上是关于Spring Data Rest:自定义 JsonDeserializer 中的 @Autowire的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data Rest - 在 Json 中禁用自我链接(HAL)

Spring Data Rest Save 可迭代实体

如何使用Spring Boot REST生成自定义JSON响应?

我可以让自定义控制器镜像 Spring-Data-Rest / Spring-Hateoas 生成的类的格式吗?

Spring Data REST 基本路径的更改不涉及自定义控制器

Spring Session + REST + 自定义身份验证过滤器(从 JSON 读取凭据而不是查询参数)