CDI(Weld)整合<1>整合JavaEE环境组件资源

别等时光非礼了梦想. 提交于 2019-12-03 11:31:17
除了基础部分和高级部分,CDI的第三个主题是整合。

CDI还设计了通过SPI提供集成点到Java EE平台的协同工作的平台之外的技术[在Java EE 6发布后,各种各样的Java EE平台扩展(构建在CDI扩展SPI之上)涌现了出来。]。这SPI CDI定位为便携式扩展和集成现有的框架和技术,作为整合JavaEE生态系统的基础。当然, Java EE平台将永远无法规范世界中所有在Java应用程序开发使用的有趣的技术.
你可能不会永远需要直接使用这些SPI ,但不要无视他们的存在。你可能会间接使用它们,比如你使用第三方扩展,如DeltaSpike 。

一:Java EE integration

CDI是完全集成到Java EE环境的.

1. Built-in beans

在Java EE环境中,容器提供了以下内置Bean,全部用限定符 @Default :
  • 当前JTA的UserTransaction,
  • 标识当前调用者主要的identity(身份ID),
  • 默认Bean Validation的 ValidationFactory
  • 一个验证器的默认ValidationFactory,
  • HttpServletRequest, HttpSession and ServletContext
注意:FacesContext 是无法注入的.但可以使用下面的Producer方法:
import javax.enterprise.inject.Produces;

class FacesContextProducer {

   @Produces @RequestScoped FacesContext getFacesContext() {
      return FacesContext.getCurrentInstance();
   }
}

2.Injecting Java EE resources into a bean

所有ManagedBean可以利用的Java EE组件环境注入,可使用 @Resource , @EJB, @PersistenceContext, @PersistenceUnit and @WebServiceRef.。我们已经看到了一些这方面的例子,
@Transactional @Interceptor
public class TransactionInterceptor {

   @Resource UserTransaction transaction;

   @AroundInvoke
   public Object manageTransaction(InvocationContext ctx) throws Exception { ... }

}
@SessionScoped
public class Login implements Serializable {

   @Inject Credentials credentials;

   @PersistenceContext EntityManager userDatabase;

    ...
}

在Java EE @PostConstruct和@PreDestroy的生命周期回调也支持所有ManagedBean。所有资源注入完成后@PostConstruct方法会被调用。

当然,我们建议组件环境注入是被用来定义CDI资源,并且在应用程序代码中以类型安全的注入。

3. Calling a bean from a servlet

从Java EE的一个servlet调用一个Bean也是很容易的.只需用字段或初始化方法注入Bean.如下所示:
public class LoginServlet extends HttpServlet {

   @Inject Credentials credentials;

   @Inject Login login;

   //只是示例,实际开发要避免重写Service方法,
   //一为了保留HttpServlet默认实现的缓存协商的机制(HTTP 304);
   //二就是禁用你没有在servlet中重写的方法,例如post、head等,这样就从一定程度上提高了安全性
   @Override
   public void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {

      credentials.setUsername(request.getParameter("username")):
      credentials.setPassword(request.getParameter("password")):
      login.login();
      if ( login.isLoggedIn() ) {

         response.sendRedirect("/home.jsp");
      }
      else {
         response.sendRedirect("/loginError.jsp");
      }
   }
}

servlet的实例共享所有传入的线程.

4. Calling a bean from a message-driven bean

CDI注入适用于所有的EJB,甚至他们不是CDI Bean。特别是你可以在消息驱动bean使用CDI注入.
你甚至可以使用拦截器绑定消息驱动Bean。
@Transactional
@MessageDriven
public class ProcessOrder implements MessageListener {

   @Inject Inventory inventory;

   @PersistenceContext EntityManager em;

   public void onMessage(Message message) {

     ...
   }
}

请注意,消息驱动bean不能注入@SessionScoped或@ConversationScoped的Bean。只有@RequestScoped和@ApplicationScopedBean可用。

5. JMS endpoints

使用JMS发送消息可能相当复杂,因为你需要处理许多不同的对象。queues方面的Queue,QueueConnectionFactory、QueueConnection QueueSession QueueSender。 topics方面的 topics ,TopicConnectionFactory、TopicConnection TopicSession TopicPublisher。每个对象都有自己的生命周期和线程模型,我们需要仔细处理这些问题, 最好的方式就是让容器控制

我们可以使用Producer字段和方法准备所有这些资源,用于注入bean:
import javax.jms.ConnectionFactory;
import javax.jms.Queue;

public class OrderResources {

   @Resource(name="jms/ConnectionFactory")
   private ConnectionFactory connectionFactory;

   @Resource(name="jms/OrderQueue")
   private Queue orderQueue;

   @Produces
   @Order
   public Connection createOrderConnection() throws JMSException {

      return connectionFactory.createConnection();
   }

   public void closeOrderConnection(@Disposes @Order Connection connection)throws JMSException {

      connection.close();
   }

   @Produces
   @Order
   public Session createOrderSession(@Order Connection connection)throws JMSException {

      return connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
   }

   public void closeOrderSession(@Disposes @Order Session session)throws JMSException {
      session.close();
   }

   @Produces
   @Order
   public MessageProducer createOrderMessageProducer(@Order Session session)throws JMSException {

      return session.createProducer(orderQueue);
   }

   public void closeOrderMessageProducer(@Disposes @Order MessageProducer producer)throws JMSException {

      producer.close();
   }
}

使用示例:

@Inject Order order;

@Inject @Order MessageProducer producer;

@Inject @Order Session orderSession;

public void sendMessage() {

   MapMessage msg = orderSession.createMapMessage();
   msg.setLong("orderId", order.getId());

   ...

   producer.send(msg);

}

注入的JMS对象的生命周期完全由容器控制。

6. Packaging and deployment

CDI没有定义任何特殊的部署类型。您可以打包成JAR文件,EJB JARs或war包.
如果使用CDI,bean.xml是必须要有的.
注意:CDI 1.1 makes use of a new XSD file for beans.xml descriptor: http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd

beans.xml文件必须位于:META-INF/beans.xml(jar包),或者,WEB-INF/beans.xml或WEB-INF/classes/META-INF/beans.xml(war包)。

Over.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!