我正在使用Spring boot 2.0.0。请使用在Kotlin中编写的gradle和webflux,我试图让ReactiveMongoDB和Elasticsearch一起工作,我也有JWT实现。因此要验证我实现ReactiveAuthenticationManager
的AuthenticationToken,如下所示:
@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) }) }
}
}
并启用反应式mongodb存储库我这样做了:
@Configuration
@EnableMongoAuditing(auditorAwareRef = "springSecurityAuditorAware")
@EnableReactiveMongoRepositories(
basePackages = ["com.example.package.repository.**.nosql"],
excludeFilters = [
ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
value = [ElasticsearchRepository::class]
)
]
)
class DatabaseConfiguration
我也像这样配置了ElasticSearchRepositories:
@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)
}
}
}
当我运行gradle bootRun
时,它会抛出以下异常:
Caused by: java.lang.IllegalStateException: availableProcessors is already set to [8], rejecting [8]
at io.netty.util.NettyRuntime$AvailableProcessorsHolder.setAvailableProcessors(NettyRuntime.java:51)
at io.netty.util.NettyRuntime.setAvailableProcessors(NettyRuntime.java:87)
at org.elasticsearch.transport.netty4.Netty4Utils.setAvailableProcessors(Netty4Utils.java:85)
at org.elasticsearch.transport.netty4.Netty4Transport.<init>(Netty4Transport.java:140)
at org.elasticsearch.transport.Netty4Plugin.lambda$getTransports$0(Netty4Plugin.java:93)
at org.elasticsearch.client.transport.TransportClient.buildTemplate(TransportClient.java:177)
at org.elasticsearch.client.transport.TransportClient.<init>(TransportClient.java:268)
at org.elasticsearch.transport.client.PreBuiltTransportClient.<init>(PreBuiltTransportClient.java:133)
at org.elasticsearch.transport.client.PreBuiltTransportClient.<init>(PreBuiltTransportClient.java:119)
at org.elasticsearch.transport.client.PreBuiltTransportClient.<init>(PreBuiltTransportClient.java:109)
at org.springframework.data.elasticsearch.client.TransportClientFactoryBean.buildClient(TransportClientFactoryBean.java:91)
at org.springframework.data.elasticsearch.client.TransportClientFactoryBean.afterPropertiesSet(TransportClientFactoryBean.java:86)
at org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration.elasticsearchClient(ElasticsearchAutoConfiguration.java:59)
at org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration$$EnhancerBySpringCGLIB$$4eba21d.CGLIB$elasticsearchClient$0(<generated>)
at org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration$$EnhancerBySpringCGLIB$$4eba21d$$FastClassBySpringCGLIB$$bc4f5c6f.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:361)
at org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration$$EnhancerBySpringCGLIB$$4eba21d.elasticsearchClient(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 137 common frames omitted
调试时,我发现setAvailableProcessors
方法在NettyRuntime
中被调用两次,第一次被MongoReactiveAutoConfiguration
调用,第二次被ElasticsearchAutoConfiguration
调用,我得到了异常。我还发现,如果我删除了UserAuthenticationManager
的实施,MongoReactiveAutoConfiguration
没有调用setAvailableProcessors
方法,那么一切正常,因为ElasticsearchAutoConfiguration
会调用一次。为什么MongoReactiveAutoConfiguration
关心ReactiveAuthenticationManager
。我真的很困惑。如何在不删除UserAuthenticationManager
实施的情况下解决此问题?
有帮助吗?
解决方案:
在@RomanDzhadan的帮助下,我找到了防止被动mongo db检查Netty可用处理器的方法。
问题是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;
}
所以我通过使用我自己的MongoClient bean定义来解决它,例如:
@Bean
fun mongoClient(): MongoClient {
logger.debug("Configuring mongo client")
return MongoClients.create(mongoProperties.determineUri())
}
答案 0 :(得分:1)
尝试自己管理配置bean。弹簧自动配置 - 总是充满陷阱。特别是,当您尝试使用多于1个弹簧数据的实现时。 (在你的情况下,它是elasticsearch和mongo)。
框架无法为您做任何事情。所以,我建议明确地设置它。