activeMQ

    最近工作需要,做了与泛微OA系统的MQ消息集成,现在与大家分享,共同学习,有不足处请提出,尽量优化提高。

一、ActiveMQ简介

    ActiveMQ是Apache软件基金下的一个开源软件,它遵循JMS1.1规范(Java Message Service),是消息驱动中间件软件(MOM)。它为企业消息传递提供高可用,出色性能,可扩展,稳定和安全保障。ActiveMQ使用Apache 许可协议。因此,任何人都可以使用和修改它而不必反馈任何改变。这对于商业上将ActiveMQ用在重要用途的人尤为关键。MOM的工作是在分布式的各应 用之间调度事件和消息,使之到达指定的接收者。所以高可用,高性能,高可扩展性尤为关键。

二、实战

    以下描述性的语言较少,只是将主要代码贴出来,有部分注释。

    1、客户端连接MQ服务器(MQConnection.java)

public class MQConnection {

	// 日志对象初始化
	private static final Logger logger = LoggerFactory.getLogger(MQConnection.class);

	// MQ服务器服务地址(failover:initialReconnectDelay:第一次连接时延迟毫秒数,
	// maxReconnectDelay:每次重连最大间隔毫秒数)
	// 建议在具体应用中调整为使用配置参数设置此默认值
//	private static final String DEFAULT_URL = "failover:(tcp://10.199.81.33:61616)";
	private static final String DEFAULT_URL = MQStateAttribute.CONNURL;

	// 可为每个对象单独设置自己的Connection url
	private String url = DEFAULT_URL;

	// 是否对每个对象都使用默认的Connection对象
	private boolean useDefaultConn = true;

	// JMS链接对象
	private Connection conn;

	// 统一的Connection对象
	private static Connection defaultConn;

	// 获得Connection
	public Connection getConn() throws Exception{

		if (useDefaultConn) {
			// 如果使用统一Connection对象且该对象未创建过,则进行创建并返回
			// 使用双层判断保证永远不可能创建一个以上的Connection对象
			if (defaultConn == null) {
				synchronized (MQConnection.class) {
					if (defaultConn == null) {
						defaultConn = createConn(DEFAULT_URL);
					}
				}
			}
			return defaultConn;
		} else {
			// 如果不使用统一Connection对象且该对象未创建过,则进行创建并返回
			// 使用双层判断保证永远不可能创建一个以上的Connection对象
			if (conn == null) {
				synchronized (this) {
					if (conn == null) {
						conn = createConn(url);
					}
				}
			}
			return conn;
		}
	}

	private Connection createConn(String url) throws Exception {
		// 创建JMS链接工厂
		ActiveMQConnectionFactory connFactory = new ActiveMQConnectionFactory(url);
		
//		RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
//		redeliveryPolicy.setMaximumRedeliveries(0);
//		RedeliveryPolicyMap redeliveryPolicyMap = new RedeliveryPolicyMap();
//		redeliveryPolicyMap.setDefaultEntry(redeliveryPolicy);
//		connFactory.setRedeliveryPolicyMap(redeliveryPolicyMap);
		connFactory.setUseAsyncSend(true);
//		connFactory.setWarnAboutUnstartedConnectionTimeout(10L);//超时警告
//		connFactory.setMaxThreadPoolSize(1);
//		TaskRunnerFactory taskRunnerFactory = new TaskRunnerFactory();
//		taskRunnerFactory.setMaxIterationsPerRun(2);
//		taskRunnerFactory.setMaxThreadPoolSize(1);
//		taskRunnerFactory.setShutdownAwaitTermination(10);
//		connFactory.setSessionTaskRunner(taskRunnerFactory);
		
		// 创建消息连接
		Connection tempConn = connFactory.createConnection();
		// 启动连接
		tempConn.start();
		logger.error("创建MQ连接成功.");
		return tempConn;
	}

	public void closeConn() throws Exception {
		if (useDefaultConn && defaultConn != null)
			defaultConn.close();
		else if (!useDefaultConn && conn != null)
			conn.close();
		logger.error("MQ连接关闭.");
		
	}

	public boolean getUseDefaultConn() {
		return useDefaultConn;
	}

	public void setUseDefaultConn(boolean useDefaultConn) {
		this.useDefaultConn = useDefaultConn;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}
}

    2、客户端以订阅方式发送消息(MQPublish.java)

public class MQPublish {
	private static final Logger logger = LoggerFactory.getLogger(MQPublish.class);
	private MQMassageEntity entity;
	private MQPublicMeaageInvoke invoke;
	
	public void sendMess(MQMassageEntity entity) throws Exception {
		MQConnection ii = new MQConnection();
//		ii.setUseDefaultConn(false);  //取消默认连接
//		ii.setUrl("failover:(tcp://localhost:61616)"); //手动设置MQ接收服务器地址
		Connection conn = ii.getConn();
		Session session = conn.createSession(true, Session.AUTO_ACKNOWLEDGE);
		// 订阅式消息模式,该模式中,除非消息被消费,否则在MQ未停止运行前,消息将一直保存
		Topic topic = new ActiveMQTopic(MQStateAttribute.TOPIC_NAME);
		// 创建生产者订阅式消息对象
		MessageProducer producer = session.createProducer(topic);
		// 设置消息持久化方式,为消息在MQ服务器中永久保存提供保障
//		producer.setDeliveryMode(DeliveryMode.PERSISTENT);
		producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
		// 创建MQ内置消息对象
		MapMessage mm = session.createMapMessage();

		mm.setString("Sender", entity.getSender());
		mm.setString("Sendertime", MQUtils.myFormatDate(entity.getSendertime(), "yyyy-MM-dd HH:mm:ss"));
		mm.setString("Flowtype", entity.getFlowtype());
		mm.setString("FlowID", entity.getFlowid());
		mm.setString("Title", entity.getTitle());
		mm.setString("Nodename", entity.getNodename());
		mm.setString("Ptpurl", entity.getPtpurl());
		mm.setString("Userid", entity.getUserid());
		mm.setString("Creator", entity.getCreator());
		mm.setString("Createdate", MQUtils.myFormatDate(entity.getCreatedate(), "yyyy-MM-dd"));
		mm.setString("Createtime", MQUtils.myFormatDate(entity.getCreatedate(), "HH:mm:ss"));
		mm.setString("Operatedate", MQUtils.myFormatDate(entity.getOperatedate(), "yyyy-MM-dd"));
		mm.setString("Operatetime", MQUtils.myFormatDate(entity.getOperatedate(), "HH:mm:ss"));
		mm.setString("Flowmess", entity.getFlowmess());
		mm.setString("Viewtype", entity.getViewtype());
		
//			mm.setString("Sender", "xxxxx系统");
//			mm.setString("Sendertime", dt.toString("yyyy-MM-dd HH:mm:ss"));
//    			mm.setString("Flowtype", "业务流程");
//			mm.setString("FlowID", BaseUtils.uuid());
//			mm.setString("Title", "请求标题");
//			mm.setString("Nodename", "创建");//创建、批准、提交、归档
//			mm.setString("Ptpurl","http://xxx.cn:8080/xxx/xxx/showDetailWithWorkFlow.do?businessKey=receiveorder:6e9aa422-8a01-4ad1-9155-7c3b80bbfeb3&taskId=46795");
//			mm.setString("Userid", "xxx");
//			mm.setString("Creator", "xxx");
//			mm.setString("Createdate", dt.toString("yyyy-MM-dd"));
//			mm.setString("Createtime", dt.toString("HH:mm:ss"));
//			mm.setString("Operatedate", dt.toString("yyyy-MM-dd"));
//			mm.setString("Operatetime", dt.toString("HH:mm:ss"));
//			mm.setString("Flowmess", "1");
//			mm.setString("Viewtype", "0");

		// 生产者发送消息
		producer.send(mm);
		session.commit();
		producer.close();
		session.close();
	}

	public MQPublish(MQMassageEntity entity, MQPublishMeaageInvoke invoke) {
		this.entity = entity;
		this.invoke = invoke;
	}
	
	public MQPublish() {
	}

        //外部程序异步调用接口,invoke是额外要做的工作
	    public void start() {
		final Thread t = new Thread(new Runnable() {
			public void run() {
				try {
					invoke.doSomeThing(entity);
					logger.info("开始发送消息....");
				} catch (Exception e) {
					e.printStackTrace();
					logger.error("发送消息失败.");
					invoke.onFailure(entity);
				}
				invoke.onSuccess(entity);
				logger.info("发送消息成功.");
			}
		});
		t.start();
	}
	
	public MQMassageEntity getEntity() {
		return entity;
	}

	public void setEntity(MQMassageEntity entity) {
		this.entity = entity;
	}
	
	public MQPublicMeaageInvoke getInvoke() {
		return invoke;
	}

        public void setInvoke(MQPublishMeaageInvoke invoke) {
		this.invoke = invoke;
	}
}

    3、服务器端接收消息(MQReceiver.java)

public class MQReceiver {  
    public static void main(String[] args) {  
        // 连接MQ服务器
        ConnectionFactory connectionFactory;  
        Connection connection = null;  
        Session session;   
        MessageConsumer consumer;  
        connectionFactory = new ActiveMQConnectionFactory("failover:(tcp://localhost:61616)");  
        try {  
            // 创建连接
            connection =connectionFactory.createConnection();  
            // 客户端id
            connection.setClientID("xxx-xx-64208-1385463895256-0:1");  
            connection.start();  
            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);  
            // 创建连接通道
            Topic topic = session.createTopic(MQStateAttribute.TOPIC_NAME);         
            consumer = session.createDurableSubscriber(topic, MQStateAttribute.TOPIC_NAME);  
            // 开始接收消息 
            while(true){  
              MapMessage message = (MapMessage) consumer.receive(100000);  
              if(null != message){  
					System.out.println("收到消息" + message.getString("Title"));
					System.out.println(message.getString("Sender"));
					System.out.println(message.getString("Sendertime"));
					System.out.println(message.getString("Flowtype"));
					System.out.println(message.getString("FlowID"));
					System.out.println(message.getString("Title"));
					System.out.println(message.getString("Nodename"));
					System.out.println(message.getString("Ptpurl"));
					System.out.println(message.getString("Userid"));
					System.out.println(message.getString("Creator"));
					System.out.println(message.getString("Createdate"));
					System.out.println(message.getString("Createtime"));
					System.out.println(message.getString("Operatedate"));
					System.out.println(message.getString("Operatetime"));
					System.out.println(message.getString("Flowmess"));
					System.out.println(message.getString("Viewtype"));
                 
                 
              }else break;  
            }  
        }catch(Exception e){  
        e.printStackTrace();  
        }finally {  
            try {  
                if (null != connection)  
                    connection.close();  
            } catch (Throwable ignore) {  
            }  
        }  
    }  
   
}
    4、发送消息需要额外做操作的接口(MQPublishMessageInvoke.java)


/**
 * 消息发送的执行类
 * <ol>
 * <li>dosomething要执行的动作</li>
 * <li>onsuccess执行成功后要执行的动作</li>
 * <li>onfailure执行失败后要执行的动作</li>
 * </ol>
 * @author zhaoxuewen
 *
 */
public abstract class MQPublishMeaageInvoke {
	protected void onSuccess(MQMassageEntity entity) {
		System.out.println("onSuccess");
	}

	protected void onFailure(MQMassageEntity entity) {
		try {
			Thread.sleep(10000);
			new MQPublish().sendMess(entity);
		} catch (InterruptedException ie) {
			ie.printStackTrace();
		}  catch (Exception e1) {
			e1.printStackTrace();
		}
	}

	protected void doSomeThing(MQMassageEntity entity) throws Exception{
		new MQPublish().sendMess(entity);
	}
}

    5、消息体实体类(MQMassageEntity.java)


/**
 * MQ消息体实体类
 *
 */
@Entity
@Table(name = "MSG_MESSAGESEND")
public class MQMassageEntity implements Serializable{

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(generator = "system-uuid")
	@GenericGenerator(strategy = "uuid", name = "system-uuid")
	@Column(name = "messagesendid")
	private String messagesendid;
	
	/**
	 * 业务系统发来的消息,固定为“XX业务系统”
	 */
	private String sender; // 消息发送者

	/**
	 * 指业务系统系统发出此消息的时间,当系统出问题时,用于定位和分析,保证系统可靠性。
	 */
	private Date sendertime; // 消息发送时间

	/**
	 * 可取以下值:
	 * <ol>
	 * <li>流程创建</li>
	 * <li>流程待办事宜到达:需要提醒相关人处理(放入到OA的相关人员待办事宜中)</li>
	 * <li>流程待办事宜已读:需要去掉new标志</li>
	 * <li>流程已办:需要把此项流程放到已办列表中</li>
	 * <li>流程已办结:表示流程已经流转完</li>
	 * </ol>
	 */
	private String flowmess; // 事件类型

	/**
	 * 用于指示流程的类别
	 */
	private String flowtype; // 流程分类
	/**
	 * 
	 * 表示流程在业务系统中的唯一ID
	 */
	private String flowid; // 流程ID

	/**
	 * 流程实例的标题,如:报销流程-关于xx项目的报销申请,在OA中显示相应流程时使用
	 */
	private String title;// 流程标题
	/**
	 * 如:业务系统的步骤名称,直接主管审批节点
	 */
	private String nodename;// 流程当前节点名称
	/**
	 * 业务系统生成的到业务系统相关流程的URL链接,通过此URL应该可以直接打开此流程处理界面,而不需要重新登录业务系统。如:http://
	 */
	private String ptpurl; // 到业务系统的URL
	/**
	 * 流程的创建人
	 */
	private String creator;// 创建人
	/**
	 * 流程的接收人
	 */
	private String userid; // 接收人
	/**
	 * 流程的创建日期
	 */
	private Date createdate;// 流程的创建日期时间
	/**
	 * 流程的更新日期
	 */
	private Date operatedate;// 流程的更新日期时间
	/**
	 * 查看的状态
	 */
	private String viewtype; 

	/**
	 * 标记 1发送,0未发送
	 */
	private String flage;
	
	private String mess;
	
	/**
	 * 发送次数
	 */
	private int resendnumber;
	
	private String notice;


}
    6、结束。经测试没有问题,可以正常发送接收消息。







你可能感兴趣的:(java,apache,activemq,消息)