我有一个EJB应用程序,它包含两个bean,ServiceEJB
(web层)和BusinessEJB
(业务层),其中BusinessEJB
is注入ServiceEJB
。
ServiceEJB
receives来自浏览器的HTTP请求,调用BusinessEJB
中的方法,获取结果,并发送HTTP响应。
此外,ServiceEJB
可以访问HttpSession
对象,其中存储了登录用户的userId
。 BusinessEJB
does无法访问HttpSession
对象。
应用程序需要记录消息(例如,使用sl4j / logback)。它可以在ServiceEJB
or BusinessEJB
方法中记录消息,当它记录消息时,它必须在日志条目中包含会话的userId
。
由于BusinessEJB
没有userId
,它需要从ServiceEJB
得到它。问题是实现这一目标的最佳方法是什么。我不想做的是在userId
中为每个方法添加一个BusinessEJB
字段作为参数,因为应用程序中有许多ServiceEJB
s和BusinessEJB
s(以及BusinessEJB
调用的其他bean也生成日志条目),我不知道我想用userId
字段污染应用程序。相反,我可以在EJB级别有一个userId
字段,但是如何填充它们?有没有办法通过注释实现这一目标?欢迎任何建议。
@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";
}
}
一些指示/评论:
getCallerPrincipal()
变体上调用EJBContext
来获取它,这里是javax.ejb.SessionContext
:
@Resource
private SessionContext sessionCtx;
Servlet可以从HttpServletRequest.getUserPrincipal()
中检索主体。 JAX-RS组件(ServiceEJB
)可以从javax.ws.rs.core.SecurityContext.getUserPrincipal()
中检索它。
您是否有任何理由不与应用程序服务器安全性集成?ContainerRequestFilter
)的过滤器设置用户数据,因此您不必担心在多个位置设置它。创建一个请求范围的CDI bean,即UserContext
。
将它注入两个EJB。
在ServiceEJB
中设置用户的id并在BusinessEJB
中读取它。