其他 servlet 可以访问 jsf 应用程序中的 cdi bean 吗?

Posted

技术标签:

【中文标题】其他 servlet 可以访问 jsf 应用程序中的 cdi bean 吗?【英文标题】:Can other servlets access cdi beans in jsf application? 【发布时间】:2017-08-18 16:05:03 【问题描述】:

我有一个问题可能源于我对 jsf 的理解不足并面临 servlet 概念......我终于让我的 jsf 应用程序在谷歌应用引擎上工作。这花了很多时间和一些解决方法,但它已经启动并运行了:) 现在我想将应用程序中的数据用于 android 应用程序。我想没问题,但当然有……我想我可以在 jsf 应用程序中放置一个额外的 servlet 并访问我用于网页的相同 cdi bean。显然这并不容易。当我尝试将 bean 注入额外的 servlet 时,它们为空。当我为我的 servlet 创建一个额外的 Faces 上下文时,它确实有效!但仅在测试环境中......当我部署到应用程序引擎时,该解决方法不起作用。有什么建议吗?

【问题讨论】:

您有一个带有 EJB 和 WAR 模块的 EAR 文件吗? WAR模块类路径中是否包含EJB模块的jar文件? 【参考方案1】:

您可以通过 BeanManager 访问 CDI bean。您可以将其作为资源注入。然后您可以从 BeanManager 获取 bean 实例。这些 bean 非常简单,它们只是返回一个值来查看它们的类型。

CDI bean:

package x;

import java.io.Serializable;
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;

@Named( value = "myCDIBean" )
@SessionScoped
public class MyCDIBean implements Serializable

  private String value = "named";

  public MyCDIBean() 

  public String getValue()
  
    return value;
  

  public void setValue( String value_ )
  
    value = value_;
  

JSF 托管 bean:

package x;

import java.io.Serializable;
import javax.annotation.ManagedBean;
import javax.enterprise.context.SessionScoped;

@ManagedBean( value = "myJSFManagedBean" )
@SessionScoped
public class MyJSFManagedBean implements Serializable

  private String value = "managed";

  public MyJSFManagedBean() 

  public String getValue()
  
    return value;
  

  public void setValue( String value_ )
  
    value = value_;
  

小服务程序:

package x;

import java.io.IOException;
import java.io.PrintWriter;
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;

@WebServlet( urlPatterns ="/MyServlet" )
public class MyServlet extends HttpServlet

  @Resource
  BeanManager beanManager;

  public static <T> T getBeanInstance( BeanManager bm_, Class<T> class_ )
  
    Bean<T> bean = (Bean<T>) bm_.getBeans( class_ ).iterator().next();
    CreationalContext<T> ctx = bm_.createCreationalContext( bean );
    T object = (T) bm_.getReference(bean, class_, ctx);
    return object;
  

  protected void processRequest( HttpServletRequest request, HttpServletResponse response )
    throws ServletException, IOException
    
    response.setContentType( "text/html;charset=UTF-8" );
    try (PrintWriter out = response.getWriter())
    
      out.println( "<!DOCTYPE html>" );
      out.println( "<html>" );
      out.println( "<head>" );
      out.println( "<title>Servlet NewServlet</title>" );      
      out.println( "</head>" );
      out.println( "<body>" );
      out.println( "<h1>Servlet MyServlet at " + request.getContextPath() + "</h1>" );
      MyCDIBean named = getBeanInstance( beanManager, MyCDIBean.class );
      out.println( "<p>named bean value: <b>" + named.getValue() + "</b></p>" );
      MyJSFManagedBean managed = getBeanInstance( beanManager, MyJSFManagedBean.class );
      out.println( "<p>managed bean value: <b>" + managed.getValue() + "</b></p>" );
      out.println( "</body>" );
      out.println( "</html>" );
    
  

【讨论】:

非常感谢您的回答!我学到了很多东西,即使它没有解决我的问题。我无法以任何方式注入或查找 bean 管理器......但问题已解决!当我意识到我需要的每个 bean 都是 requestscoped 时,一个简单的 Bean bean = new Bean() 就足够了。感觉有点尴尬,我把一切都比原来复杂得多...... 不客气! BalusC主页值得一看:jsf.zeef.com/bauke.scholtz#block_24059希望你不介意我推荐它,亲爱的@BalusC :) 永远不要手动实例化企业 bean,因为它的资源不会被初始化(它会创建容器)。始终使用 @EJB/@Inject 注释注入 bean。在这种情况下,具有容器管理生命周期的 bean 将在调用业务方法之前初始化

以上是关于其他 servlet 可以访问 jsf 应用程序中的 cdi bean 吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 Servlet 2.4 容器上运行 JSF 2.0

Java EE 6:JSF 与 Servlet + JSP。我应该费心学习 JSF 吗?

JSF - Spring 安全集成问题

JSF Servlet 模式/奇怪的请求

JSF 托管 bean 如何比普通的 Javax Servlet 更有益[重复]

如何使用 faces servlet 映射设置 JSF2 <welcome-file>?