本篇深入剖析質量報告系統的核心共享組件——Payload 包,包含 ClientReport 數據模型、CurrentReport 事務邊界管理器、Serializer 序列化與隊列傳輸引擎,揭示輕量級、容錯設計精髓。
public class ClientReport implements Serializable {
public Date clientStartDateTime; // 客戶端事務開始時間
public Date serverStartDateTime; // 服務端事務開始時間 (預留)
public long clientElapsedMS; // 核心指標:客戶端感知響應毫秒數
public String type; // 事務類型特征 (如 "1 submit,check,gets")
public String status; // 完成狀態 (success/failed)
public String transactionID; // 服務端返回的事務標識
public String clientID; // 客戶端唯一標識 (UID 生成)
// 默認構造器 (WSDL 要求)
public ClientReport() {}
// getter/setter 省略...
}
BeginTransaction() 到最後調用返回的牆鐘時間,反映用戶真實體驗UID,區分同一客戶端多事務;生產環境應升級為全局唯一標識 (GUID)public class CurrentReport {
public static UID ClientIdentifier = new UID(); // 客戶端標識
public static ClientReport Report; // 進行中事務報告
public static ClientReport LastReport; // 已完成事務報告 (待上傳)
public void BeginTransaction() {
Report = new ClientReport();
Report.setClientID(ClientIdentifier.toString());
Report.setClientStartDateTime(new Date());
}
public void CommitTransaction(String transactionID, String type, String status) {
Report.setTransactionID(transactionID);
Report.setStatus(status);
Report.setType(type);
long l1 = Report.getClientStartDateTime().getTime();
long l2 = new Date().getTime();
Report.setClientElapsedMS(l2 - l1); // 計算耗時
LastReport = Report; // 轉為待上傳狀態
Report = null; // 清空當前事務
}
public static ClientReport getReport() {
ClientReport last = LastReport;
LastReport = null; // 取走即清空,確保單次上傳
return last;
}
// setter 省略...
}
Report (構建中) ↔ LastReport (待上傳)getReport() 取走即清空,防止重複上傳System.currentTimeMillis() 差值,簡單高效private static String ClientReportXML(ClientReport r) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
XMLEncoder sstream = new XMLEncoder(baos);
sstream.writeObject(r);
sstream.flush(); sstream.close();
return baos.toString();
}
public static ClientReport ClientReportXML(String crXML) {
ByteArrayInputStream bais = new ByteArrayInputStream(crXML.getBytes());
XMLDecoder sstream = new XMLDecoder(bais);
return (ClientReport) sstream.readObject();
}
public static void attachPendingReportToMessage(SOAPMessageContext smc) {
try {
ClientReport cr = CurrentReport.getReport();
if (cr != null) {
SOAPMessage mc = smc.getMessage();
AttachmentPart ap = mc.createAttachmentPart(
Serializer.ClientReportXML(cr), "text/plain");
mc.addAttachmentPart(ap);
}
} catch (Exception e) {
// 靜默吞噬:確保業務處理不受監控邏輯影響
}
}
public static void queueFirstAttachmentText(SOAPMessageContext smc) {
try {
SOAPMessage mc = smc.getMessage();
Iterator attachments = mc.getAttachments();
if (attachments.hasNext()) {
AttachmentPart attachment = (AttachmentPart) attachments.next();
String sattachment = attachment.getContent().toString();
attachments.remove(); // 移除避免干擾業務解析
queueReportXML(sattachment);
}
} catch (SOAPException e) { /* 記錄日誌 */ }
}
// 靜態連接資源 (共享)
private static Context jndiContext = null;
private static QueueConnectionFactory queueConnectionFactory = null;
private static QueueConnection queueConnection = null;
private static QueueSession queueSession = null;
private static Queue queue = null;
private static QueueSender queueSender = null;
private static boolean connectionEstablished = false;
public static synchronized void queueReportXML(String clientReportXML) {
TextMessage message = null;
// 惰性初始化連接
if (!connectionEstablished) {
try {
jndiContext = new InitialContext();
queueConnectionFactory = (QueueConnectionFactory) jndiContext.lookup("jms/TestMDBFactory");
queue = (Queue) jndiContext.lookup("jms/TestMDBQueue");
queueConnection = queueConnectionFactory.createQueueConnection();
queueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queueSender = queueSession.createSender(queue);
connectionEstablished = true;
} catch (Exception e) { /* 記錄連接失敗 */ }
}
// 發送消息
try {
message = queueSession.createTextMessage();
message.setText(clientReportXML);
queueSender.send(message);
} catch (JMSException e) { /* 記錄發送失敗 */ }
catch (Exception e) { /* 兜底保護 */ }
}
try-catch 兜底,監控故障決不影響業務流程synchronized 保證單一連接多線程安全debug=true,調用 ((EDataGraph)dataGraph).getDataGraphResource().save(System.out, null) 輸出序列化 XMLVariables 面板:數據對象屬性、變更摘要內容Payload 包以極簡接口 (Begin/CommitTransaction、attach/queue) 實現全鏈路報告流轉:客戶端構建 → SOAP 附件攜帶 → 服務端剝離 → JMS 異步持久化。其零業務侵入、容錯優先、輕量級特性,使之成為服務質量監控的理想基礎設施。