Dor*_*old 7 java jackson spring-boot
我有一个包含多个@RestController类的 Spring Boot Web 应用程序。我喜欢我的 REST 控制器返回的默认 json 格式。
为了在我的 DAO bean(执行 json 序列化和反序列化)中使用,我创建了一个自定义ObjectMapper:
@Configuration
public class Config{
@Bean
public ObjectMapper getCustomObjectMapper() {
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.SnakeCaseStrategy());
return objectMapper;
}
}
Run Code Online (Sandbox Code Playgroud)
在我的每个 DAO 类中,我都会自动装配我的自定义ObjectMapper:
@Repository
@Transactional
public class MyDaoImpl implements MyDao {
@Autowired
ObjectMapper objectMapper
//Dao implementation...
}
Run Code Online (Sandbox Code Playgroud)
这一切正常。问题是我的自定义ObjectMapper被 Spring 自动获取并用于序列化 REST 响应。
这是不可取的。对于 REST 控制器,我想保留ObjectMapperSpring 默认创建的。
我如何告诉 Spring Boot不检测也不将我的自定义ObjectMapperbean 用于其内部工作?
Simone Pontiggia 的答案是正确的。您应该创建一个@Primary bean,Spring 将在其内部使用它,然后创建您自己的 ObjectMapper bean 并使用@Qualifier自动装配它们。
这里的问题是,创建默认 bean,如下所示:
@Bean
@Primary
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
Run Code Online (Sandbox Code Playgroud)
实际上不会按预期工作,因为 Spring 默认的 ObjectMapper 有额外的配置。 创建 spring 将使用的默认 ObjectMapper 的正确方法是:
@Bean
@Primary
public ObjectMapper objectMapper() {
return Jackson2ObjectMapperBuilder.json().build();
}
Run Code Online (Sandbox Code Playgroud)
您可以在此处找到有关 Spring 默认 ObjectMapper 的更多信息: https: //docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html下的79.3 自定义 Jackson ObjectMapper
由于我不想触及 Spring 的默认值ObjectMapper,因此不可能创建一个@Primary ObjectMapper阴影 Spring 的默认值。ObjectMapper
相反,我最终做的是创建一个BeanFactoryPostProcessor在 Spring 上下文中注册一个自定义的、非主要的ObjectMapper:
@Component
public class ObjectMapperPostProcessor implements BeanFactoryPostProcessor {
public static final String OBJECT_MAPPER_BEAN_NAME = "persistenceObjectMapper";
@Override
public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) {
final AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
.genericBeanDefinition(ObjectMapper.class, this::getCustomObjectMapper)
.getBeanDefinition();
// Leave Spring's default ObjectMapper (configured by JacksonAutoConfiguration)
// as primary
beanDefinition.setPrimary(false);
final AutowireCandidateQualifier mapperQualifier = new AutowireCandidateQualifier(PersistenceObjectMapper.class);
beanDefinition.addQualifier(mapperQualifier);
((DefaultListableBeanFactory) beanFactory).registerBeanDefinition(OBJECT_MAPPER_BEAN_NAME, beanDefinition);
}
private ObjectMapper getCustomObjectMapper() {
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setPropertyNamingStrategy(new PropertyNamingStrategy.SnakeCaseStrategy());
return objectMapper;
}
}
Run Code Online (Sandbox Code Playgroud)
从上面的代码可以看出,我还为我的自定义ObjectMapperbean 分配了一个限定符。
我的限定符是一个注释,其注释为@Qualifier:
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface PersistenceObjectMapper {
}
Run Code Online (Sandbox Code Playgroud)
然后,我可以ObjectMapper使用自定义注释自动装配我的自定义,如下所示:
@Repository
public class MyDao {
@Autowired
public MyDao(DataSource dataSource, @PersistenceObjectMapper ObjectMapper objectMapper) {
// constructor code
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5004 次 |
| 最近记录: |