【问题标题】:Pass value to injected EJB将值传递给注入的 EJB
【发布时间】:2019-03-28 00:15:25
【问题描述】:

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

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

此外,ServiceEJB 可以访问 HttpSession 对象,其中存储了登录用户的 userIdBusinessEJB 无权访问 HttpSession 对象。

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

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

【问题讨论】:

    标签: java jakarta-ee java-8 ejb cdi


    【解决方案1】:

    一些指针/cmets:

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

      @Resource
      private SessionContext sessionCtx;
      

      Servlet 可以从HttpServletRequest.getUserPrincipal() 检索主体。 JAX-RS 组件(ServiceEJB)可以从javax.ws.rs.core.SecurityContext.getUserPrincipal() 中检索它。

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

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

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

    【讨论】:

    • 谢谢,我最终使用了 MDC,这是最简单的解决方案。
    【解决方案2】:

    创建一个请求范围的 CDI bean,即UserContext

    将它注入到两个 EJB 中。

    ServiceEJB 中设置用户ID 并在BusinessEJB 中读取。

    【讨论】:

      猜你喜欢
      • 2021-03-23
      • 1970-01-01
      • 2011-01-24
      • 1970-01-01
      • 1970-01-01
      • 2014-04-25
      • 1970-01-01
      • 1970-01-01
      • 2019-02-21
      相关资源
      最近更新 更多