为了验证ActiveMQ传递序列化对象与同步的可行性,搭建一个小的测试系统来测试。这个系统的结构为:
其中DB为数据库,服务器端和客户端数据定义和数据是一致的。服务器端CURD为数据库操作类,它将操作对象信息序列化后发送给MQAPP,MQAPP负责和ActiveMQ交互传递序列化后的信息。客户端MQAPP接收到序列化后对象反序列化后,重新交给CURD程序写到数据库中。以上步骤来保证数据库同步。
这个实验的步骤大体如下:
1. 对象序列化、重建对象
2. 传递序列化消息、重建对象
3. 建立数据库、数据库操作类、封装操作对象
4. 传递操作信息、重建对象、数据库操作
5. 消息平台实现与完善
实验一的实现方法,序列化对象需要实现Serializable接口,由ObjectOutputStream输出对象到文件或网络,再由ObjectInputStream接受流重新生成对象。序列化代码如下:
user u = new user();
u.setName("gongqingkui");
u.setPassword("123");
ObjectOutputStream oos = new ObjectOutputStream(newFileOutputStream("a.txt"));
oos.writeObject(u);
以上代码序列化一个用户到文件a.txt中,以下程序解析a.txt中内容,反序列化为对象之后输出:
ObjectInputStream in = new ObjectInputStream(newFileInputStream("a.txt"));
user u = (user)in.readObject();
System.out.println(u.toString());
第二步,在ActiveMQ上,传递序列化之后的消息,再由客户端接收到消息后反序列化成新的对象。序列化之后的字串,存储在文本文件中,再重新生成对象是可行的。但是在ActiveMQ中传递文本消息牵涉到消息头问题,比较复杂。这里采用对象消息的形式,在ActiveMQ中采用ObjectMessage(serializables)的方法传递序列化之后的对象,在接收端重新恢复为对象即可。发送对象消息的代码为:
public void produceObeject(Serializable s) throws JMSException,Exception{
initialize();
ObjectMessageom = session.createObjectMessage(s);
connection.start();
producer.send(om);
//System.out.println("objectmessage ok");
}
上述代码建立了ObjectMessage消息,传递了序列化之后的User对象到消息队列中。解析对象消息的客户端代码为:
if(message instanceof ObjectMessage){
//System.out.println(message);
ObjectMessageom = (ObjectMessage)message;
useru = null;
try{
u= (user)om.getObject();
}catch (JMSException e) {
e.printStackTrace();
}
System.out.println("A"+u.toString());
}
上述代码,接受传递过来的ObjectMessage,强制类型转换后,重新构建为user对象,调用user对象的方法,输出信息。
实验三,建立数据库和数据库操作类,并对操作对象进行封装。这里采用SQLServer数据库,数据表为user,定义SQL语句为:
if exists (select * from dbo.sysobjects where id =object_id(N'[dbo].[user]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[user]
GO
CREATE TABLE [dbo].[user] (
[id] [int] IDENTITY(1, 1) NOT NULL ,
[name] [char] (15)COLLATE Chinese_PRC_CI_AS NULL ,
[password] [char] (32)COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]
GO
对数据表user的封装采用类user,其定义为:
package db;
import java.io.Serializable;
public class user implements Serializable{
private String name;
private Stringpassword;
//访问器略
@Override
public StringtoString() {
return"object user: name:"+getName()+" password:"+getPassword();
}
}
对sql操作语句封装为sql对象:
package curd;
import java.io.Serializable;
public class sql implements Serializable{
private String query;
//访问器略
public StringtoString() {
return"object sql: query:"+getQuery();
}
}
以上两者作为一个对象的两个属性,封装到report类中,report类作为消息传递的主题来进行传递,report定义为:
package curd;
import java.io.Serializable;
public class report implements Serializable{
Object o;
sql sqlQuery;
//访问器略
public StringtoString() {
return"object report: object:"+getO()+" SqlQuery:"+getSqlQuery();
}
}
在Producer类中,调用ProducerTool类中的方法,将report类作为对象传递给ActiveMQ服务器。producerTool等代码实现参考3。这段代码是:
ProducerTool pt = new ProducerTool();
user u = newuser();
u.setName("Test:gongqingkui");
u.setPassword("Test:123");
sql s = newsql();
s.setQuery("select* from user");
report r =new report();
r.setO(u);
r.setSqlQuery(s);
pt.produceObject(r);
pt.close();
接收端代码是:
ConsumerTool ct = new ConsumerTool();
ct.consumeMessage();
ct.close();
参考
2. QX项目实战-8.ActiveMQ的Queue消息和Topic消息