我有一个 EJB 应用程序,它由两个 Bean 组成:ServiceEJB
(网络层)和 BusinessEJB
(业务层),其中 BusinessEJB
被注入(inject) ServiceEJB
。
ServiceEJB
接收来自浏览器的HTTP请求,调用BusinessEJB
中的方法,获取结果,并发送HTTP响应。
此外,ServiceEJB
可以访问 HttpSession
对象,其中userId
存储登录用户的信息。 BusinessEJB
无法访问HttpSession
对象。
应用程序需要记录消息(例如使用 sl4j/logback)。它可以将消息记录在 ServiceEJB
中或BusinessEJB
方法,并且当它记录消息时,它必须包含 userId
日志条目中的 session 的信息。
自 BusinessEJB
没有userId
,它需要从 ServiceEJB
获取它。问题是实现这一目标的最佳方法是什么。我不想做的是添加 userId
BusinessEJB
中每个方法的字段作为参数,因为有很多ServiceEJB
和 BusinessEJB
应用程序中的 s(以及由 BusinessEJB
调用的其他也会生成日志条目的 bean),并且我不想用 userId
污染应用程序 field 。相反,我可以有一个 userId
EJB 级别的字段,但是如何填充它们呢?有没有办法通过注释来实现这一点?欢迎任何建议。
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
@Stateless
public class ServiceEJB {
@Context
HttpServletRequest httpRequest;
@Inject
private BusinessEJB bean;
private String userId;
@Path("someurl")
public Response someMethod1() {
final HttpSession session = httpRequest.getSession();
// get the userId from the session
String s = bean.someMethod2();
// return Response
}
}
@Stateless
public class BusinessEJB {
private String userId;
public String someMethod2() {
// .... log an entry with userId
return "something";
}
}
最佳答案
一些指示/评论:
如果您与应用程序服务器安全性集成,则用户名可在任何组件中使用。 EJB 可以通过在
EJBContext
的注入(inject)变体上调用getCallerPrincipal()
来获取它,这里是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,并使其可用于此后的所有日志记录语句。
关于java - 将值传递给注入(inject)的 EJB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55388364/