如何在代码中获取QuickFIX/J的入站/出站/心跳消息?
获取QuickFIX/J 1.6.4中的入站、出站及心跳消息
当然可以!在QuickFIX/J中,你完全可以通过代码拦截并处理入站、出站消息,以及作为会话核心的心跳消息。核心思路是利用框架提供的Application接口,它定义了消息流转各阶段的回调方法,下面是具体实现方案:
1. 核心实现:自定义Application类
Application是QuickFIX/J的核心扩展点,其中的方法对应不同类型的消息处理场景:
fromApp():处理入站应用级业务消息(比如订单请求、成交回报等)toApp():拦截出站应用级业务消息(发送前可修改或阻止)fromAdmin():处理入站会话级消息(包含心跳、登录请求等)toAdmin():拦截出站会话级消息(包含心跳、登出请求等)
基础代码示例
import quickfix.Application; import quickfix.DoNotSend; import quickfix.FieldNotFound; import quickfix.Message; import quickfix.SessionID; import quickfix.field.MsgType; public class CustomFixHandler implements Application { @Override public void onCreate(SessionID sessionId) { // 会话创建时触发,可做初始化操作 } @Override public void onLogon(SessionID sessionId) { System.out.println("会话已登录: " + sessionId); } @Override public void onLogout(SessionID sessionId) { System.out.println("会话已登出: " + sessionId); } // 处理入站应用消息 @Override public void fromApp(Message message, SessionID sessionId) throws FieldNotFound { String msgType = message.getHeader().getString(MsgType.FIELD); System.out.println("[入站应用消息] 类型: " + msgType + " | 会话: " + sessionId); // 这里可根据消息类型做业务逻辑处理 } // 拦截出站应用消息 @Override public void toApp(Message message, SessionID sessionId) throws DoNotSend { String msgType = message.getHeader().getString(MsgType.FIELD); System.out.println("[出站应用消息] 类型: " + msgType + " | 会话: " + sessionId); // 若需阻止消息发送,抛出DoNotSend异常即可 } // 处理入站会话消息(含心跳) @Override public void fromAdmin(Message message, SessionID sessionId) throws FieldNotFound { String msgType = message.getHeader().getString(MsgType.FIELD); if (MsgType.HEARTBEAT.equals(msgType)) { System.out.println("[入站心跳] 会话: " + sessionId); } else { System.out.println("[入站会话消息] 类型: " + msgType + " | 会话: " + sessionId); } } // 拦截出站会话消息(含心跳) @Override public void toAdmin(Message message, SessionID sessionId) { String msgType = message.getHeader().getString(MsgType.FIELD); if (MsgType.HEARTBEAT.equals(msgType)) { System.out.println("[出站心跳] 会话: " + sessionId); } else { System.out.println("[出站会话消息] 类型: " + msgType + " | 会话: " + sessionId); } } }
2. 更优雅的消息拆分:使用MessageCracker
如果需要针对特定消息类型(比如心跳、测试请求、订单等)编写单独的处理逻辑,可以继承MessageCracker类,它会自动根据消息类型(MsgType)分发到对应的处理方法,避免大量的if-else判断:
import quickfix.Application; import quickfix.FieldNotFound; import quickfix.Message; import quickfix.SessionID; import quickfix.MessageCracker; import quickfix.fix42.Heartbeat; import quickfix.fix42.TestRequest; public class CrackingFixHandler extends MessageCracker implements Application { @Override public void onCreate(SessionID sessionId) {} @Override public void onLogon(SessionID sessionId) {} @Override public void onLogout(SessionID sessionId) {} @Override public void fromApp(Message message, SessionID sessionId) throws FieldNotFound { crack(message, sessionId); // 交给MessageCracker自动分发 } @Override public void toApp(Message message, SessionID sessionId) throws DoNotSend {} @Override public void fromAdmin(Message message, SessionID sessionId) throws FieldNotFound { crack(message, sessionId); // 会话消息也可通过Cracker处理 } @Override public void toAdmin(Message message, SessionID sessionId) {} // 专门处理心跳消息的方法 public void onMessage(Heartbeat heartbeat, SessionID sessionId) throws FieldNotFound { System.out.println("[心跳消息] 会话: " + sessionId); } // 可添加其他消息类型的处理方法 public void onMessage(TestRequest testRequest, SessionID sessionId) throws FieldNotFound { System.out.println("[测试请求] 会话: " + sessionId); } }
3. 关键注意事项
- 心跳属于会话级消息(Admin Message),所以要在
fromAdmin和toAdmin中处理,fromApp/toApp是用来处理业务级应用消息的。 - 如果需要修改出站消息(比如添加自定义字段),直接在
toApp或toAdmin中操作Message对象即可。 - 若要取消某条消息的发送,在
toApp方法中抛出DoNotSend异常即可。
内容的提问来源于stack exchange,提问作者Sakshi Singla
相关产品推荐
相关产品推荐

