Java MongoDB和ElasticSearch弹簧靴
我使用的是SpringBoot2.0.0.Release,gradle和webflux都是用Kotlin编写的,我试图让ReactiveMongoDB和Elasticsearch协同工作,我也有JWT实现。因此,为了验证我实现的AuthenticationTokenJava MongoDB和ElasticSearch弹簧靴,java,spring-boot,
elasticsearch,kotlin,Java,Spring Boot,
elasticsearch,Kotlin,我使用的是SpringBoot2.0.0.Release,gradle和webflux都是用Kotlin编写的,我试图让ReactiveMongoDB和Elasticsearch协同工作,我也有JWT实现。因此,为了验证我实现的AuthenticationTokenReactiveAuthenticationManager,如下所示: @Component class UserAuthenticationManager(@Inject private val service: UserServi
ReactiveAuthenticationManager
,如下所示:
@Component
class UserAuthenticationManager(@Inject private val service: UserService,
@Inject private val encoder: PasswordEncoder) : ReactiveAuthenticationManager {
override fun authenticate(authentication: Authentication): Mono<Authentication> {
return service.findByUsernameWithPassword(authentication.name)
.publishOn(Schedulers.parallel())
.filter { u -> encoder.matches(authentication.credentials as String, u.password) }
.switchIfEmpty(Mono.defer<User> { Mono.error<User>(BadCredentialsException("Invalid Credentials")) })
.map { u -> AuthenticationToken(u.id, u.username, u.password!!, u.roles.map { SimpleGrantedAuthority(it.name) }) }
}
}
我还将ElasticSearch存储库配置为:
@Configuration
@EnableElasticsearchRepositories(
basePackages = ["com.example.package.repository.**.search"],
excludeFilters = [
ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
value = [ReactiveMongoRepository::class]
)
]
)
class ElasticsearchConfiguration {
@Bean
fun elasticsearchTemplate(client: Client, builder: Jackson2ObjectMapperBuilder): ElasticsearchTemplate {
return ElasticsearchTemplate(client, CustomEntityMapper(builder.createXmlMapper(false).build()))
}
inner class CustomEntityMapper(private val objectMapper: ObjectMapper) : EntityMapper {
init {
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true)
}
@Throws(IOException::class)
override fun mapToString(`object`: Any): String {
return objectMapper.writeValueAsString(`object`)
}
@Throws(IOException::class)
override fun <T> mapToObject(source: String, clazz: Class<T>): T {
return objectMapper.readValue(source, clazz)
}
}
}
@Bean
fun mongoClient(): MongoClient {
logger.debug("Configuring mongo client")
return MongoClients.create(mongoProperties.determineUri())
}
在调试过程中,我发现,setAvailableProcessors
方法在NettyRuntime
中被调用了两次,第一次用于MongoReactiveAutoConfiguration
,第二次用于ElasticsearchAutoConfiguration
,我得到了异常。此外,我还发现,如果我删除UserAuthenticationManager
的实现,MongoReactiveAutoConfiguration
不会调用setAvailableProcessors
方法,因此一切正常,因为ElasticsearchAutoConfiguration
只调用了一次。为什么MongoReactiveAutoConfiguration
关心ReactiveAuthenticationManager
。我真的很困惑。如何在不删除UserAuthenticationManager
实现的情况下解决此问题
有什么帮助吗
解决方案:
在@RomanDzhadan的帮助下,我找到了防止反应性mongo db检查网络可用处理器的方法。
问题在于MongoReactiveAutoConfiguration
@Bean
@ConditionalOnMissingBean
public MongoClient reactiveStreamsMongoClient(MongoProperties properties,
Environment environment,
ObjectProvider<List<MongoClientSettingsBuilderCustomizer>> builderCustomizers) {
ReactiveMongoClientFactory factory = new ReactiveMongoClientFactory(properties,
environment, builderCustomizers.getIfAvailable());
this.mongo = factory.createMongoClient(this.settings);
return this.mongo;
}
尝试自己管理配置bean。Spring自动配置-总是充满陷阱。特别是,当您试图使用不止一个spring数据实现时。(在您的案例中,是elasticsearch和mongo) 框架不能为你做任何事情。因此,我建议显式设置它
- 缺点:1或2个额外的类,创建bean
- 优点:更多地控制和理解应用程序的工作方式
EnableReactiveMongorPositories
,但我真的不明白发生了什么?你使用的elasticsearch版本是什么?什么版本的spring data elasticsearch?我正在使用6.1.2
进行elasticsearch,并且spring data elasticsearch
将由spring Boot版本2.0.0加载。发布
dependency managementorg.springframework.cloud:spring cloud dependencies:Finchley.M8
尝试覆盖pom.xml中的elasticsearch版本或者在格拉德尔。到什么版本?我也很感激给我提供解决方案,但我首先需要知道这背后的原因。在更糟糕的情况下,我将按照您的建议手动加载bean,或者设置System.setProperty(“es.set.netty.runtime.available.processors”,“false”)代码>以避免elasticsearch检查可用处理器。你知道我为什么会犯这个错误吗?
@Bean
@ConditionalOnMissingBean
public MongoClient reactiveStreamsMongoClient(MongoProperties properties,
Environment environment,
ObjectProvider<List<MongoClientSettingsBuilderCustomizer>> builderCustomizers) {
ReactiveMongoClientFactory factory = new ReactiveMongoClientFactory(properties,
environment, builderCustomizers.getIfAvailable());
this.mongo = factory.createMongoClient(this.settings);
return this.mongo;
}
@Bean
fun mongoClient(): MongoClient {
logger.debug("Configuring mongo client")
return MongoClients.create(mongoProperties.determineUri())
}