javascript
hornetq_Spring 3 HornetQ 2.1集成教程
hornetq
通過Spring框架使用JBoss的新超高性能消息傳遞系統(tǒng)。
HornetQ是一個(gè)開放源代碼項(xiàng)目,用于構(gòu)建多協(xié)議,可嵌入,非常高性能的集群異步消息傳遞系統(tǒng)。 它是用Java編寫的,并且可以在具有Java 5或更高版本運(yùn)行時(shí)的任何平臺(tái)上運(yùn)行。 HornetQ一流的高性能日志以非持久消息傳遞通常看到的速度提供持久消息傳遞性能。 非持久消息傳遞性能也非常高。 HornetQ除其他“性感”功能外,還提供服務(wù)器復(fù)制和自動(dòng)客戶端故障轉(zhuǎn)移功能,以消除服務(wù)器故障時(shí)丟失或重復(fù)的消息,可以配置成群集使用,其中HornetQ服務(wù)器的地理位置分散的群集知道如何負(fù)載均衡消息并提供全面的信息。管理API,用于管理和監(jiān)視所有HornetQ服務(wù)器。
在本教程中,我們將向您展示如何通過Spring框架利用HornetQ 。 為了使事情變得更加有趣,我們將從上一篇關(guān)于Spring GWT Hibernate JPA Infinispan集成的文章的 結(jié)尾處繼續(xù) 。 我們將使用我們的GWTSpringInfinispan項(xiàng)目,并通過消息傳遞功能對(duì)其進(jìn)行授權(quán)! 當(dāng)然,您可以閱讀本文,將基于Spring的項(xiàng)目與HornetQ集成。
我們將使用HornetQ 2.1.0.Final版本,您可以從此處下載。 我們還將需要jboss-logging-spi庫。 將使用JBoss Logging SPI 2.1.1.GA版本,您可以在此處從JBoss Maven存儲(chǔ)庫下載該版本。
為了在運(yùn)行時(shí)正確集成Spring和HornetQ ,我們必須為Web應(yīng)用程序提供所有必需的庫。 因此,復(fù)制下面在/ war / WEB-INF / lib下列出的文件(如果使用的是不同版本,請(qǐng)復(fù)制相關(guān)文件)
從HornetQ發(fā)行
- /lib/hornetq-bootstrap.jar
- /lib/hornetq-core.jar
- /lib/hornetq-jms.jar
- /lib/hornetq-logging.jar
- /lib/jnpserver.jar
- /lib/netty.jar
JBoss Logging SPI庫
- jboss-logging-spi-2.1.1.GA.jar
最后,為了使HornetQ在運(yùn)行時(shí)正常工作,Web應(yīng)用程序的類路徑中必須有幾個(gè)配置文件。 如本教程的介紹部分所述,我們可以創(chuàng)建HornetQ服務(wù)器群集,以實(shí)現(xiàn)負(fù)載平衡和高可用性消息傳遞,也可以在非群集環(huán)境中使用HornetQ 。 兩種情況都需要不同的配置。 HornetQ發(fā)行版包含/ config目錄下的所有配置文件。 我們將使用jboss-as-5集群配置,以便能夠使用消息傳遞平臺(tái)的全部功能。 將以下文件從/ config / jboss-as-5 / clustered目錄復(fù)制到應(yīng)用程序/ resources包中:
- hornetq-configuration.xml –這是主要的HornetQ配置文件
- hornetq-jms.xml –服務(wù)器端JMS服務(wù)配置文件
除非您要在JBoss應(yīng)用服務(wù)器中進(jìn)行部署,否則請(qǐng)編輯hornetq-configuration.xml文件,并將“ $ {jboss.server.data.dir}”替換為“ $ {data.dir:../ data}”。
將以下文件從/ config / stand-alone / clustered目錄復(fù)制到應(yīng)用程序/ resources包中:
- hornetq-users.xml – HornetQ安全管理器的用戶憑證文件
在繼續(xù)實(shí)際的集成和客戶端實(shí)現(xiàn)示例之前,讓我們確定一些有關(guān)HornetQ服務(wù)器體系結(jié)構(gòu)和上述配置文件的有用信息。
HornetQ服務(wù)器不會(huì)講JMS ,實(shí)際上對(duì)JMS一無所知,它是一種協(xié)議不可知的消息傳遞服務(wù)器,旨在與多種不同的協(xié)議一起使用。 HornetQ客戶端(可能在不同的物理計(jì)算機(jī)上)與HornetQ服務(wù)器交互。 HornetQ當(dāng)前在客戶端提供了兩種用于消息傳遞的API:
- 核心客戶端API。 這是一個(gè)簡(jiǎn)單而直觀的Java API,可在沒有JMS的某些復(fù)雜性的情況下提供完整的消息傳遞功能集
- JMS客戶端API。 客戶端提供了標(biāo)準(zhǔn)的JMS API
JMS語義由客戶端上的瘦JMS外觀層實(shí)現(xiàn)。 當(dāng)用戶在客戶端上使用JMS API時(shí),所有JMS交互都將轉(zhuǎn)換為HornetQ核心客戶端API上的操作,然后再使用HornetQ有線格式通過有線進(jìn)行傳輸。 服務(wù)器始終只處理核心API交互。
標(biāo)準(zhǔn)的獨(dú)立消息傳遞服務(wù)器配置包括核心消息傳遞服務(wù)器, JMS服務(wù)和JNDI服務(wù)。
JMS服務(wù)的作用是將任何服務(wù)器端hornetq-jms.xml配置文件中的任何JMS Queue,Topic和ConnectionFactory實(shí)例部署并綁定到JNDI 。 它還提供了用于創(chuàng)建和銷毀隊(duì)列,主題和ConnectionFactory實(shí)例的簡(jiǎn)單管理API,可以通過JMX或連接對(duì)其進(jìn)行訪問。 由于核心服務(wù)器與JMS無關(guān),因此它是HornetQ核心服務(wù)器的一項(xiàng)單獨(dú)服務(wù)。 如果您不想通過服務(wù)器端XML配置部署任何JMS Queue,Topic或ConnectionFactory實(shí)例,并且不需要在服務(wù)器端使用JMS管理API,則可以禁用此服務(wù)。
還包括一個(gè)JNDI服務(wù)器,因?yàn)樵谑褂肑MS查找隊(duì)列,主題和ConnectionFactory實(shí)例時(shí), JNDI是常見的要求。 如果您不需要JNDI,則也可以禁用此服務(wù)。 HornetQ允許您直接在客戶端上以編程方式創(chuàng)建JMS和核心對(duì)象,而不是從JNDI查找它們,因此JNDI服務(wù)器并不總是必需的。
HornetQ附帶了一個(gè)基本的安全管理器實(shí)現(xiàn),該實(shí)現(xiàn)可獲取用戶憑證
從hornetq-users.xml文件中。 該文件包含用戶,密碼和角色信息。
我們將使用HornetQ JMS服務(wù),并在與命名服務(wù)器相同的JVM中執(zhí)行JMS客戶端代碼,因此我們必須創(chuàng)建一個(gè)“ jndi.properties”文件,并將其與上述其余HornetQ配置文件一起放在我們的application / resources包下。 “ jndi.properties”文件的內(nèi)容應(yīng)如下所示:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory在繼續(xù)之前,我們必須注意Eclipse項(xiàng)目的依賴性。 以下jars應(yīng)該包含在項(xiàng)目的Java構(gòu)建路徑中:
- jms.jar
現(xiàn)在讓我們將Spring與HornetQ集成。 找到您的applicationContext.xml文件/ war / WEB-INF文件夾,并添加以下bean:
<bean name="namingServerImpl" class="org.jnp.server.NamingBeanImpl" init-method="start" destroy-method="stop" /><bean name="namingServer" class="org.jnp.server.Main" init-method="start" destroy-method="stop"><property name="namingInfo" ref="namingServerImpl" /><property name="port" value="1099" /><property name="bindAddress" value="localhost" /><property name="rmiPort" value="1098" /><property name="rmiBindAddress" value="localhost" /> </bean><bean name="mbeanServer" class="java.lang.management.ManagementFactory" factory-method="getPlatformMBeanServer" /><bean name="fileConfiguration" class="org.hornetq.core.config.impl.FileConfiguration" init-method="start" destroy-method="stop" /><bean name="hornetQSecurityManagerImpl" class="org.hornetq.spi.core.security.HornetQSecurityManagerImpl" /><!-- The core server --> <bean name="hornetQServerImpl" class="org.hornetq.core.server.impl.HornetQServerImpl"><constructor-arg ref="fileConfiguration" /><constructor-arg ref="mbeanServer" /><constructor-arg ref="hornetQSecurityManagerImpl" /> </bean><!-- The JMS server --> <bean name="jmsServerManagerImpl" class="org.hornetq.jms.server.impl.JMSServerManagerImpl" init-method="start" destroy-method="stop" depends-on="namingServer"><constructor-arg ref="hornetQServerImpl" /> </bean>如果打算在獨(dú)立環(huán)境中配置Spring和HornetQ ,則上述配置就足夠了。 在我們的例子中,如果要在Apache – Tomcat上部署Web應(yīng)用程序,則應(yīng)進(jìn)行一些小的修改。
Apache – Tomcat為所有已部署的Web應(yīng)用程序提供JNDI服務(wù),以配置環(huán)境屬性和資源。 此外,由于環(huán)境和資源管理是使用部署描述符文件(例如web.xml和context.xml)完成的,因此在運(yùn)行時(shí)可用的命名上下文是只讀的。 另外,在啟動(dòng)時(shí), Apache – Tomcat使用系統(tǒng)屬性初始化其JNDI環(huán)境。 結(jié)果,使用JNDI InitialContext類(不提供構(gòu)造函數(shù)環(huán)境參數(shù))來執(zhí)行命名操作的“在VM中”客戶端始終檢索Apache – Tomcat JNDI實(shí)現(xiàn)Context接口。
為了使HornetQ JNDI服務(wù)器與Apache-Tomcat命名服務(wù)和HornetQ JMS服務(wù)共存,以便將隊(duì)列,主題和ConnectionFactory實(shí)例綁定到JNDI ,我們必須執(zhí)行以下操作:
- 對(duì)我們的Web應(yīng)用程序禁用Apache – Tomcat命名服務(wù)
- 將HornetQ JNDI服務(wù)器配置為不使用現(xiàn)有的JNDI服務(wù)(如果可用),但始終創(chuàng)建??一個(gè)新的服務(wù)
要為我們的Web應(yīng)用程序禁用Apache – Tomcat命名服務(wù),我們必須執(zhí)行以下操作:
- 在我們項(xiàng)目的/ war文件夾下創(chuàng)建一個(gè)META-INF文件夾
- 創(chuàng)建一個(gè)包含以下context指令的context.xml文件:
要將HornetQ JNDI服務(wù)器配置為不使用現(xiàn)有的JNDI服務(wù)(如果可用),我們必須在Spring bean的“ namingServerImpl”中添加以下屬性:
<property name="useGlobalService" value="false" />為了通過Spring使用HornetQ消息服務(wù),我們可以創(chuàng)建一個(gè)連接工廠,也可以從JNDI查找一個(gè)。 下面提供了連接工廠和“ JmsTemplate”示例:
<bean name="connectionFactory" class="org.hornetq.jms.client.HornetQConnectionFactory" ><constructor-arg><bean class="org.hornetq.api.core.TransportConfiguration"><constructor-arg value="org.hornetq.integration.transports.netty.NettyConnectorFactory" /><constructor-arg><map key-type="java.lang.String" value-type="java.lang.Object"><entry key="port" value="5445"></entry></map></constructor-arg></bean></constructor-arg> </bean><bean name="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"><property name="connectionFactory" ref="connectionFactory"></property> </bean>連接工廠示例的JNDI查找如下所示:
<bean id="inVMConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean" depends-on="jmsServerManagerImpl"><property name="jndiName"><value>java:/ConnectionFactory</value></property> </bean>我們將使用JNDI查找方法來獲取連接工廠,因此將上述配置添加到applicationContext.xml文件中。
這就是我們要做的所有配置,讓我們繼續(xù)使用我們新集成的消息傳遞服務(wù)來實(shí)現(xiàn)假設(shè)的業(yè)務(wù)案例。 我們的Web應(yīng)用程序提供了添加,更新和檢索“員工”數(shù)據(jù)的功能。 假設(shè)我們希望在每次添加或更改“員工”數(shù)據(jù)時(shí)都收到通知。 為了簡(jiǎn)單起見,該通知將是Apache – Tomcat控制臺(tái)上的日志。 我們將實(shí)現(xiàn)一個(gè)JMS生產(chǎn)者,以便在用戶每次對(duì)“員工”數(shù)據(jù)進(jìn)行更新時(shí)將消息發(fā)送到“通知”隊(duì)列。 另外,必須實(shí)現(xiàn)JMS使用者,以便處理“通知”隊(duì)列消息并登錄到控制臺(tái)。
要?jiǎng)?chuàng)建“通知”隊(duì)列并將其綁定到名稱為“ / queue / Notifications”的JNDI ,請(qǐng)將以下內(nèi)容添加到hornetq-jms.xml文件中:
<queue name="Notifications"><entry name="/queue/Notifications"/> </queue>為了能夠通過Spring Bean使用新創(chuàng)建的“通知”隊(duì)列,請(qǐng)將以下JNDI查找指令添加到applicationContext.xml文件:
<bean id="notificationsQueue" class="org.springframework.jndi.JndiObjectFactoryBean" depends-on="jmsServerManagerImpl"><property name="jndiName"><value>/queue/Notifications</value></property> </bean>由于JMS生產(chǎn)者和使用者都是服務(wù)器端組件,因此必須將它們放在我們應(yīng)用程序的/ server子包下。 我們選擇在/ server / utils子包下創(chuàng)建它們,因?yàn)樗鼈儽举|(zhì)上是實(shí)用程序類。 下面提供了示例JMS生產(chǎn)者和消費(fèi)者類:
package com.javacodegeeks.gwtspring.server.utils;import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.DeliveryMode; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;@Service("notificationsProducer") public class NotificationsProducer {@AutowiredQueue notificationsQueue;@AutowiredConnectionFactory inVMConnectionFactory;private Connection notificationsQueueConnection;private Session notificationsQueueSession;private MessageProducer notificationsQueueProducer;@PostConstructpublic void init() throws Exception {notificationsQueueConnection = inVMConnectionFactory.createConnection();notificationsQueueSession = notificationsQueueConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);notificationsQueueProducer = notificationsQueueSession.createProducer(notificationsQueue);notificationsQueueProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);}@PreDestroypublic void destroy() throws Exception {if(notificationsQueueConnection != null)notificationsQueueConnection.close();}public void sendNotification(final String message) throws Exception {TextMessage textMessage = notificationsQueueSession.createTextMessage(message);notificationsQueueProducer.send(textMessage);}}還有消費(fèi)者
package com.javacodegeeks.gwtspring.server.utils;import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.Queue; import javax.jms.Session; import javax.jms.TextMessage;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service;@Service("notificationsConsumer") public class NotificationsConsumer implements MessageListener {@AutowiredQueue notificationsQueue;@AutowiredConnectionFactory inVMConnectionFactory;private Connection notificationsQueueConnection;@PostConstructpublic void init() throws Exception {notificationsQueueConnection = inVMConnectionFactory.createConnection();Session notificationsQueueSession = notificationsQueueConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);MessageConsumer notificationsQueueConsumer = notificationsQueueSession.createConsumer(notificationsQueue);notificationsQueueConsumer.setMessageListener(this);notificationsQueueConnection.start();}@PreDestroypublic void destroy() throws Exception {if(notificationsQueueConnection != null)notificationsQueueConnection.close();}@Overridepublic void onMessage(Message message) {if (message instanceof TextMessage) {try {String text = ((TextMessage) message).getText();System.out.println("The Notification Message is : \n" + text);} catch (JMSException ex) {throw new RuntimeException(ex);}} else {throw new IllegalArgumentException("Message must be of type TextMessage");}}}要結(jié)束我們的示例業(yè)務(wù)案例,我們必須修改Spring員工“ employeeService”,以便在用戶每次請(qǐng)求保存或更新“ employee”數(shù)據(jù)時(shí)使用“ notificationsProducer”實(shí)用程序bean發(fā)送通知消息。 我們使用“ @Autowire”注釋在“ employeeService”內(nèi)部連接“ notificationProducer”,并從“ notificationProducer”調(diào)用“ sendNotification”操作,以便每次請(qǐng)求“ employeeService”的saveOrUpdateEmployee“操作時(shí)發(fā)送通知。 完整的代碼如下所示:
package com.javacodegeeks.gwtspring.server.services;import javax.annotation.PostConstruct; import javax.annotation.PreDestroy;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional;import com.javacodegeeks.gwtspring.server.dao.EmployeeDAO; import com.javacodegeeks.gwtspring.server.utils.NotificationsProducer; import com.javacodegeeks.gwtspring.shared.dto.EmployeeDTO; import com.javacodegeeks.gwtspring.shared.services.EmployeeService;@Service("employeeService") public class EmployeeServiceImpl implements EmployeeService {@Autowiredprivate EmployeeDAO employeeDAO;@AutowiredNotificationsProducer notificationsProducer;@PostConstructpublic void init() throws Exception {}@PreDestroypublic void destroy() {}@Transactional(propagation=Propagation.SUPPORTS, rollbackFor=Exception.class)public EmployeeDTO findEmployee(long employeeId) {return employeeDAO.findById(employeeId);}@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)public void saveEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception {EmployeeDTO employeeDTO = employeeDAO.findById(employeeId);if(employeeDTO == null) {employeeDTO = new EmployeeDTO(employeeId, name,surname, jobDescription);employeeDAO.persist(employeeDTO);}}@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)public void updateEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception {EmployeeDTO employeeDTO = employeeDAO.findById(employeeId);if(employeeDTO != null) {employeeDTO.setEmployeeName(name);employeeDTO.setEmployeeSurname(surname);employeeDTO.setJob(jobDescription);}}@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)public void deleteEmployee(long employeeId) throws Exception {EmployeeDTO employeeDTO = employeeDAO.findById(employeeId);if(employeeDTO != null)employeeDAO.remove(employeeDTO);}@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)public void saveOrUpdateEmployee(long employeeId, String name, String surname, String jobDescription) throws Exception {EmployeeDTO employeeDTO = new EmployeeDTO(employeeId, name,surname, jobDescription);employeeDAO.merge(employeeDTO);notificationsProducer.sendNotification("Save Or Update Employee with values : \nID : " + employeeId + "\nName : " + name + "\nSurname : " + surname + "\nJob description : " + jobDescription);}}而已! 要部署Web應(yīng)用程序,只需將/ war文件夾復(fù)制到Apache – Tomcat “ webapps”文件夾中。 您可以將war文件夾的名稱更改為任意名稱,最好在項(xiàng)目名稱后重命名,例如GWTSpringInfinispanHornetQ
在午餐之前,應(yīng)用程序不要忘記創(chuàng)建數(shù)據(jù)庫模式,這里是“ javacodegeeks”。
午餐應(yīng)用程序?qū)⒛臑g覽器指向以下地址
http:// localhost:8080 / GWTSpringInfinispanHornetQ /
如果一切順利,您應(yīng)該會(huì)看到您的主頁。 應(yīng)該顯示兩個(gè)文本框,每個(gè)文本框后面都有一個(gè)按鈕。 在第一個(gè)文本框中,您可以將員工保存或更新到數(shù)據(jù)庫。 作為輸入,提供ID,名稱,姓氏和職位描述,并用空格字符分隔。 單擊“ SaveOrUpdate”按鈕,將提供的信息存儲(chǔ)到數(shù)據(jù)庫中。 對(duì)于現(xiàn)有的“員工”條目(相同ID),將執(zhí)行更新。 在這兩種情況下,都應(yīng)記錄一個(gè)通知日志。 日志格式應(yīng)如下:
通知消息為:
使用值保存或更新員工:
編號(hào):xxx 名稱:xxx 姓:xxx 職位描述:xxx
其中“ xxx”應(yīng)為您提供的“員工”信息。 請(qǐng)查看日志文件(catalina.out)。 第二個(gè)文本框用于檢索現(xiàn)有的“雇員”條目。 提供一個(gè)“雇員” ID,然后單擊“檢索”按鈕。 如果“雇員”存在,則應(yīng)看到“雇員” ID,姓名,姓氏和職位描述。
您可以從此處下載該項(xiàng)目(如開頭所述,并且不包含先前的文章,所需的第三方庫)
玩得開心!
賈斯汀
相關(guān)文章 :- GWT 2 Spring 3 JPA 2 Hibernate 3.5教程
- GWT Spring和Hibernate進(jìn)入數(shù)據(jù)網(wǎng)格世界
- Spring 3 RESTful Web服務(wù)
- GWT 2 Spring 3 JPA 2 Hibernate 3.5教程– Eclipse和Maven 2展示
- 具有Spring和Maven教程的JAX–WS
翻譯自: https://www.javacodegeeks.com/2010/06/spring-3-hornetq-21-integration.html
hornetq
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的hornetq_Spring 3 HornetQ 2.1集成教程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 六边七彩连珠电脑版(七彩连珠手机版官方下
- 下一篇: 封装电脑系统推荐软件(新电脑装机软件推荐