Compare commits

...

5 Commits

17 changed files with 1242 additions and 79 deletions

View File

@ -108,6 +108,17 @@
<artifactId>dom4j</artifactId> <artifactId>dom4j</artifactId>
<version>1.6.1</version> <version>1.6.1</version>
</dependency> </dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -0,0 +1,420 @@
package com.qaup.adxp.adapter.dto;
public class AllXml {
// 将原始的 XML 字符串存储为常量
public static final String XML_ARR = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
"<Msg>\n" +
" <Head>\n" +
" <Svc_ServiceCode>ADXP_NAOMS_O_DYN_ARR</Svc_ServiceCode>\n" +
" <Svc_Version>1.0</Svc_Version>\n" +
" <Svc_Sender_Org>ADXP</Svc_Sender_Org>\n" +
" <Svc_Sender>NAOMS</Svc_Sender>\n" +
" <Svc_Receiver_Org></Svc_Receiver_Org>\n" +
" <Svc_Receiver></Svc_Receiver>\n" +
" <Svc_SerialNumber>be58e345-7bcf-4cbb-915f-28c16f0e09a4</Svc_SerialNumber>\n" +
" <Svc_SessionId>20171208140658867</Svc_SessionId>\n" +
" <Svc_SendTimeStamp>20171208140658867</Svc_SendTimeStamp>\n" +
" </Head>\n" +
" <Body>\n" +
" <DynFlight>\n" +
" <FlightId>4155920</FlightId>\n" +
" <BizKey>CZ3158-A-20170906230500</BizKey>\n" +
" <AirportIATA>TAO</AirportIATA>\n" +
" <FLIGHTSTATUS>ARR</FLIGHTSTATUS>\n" +
" <RealLanding>20170906230500</RealLanding>\n" +
" </DynFlight>\n" +
" </Body>\n" +
"</Msg>";
//
public static final String XML_CRAFTSEAT = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
"<Msg>\n" +
" <Head>\n" +
" <Svc_ServiceCode>ADXP_NAOMS_O_DYN_CRAFTSEAT</Svc_ServiceCode>\n" +
" <Svc_Version>1.0</Svc_Version>\n" +
" <Svc_Sender_Org>ADXP</Svc_Sender_Org>\n" +
" <Svc_Sender>NAOMS</Svc_Sender>\n" +
" <Svc_Receiver_Org></Svc_Receiver_Org>\n" +
" <Svc_Receiver></Svc_Receiver>\n" +
" <Svc_SerialNumber>9a6b67e0-f061-4d0d-9a6a-f31328283d54</Svc_SerialNumber>\n" +
" <Svc_SessionId>20171208140658867</Svc_SessionId>\n" +
" <Svc_SendTimeStamp>20171208140658867</Svc_SendTimeStamp>\n" +
" </Head>\n" +
" <Body>\n" +
" <DynFlight>\n" +
" <FlightId>4155920</FlightId>\n" +
" <BizKey>CZ3158-D-20170906230500</BizKey>\n" +
" <CraftseatList>\n" +
" <Craftseat>\n" +
" <Code>32</Code>\n" +
" <PlanStart>20170920173500</PlanStart>\n" +
" <PlanEnd>20170920171500</PlanEnd>\n" +
" <RealStart>20170920173500</RealStart>\n" +
" <RealEnd>20170920173500</RealEnd>\n" +
" </Craftseat>\n" +
" </CraftseatList>\n" +
" </DynFlight>\n" +
" </Body>\n" +
"</Msg>";
// 存储 XML 字符串作为常量
public static final String XML_DFIE = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
"<Msg>\n" +
" <Head>\n" +
" <Svc_ServiceCode>ADXP_NAOMS_O_DYN_DFIE</Svc_ServiceCode>\n" +
" <Svc_Version>1.0</Svc_Version>\n" +
" <Svc_Sender_Org>ADXP</Svc_Sender_Org>\n" +
" <Svc_Sender>NAOMS</Svc_Sender>\n" +
" <Svc_Receiver_Org></Svc_Receiver_Org>\n" +
" <Svc_Receiver></Svc_Receiver>\n" +
" <Svc_SerialNumber>97b79684-f755-41a1-82ab-f7e34352c6af</Svc_SerialNumber>\n" +
" <Svc_SessionId>20171208140658867</Svc_SessionId>\n" +
" <Svc_SendTimeStamp>20171208140658867</Svc_SendTimeStamp>\n" +
" </Head>\n" +
" <Body>\n" +
" <DynFlightList>\n" +
" <DynFlight>\n" +
" <FlightId>4155920</FlightId>\n" +
" <BizKey>CZ3158-A-20170906230500</BizKey>\n" +
" <ConnectId>4155935</ConnectId>\n" +
" <ConnectIdBizKey> CZ3158-D-20170906230500</ConnectIdBizKey>\n" +
" <PlanDate>20170906</PlanDate>\n" +
" <ExecDate>20170906</ExecDate>\n" +
" <PlanTime>20170906230500</PlanTime>\n" +
" <Airline>SC</Airline>\n" +
" <FlightNo>4753</FlightNo>\n" +
" <Region>D</Region>\n" +
" <InOut>A</InOut>\n" +
" <CraftModel>CRJ200</CraftModel>\n" +
" <CraftNo>B738L</CraftNo>\n" +
" <Task>W/Z</Task>\n" +
" <FlightProxy>1</FlightProxy>\n" +
" <Terminal>T1</Terminal>\n" +
" <RunwayNum>1</RunwayNum>\n" +
" <DispatchLevel>一级特勤保障</DispatchLevel>\n" +
" <Hasvip>1</Hasvip>\n" +
" <AirportList>\n" +
" <Airport>\n" +
" <AirportIATA>TAO</AirportIATA>\n" +
" <AirportStatus>ALT</AirportStatus>\n" +
" <PlanTakeoff>20170906232200</PlanTakeoff>\n" +
" <AlterTakeoff>20170906232500</AlterTakeoff>\n" +
" <RealTakeoff/>\n" +
" <PlanLanding/>\n" +
" <AlterLanding/>\n" +
" <RealLanding/>\n" +
" <RouteOrder>1</RouteOrder>\n" +
" </Airport>\n" +
" <Airport>\n" +
" <AirportIATA>HHA</AirportIATA>\n" +
" <AirportStatus/>\n" +
" <PlanTakeoff/>\n" +
" <AlterTakeoff/>\n" +
" <RealTakeoff/>\n" +
" <PlanLanding>20170906232200</PlanLanding>\n" +
" <AlterLanding/>\n" +
" <RealLanding/>\n" +
" <RouteOrder>1</RouteOrder>\n" +
" </Airport>\n" +
" </AirportList>\n" +
" <ShareFlightList>\n" +
" <ShareFlight>\n" +
" <Airline>SC</Airline>\n" +
" <FlightNo>1234</FlightNo>\n" +
" <AirFlightNo>SC1234</AirFlightNo>\n" +
" </ShareFlight>\n" +
" <ShareFlight>\n" +
" <Airline>MU</Airline>\n" +
" <FlightNo>2345</FlightNo>\n" +
" <AirFlightNo>MU2345</AirFlightNo>\n" +
" </ShareFlight>\n" +
" </ShareFlightList>\n" +
" <VirtualFlightList>\n" +
" <VirtualFlight>\n" +
" <Airline>SC</Airline>\n" +
" <FlightNO>1234</FlightNO>\n" +
" <AirFlightNo>SC1234</AirFlightNo>\n" +
" <Region>D</Region>\n" +
" <DeptAirport>TAO</DeptAirport>\n" +
" <ViaAirport>HGH</ViaAirport>\n" +
" <DestAirport>SZX</DestAirport>\n" +
" </VirtualFlight>\n" +
" </VirtualFlightList>\n" +
" </DynFlight>\n" +
" </DynFlightList>\n" +
" </Body>\n" +
"</Msg>";
public static final String XML_DFDL ="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<Msg>\n" +
"<Head>\n" +
" <Svc_ServiceCode>ADXP_NAOMS_O_DYN_DFDL</Svc_ServiceCode>\n" +
" <Svc_Version>1.0</Svc_Version>\n" +
" <Svc_Sender_Org>ADXP</Svc_Sender_Org>\n" +
" <Svc_Sender>NAOMS</Svc_Sender>\n" +
" <Svc_Receiver_Org>ADXP</Svc_Receiver_Org>\n" +
" <Svc_Receiver>FIDS</Svc_Receiver>\n" +
" <Svc_SerialNumber></Svc_SerialNumber>\n" +
" <Svc_SessionId>20171208140658867</Svc_SessionId>\n" +
" <Svc_SendTimeStamp>20171208140658867</Svc_SendTimeStamp>\n" +
"</Head>\n" +
"<Body>\n" +
"<SerialNum>5-3</SerialNum>\n" +
" <DynFlightList>\n" +
" <DynFlight>\n" +
" <FlightId>4155920</FlightId>\n" +
" <BizKey>CZ3158-A-20170906230500</BizKey>\n" +
" <ConnectId>4155935</ConnectId>\n" +
" <ConnectIdBizKey> CZ3158-D-20170906230500</ConnectIdBizKey>\n" +
" <PlanDate>20170906</PlanDate>\n" +
" <ExecDate>20170906</ExecDate>\n" +
" <PlanTime>20170906230500</PlanTime>\n" +
" <Airline>SC</Airline>\n" +
" <FlightNo>4753</FlightNo>\n" +
" <Region>D</Region>\n" +
" <InOut>A</InOut>\n" +
" <CraftModel>CRJ200</CraftModel>\n" +
" <CraftNo>B738L</CraftNo>\n" +
" <Task>W/Z</Task>\n" +
" <FlightProxy>1</FlightProxy>\n" +
" <Terminal>T1</Terminal>\n" +
" <RunwayNum>1</RunwayNum>\n" +
" <DispatchLevel>一级特勤保障</DispatchLevel>\n" +
" <Hasvip>1</Hasvip>\n" +
" <FlightStatus>BOR</FlightStatus>\n" +
" <InterFlightStatus>BOR</InterFlightStatus>\n" +
" <AirportList>\n" +
" <Airport>\n" +
" <AirportIATA>TAO</AirportIATA>\n" +
" <AirportStatus>ALT</AirportStatus>\n" +
" <PlanTakeoff>20170906232200</PlanTakeoff>\n" +
" <AlterTakeoff>20170906232500</AlterTakeoff>\n" +
" <RealTakeoff></RealTakeoff>\n" +
" <PlanLanding></PlanLanding>\n" +
" <AlterLanding></AlterLanding>\n" +
" <RealLanding></RealLanding>\n" +
" <RouteOrder>1</RouteOrder>\n" +
" </Airport>\n" +
" <Airport>\n" +
" <AirportIATA>HHA</AirportIATA>\n" +
" <AirportStatus></AirportStatus>\n" +
" <PlanTakeoff></PlanTakeoff>\n" +
" <AlterTakeoff></AlterTakeoff>\n" +
" <RealTakeoff></RealTakeoff>\n" +
" <PlanLanding>20170906232200</PlanLanding>\n" +
" <AlterLanding></AlterLanding>\n" +
" <RealLanding></RealLanding>\n" +
" <RouteOrder>1</RouteOrder>\n" +
" </Airport>\n" +
" </AirportList>\n" +
" <ShareFlightList>\n" +
" <ShareFlight>\n" +
" <Airline>SC</Airline>\n" +
" <FlightNo>1234</FlightNo>\n" +
" <AirFlightNo>SC1234</AirFlightNo>\n" +
" </ShareFlight>\n" +
" <ShareFlight>\n" +
" <Airline>MU</Airline>\n" +
" <FlightNo>2345</FlightNo>\n" +
" <AirFlightNo>MU2345</AirFlightNo>\n" +
" </ShareFlight>\n" +
" </ShareFlightList>\n" +
" <VirtualFlightList>\n" +
" <VirtualFlight>\n" +
" <Airline>SC</Airline>\n" +
" <FlightNO>1234</FlightNO>\n" +
" <AirFlightNo>SC1234</AirFlightNo>\n" +
" <Region>D</Region>\n" +
" <DeptAirport>TAO</DeptAirport>\n" +
" <ViaAirport>HGH</ViaAirport>\n" +
" <DestAirport>SZX</DestAirport>\n" +
" </VirtualFlight>\n" +
" </VirtualFlightList>\n" +
" <AbnStatusList>\n" +
" <AbnStatus>\n" +
" <AirportIATA>TAO</AirportIATA>\n" +
" <Region>D</Region>\n" +
" <AbnStatusCode>CAN</AbnStatusCode>\n" +
" <AbnStatusDesc>取消</AbnStatusDesc>\n" +
" <AbnReasonCode>1001</AbnReasonCode>\n" +
" <PublishTime>20170906234200</PublishTime>\n" +
" </AbnStatus>\n" +
" </AbnStatusList>\n" +
" <BorTimeList>\n" +
" <BorTime>\n" +
" <Region>D</Region>\n" +
" <OpenTime>20170920173100</OpenTime>\n" +
" <BeginTime>20170920173500</BeginTime>\n" +
" <TbrTime>20170920171500</TbrTime>\n" +
" <LbdTime>20170920173500</LbdTime>\n" +
" <BorEndTime>20170920175500</BorEndTime>\n" +
" <CloseTime>20170920175800</CloseTime>\n" +
" </BorTime>\n" +
" </BorTimeList>\n" +
" <CkicList>\n" +
" <Ckic>\n" +
" <Code>E35</Code>\n" +
" <Region>D</Region>\n" +
" <PlanStart>20170920173500</PlanStart>\n" +
" <PlanEnd>20170920171500</PlanEnd>\n" +
" <RealStart>20170920173500</RealStart>\n" +
" <RealEnd>20170920173500</RealEnd>\n" +
" <Airline>CZ</Airline>\n" +
" <Class>0701</Class>\n" +
" <OpenType>N</OpenType>\n" +
" </Ckic>\n" +
" </CkicList>\n" +
" <GateList>\n" +
" <Gate>\n" +
" <Code>32</Code>\n" +
" <Region>D</Region>\n" +
" <PlanStart>20170920173500</PlanStart>\n" +
" <PlanEnd>20170920171500</PlanEnd>\n" +
" <RealStart>20170920173500</RealStart>\n" +
" <RealEnd>20170920173500</RealEnd>\n" +
" </Gate>\n" +
" </GateList>\n" +
" <AcrslList>\n" +
" <Acrsl>\n" +
" <Code>32</Code>\n" +
" <Region>D</Region>\n" +
" <PlanStart>20170920173500</PlanStart>\n" +
" <PlanEnd>20170920171500</PlanEnd>\n" +
" <RealStart>20170920173500</RealStart>\n" +
" <RealEnd>20170920173500</RealEnd>\n" +
" </Acrsl>\n" +
" </AcrslList>\n" +
" <DcrslPosList>\n" +
" <DcrslPos>\n" +
" <Code>32</Code>\n" +
"<DcrslCode>12</DcrslCode>\n" +
" <Region>D</Region>\n" +
" <PlanStart>20170920173500</PlanStart>\n" +
" <PlanEnd>20170920171500</PlanEnd>\n" +
" <RealStart>20170920173500</RealStart>\n" +
" <RealEnd>20170920173500</RealEnd>\n" +
" </DcrslPos>\n" +
" </DcrslPosList>\n" +
" <CraftseatList>\n" +
" <Craftseat>\n" +
" <Code>32</Code>\n" +
" <PlanStart>20170920173500</PlanStart>\n" +
" <PlanEnd>20170920171500</PlanEnd>\n" +
" <RealStart>20170920173500</RealStart>\n" +
" <RealEnd>20170920173500</RealEnd>\n" +
" </Craftseat>\n" +
" </CraftseatList>\n" +
" </DynFlight>\n" +
" </DynFlightList> \n" +
"</Body>\n" +
"</Msg>";
public static final String XML_RUNWAY = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<Msg>\n" +
" <Head>\n" +
" <Svc_ServiceCode>" +
"</Svc_ServiceCode>\n" +
" <Svc_Version>1.0</Svc_Version>\n" +
" <Svc_Sender_Org>ADXP</Svc_Sender_Org>\n" +
" <Svc_Sender>NAOMS</Svc_Sender>\n" +
" <Svc_Receiver_Org></Svc_Receiver_Org>\n" +
" <Svc_Receiver></Svc_Receiver>\n" +
" <Svc_SerialNumber></Svc_SerialNumber>\n" +
" <Svc_SessionId> 20200331103923314</Svc_SessionId>\n" +
" <Svc_SendTimeStamp> 20200331103923314</Svc_SendTimeStamp>\n" +
" </Head>\n" +
" <Body>\n" +
" <Flight>\n" +
" <SourceKey>QDCDM</SourceKey>\n" +
" <BizKey> SC8775-D-20200331132500</BizKey>\n" +
" <RUNWAYDEP>35L</RUNWAYDEP>\n" +
" <RUNWAYARR></RUNWAYARR>\n" +
" </Flight>\n" +
" </Body>\n" +
"</Msg>";
public static final String XML_AXOT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<Msg>\n" +
" <Head>\n" +
" <Svc_ServiceCode>ADXP_NAOMS_O_CDM_AXOT</Svc_ServiceCode>\n" +
" <Svc_Version>1.0</Svc_Version>\n" +
" <Svc_Sender_Org>ADXP</Svc_Sender_Org>\n" +
" <Svc_Sender>NAOMS</Svc_Sender>\n" +
" <Svc_Receiver_Org></Svc_Receiver_Org>\n" +
" <Svc_Receiver></Svc_Receiver>\n" +
" <Svc_SerialNumber></Svc_SerialNumber>\n" +
" <Svc_SessionId> 20200331103923314</Svc_SessionId>\n" +
" <Svc_SendTimeStamp> 20200331103923314</Svc_SendTimeStamp>\n" +
" </Head>\n" +
" <Body>\n" +
" <Flight>\n" +
" <SourceKey>HCDM</SourceKey>\n" +
" <BizKey> SC8775-D-20200331132500</BizKey>\n" +
" <AXOT>202003311401</AXOT>\n" +
" </Flight>\n" +
" </Body>\n" +
"</Msg>";
public static final String XML_TISFLIGHT = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
"<Msg>\n" +
" <Head>\n" +
" <Svc_ServiceCode>ADXP_NAOMS_O_DYN_TISFLIGHT</Svc_ServiceCode>\n" +
" <Svc_Version>1.0</Svc_Version>\n" +
" <Svc_Sender_Org>ADXP</Svc_Sender_Org>\n" +
" <Svc_Sender>naomsdevc</Svc_Sender>\n" +
" <Svc_Receiver_Org></Svc_Receiver_Org>\n" +
" <Svc_Receiver></Svc_Receiver> <Svc_SerialNumber>5b2fc9a7-c40b-4d53-8267-9e9ff36cb7a8</Svc_SerialNumber>\n" +
" <Svc_SessionId>20251110133327781</Svc_SessionId>\n" +
" <Svc_SendTimeStamp>20251110133327781</Svc_SendTimeStamp>\n" +
" </Head>\n" +
" <Body>\n" +
" <TisFlight>\n" +
" <TisFlightIdentity>\n" +
" <FuId>41317B75FC8311BCE0633D411CAC4CEB</FuId>\n" +
" <FlNo>CDG4969</FlNo>\n" +
" <Carrier>CDG</Carrier>\n" +
" <Adep>ZSQD</Adep>\n" +
" <Ades>ZLXY</Ades>\n" +
" <Stod>20251104123500</Stod>\n" +
" <Stoa>20251104145000</Stoa>\n" +
" </TisFlightIdentity>\n" +
" <TisInfo>\n" +
" <DeIceState>132</DeIceState>\n" +
" <ContactCross>道口22</ContactCross>\n" +
" <CtotInfo>前3后3;</CtotInfo>\n" +
" <DepartureCorridor>WFG</DepartureCorridor>\n" +
" </TisInfo>\n" +
" <TisStateTime>\n" +
" <Type>DEP</Type>\n" +
" <Seat>APE</Seat>\n" +
" <State>TXI</State>\n" +
" <Time>20251104123623</Time>\n" +
" </TisStateTime>\n" +
" </TisFlight>\n" +
" </Body>\n" +
"</Msg>";
public static final String XML_DFDE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<Msg>\n" +
"<Head>\n" +
" <Svc_ServiceCode>ADXP_NAOMS_O_DYN_DFDE</Svc_ServiceCode>\n" +
" <Svc_Version>1.0</Svc_Version>\n" +
" <Svc_Sender_Org>ADXP</Svc_Sender_Org>\n" +
" <Svc_Sender>NAOMS</Svc_Sender>\n" +
" <Svc_Receiver_Org></Svc_Receiver_Org>\n" +
" <Svc_Receiver></Svc_Receiver>\n" +
" <Svc_SerialNumber></Svc_SerialNumber>\n" +
" <Svc_SessionId>20171208140658867</Svc_SessionId>\n" +
" <Svc_SendTimeStamp>20171208140658867</Svc_SendTimeStamp>\n" +
"</Head>\n" +
"<Body>\n" +
" <DynFlight>\n" +
" <FlightId>4155920</FlightId>\n" +
" <BizKey>CZ3158-A-20170906230500</BizKey>\n" +
" </DynFlight>\n" +
"</Body>\n" +
"</Msg>";
}

View File

@ -37,4 +37,13 @@ public class FlightMessage {
public void setContent(String content) { public void setContent(String content) {
this.content = content; this.content = content;
} }
@Override
public String toString() {
return "FlightMessage{" +
"serviceCode='" + serviceCode + '\'' +
", actionCode='" + actionCode + '\'' +
", content='" + content + '\'' +
'}';
}
} }

View File

@ -15,13 +15,32 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.*; import java.util.*;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
import javax.xml.parsers.*;
import java.io.*;
@Service @Service
public class AdxpSdkService { public class AdxpSdkService {
@ -186,6 +205,10 @@ public class AdxpSdkService {
List<FlightMessage> messages = receiveMessages(); List<FlightMessage> messages = receiveMessages();
if (!messages.isEmpty()) { if (!messages.isEmpty()) {
log.info("接收到 {} 条消息", messages.size()); log.info("接收到 {} 条消息", messages.size());
// 单独打印每条消息使日志更清晰
for (int i = 0; i < messages.size(); i++) {
log.info("消息 {}: {}", i + 1, messages.get(i));
}
// 处理接收到的消息 // 处理接收到的消息
processMessages(messages); processMessages(messages);
} }
@ -219,7 +242,6 @@ public class AdxpSdkService {
try { try {
MessageResult result = adxpClient.receiveMessage(); MessageResult result = adxpClient.receiveMessage();
// 使用统一的错误码处理方法 // 使用统一的错误码处理方法
if (handleMessageResultError(result)) { if (handleMessageResultError(result)) {
return Collections.emptyList(); return Collections.emptyList();
@ -231,17 +253,24 @@ public class AdxpSdkService {
List<FlightMessage> messages = new ArrayList<>(); List<FlightMessage> messages = new ArrayList<>();
MessageList messageList = result.getMessageList(); MessageList messageList = result.getMessageList();
// 处理XML字符串
List<String> messageStringList = result.getMessageStringList();
if (messageList != null && messageList.getMsg() != null) { if (messageList != null && messageList.getMsg() != null) {
for (MsgType msg : messageList.getMsg()) { for (int i = 0; i < messageList.getMsg().size(); i++) {
MsgType msg = messageList.getMsg().get(i); // 获取 MsgType
String messageString = messageStringList.get(i); // 获取对应的字符串
HeadType head = msg.getHead(); HeadType head = msg.getHead();
Object body = msg.getBody(); Object body = msg.getBody();
if (head != null && body != null) { if (head != null && body != null) {
//log.info("本条消息的接收到消息头{},消息体{}", head.getSvcServiceCode(), messageString);
FlightMessage flightMessage = new FlightMessage( FlightMessage flightMessage = new FlightMessage(
head.getSvcServiceCode(), head.getSvcServiceCode(),
null, // actionCode body null, // actionCode body
body.toString() messageString
); );
messages.add(flightMessage); messages.add(flightMessage);
} }
@ -266,8 +295,47 @@ public class AdxpSdkService {
/** /**
* 处理接收到的消息并广播到WebSocket客户端 * 处理接收到的消息并广播到WebSocket客户端
*/ */
private void processMessages(List<FlightMessage> messages) { private void processMessages(List<FlightMessage> messages) throws ParserConfigurationException, IOException, SAXException {
if (messages != null && !messages.isEmpty()) { if (messages != null && !messages.isEmpty()) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
for (FlightMessage message : messages){
String txt = message.getContent();
//log.info("接收到的XML字符串{}", txt);
// 解析 XML 字符串
DocumentBuilder builder = factory.newDocumentBuilder();
InputStream is = new ByteArrayInputStream(txt.getBytes("UTF-8"));
Document document = builder.parse(is);
log.info("事件的类型是{}",message.getServiceCode());
switch (message.getServiceCode()){
case "ADXP_NAOMS_O_DYN_DFDL":
handleDFDL(document);
break;
case "ADXP_NAOMS_O_DYN_CRAFTSEAT":
handleCRAFTSEAT(document);
break;
case "ADXP_NAOMS_O_DYN_ARR":
handleARR(document);
break;
case "ADXP_NAOMS_O_DYN_DFIE":
handleDFIE(document);
break;
case "ADXP_NAOMS_O_CDM_AXOT":
handleAXOT(document);
break;
case "ADXP_NAOMS_O_CDM_RUNWAY":
handleRUNWAY(document);
break;
case "ADXP_NAOMS_O_DYN_TISFLIGHT":
handleTISFLIGHT(document);
break;
default:
System.out.println("未定义的消息");
handleNEW(txt);
break;
}
}
try { try {
log.info("接收到 {} 条消息,准备广播", messages.size()); log.info("接收到 {} 条消息,准备广播", messages.size());
// 将消息广播到WebSocket客户端 // 将消息广播到WebSocket客户端
@ -367,4 +435,208 @@ public class AdxpSdkService {
return health; return health;
} }
/**
*向数据中台发送 动态航班请求事件RQDF
*/
public MessageResult sendMessage(List<String> message) {
if (!connected) {
log.error("ADXP数据中台未连接无法发送消息");
return null;
}
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<Msg>\n" +
"<Head>\n" +
" <Svc_ServiceCode>ADXP_NAOMS_O_DYN_RQDF</Svc_ServiceCode>\n" +
" <Svc_Version>1.0</Svc_Version>\n" +
" <Svc_Sender_Org>ADXP</Svc_Sender_Org>\n" +
" <Svc_Sender>FIDS</Svc_Sender>\n" +
" <Svc_Receiver_Org>ADXP</Svc_Receiver_Org>\n" +
" <Svc_Receiver>NAOMS</Svc_Receiver>\n" +
" <Svc_SerialNumber></Svc_SerialNumber>\n" +
" <Svc_SessionId>2017120814065886</Svc_SessionId>\n" +
" <Svc_SendTimeStamp>20171208140658867</Svc_SendTimeStamp>\n" +
"</Head>\n" +
"<Body>\n" +
" <Request>\n" +
" <PlanDate>20171209</PlanDate>\n" +
" </Request> \n" +
"</Body>\n" +
"</Msg>";
List<String> xmls = new ArrayList<>();
xmls.add( xml);
adxpClient.sendMessage(xmls);
return null;
}
/**
* 处理 动态航班响应事件DFDL 消息
* @param document
*/
private static void handleDFDL(Document document) {
// 获取 <Body> 元素下的 <DynFlightList>
NodeList dynFlightNodes = document.getElementsByTagName("DynFlight");
if (dynFlightNodes.getLength() > 0) {
Element dynFlight = (Element) dynFlightNodes.item(0);
// 提取所需的值
String flightId = getElementValue(dynFlight, "FlightId");
String inOut = getElementValue(dynFlight, "InOut");
String runwayNum = getElementValue(dynFlight, "RunwayNum");
// 输出提取的值
log.info("动态航班信息: {}", flightId);
log.info("动态航班信息: {}", inOut);
log.info("动态航班信息: {}", runwayNum);
log.info("RunwayNum: " + runwayNum);
// 获取 CraftseatList 并提取 Code
NodeList craftseatListNodes = dynFlight.getElementsByTagName("CraftseatList");
if (craftseatListNodes.getLength() > 0) {
Element craftseatList = (Element) craftseatListNodes.item(0);
NodeList craftseatNodes = craftseatList.getElementsByTagName("Craftseat");
for (int i = 0; i < craftseatNodes.getLength(); i++) {
Element craftseat = (Element) craftseatNodes.item(i);
// 提取 Code
String code = getElementValue(craftseat, "Code");
// 输出提取的值
log.info("Craftseat Code: " + code);
}
}
}
}
/**
* 处理 运行跑道响应事件RUNWAY 消息
* @param document
*/
private static void handleRUNWAY(Document document) {
// 获取 <Flight> 元素
NodeList flightList = document.getElementsByTagName("Flight");
if (flightList.getLength() > 0) {
Element flightElement = (Element) flightList.item(0);
// 提取 BizKey
String bizKey = getElementValue(flightElement, "BizKey");
log.info("BizKey: " + bizKey);
// 提取 RUNWAYDEP
String runwayDep = getElementValue(flightElement, "RUNWAYDEP");
log.info("RUNWAYDEP: " + runwayDep);
// 提取 RUNWAYARR
String runwayArr = getElementValue(flightElement, "RUNWAYARR");
log.info("RunwayArr: " + runwayArr);
}
}
private static void handleCRAFTSEAT(Document document) {
// 获取 <DynFlight> 元素
NodeList dynFlightList = document.getElementsByTagName("DynFlight");
if (dynFlightList.getLength() > 0) {
Element dynFlightElement = (Element) dynFlightList.item(0);
// 提取 FlightId
String flightId = getElementValue(dynFlightElement, "FlightId");
log.info("FlightId: " + flightId);
// 获取 CraftseatList 元素
NodeList craftseatList = dynFlightElement.getElementsByTagName("Craftseat");
if (craftseatList.getLength() > 0) {
Element craftseatElement = (Element) craftseatList.item(0);
// 提取 Code
String code = getElementValue(craftseatElement, "Code");
log.info("Code: " + code);
}
}
}
private static void handleARR(Document document) {
// 获取 <Body> 元素
NodeList dynFlightNodes = document.getElementsByTagName("DynFlight");
if (dynFlightNodes.getLength() > 0) {
Element dynFlight = (Element) dynFlightNodes.item(0);
// 提取所需的值
String flightId = getElementValue(dynFlight, "FlightId");
String bizKey = getElementValue(dynFlight, "BizKey");
log.info("FlightId: " + flightId);
log.info("BizKey: " + bizKey);
}
}
private static void handleAXOT(Document document) {
// 获取 <Body> 元素
NodeList bodyNodes = document.getElementsByTagName("Body");
if (bodyNodes.getLength() > 0) {
Element body = (Element) bodyNodes.item(0);
// 获取 <Flight> 元素
NodeList flightNodes = body.getElementsByTagName("Flight");
if (flightNodes.getLength() > 0) {
Element flight = (Element) flightNodes.item(0);
// 提取 BizKey 元素的值
String bizKey = getElementValue(flight, "BizKey");
log.info("BizKey: " + bizKey);
}
}
}
private static void handleDFIE(Document document) {
// 获取 <DynFlight> 元素
NodeList dynFlightNodes = document.getElementsByTagName("DynFlight");
if (dynFlightNodes.getLength() > 0) {
Element dynFlight = (Element) dynFlightNodes.item(0);
// 提取所需的值
String flightId = getElementValue(dynFlight, "FlightId");
String inOut = getElementValue(dynFlight, "InOut");
String runwayNum = getElementValue(dynFlight, "RunwayNum");
String bizKey = getElementValue(dynFlight, "BizKey");
log.info("FlightId: " + flightId);
log.info("InOut: " + inOut);
log.info("RunwayNum: " + runwayNum);
log.info("BizKey: " + bizKey);
}
}
private static void handleTISFLIGHT(Document document) {
// 获取 <TisFlight> 元素
NodeList tisFlightNodes = document.getElementsByTagName("TisFlight");
if (tisFlightNodes.getLength() > 0) {
Element tisFlight = (Element) tisFlightNodes.item(0);
// 提取所需的值
String fuId = getElementValue(tisFlight, "FuId");
String state = getElementValue(tisFlight, "State");
String contactCross = getElementValue(tisFlight, "ContactCross");
// 打印提取的内容
log.info("FuId: " + fuId);
log.info("State: " + state);
log.info("ContactCross: " + contactCross);
}
}
/**
* 处理 未定义的消息
* @param message
*/
private static void handleNEW(String message) {
System.out.println("新的报文是: " + message);
}
// 获取元素的值
private static String getElementValue(Element parentElement, String tagName) {
NodeList nodeList = parentElement.getElementsByTagName(tagName);
if (nodeList.getLength() > 0) {
return nodeList.item(0).getTextContent();
}
return null;
}
} }

View File

@ -2,6 +2,7 @@ package com.qaup.adxp.adapter.websocket;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.databind.SerializationFeature;
import com.qaup.adxp.adapter.dto.AllXml;
import com.qaup.adxp.adapter.dto.FlightMessage; import com.qaup.adxp.adapter.dto.FlightMessage;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -41,7 +42,27 @@ public class AdxpWebSocketHandler extends TextWebSocketHandler {
// 可以处理一些控制命令比如心跳 // 可以处理一些控制命令比如心跳
if ("ping".equals(message.getPayload())) { if ("ping".equals(message.getPayload())) {
session.sendMessage(new TextMessage("pong")); session.sendMessage(new TextMessage("pong"));
List<FlightMessage> messages = new CopyOnWriteArrayList<>();
FlightMessage mgDFIE = new FlightMessage("ADXP_NAOMS_O_DYN_DFIE", "pong", AllXml.XML_DFIE);
messages.add(mgDFIE);
FlightMessage mgRUNWAY = new FlightMessage("ADXP_NAOMS_O_CDM_RUNWAY", "pong", AllXml.XML_RUNWAY);
messages.add(mgRUNWAY);
FlightMessage mgCRAFTSEAT = new FlightMessage("ADXP_NAOMS_O_DYN_CRAFTSEAT", "pong", AllXml.XML_CRAFTSEAT);
messages.add(mgCRAFTSEAT);
FlightMessage mgTISFLIGHT = new FlightMessage("ADXP_NAOMS_O_DYN_TISFLIGHT", "pong", AllXml.XML_TISFLIGHT);
messages.add(mgTISFLIGHT);
FlightMessage mgAXOT = new FlightMessage("ADXP_NAOMS_O_CDM_AXOT", "pong", AllXml.XML_AXOT);
messages.add(mgAXOT);
FlightMessage mgARR = new FlightMessage("ADXP_NAOMS_O_DYN_ARR", "pong", AllXml.XML_ARR);
messages.add(mgARR);
broadcastMessages(messages);
log.debug("发送心跳响应到客户端: sessionId={}", session.getId()); log.debug("发送心跳响应到客户端: sessionId={}", session.getId());
}else if ("delete".equals(message.getPayload())) {
List<FlightMessage> messages = new CopyOnWriteArrayList<>();
FlightMessage mgDFIE = new FlightMessage("ADXP_NAOMS_O_DYN_DFDE", "pong", AllXml.XML_DFIE);
messages.add(mgDFIE);
broadcastMessages(messages);
log.debug("收到客户端心跳响应: sessionId={}", session.getId());
} }
} }

View File

@ -19,7 +19,8 @@
数据来源:接入并转发从空管接收到的融合数据 数据来源:接入并转发从空管接收到的融合数据
1. 接口地址:<http://IP:端口/openApi/getCurrentFlightPositions> 1. 接口地址:<http://IP:端口/openApi/getCurrentFlightPositionsPro>
弃用接口地址:<http://IP:端口/openApi/getCurrentFlightPositions>
2. 请求方式get需要在 Header 中携带认证信息,字段名为 Authorization值为认证接口返回的token 2. 请求方式get需要在 Header 中携带认证信息,字段名为 Authorization值为认证接口返回的token

View File

@ -134,8 +134,10 @@ public class FlightNotification {
* 检查通知是否有效 * 检查通知是否有效
*/ */
public boolean isValid() { public boolean isValid() {
// return flightNo != null && !flightNo.trim().isEmpty()
// && type != null
// && eventTime != null;
return flightNo != null && !flightNo.trim().isEmpty() return flightNo != null && !flightNo.trim().isEmpty()
&& type != null && type != null;
&& eventTime != null;
} }
} }

View File

@ -6,12 +6,31 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.client.WebSocketClient; import org.springframework.web.socket.client.WebSocketClient;
import org.springframework.web.socket.client.standard.StandardWebSocketClient; import org.springframework.web.socket.client.standard.StandardWebSocketClient;
import java.util.HashMap;
import java.util.Map;
@Configuration @Configuration
public class ADXPWebSocketConfig { public class ADXPWebSocketConfig {
@Bean @Bean
public WebSocketClient webSocketClient() { public WebSocketClient webSocketClient() {
return new StandardWebSocketClient(); StandardWebSocketClient client = new StandardWebSocketClient();
Map<String, Object> props = new HashMap<>();
// ====== JSR-356 标准配置一定生效======
props.put("javax.websocket.maxTextMessageBufferSize", 10 * 1024 * 1024); // 10MB
props.put("javax.websocket.maxBinaryMessageBufferSize", 10 * 1024 * 1024);
// ====== Tomcat 实现专用有则更稳======
props.put("org.apache.tomcat.websocket.textBufferSize", 10 * 1024 * 1024);
props.put("org.apache.tomcat.websocket.binaryBufferSize", 10 * 1024 * 1024);
client.setUserProperties(props);
client.setUserProperties(props);
return client;
//return new StandardWebSocketClient();
} }
@Bean @Bean

View File

@ -354,44 +354,43 @@ public class DataCollectorDao {
* @return 航班路由参数数据 * @return 航班路由参数数据
*/ */
public AircraftRouteParamsDTO getAircraftRouteParams(String flightNo, String routeType) { public AircraftRouteParamsDTO getAircraftRouteParams(String flightNo, String routeType) {
try { // try {
String token = authService.getToken(airportBaseUrl); // String token = authService.getToken(airportBaseUrl);
if (token == null) { // if (token == null) {
log.error("无法获取有效的认证token"); // log.error("无法获取有效的认证token");
return null; // return null;
} // }
//
String url = UriComponentsBuilder.fromUriString(airportBaseUrl) // String url = UriComponentsBuilder.fromUriString(airportBaseUrl)
.path("/aircraftRouteParamsController/getRouteParams") // .path("/aircraftRouteParamsController/getRouteParams")
.queryParam("flightNo", flightNo) // .queryParam("flightNo", flightNo)
.queryParam("routeType", routeType) // .queryParam("routeType", routeType)
.toUriString(); // .toUriString();
//
HttpHeaders headers = new HttpHeaders(); // HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", token); // headers.set("Authorization", token);
headers.set("Content-Type", "application/json"); // headers.set("Content-Type", "application/json");
//
HttpEntity<String> requestEntity = new HttpEntity<>(headers); // HttpEntity<String> requestEntity = new HttpEntity<>(headers);
// ResponseEntity<Response<AircraftRouteParamsDTO>> response = restTemplate.exchange(
ResponseEntity<Response<AircraftRouteParamsDTO>> response = restTemplate.exchange( // url,
url, // HttpMethod.GET,
HttpMethod.GET, // requestEntity,
requestEntity, // new ParameterizedTypeReference<Response<AircraftRouteParamsDTO>>() {}
new ParameterizedTypeReference<Response<AircraftRouteParamsDTO>>() {} // );
); // Response<AircraftRouteParamsDTO> responseBody = response.getBody();
// if (responseBody != null && responseBody.getStatus() == 200) {
Response<AircraftRouteParamsDTO> responseBody = response.getBody(); // log.info("成功获取航班路由参数: flightNo={}, routeType={}", flightNo, routeType);
if (responseBody != null && responseBody.getStatus() == 200) { // return responseBody.getData();
log.info("成功获取航班路由参数: flightNo={}, routeType={}", flightNo, routeType); // } else {
return responseBody.getData(); // log.warn("获取航班路由参数失败: {}", responseBody != null ? responseBody.getMsg() : "未知错误");
} else { // return null;
log.warn("获取航班路由参数失败: {}", responseBody != null ? responseBody.getMsg() : "未知错误"); // }
return null; // } catch (Exception e) {
} // log.error("获取航班路由参数时发生异常: flightNo={}, routeType={}", flightNo, routeType, e);
} catch (Exception e) { // return null;
log.error("获取航班路由参数时发生异常: flightNo={}, routeType={}", flightNo, routeType, e); // }
return null; return null;
}
} }
/** /**

View File

@ -137,7 +137,9 @@ public class DataCollectorService {
return; return;
} }
log.info("通过WebSocket接收到 {} 条航班进出港通知", notifications.size()); //log.info("通过WebSocket接收到 {} 条航班进出港通知", notifications.size());
log.error("通过WebSocket接收到 {} 条航班进出港通知hhhhhhhhhhhhhhh", notifications.size());
log.error("通过WebSocket接收到 {} 条航班进出港通知hhhhhhhhhhhhhhh", notifications);
// 将DTO转换为业务对象并处理 // 将DTO转换为业务对象并处理
for (FlightNotificationDTO dto : notifications) { for (FlightNotificationDTO dto : notifications) {
@ -681,6 +683,7 @@ public class DataCollectorService {
if (adxpFlightServiceWebSocketClient != null && adxpFlightServiceWebSocketClient.isConnected()) { if (adxpFlightServiceWebSocketClient != null && adxpFlightServiceWebSocketClient.isConnected()) {
// WebSocket客户端已连接消息通过WebSocket实时接收 // WebSocket客户端已连接消息通过WebSocket实时接收
log.debug("使用WebSocket客户端接收航班通知"); log.debug("使用WebSocket客户端接收航班通知");
return; return;
} }
@ -778,9 +781,32 @@ public class DataCollectorService {
*/ */
private void cacheFlightNotification(FlightNotification notification) { private void cacheFlightNotification(FlightNotification notification) {
String cacheKey = notification.getFlightNo() + ":" + notification.getType().name(); String cacheKey = notification.getFlightNo() + ":" + notification.getType().name();
flightNotificationCache.put(cacheKey, notification);
log.debug("缓存航班通知: flightNo={}, type={}, 缓存数量={}", // 检查缓存中是否已有该键值
notification.getFlightNo(), notification.getType(), flightNotificationCache.size()); FlightNotification existingNotification = flightNotificationCache.get(cacheKey);
if (existingNotification != null) {
// 合并通知新的有值的字段覆盖旧的没有值的字段延用旧的
FlightNotification mergedNotification = FlightNotification.builder()
.flightNo(notification.getFlightNo())
.type(notification.getType())
.runway(notification.getRunway() != null ? notification.getRunway() : existingNotification.getRunway())
.contactCross(notification.getContactCross() != null ? notification.getContactCross() : existingNotification.getContactCross())
.seat(notification.getSeat() != null ? notification.getSeat() : existingNotification.getSeat())
.eventTime(notification.getEventTime() != null ? notification.getEventTime() : existingNotification.getEventTime())
.eventDateTime(notification.getEventDateTime() != null ? notification.getEventDateTime() : existingNotification.getEventDateTime())
.receivedTime(existingNotification.getReceivedTime()) // 保持接收时间不变
.active(notification.getActive() != null ? notification.getActive() : existingNotification.getActive())
.build();
flightNotificationCache.put(cacheKey, mergedNotification);
log.info("合并航班通知缓存: flightNo={}, type={}, 缓存数量={}",
notification.getFlightNo(), notification.getType(), flightNotificationCache.size());
} else {
// 缓存中没有该键值直接放入
flightNotificationCache.put(cacheKey, notification);
log.info("新增航班通知缓存: flightNo={}, type={}, 缓存数量={}",
notification.getFlightNo(), notification.getType(), flightNotificationCache.size());
}
} }
/** /**
@ -813,13 +839,13 @@ public class DataCollectorService {
} }
// 清理 flightNotificationCache - 使用 eventTime 字段判断 // 清理 flightNotificationCache - 使用 eventTime 字段判断
int sizeBefore = flightNotificationCache.size(); // int sizeBefore = flightNotificationCache.size();
flightNotificationCache.entrySet().removeIf(entry -> { // flightNotificationCache.entrySet().removeIf(entry -> {
FlightNotification notification = entry.getValue(); // FlightNotification notification = entry.getValue();
long eventTime = (notification.getEventTime() != null) ? notification.getEventTime() : 0; // long eventTime = (notification.getEventTime() != null) ? notification.getEventTime() : 0;
return (now - eventTime) > inactiveThreshold; // return (now - eventTime) > inactiveThreshold;
}); // });
removedFlightNotifications = sizeBefore - flightNotificationCache.size(); // removedFlightNotifications = sizeBefore - flightNotificationCache.size();
if (removedMovingObjects > 0 || removedFlightNotifications > 0) { if (removedMovingObjects > 0 || removedFlightNotifications > 0) {
log.info("清理不活跃缓存对象: {} 个移动对象, {} 个航班通知; 剩余: {} 个移动对象, {} 个航班通知", log.info("清理不活跃缓存对象: {} 个移动对象, {} 个航班通知; 剩余: {} 个移动对象, {} 个航班通知",
@ -842,3 +868,4 @@ public class DataCollectorService {
log.info("缓存已清理"); log.info("缓存已清理");
} }
} }

View File

@ -177,7 +177,7 @@ public class RoutePersistenceService {
* @param routeType 路由类型IN/OUT * @param routeType 路由类型IN/OUT
*/ */
@Transactional @Transactional
private void saveRouteAssignment(String objectName, Long routeId, String routeType) { public void saveRouteAssignment(String objectName, Long routeId, String routeType) {
try { try {
// 查找当前路由信息 // 查找当前路由信息
Optional<TransportRoute> currentRoute = transportRouteRepository.findById(routeId); Optional<TransportRoute> currentRoute = transportRouteRepository.findById(routeId);

View File

@ -4,9 +4,12 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.qaup.collision.datacollector.config.FlightSdkProperties; import com.qaup.collision.datacollector.config.FlightSdkProperties;
import com.qaup.collision.datacollector.dto.FlightNotificationDTO; import com.qaup.collision.datacollector.dto.FlightNotificationDTO;
import com.qaup.collision.dataprocessing.service.DataProcessingService;
import com.qaup.common.core.redis.RedisCache;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy; import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage; import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler; import org.springframework.web.socket.WebSocketHandler;
@ -38,6 +41,12 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler {
private Thread reconnectThread; private Thread reconnectThread;
@Autowired
private RedisCache redisCache;
@Autowired
private DataProcessingService dataProcessingService;
public AdxpFlightServiceWebSocketClient(WebSocketClient webSocketClient, public AdxpFlightServiceWebSocketClient(WebSocketClient webSocketClient,
FlightSdkProperties properties) { FlightSdkProperties properties) {
this.webSocketClient = webSocketClient; this.webSocketClient = webSocketClient;
@ -49,7 +58,7 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler {
/** /**
* 启动WebSocket客户端 * 启动WebSocket客户端
*/ */
@PostConstruct //@PostConstruct
public void start() { public void start() {
if (isRunning.compareAndSet(false, true)) { if (isRunning.compareAndSet(false, true)) {
log.info("启动ADXP航班通知WebSocket客户端"); log.info("启动ADXP航班通知WebSocket客户端");
@ -75,6 +84,7 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler {
public void connect() { public void connect() {
if (!properties.isConfigurationReady()) { if (!properties.isConfigurationReady()) {
log.warn("数据中台航班 SDK 配置不完整WebSocket客户端将无法正常工作"); log.warn("数据中台航班 SDK 配置不完整WebSocket客户端将无法正常工作");
scheduleReconnect();
return; return;
} }
@ -159,20 +169,48 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler {
isConnected.set(true); isConnected.set(true);
messageCount.set(0); // 重置消息计数 messageCount.set(0); // 重置消息计数
} }
// 新增用于拼接 WebSocket 分片消息
private final StringBuilder partialMessageBuffer = new StringBuilder(1024 * 1024);
@Override @Override
public void handleMessage(@NonNull WebSocketSession session, @NonNull WebSocketMessage<?> message) throws Exception { public void handleMessage(@NonNull WebSocketSession session, @NonNull WebSocketMessage<?> message) throws Exception {
if (message instanceof TextMessage) {
handleTextMessage(session, (TextMessage) message); if (!(message instanceof TextMessage textMessage)) {
return;
} }
//每来一片就拼
partialMessageBuffer.append(textMessage.getPayload());
//不是最后一片直接等
if (!textMessage.isLast()) {
return;
}
//最后一片才算一条完整消息
String fullPayload = partialMessageBuffer.toString();
partialMessageBuffer.setLength(0);
try {
// 👇 用你原来的逻辑处理
handleTextMessage(session, fullPayload);
} catch (Exception e) {
log.error("处理完整 WebSocket 消息失败", e);
}
// if (message instanceof TextMessage) {
// handleTextMessage(session, (TextMessage) message);
// }
} }
public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception { public void handleTextMessage(WebSocketSession session, String payload) throws Exception {
try { try {
// 解析接收到的消息 // // 解析接收到的消息
String payload = message.getPayload(); // String payload = message.getPayload();
log.debug("📥 收到WebSocket消息 ({} bytes)", payload.length());
//log.debug("📥 收到WebSocket消息 ({} bytes)", payload.length());
// 增加消息计数 // 增加消息计数
messageCount.incrementAndGet(); messageCount.incrementAndGet();
@ -181,7 +219,8 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler {
if (!notifications.isEmpty()) { if (!notifications.isEmpty()) {
log.info("🛬 接收到 {} 条航班通知", notifications.size()); log.info("🛬 接收到 {} 条航班通知", notifications.size());
log.error("🛬 接收到 {} 条航班通知", notifications.size());
// 通知所有监听器 // 通知所有监听器
for (Consumer<List<FlightNotificationDTO>> listener : messageListeners) { for (Consumer<List<FlightNotificationDTO>> listener : messageListeners) {
try { try {
@ -227,7 +266,7 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler {
@Override @Override
public boolean supportsPartialMessages() { public boolean supportsPartialMessages() {
return false; return true;
} }
/** /**
@ -238,11 +277,15 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler {
// 解析FlightMessage列表 // 解析FlightMessage列表
List<FlightMessage> flightMessages = List<FlightMessage> flightMessages =
objectMapper.readValue(jsonContent, new TypeReference<List<FlightMessage>>() {}); objectMapper.readValue(jsonContent, new TypeReference<List<FlightMessage>>() {});
//log.error("📥 收到WebSocket消息 ({})", flightMessages);
List<FlightNotificationDTO> notifications = new java.util.ArrayList<>(); List<FlightNotificationDTO> notifications = new java.util.ArrayList<>();
for (FlightMessage message : flightMessages) { for (FlightMessage message : flightMessages) {
try { try {
log.error("获取消息类型: serviceCode={}", message.getServiceCode());
//log.error("获取消息内容: content={}", message.getContent());
FlightNotificationDTO dto = parseXmlMessage(message.getServiceCode(), message.getContent()); FlightNotificationDTO dto = parseXmlMessage(message.getServiceCode(), message.getContent());
if (dto != null) { if (dto != null) {
notifications.add(dto); notifications.add(dto);
@ -252,7 +295,7 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler {
errorCount.incrementAndGet(); errorCount.incrementAndGet();
} }
} }
log.error("notifications={}", notifications);
return notifications; return notifications;
} catch (Exception e) { } catch (Exception e) {
log.error("解析消息失败", e); log.error("解析消息失败", e);
@ -272,13 +315,23 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler {
switch (serviceCode) { switch (serviceCode) {
case "ADXP_NAOMS_O_DYN_ARR": case "ADXP_NAOMS_O_DYN_ARR":
return parseArrival(root); //return parseArrival(root);
return handleARR(root);
case "ADXP_NAOMS_O_CDM_AXOT": case "ADXP_NAOMS_O_CDM_AXOT":
return parsePushback(root); //return parsePushback(root);
return handleAXOT(root);
case "ADXP_NAOMS_O_CDM_RUNWAY": case "ADXP_NAOMS_O_CDM_RUNWAY":
return parseRunway(root); //return parseRunway(root);
return handleRUNWAY(root);
case "ADXP_NAOMS_O_DYN_CRAFTSEAT": case "ADXP_NAOMS_O_DYN_CRAFTSEAT":
return parseGate(root); //return parseGate(root);
return handleCRAFTSEAT(root);
case "ADXP_NAOMS_O_DYN_DFIE":
return handleDFIE(root);
case "ADXP_NAOMS_O_DYN_TISFLIGHT":
return handleTISFLIGHT(root);
case "ADXP_NAOMS_O_DYN_DFDE":
return handleDFDE(root);
default: default:
log.debug("未知的服务代码: {}", serviceCode); log.debug("未知的服务代码: {}", serviceCode);
return null; return null;
@ -312,7 +365,7 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler {
return dto; return dto;
} }
private FlightNotificationDTO parsePushback(org.w3c.dom.Element root) { private FlightNotificationDTO parsePushback(org.w3c.dom.Element root) {
String flightNo = getTextContent(root, "FlightNumber"); String flightNo = getTextContent(root, "FlightNumber");
String actualPushback = getTextContent(root, "ActualPushback"); String actualPushback = getTextContent(root, "ActualPushback");
@ -439,4 +492,191 @@ public class AdxpFlightServiceWebSocketClient implements WebSocketHandler {
errorCount.get(), errorCount.get(),
isRunning.get()); isRunning.get());
} }
//处理ARR事件
private FlightNotificationDTO handleARR(org.w3c.dom.Element root) {
String flightNo = getTextContent(root, "BizKey");
//分解BizKey
String[] arr = flightNo.split("-", 3); // 最多切 3
FlightNotificationDTO dto = new FlightNotificationDTO();
dto.setFlightNo(flightNo);
dto.setType("IN");
// 存储到Redis
if (arr.length >= 3) {
try {
String key = "flight:" + arr[0]; // 使用航班号作为键
redisCache.setCacheMapValue(key, "flightNumber", arr[0]);
redisCache.setCacheMapValue(key, "type", arr[1]);
redisCache.setCacheMapValue(key, "time", arr[2]);
log.info("成功将航班数据存储到Redis: flightNumber={}, type={}, time={}", arr[0], arr[1], arr[2]);
} catch (Exception e) {
log.error("存储航班数据到Redis失败: {}", e.getMessage());
}
}
//假装模拟请求接口
dataProcessingService.ARR(arr[0]);
return dto;
}
private FlightNotificationDTO handleDFIE(org.w3c.dom.Element root) {
String flightNo = getTextContent(root, "BizKey");
String RunwayNum = getTextContent(root, "RunwayNum");
String InOut = getTextContent(root, "InOut");
//分解BizKey
String[] arr = flightNo.split("-", 3); // 最多切 3
FlightNotificationDTO dto = new FlightNotificationDTO();
dto.setFlightNo(flightNo);
if (InOut.equals("A")){
dto.setType("IN");
}else {
dto.setType("OUT");
}
dto.setRunway(RunwayNum);
// 存储到Redis
if (arr.length >= 3) {
try {
String key = "flight:" + arr[0]; // 使用航班号作为键
redisCache.setCacheMapValue(key, "flightNumber", arr[0]);
redisCache.setCacheMapValue(key, "type", arr[1]);
redisCache.setCacheMapValue(key, "time", arr[2]);
if (InOut.equals("A")){
redisCache.setCacheMapValue(key, "inRunway", RunwayNum);
}else {
redisCache.setCacheMapValue(key, "outRunway", RunwayNum);
}
log.info("成功将航班数据存储到Redis: flightNumber={}, type={}, time={}", arr[0], arr[1], arr[2]);
} catch (Exception e) {
log.error("存储航班数据到Redis失败: {}", e.getMessage());
}
}
return dto;
}
//处理RUNWAY事件
private FlightNotificationDTO handleRUNWAY(org.w3c.dom.Element root) {
String flightNo = getTextContent(root, "BizKey");
String outRunway = getTextContent(root, "RUNWAYDEP");
String inRunway = getTextContent(root, "RUNWAYARR");
log.error("inRunway-{}",inRunway);
log.error("outRunway-{}",outRunway);
//分解BizKey
String[] arr = flightNo.split("-", 3); // 最多切 3
FlightNotificationDTO dto = new FlightNotificationDTO();
dto.setFlightNo(flightNo);
if (arr[1].equals("A")){
dto.setType("IN");
}else {
dto.setType("OUT");
}
// 存储到Redis
if (arr.length >= 3) {
try {
String key = "flight:" + arr[0]; // 使用航班号作为键
redisCache.setCacheMapValue(key, "flightNumber", arr[0]);
redisCache.setCacheMapValue(key, "type", arr[1]);
redisCache.setCacheMapValue(key, "time", arr[2]);
if (!inRunway.equals("")){
redisCache.setCacheMapValue(key, "inRunway", inRunway);
}
if (!outRunway.equals("")){
redisCache.setCacheMapValue(key, "outRunway", outRunway);
}
log.info("成功将航班数据存储到Redis: flightNumber={}, type={}, time={}", arr[0], arr[1], arr[2]);
} catch (Exception e) {
log.error("存储航班数据到Redis失败: {}", e.getMessage());
}
}
return dto;
}
//处理CRAFTSEAT事件
private FlightNotificationDTO handleCRAFTSEAT(org.w3c.dom.Element root) {
String flightNo = getTextContent(root, "BizKey");
String code = getTextContent(root, "Code");
log.error("seat-{}",code);
//分解BizKey
String[] arr = flightNo.split("-", 3); // 最多切 3
FlightNotificationDTO dto = new FlightNotificationDTO();
dto.setFlightNo(flightNo);
// 存储到Redis
if (arr.length >= 3) {
try {
String key = "flight:" + arr[0]; // 使用航班号作为键
redisCache.setCacheMapValue(key, "flightNumber", arr[0]);
redisCache.setCacheMapValue(key, "type", arr[1]);
redisCache.setCacheMapValue(key, "time", arr[2]);
redisCache.setCacheMapValue(key, "seat", code);
log.info("成功将航班数据存储到Redis: flightNumber={}, type={}, time={}", arr[0], arr[1], arr[2]);
} catch (Exception e) {
log.error("存储航班数据到Redis失败: {}", e.getMessage());
}
}
return dto;
}
private FlightNotificationDTO handleTISFLIGHT(org.w3c.dom.Element root) {
String flightNumber = getTextContent(root, "FlNo");
String contactCross = getTextContent(root, "ContactCross");
FlightNotificationDTO dto = new FlightNotificationDTO();
dto.setFlightNo(flightNumber);
dto.setType("IN");
String key = "flight:" + flightNumber;
try {
redisCache.setCacheMapValue(key, "flightNumber", flightNumber);
redisCache.setCacheMapValue(key, "contactCross",contactCross);
} catch (Exception e) {
log.error("存储航班数据到Redis失败: {}", e.getMessage());
}
return dto;
}
private FlightNotificationDTO handleAXOT(org.w3c.dom.Element root) {
String flightNo = getTextContent(root, "BizKey");
//分解BizKey
String[] arr = flightNo.split("-", 3); // 最多切 3
FlightNotificationDTO dto = new FlightNotificationDTO();
dto.setFlightNo(flightNo);
dto.setType("OUT");
// 存储到Redis
if (arr.length >= 3) {
try {
String key = "flight:" + arr[0]; // 使用航班号作为键
redisCache.setCacheMapValue(key, "flightNumber", arr[0]);
redisCache.setCacheMapValue(key, "type", arr[1]);
redisCache.setCacheMapValue(key, "time", arr[2]);
log.info("成功将航班数据存储到Redis: flightNumber={}, type={}, time={}", arr[0], arr[1], arr[2]);
} catch (Exception e) {
log.error("存储航班数据到Redis失败: {}", e.getMessage());
}
}
//假装模拟请求接口
dataProcessingService.AXOT(arr[0]);
return dto;
}
private FlightNotificationDTO handleDFDE(org.w3c.dom.Element root) {
String flightNo = getTextContent(root, "BizKey");
//分解BizKey
String[] arr = flightNo.split("-", 3); // 最多切 3
FlightNotificationDTO dto = new FlightNotificationDTO();
if (arr[1].equals("A")){
dto.setType("IN");
}else {
dto.setType("OUT");
}
String key = "flight:" + arr[0]; // 使用航班号作为键
redisCache.deleteObject(key);
return null;
}
} }

View File

@ -0,0 +1,20 @@
package com.qaup.collision.datacollector.websocket;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class AdxpWebSocketStarter {
private final AdxpFlightServiceWebSocketClient client;
public AdxpWebSocketStarter(AdxpFlightServiceWebSocketClient client) {
this.client = client;
}
@EventListener(ApplicationReadyEvent.class)
public void startWhenReady() {
client.start();
}
}

View File

@ -15,6 +15,7 @@ import com.qaup.collision.websocket.event.VehicleStatusUpdateEvent;
import com.qaup.collision.datacollector.service.DataCollectorService; import com.qaup.collision.datacollector.service.DataCollectorService;
import com.qaup.collision.common.model.FlightNotification; import com.qaup.collision.common.model.FlightNotification;
import com.qaup.collision.websocket.event.FlightNotificationEvent; import com.qaup.collision.websocket.event.FlightNotificationEvent;
import com.qaup.common.core.redis.RedisCache;
import com.qaup.system.domain.SysVehicleInfo; import com.qaup.system.domain.SysVehicleInfo;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -87,6 +88,9 @@ public class DataProcessingService {
@Autowired @Autowired
private ApplicationContext applicationContext; private ApplicationContext applicationContext;
@Autowired
private RedisCache redisCache;
// 从DataCollectorService获取缓存的引用 // 从DataCollectorService获取缓存的引用
private Map<String, MovingObject> activeMovingObjectsCache; private Map<String, MovingObject> activeMovingObjectsCache;
@ -136,8 +140,8 @@ public class DataProcessingService {
// 第三步处理通用车辆状态数据并发送WebSocket更新 // 第三步处理通用车辆状态数据并发送WebSocket更新
processUniversalVehicleStatusUpdates(); processUniversalVehicleStatusUpdates();
// 第四步处理航班通知数据并发送WebSocket更新 // 第四步处理航班通知数据并发送WebSocket更新, 暂时关闭改为用websocket接收
processFlightNotificationUpdates(); //processFlightNotificationUpdates();
// 第五步执行路径冲突检测 // 第五步执行路径冲突检测
pathConflictDetectionService.detectPathConflicts(currentActiveObjects); pathConflictDetectionService.detectPathConflicts(currentActiveObjects);
@ -488,6 +492,10 @@ public class DataProcessingService {
DataCollectorService dataCollectorService = applicationContext.getBean(DataCollectorService.class); DataCollectorService dataCollectorService = applicationContext.getBean(DataCollectorService.class);
Map<String, FlightNotification> flightNotificationCache = dataCollectorService.getFlightNotificationCache(); Map<String, FlightNotification> flightNotificationCache = dataCollectorService.getFlightNotificationCache();
// 打印缓存数量
log.error("航班通知缓存数量: {}", flightNotificationCache.size());
log.error("航班通知缓存内容: {}", flightNotificationCache);
if (flightNotificationCache.isEmpty()) { if (flightNotificationCache.isEmpty()) {
log.debug("航班通知缓存为空,跳过处理"); log.debug("航班通知缓存为空,跳过处理");
return; return;
@ -1244,6 +1252,7 @@ public class DataProcessingService {
*/ */
private void publishAircraftRouteUpdateEvent(String flightNo, AircraftRoute route, private void publishAircraftRouteUpdateEvent(String flightNo, AircraftRoute route,
com.qaup.collision.datacollector.dto.AircraftRouteParamsDTO routeParams) { com.qaup.collision.datacollector.dto.AircraftRouteParamsDTO routeParams) {
log.error( "发布航空器路由更新事件: flightNo={}", flightNo);
try { try {
// 创建路由更新事件 // 创建路由更新事件
com.qaup.collision.websocket.event.AircraftRouteUpdateEvent routeUpdateEvent = com.qaup.collision.websocket.event.AircraftRouteUpdateEvent routeUpdateEvent =
@ -1268,4 +1277,112 @@ public class DataProcessingService {
log.error("❌ 发布航空器路由更新事件失败: flightNo={}", flightNo, e); log.error("❌ 发布航空器路由更新事件失败: flightNo={}", flightNo, e);
} }
} }
/**
* 触发查询航班号对应的路由
*/
public void ARR(String flightNo){
String key = "flight:"+flightNo;
String time =(String) redisCache.getCacheMapValue(key, "time");
log.error("time是{}",time);
// String inRunway = "35";
// String outRunway = "34";
// String contactCross = "F1";
// String seat = "138";
String inRunway = (String) redisCache.getCacheMapValue(key, "inRunway");
String outRunway = (String) redisCache.getCacheMapValue(key, "outRunway");
String contactCross = (String) redisCache.getCacheMapValue(key, "contactCross");
String seat = (String) redisCache.getCacheMapValue(key, "seat");
log.error("进港参数是{}",inRunway);
log.error("出港参数是{}",outRunway);
log.error("接触交叉参数是{}",contactCross);
log.error("座位参数是{}",seat);
// 获取DataCollectorDao进行路由数据查询
DataCollectorDao dataCollectorDao = applicationContext.getBean(DataCollectorDao.class);
AircraftRouteDTO routeData = null;
// 进港路由查询
routeData = dataCollectorDao.getArrivalRoute(
inRunway,
outRunway,
contactCross,
seat);
log.error("进港路由数据routeData是{}",routeData);
// 创建路由参数:目前有用的只有type
com.qaup.collision.datacollector.dto.AircraftRouteParamsDTO routeParams = new com.qaup.collision.datacollector.dto.AircraftRouteParamsDTO();
routeParams.setFlightNo(flightNo);
routeParams.setRouteType("IN");
routeParams.setInRunway(inRunway);
routeParams.setOutRunway(outRunway);
routeParams.setContactCross(contactCross);
routeParams.setSeat(seat);
//处理路由数据并发布
handleRouteData(flightNo, routeData, routeParams);
}
public void AXOT(String flightNo){
String key = "flight:"+flightNo;
String time =(String) redisCache.getCacheMapValue(key, "time");
log.error("time是{}",time);
// String inRunway = "17";
// String outRunway = "35";
// String startSeat = "201";
String inRunway = (String) redisCache.getCacheMapValue(key, "inRunway");
String outRunway = (String) redisCache.getCacheMapValue(key, "outRunway");
String startSeat = (String) redisCache.getCacheMapValue(key, "startSeat");
log.error("进港参数是{}",inRunway);
log.error("出港参数是{}",outRunway);
log.error("起始座位参数是{}",startSeat);
// 获取DataCollectorDao进行路由数据查询
DataCollectorDao dataCollectorDao = applicationContext.getBean(DataCollectorDao.class);
AircraftRouteDTO routeData = null;
// 进港路由查询
routeData = dataCollectorDao.getDepartureRoute(
inRunway,
outRunway,
startSeat);
log.error("出港路由数据是routeData是{}",routeData);
// 创建路由参数:目前有用的只有type
com.qaup.collision.datacollector.dto.AircraftRouteParamsDTO routeParams = new com.qaup.collision.datacollector.dto.AircraftRouteParamsDTO();
routeParams.setFlightNo(flightNo);
routeParams.setRouteType("OUT");
routeParams.setInRunway(inRunway);
routeParams.setOutRunway(outRunway);
routeParams.setStartSeat(startSeat);
//处理路由数据并发布
handleRouteData(flightNo, routeData, routeParams);
}
private void handleRouteData(String flightNo, AircraftRouteDTO routeData,
com.qaup.collision.datacollector.dto.AircraftRouteParamsDTO routeParams){
// 步骤3: 处理路由查询结果
if (routeData != null) {
log.info("🎯 成功获取{}路由数据: 编码={}, 状态={}",
routeData.getType(), routeData.getCodes(), routeData.getStatus());
// 转换DTO为航空器路由对象
AircraftRoute aircraftRoute = convertToAircraftRoute(routeData);
if (aircraftRoute != null) {
// 保存路由到数据库
saveAircraftRouteToDatabase(flightNo, aircraftRoute);
// 发布WebSocket路由更新事件
publishAircraftRouteUpdateEvent(flightNo, aircraftRoute, routeParams);
} else {
log.warn("⚠️ 路由数据转换失败: flightNo={}", flightNo);
}
} else {
log.warn("⚠️ 未获取到路由数据: flightNo={}", flightNo);
}
}
} }

View File

@ -74,7 +74,7 @@ public class LocationRuleQueryServiceImpl implements LocationRuleQueryService {
// ============================================ // ============================================
@Override @Override
@Cacheable(value = "locationRules", key = "#location.toString() + '_' + #vehicleType + '_' + #timestamp.toString()") //@Cacheable(value = "locationRules", key = "#location.toString() + '_' + #vehicleType + '_' + #timestamp.toString()")
public List<SpatialRule> findApplicableRules(Point location, MovingObjectType vehicleType, LocalDateTime timestamp) { public List<SpatialRule> findApplicableRules(Point location, MovingObjectType vehicleType, LocalDateTime timestamp) {
try { try {
logger.debug("查询位置适用规则: location={}, vehicleType={}, timestamp={}", logger.debug("查询位置适用规则: location={}, vehicleType={}, timestamp={}",

View File

@ -36,6 +36,7 @@ public class AircraftRouteUpdateEventListener {
*/ */
@EventListener @EventListener
public void handleAircraftRouteUpdateEvent(AircraftRouteUpdateEvent event) { public void handleAircraftRouteUpdateEvent(AircraftRouteUpdateEvent event) {
log.error("处理航空器路由更新事件: flightNo={}", event.getFlightNo());
try { try {
// 构建WebSocket消息 // 构建WebSocket消息
String message = objectMapper.writeValueAsString(new WebSocketMessage( String message = objectMapper.writeValueAsString(new WebSocketMessage(

View File

@ -236,8 +236,12 @@ public class RedisCache
public <T> void setCacheMapValue(final String key, final String hKey, final T value) public <T> void setCacheMapValue(final String key, final String hKey, final T value)
{ {
redisTemplate.opsForHash().put(key, hKey, value); redisTemplate.opsForHash().put(key, hKey, value);
// 统一设置 Hash 的过期时间对整个 key 生效
//redisTemplate.expire(key, DEFAULT_EXPIRE_TIME, DEFAULT_TIME_UNIT);
redisTemplate.expire(key, 24 * DEFAULT_EXPIRE_TIME , DEFAULT_TIME_UNIT);
} }
/** /**
* 获取Hash中的数据 * 获取Hash中的数据
* *