我必须在我的 kotlin spring 应用程序中为某些 utils 逻辑使用标头值。我找到了一种获取每个请求的标头值的方法,但我意识到由于并发性,这种方法不太好。
这就是我获取和保存标题值的方式:
class HeaderInterceptor : HandlerInterceptor {
@Throws(Exception::class)
override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {
val anonymousUserId = request.getHeader("anonymous_user_id")
headerHolder = HeaderHolder(anonymousUserId)
return true
}
companion object {
private var headerHolder: HeaderHolder = HeaderHolder()
fun getHeaders(): HeaderHolder = headerHolder
}
}
@Configuration
class HeaderInterceptorConfig : WebMvcConfigurer {
override fun addInterceptors(registry: InterceptorRegistry) {
registry.addInterceptor(anonymousUserIdInterceptor())
}
@Bean
fun anonymousUserIdInterceptor(): HeaderInterceptor {
return HeaderInterceptor()
}
}
data class HeaderHolder(
val anonymousUserId: String? = null
)
要获取标头的值,我只需调用
HeaderInterceptor.getHeaders()
。但由于并发安全的重要性,这完全是个坏主意。
看起来理想的解决方案是以某种方式将标头的值放入 spring 安全上下文中。然后我只需调用即可访问它:
class SecurityUtils private constructor() {
companion object {
fun getAnonymousUserId(): String? = SecurityContextHolder.getContext()... // an example way to access a stored value
}
}
由于我需要使用包含在静态方法中的实用程序类中的标头值,因此我希望能够在不注入 bean 的情况下访问它。
也许有人已经遇到过类似的事情并且能够解决这个问题?如果有任何提示,我将不胜感激
我的问题的解决方案非常简单。要获取标头的值,只需引用
RequestContextHolder
即可。由于还有异步执行的代码,因此我添加了对 RequestContextHolder.getRequestAttributes()
是否存在的检查。
private fun getValueFromHeader(headerName: String): String? {
return if (RequestContextHolder.getRequestAttributes() == null) {
return null
} else if (RequestContextHolder.currentRequestAttributes() is ServletRequestAttributes) {
(RequestContextHolder.currentRequestAttributes() as ServletRequestAttributes)
.request.getHeader(headerName)
} else null
}
这个方法也可以是静态的。