我有一个EJB应用程序,它由两个bean组成:sudo helm upgrade --install prometheus \
--set rbac.create=true \
--set server.persistentVolume.enabled=false \
--set alertmanager.persistentVolume.enabled=false \
--set alertmanager.enabled=false \
--set kubeStateMetrics.enabled=false \
--set nodeExporter.enabled=false \
--set pushgateway.enabled=false \
--set-file extraScrapeConfigs=extraScrapeConfigs.yaml \
stable/prometheus
(网络层)和ServiceEJB
(业务层),其中BusinessEJB
被注入到BusinessEJB
中。
ServiceEJB
从浏览器接收HTTP请求,在ServiceEJB
中调用方法,获取结果,然后发送HTTP响应。
此外,BusinessEJB
可以访问ServiceEJB
对象,该对象存储了登录用户的HttpSession
。 userId
无权访问BusinessEJB
对象。
应用程序需要记录消息(例如,使用sl4j / logback)。它可以使用HttpSession
或ServiceEJB
方法记录消息,并且在记录消息时,必须在记录条目中包含会话的BusinessEJB
。
由于userId
没有BusinessEJB
,因此需要从userId
获取它。问题是实现这一目标的最佳方法是什么。我不想做的是在ServiceEJB
中的每个方法中添加一个userId
字段作为参数,因为其中有许多BusinessEJB
和ServiceEJB
应用程序(以及由BusinessEJB
调用的其他bean也会生成日志条目),并且我不想使用BusinessEJB
字段来污染应用程序。相反,我可以在EJB级别上有一个userId
字段,但是如何填充它们呢?有没有办法通过注释来实现这一目标?任何建议都将受到欢迎。
userId
答案 0 :(得分:3)
一些指针/评论:
如果您与应用程序服务器安全性集成,则用户名在任何组件上都可用。 EJB可以通过在getCallerPrincipal()
的注入变量(这里为EJBContext
:)上调用javax.ejb.SessionContext
来获得它:
@Resource
private SessionContext sessionCtx;
Servlet可以从HttpServletRequest.getUserPrincipal()
中检索主体。 JAX-RS组件(ServiceEJB
)可以从javax.ws.rs.core.SecurityContext.getUserPrincipal()
检索它。
您是否有理由不与应用程序服务器安全性集成?
如果您有充分的理由不与应用程序服务器安全性集成,那么我将提出the previous answer的另一种解决方案。变体是从应用于所有资源的过滤器(servlet过滤器或JAX-RS ContainerRequestFilter
)设置用户数据,这样您就不必担心在多个位置进行设置。
如果只需要用于登录的用户ID,建议您看看slf4j中的映射诊断上下文(MDC)的概念。有了它,您可以在请求开始时及早设置用户ID,然后将其提供给所有日志记录语句。
答案 1 :(得分:2)
创建一个请求范围内的CDI bean,即UserContext
。
将其注入两个EJB中。
在ServiceEJB
中设置用户ID,然后在BusinessEJB
中读取它。