JMS : Java Message Service (Java消息服务)之三

6.12.多线程的消息发送
代码说明:首先要在主类里创建一个内部类继承thread的run方法,以实现多线程的发送,在主类里构建一个构造函数,把一些发送消息的预备工作初始化,从而让多线程只处理发送的动作,节省每次线程初始发送的预备动作,来达到快速的发送消息.
这个示例是创建一个消息发送器发送两个分别设置不同属性的消息构造器

public class Sendert {

private static transient final Log log = LogFactory.getLog(Sendert.class);
    QueueConnection        queueConnection = null;
    QueueSession            queueSession = null;
    QueueSender             queueSender = null;
      final String       MSG_TEXT1 =
          new String("Here is a client-acknowledge message 4tetrtretertert4t45ewrwerwrgergrt4rqwerew5t479347597505890 34535&%^*&$&^$^%$&%&*)_*)&^*%*^$&$^(*&(*&(*%*%&^%*%^%*&^*&^&*^*&^*&^");
      final String       MSG_TEXT2 =
      new String("Here is a Message  327893475984 ryeirrfr9urtyureyt&&&&&&&)))__^&&&))gerg)%%^%^%^%&(*(*(*)*(**)(*)*)*)T^HJCJBDKJFBKJJDOAIWEU(Q�(&E(*�Q*E&QEUODIJEDLJLHDKGDUWTE&QE");
      TextMessage         message1 = null;
      TextMessage         message2 = null;
      static long time1;
      static long time4;

public Sendert() throws JMSException, NamingException {

//javax.naming.Context ictx = new InitialContext(JMSConstant.getProp());

Properties pr =new Properties();
pr.put("82.0.176.214","16400");
javax.naming.Context  ictx = new InitialContext(pr);
QueueConnectionFactory  queueConnectionFactory = (QueueConnectionFactory) ictx.lookup("qcf");

queueConnection = queueConnectionFactory.createQueueConnection("user1","user1");
queueSession = queueConnection.createQueueSession(false,
Session.CLIENT_ACKNOWLEDGE);
Queue queue = (Queue) ictx.lookup("queue");
ictx.close();
queueSender = queueSession.createSender(queue);//创建消息发送器
message1 = queueSession.createTextMessage();//创建消息生成器
message2 = queueSession.createTextMessage();//创建消息生成器
message1.setIntProperty("sessionID", 1);//设置消息属性.以便消息接收的过滤
message2.setIntProperty("sessionID", 2);//设置消息属性, 以便消息接收的过滤
}
class AsynSender extends Thread {

public void run () {   
try {
for(int i=0;i<100;i++){
message1.setText("i"+MSG_TEXT1);//设置消息
message2.setText("i"+MSG_TEXT2);//设置消息
System.out.println("  message1: "  + message1.getText());
System.out.println("  message2: "  + message2.getText());
queueSender.send(message1);//发送消息
queueSender.send(message2);//发送消息
}
} catch (JMSException e) {
System.out.println("Exception occurred: " + e.toString());
}
}
}


//         finally {
//         if(queueSender!=null){
//         try{queueSender.close();
//        
//         }catch(JMSException e){}
//         if(queueSession!=null)
//         {
//         try{
//         queueSession.commit();
//         }catch(JMSException e){}
//         }
//             if (queueConnection != null)
//             {
//                 try {
//                     queueConnection.close();
//                 } catch (JMSException e) {}
//             }
//         }
//         }

public void run_threads() {
AsynSender[] tt = new AsynSender[100];
for (int i = 0; i < tt.length; i++)
{
tt[i] = new AsynSender();
tt[i].start();

}

for (int i = 0; i < tt.length; i++) {
System.out.println("go1");
try {
tt[i].join();//让子线程发送消息完毕后,才执行主控线程,关闭发送器,连接,会话对象

} catch (InterruptedException je)
{
Je.printstacktrace();}
}
}

void close() throws JMSException {
queueSender.close();
queueSession.close();
queueConnection.close();
}


public static void main(String[] args) throws JMSException, NamingException, IOException {
System.out.println(" sender: Created client-acknowledge session");
Sendert se = new Sendert();
se.run_threads();
se.close();//发送消息完毕关闭消息发送器,会话,连接对象.
}

}
6.13 joram远程部署.
Joarm的远程部署,即jms服务器和jms客户端不在同一ip主机上,首先我们选定一服务器主机名是KBF_BCR, ip地址是82.0.176.214.在这台主机上安装joram,配置好服务器的a3server.xml.文件如下:
<?xml version="1.0"?>
<config>
<property name="Transaction" value="fr.dyade.aaa.util.NullTransaction"/>
<server id="0" name="S0" hostname="KBF_BCR">
<service class="org.objectweb.joram.mom.proxies.ConnectionManager"
args="root root"/>
<service class="org.objectweb.joram.mom.proxies.tcp.TcpProxyService"
args="16010"/>
<service class="fr.dyade.aaa.jndi2.server.JndiServer" args="16400"/>
</server>
</config>
启动服务器.就ok了!
二:接下来是在选定另一台主机做为jms的客户端:我们执行如下代码,在服务器下创建queue,topic,user,和jndi对它们的绑顶。代码如下:
public class Amdinx {
public static void main(String args[])throws Exception{
System.out.println("begin the admin test!");
//connecting to JORAM server
AdminModule.connect("82.0.176.214",16010,"root", "root", 60);
// AdminModule连接服务器,参数为服务器ip地址,连接工厂的端口,登陆用户名,密码和每
//秒尝试连接的次数.
Queue queue = (Queue) Queue.create(0);//参数0为服务器id,与a3server.xml对应.
User user1 = User.create("user1","user1",0); //参数0为服务器id,与a3server.xml对应.
User user2 = User.create("user2","user2",0); //参数0为服务器id,与a3server.xml对应.
User user3 = User.create("user3","user3",0); //参数0为服务器id,与a3server.xml对应.
queue.setFreeReading(user1);//只让user1读
queue.setFreeWriting(user1);//只让user1写
javax.jms.QueueConnectionFactory qcf =
QueueTcpConnectionFactory.create("82.0.176.214", 16010);//服务器的连接工厂,参数为服务器ip,和连接工厂的端口号.

Properties pr =new Properties();
pr.put("82.0.176.214","16400");
javax.naming.Context jndiCtx = new InitialContext(pr);
// javax.naming.Context jndiCtx = new javax.naming.InitialContext(JMSConstant.getProp());

jndiCtx.bind("qcf", qcf);
jndiCtx.bind("queue", queue);
jndiCtx.close();//关闭上下文目录

AdminModule.disconnect();//关闭AdminModule连接
System.out.println("close the admin!");
}
}
这样就执行代码后,就在服务器上创建了用户,目的地,和对它们的jndi绑定.
三:然后执行多线程的发送消息的代码:(见6.12多线程的消息发送)
四:多线程的接收消息,代码如下.
public class Receiver1
{

QueueReceiver qrec1=null;
QueueSession qs =null;
QueueConnection qc=null;

public Receiver1() throws NamingException, JMSException{
//ictx = new InitialContext(JMSConstant.getProp());

Properties pr =new Properties();
pr.put("82.0.176.214","16400");
Context ictx = new InitialContext(pr);
Queue queue = (Queue) ictx.lookup("queue");
QueueConnectionFactory qcf = (QueueConnectionFactory) ictx.lookup("qcf");
ictx.close();
qc = qcf.createQueueConnection("user1","user1");//创建只属于user1的连接,以区别其他连接.
qs = qc.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);
qrec1 = qs.createReceiver(queue,"sessionID=2");
}

class Brun extends Thread{
public void run(){
try{
qrec1.setMessageListener(new MsgListener1());
qc.start();//把连接开始应该放在此处.设置消息监听动作之后
}catch(JMSException e){}
}
}

public void run_thread() {
Brun[] tt = new Brun[300];
for (int i = 0; i < tt.length; i++) {
tt[i] = new Brun();
tt[i].start();

}

}

void close() throws JMSException {
qrec1.close();
qs.close();
qc.close();
}

public static void main(String[] args) throws Exception
{
System.out.println("Requests to receive messages...");

Receiver1 rc=new Receiver1();
rc.run_thread();
// qc.start();   不能把连接开始放在此处,而是放在设置消息监听的动作之后.
System.in .read();//当消息接收完毕,在控制台上输入任意字符,执行关闭的动作.
rc.close();
System.out.println( " messages received.");
}
}
7 joram和spring的集成
7.1 简单的消息发送
一.首先启动joram服务器,管理各种对象和jndi绑定(详细请看前面章节).
二.在工程目录下引入spring支持的包和joram包.
三.在工程目录下创建applicationContext.xml文件.这个文件是spring的配置文件.示例如下

<!-----xml文件头,为默认,我们不需要修改---------------->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<!------配置文件内容------->
<beans>
<!------连接工厂配置.注意:value值为jndi绑定后的key=”qcf”------->
<bean id="connectionFactory"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>qcf</value>
</property>
<property name="jndiTemplate">
<ref local="jndiTemplate"></ref>
</property>
</bean>
<!-----目的地配置,注意:queue为jndi绑定后的key而不是value>
<bean id="destination"
class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>queue</value>
</property>
<property name="jndiTemplate">
<ref local="jndiTemplate"></ref>
</property>
</bean>
<!---spring-jms模版:注意:joram是支持jms1.1的所以用org.springframework.jms.core.JmsTemplate而不是用org.springframework.jms.core.JmsTemplate102------- >

<bean id="jmsTemplate"
class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory">
<ref local="connectionFactory" />
</property>
<property name="defaultDestination">
<ref local="destination" />
</property>
</bean>
<!-----配置jndi环境------->
<bean id="jndiTemplate"
class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">
fr.dyade.aaa.jndi2.client.NamingContextFactory
</prop>
<prop key="java.naming.factory.host">localhost</prop>
<prop key="java.naming.factory.port">16400</prop>
</props>
</property>
</bean>

 


</beans>
四.发送消息客户端代码:
public class JmsTemplateTest11 {
protected static final Log log = LogFactory.getLog(JmsTemplateTest11.class);

static Context ictx = null;

public static void main(String[] args) throws NamingException, JMSException {

System.out.println();
System.out.println("Sends messages on the queue...");
.

ApplicationContext ac = new FileSystemXmlApplicationContext(
new String[]{
"F:\\project\\SpringJMS\\src\\applicationContext.xml"});

JmsTemplate jt = (JmsTemplate) ac.getBean("jmsTemplate");
//注入bean,由于配置文件各个bean是相互关联的,所以注入jmsTemplate就注入了//其它bean,当然你也可以这样写.但是配置文件中各个bean没有关联.这段代码可以//更深入理解spring的ioc模式
//Destination de = (Destination) ac.getBean(“destination”)
//QueueConnetionfactory cf =( QueueConnectionFactory)  //ac.getBean(“connectionFactory”)


jt.send(new MessageCreator() {
public Message createMessage(Session session) throws JMSException {
//            return session
//                  .createTextMessage("Hello World(11),queue!");
TextMessage message = (TextMessage) session.createTextMessage("bbc");//创建一个消息,内容为bbc.
return message;
}
});
log.info("成功发送消息!");
System.out.println("Success Sends messages to the queue...");

}
}

posted @ 2010-07-17 07:38  采云摘月  阅读(490)  评论(0编辑  收藏  举报