首页 > 解决方案 > 将值传递给注入的 EJB

问题描述

我有一个 EJB 应用程序,它包含两个 bean,ServiceEJB(Web 层)和BusinessEJB(业务层),其中BusinessEJB注入了ServiceEJB.

ServiceEJB接收来自浏览器的 HTTP 请求,调用 中的方法BusinessEJB,获取结果,发送 HTTP 响应。

此外,ServiceEJB可以访问存储登录用户的HttpSession对象的对象。无权访问该对象。userIdBusinessEJBHttpSession

应用程序需要记录消息(例如,使用 sl4j/logback)。它可以记录消息ServiceEJBBusinessEJB方法,当它记录消息时,它必须userId在日志条目中包含会话的。

由于BusinessEJB没有userId,它需要从ServiceEJB. 问题是实现这一目标的最佳方法是什么。我不想做的是在userId每个方法中添加一个字段BusinessEJB作为参数,因为应用程序中有很多ServiceEJBs 和BusinessEJBs (以及由它调用的其他 beanBusinessEJB也会生成日志条目),我不想要污染该userId领域的应用程序。相反,我可以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";
  }   
}

标签: javajakarta-eejava-8ejbcdi

解决方案


一些指针/评论:

  1. 如果您与应用程序服务器安全性集成,则用户名可在任何组件中使用。EJB 可以通过调用getCallerPrincipal()的注入变体来获取它EJBContext,这里是javax.ejb.SessionContext

    @Resource
    private SessionContext sessionCtx;
    

    Servlet 可以从HttpServletRequest.getUserPrincipal(). JAX-RS 组件(ServiceEJB)可以从javax.ws.rs.core.SecurityContext.getUserPrincipal().

    您是否有任何理由不与应用程序服务器安全性集成?

  2. 如果您有充分的理由不与应用程序服务器安全性集成,我会建议对上一个答案的解决方案进行变体。变体是从应用于所有资源的过滤器(servlet 过滤器或 JAX-RS ContainerRequestFilter)中设置用户数据,这样您就不必担心在多个地方设置它。

  3. 如果您只需要用于记录的用户 ID,我建议您查看 slf4j 中映射诊断上下文 (MDC) 的概念。有了它,您可以在请求开始时尽早设置用户 ID,并使其可用于此后的所有日志记录语句。


推荐阅读