java - 将值传递给注入(inject)的 EJB

标签 java jakarta-ee java-8 ejb cdi

我有一个 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 中每个方法的字段作为参数,因为有很多ServiceEJBBusinessEJB应用程序中的 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";
  }   
}

最佳答案

一些指示/评论:

  1. 如果您与应用程序服务器安全性集成,则用户名可在任何组件中使用。 EJB 可以通过在 EJBContext 的注入(inject)变体上调用 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,并使其可用于此后的所有日志记录语句。

关于java - 将值传递给注入(inject)的 EJB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55388364/

相关文章:

Java Spring - 使用 API 持久化对象可以工作,但我无法在测试中使用服务持久化对象,空指针

java - 两个不同的对象打印相同的属性值

java - Spring MVC 应用程序的这些 mvc :resources mapping tags declared into the servlet-context. xml 意味着什么?

java - ServiceLoader + EJB注入(inject)

java - 使用 Java8 的可选返回的 JPA 的最佳实践?

java - 如何设置swing组件的大小

java - 我可以为 complexType 和元素指定相同的名称吗 - XSD 标准

java - Jersey 客户服务 - 关闭资源

java - 使用 lambda 获取 Map<K,V> 的最大键

java - 如何将 OffsetTime 转换为本地 OffsetTime?