Browse Source

first commit

xyh 2 months ago
commit
213be7fa84
29 changed files with 2841 additions and 0 deletions
  1. 2 0
      .gitattributes
  2. 62 0
      .gitignore
  3. 259 0
      mvnw
  4. 149 0
      mvnw.cmd
  5. 96 0
      pom.xml
  6. 18 0
      src/main/java/com/example/backend/BackendApplication.java
  7. 35 0
      src/main/java/com/example/backend/config/WebConfig.java
  8. 293 0
      src/main/java/com/example/backend/controller/RadarStatusController.java
  9. 252 0
      src/main/java/com/example/backend/dds/DataReaderListenerImpl.java
  10. 241 0
      src/main/java/com/example/backend/dds/TestPublisher.java
  11. 189 0
      src/main/java/com/example/backend/dds/TestSubscriber.java
  12. 57 0
      src/main/java/com/example/backend/exception/GlobalExceptionHandler.java
  13. 12 0
      src/main/java/com/example/backend/exception/ResourceNotFoundException.java
  14. 11 0
      src/main/java/com/example/backend/exception/ServiceException.java
  15. 69 0
      src/main/java/com/example/backend/model/Message.java
  16. 32 0
      src/main/java/com/example/backend/model/MessageStatus.java
  17. 22 0
      src/main/java/com/example/backend/model/Platform.java
  18. 59 0
      src/main/java/com/example/backend/model/Position.java
  19. 13 0
      src/main/java/com/example/backend/model/RadarParam.java
  20. 169 0
      src/main/java/com/example/backend/model/RadarStatus.java
  21. 20 0
      src/main/java/com/example/backend/model/RadarTarget.java
  22. 51 0
      src/main/java/com/example/backend/model/compMsg.java
  23. 77 0
      src/main/java/com/example/backend/model/disturbMsg.java
  24. 59 0
      src/main/java/com/example/backend/model/ecmParams.java
  25. 41 0
      src/main/java/com/example/backend/model/ecmStatus.java
  26. 78 0
      src/main/java/com/example/backend/model/radarPulseMsg.java
  27. 458 0
      src/main/java/com/example/backend/service/RadarStatusService.java
  28. 4 0
      src/main/resources/application.properties
  29. 13 0
      src/test/java/com/example/backend/BackendApplicationTests.java

+ 2 - 0
.gitattributes

@@ -0,0 +1,2 @@
+/mvnw text eol=lf
+*.cmd text eol=crlf

+ 62 - 0
.gitignore

@@ -0,0 +1,62 @@
+HELP.md
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# Package Files
+*.jar
+*.war
+*.ear
+*.zip
+
+# IDE
+.idea/
+*.iml
+.classpath
+.project
+.settings/
+
+# Maven
+target/
+.mvn/timing.properties
+
+# Spring Boot
+application-*.yml
+application-*.properties
+!application.properties
+!application.yml

+ 259 - 0
mvnw

@@ -0,0 +1,259 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.3.2
+#
+# Optional ENV vars
+# -----------------
+#   JAVA_HOME - location of a JDK home dir, required when download maven via java source
+#   MVNW_REPOURL - repo url base for downloading maven distribution
+#   MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+#   MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
+# ----------------------------------------------------------------------------
+
+set -euf
+[ "${MVNW_VERBOSE-}" != debug ] || set -x
+
+# OS specific support.
+native_path() { printf %s\\n "$1"; }
+case "$(uname)" in
+CYGWIN* | MINGW*)
+  [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
+  native_path() { cygpath --path --windows "$1"; }
+  ;;
+esac
+
+# set JAVACMD and JAVACCMD
+set_java_home() {
+  # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
+  if [ -n "${JAVA_HOME-}" ]; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ]; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+      JAVACCMD="$JAVA_HOME/jre/sh/javac"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+      JAVACCMD="$JAVA_HOME/bin/javac"
+
+      if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
+        echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
+        echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
+        return 1
+      fi
+    fi
+  else
+    JAVACMD="$(
+      'set' +e
+      'unset' -f command 2>/dev/null
+      'command' -v java
+    )" || :
+    JAVACCMD="$(
+      'set' +e
+      'unset' -f command 2>/dev/null
+      'command' -v javac
+    )" || :
+
+    if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
+      echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
+      return 1
+    fi
+  fi
+}
+
+# hash string like Java String::hashCode
+hash_string() {
+  str="${1:-}" h=0
+  while [ -n "$str" ]; do
+    char="${str%"${str#?}"}"
+    h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
+    str="${str#?}"
+  done
+  printf %x\\n $h
+}
+
+verbose() { :; }
+[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
+
+die() {
+  printf %s\\n "$1" >&2
+  exit 1
+}
+
+trim() {
+  # MWRAPPER-139:
+  #   Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
+  #   Needed for removing poorly interpreted newline sequences when running in more
+  #   exotic environments such as mingw bash on Windows.
+  printf "%s" "${1}" | tr -d '[:space:]'
+}
+
+# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
+while IFS="=" read -r key value; do
+  case "${key-}" in
+  distributionUrl) distributionUrl=$(trim "${value-}") ;;
+  distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
+  esac
+done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
+[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
+
+case "${distributionUrl##*/}" in
+maven-mvnd-*bin.*)
+  MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
+  case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
+  *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
+  :Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
+  :Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
+  :Linux*x86_64*) distributionPlatform=linux-amd64 ;;
+  *)
+    echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
+    distributionPlatform=linux-amd64
+    ;;
+  esac
+  distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
+  ;;
+maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
+*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
+esac
+
+# apply MVNW_REPOURL and calculate MAVEN_HOME
+# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
+[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
+distributionUrlName="${distributionUrl##*/}"
+distributionUrlNameMain="${distributionUrlName%.*}"
+distributionUrlNameMain="${distributionUrlNameMain%-bin}"
+MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
+MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
+
+exec_maven() {
+  unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
+  exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
+}
+
+if [ -d "$MAVEN_HOME" ]; then
+  verbose "found existing MAVEN_HOME at $MAVEN_HOME"
+  exec_maven "$@"
+fi
+
+case "${distributionUrl-}" in
+*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
+*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
+esac
+
+# prepare tmp dir
+if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
+  clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
+  trap clean HUP INT TERM EXIT
+else
+  die "cannot create temp dir"
+fi
+
+mkdir -p -- "${MAVEN_HOME%/*}"
+
+# Download and Install Apache Maven
+verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
+verbose "Downloading from: $distributionUrl"
+verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
+
+# select .zip or .tar.gz
+if ! command -v unzip >/dev/null; then
+  distributionUrl="${distributionUrl%.zip}.tar.gz"
+  distributionUrlName="${distributionUrl##*/}"
+fi
+
+# verbose opt
+__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
+[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
+
+# normalize http auth
+case "${MVNW_PASSWORD:+has-password}" in
+'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
+has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
+esac
+
+if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
+  verbose "Found wget ... using wget"
+  wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
+elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
+  verbose "Found curl ... using curl"
+  curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
+elif set_java_home; then
+  verbose "Falling back to use Java to download"
+  javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
+  targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
+  cat >"$javaSource" <<-END
+	public class Downloader extends java.net.Authenticator
+	{
+	  protected java.net.PasswordAuthentication getPasswordAuthentication()
+	  {
+	    return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
+	  }
+	  public static void main( String[] args ) throws Exception
+	  {
+	    setDefault( new Downloader() );
+	    java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
+	  }
+	}
+	END
+  # For Cygwin/MinGW, switch paths to Windows format before running javac and java
+  verbose " - Compiling Downloader.java ..."
+  "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
+  verbose " - Running Downloader.java ..."
+  "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
+fi
+
+# If specified, validate the SHA-256 sum of the Maven distribution zip file
+if [ -n "${distributionSha256Sum-}" ]; then
+  distributionSha256Result=false
+  if [ "$MVN_CMD" = mvnd.sh ]; then
+    echo "Checksum validation is not supported for maven-mvnd." >&2
+    echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
+    exit 1
+  elif command -v sha256sum >/dev/null; then
+    if echo "$distributionSha256Sum  $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
+      distributionSha256Result=true
+    fi
+  elif command -v shasum >/dev/null; then
+    if echo "$distributionSha256Sum  $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
+      distributionSha256Result=true
+    fi
+  else
+    echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
+    echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
+    exit 1
+  fi
+  if [ $distributionSha256Result = false ]; then
+    echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
+    echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
+    exit 1
+  fi
+fi
+
+# unzip and move
+if command -v unzip >/dev/null; then
+  unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
+else
+  tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
+fi
+printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
+mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
+
+clean || :
+exec_maven "$@"

+ 149 - 0
mvnw.cmd

@@ -0,0 +1,149 @@
+<# : batch portion
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Apache Maven Wrapper startup batch script, version 3.3.2
+@REM
+@REM Optional ENV vars
+@REM   MVNW_REPOURL - repo url base for downloading maven distribution
+@REM   MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
+@REM   MVNW_VERBOSE - true: enable verbose log; others: silence the output
+@REM ----------------------------------------------------------------------------
+
+@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
+@SET __MVNW_CMD__=
+@SET __MVNW_ERROR__=
+@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
+@SET PSModulePath=
+@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
+  IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
+)
+@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
+@SET __MVNW_PSMODULEP_SAVE=
+@SET __MVNW_ARG0_NAME__=
+@SET MVNW_USERNAME=
+@SET MVNW_PASSWORD=
+@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
+@echo Cannot start maven from wrapper >&2 && exit /b 1
+@GOTO :EOF
+: end batch / begin powershell #>
+
+$ErrorActionPreference = "Stop"
+if ($env:MVNW_VERBOSE -eq "true") {
+  $VerbosePreference = "Continue"
+}
+
+# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
+$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
+if (!$distributionUrl) {
+  Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
+}
+
+switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
+  "maven-mvnd-*" {
+    $USE_MVND = $true
+    $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
+    $MVN_CMD = "mvnd.cmd"
+    break
+  }
+  default {
+    $USE_MVND = $false
+    $MVN_CMD = $script -replace '^mvnw','mvn'
+    break
+  }
+}
+
+# apply MVNW_REPOURL and calculate MAVEN_HOME
+# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
+if ($env:MVNW_REPOURL) {
+  $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
+  $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
+}
+$distributionUrlName = $distributionUrl -replace '^.*/',''
+$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
+$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
+if ($env:MAVEN_USER_HOME) {
+  $MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
+}
+$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
+$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
+
+if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
+  Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
+  Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
+  exit $?
+}
+
+if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
+  Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
+}
+
+# prepare tmp dir
+$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
+$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
+$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
+trap {
+  if ($TMP_DOWNLOAD_DIR.Exists) {
+    try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
+    catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
+  }
+}
+
+New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
+
+# Download and Install Apache Maven
+Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
+Write-Verbose "Downloading from: $distributionUrl"
+Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
+
+$webclient = New-Object System.Net.WebClient
+if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
+  $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
+}
+[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
+$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
+
+# If specified, validate the SHA-256 sum of the Maven distribution zip file
+$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
+if ($distributionSha256Sum) {
+  if ($USE_MVND) {
+    Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
+  }
+  Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
+  if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
+    Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
+  }
+}
+
+# unzip and move
+Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
+Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
+try {
+  Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
+} catch {
+  if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
+    Write-Error "fail to move MAVEN_HOME"
+  }
+} finally {
+  try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
+  catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
+}
+
+Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"

+ 96 - 0
pom.xml

@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.6.7</version>
+        <relativePath/> <!-- lookup parent from repository -->
+    </parent>
+    <groupId>com.example</groupId>
+    <artifactId>backend</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>backend</name>
+    <description>backend</description>
+    <url/>
+    <licenses>
+        <license/>
+    </licenses>
+    <developers>
+        <developer/>
+    </developers>
+    <scm>
+        <connection/>
+        <developerConnection/>
+        <tag/>
+        <url/>
+    </scm>
+    <properties>
+        <java.version>1.8</java.version>
+        <spring-boot.version>2.3.10.RELEASE</spring-boot.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-websocket</artifactId>
+        </dependency>
+
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>jakarta.annotation</groupId>
+            <artifactId>jakarta.annotation-api</artifactId>
+            <version>2.1.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.76</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                        </exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 18 - 0
src/main/java/com/example/backend/BackendApplication.java

@@ -0,0 +1,18 @@
+package com.example.backend;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+@EnableAsync
+@EnableScheduling   // 启用定时任务
+@SpringBootApplication(exclude = {SecurityAutoConfiguration.class})
+public class BackendApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(BackendApplication.class, args);
+    }
+
+}

+ 35 - 0
src/main/java/com/example/backend/config/WebConfig.java

@@ -0,0 +1,35 @@
+package com.example.backend.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.CorsRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebConfig implements WebMvcConfigurer {
+
+    @Value("${frontend.url}")
+    private String frontendUrl;
+
+    @Override
+    public void addCorsMappings(CorsRegistry registry) {
+        registry.addMapping("/api/**")
+                .allowedOrigins(frontendUrl)
+                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
+                .allowedHeaders("*")
+                .exposedHeaders("Authorization")
+                .allowCredentials(true)
+                .maxAge(3600);
+    }
+
+    @Bean
+    public WebMvcConfigurer corsConfigurer() {
+        return new WebMvcConfigurer() {
+            @Override
+            public void addCorsMappings(CorsRegistry registry) {
+                registry.addMapping("/**");
+            }
+        };
+    }
+}

+ 293 - 0
src/main/java/com/example/backend/controller/RadarStatusController.java

@@ -0,0 +1,293 @@
+package com.example.backend.controller;
+
+import com.example.backend.model.*;
+import com.example.backend.service.RadarStatusService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import org.springframework.validation.annotation.Validated;
+import com.example.backend.exception.ServiceException;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+import java.util.*;
+
+@RestController
+@RequestMapping("/api")
+@Validated
+public class RadarStatusController {
+
+    private final RadarStatusService radarStatusService;
+    private static final Logger logger = LoggerFactory.getLogger(RadarStatusController.class);
+
+    @Autowired
+    public RadarStatusController(RadarStatusService radarStatusService) {
+        this.radarStatusService = radarStatusService;
+    }
+
+    @GetMapping("/platform/getPlatforms")
+    public ResponseEntity<List<Platform>> getPlatforms()
+            {
+        try {
+            List list = new ArrayList();
+            for(String key : radarStatusService.getPlatforms()){
+                Platform p = new Platform();
+                p.setPlatformID(key);
+                p.setPlatformName("干扰平台-"+key);
+                list.add(p);
+            }
+            return ResponseEntity.ok(list);
+        } catch (Exception e) {
+            logger.error("获取干扰平台列表", e);
+            throw new ServiceException("获取干扰平台列表");
+        }
+    }
+
+    @GetMapping("/platform/{platformId}/radar-status")
+    public ResponseEntity<List<Map<String, Object>>> getRadarStatus(
+            @PathVariable @NotBlank String platformId) {
+        logger.info("获取平台 {} 的雷达状态", platformId);
+        try {
+            List<Map<String, Object>> status = radarStatusService.getRadarStatus(platformId);
+            return ResponseEntity.ok(status);
+        } catch (Exception e) {
+            logger.error("获取雷达状态失败", e);
+            throw new ServiceException("获取雷达状态失败");
+        }
+    }
+
+    @PostMapping("/platform/{platformId}/radar-status")
+    public ResponseEntity<RadarStatus> updateRadarStatus(
+            @PathVariable @NotBlank String platformId,
+            @RequestBody @Valid RadarStatus radarStatus) {
+        logger.info("更新平台 {} 的雷达状态", platformId);
+        try {
+            RadarStatus updated = radarStatusService.updateRadarStatus(platformId, radarStatus);
+            return ResponseEntity.ok(updated);
+        } catch (Exception e) {
+            logger.error("更新雷达状态失败", e);
+            throw new ServiceException("更新雷达状态失败");
+        }
+    }
+
+    @PostMapping("/platform/{platformId}/radar-params")
+    public ResponseEntity<List<RadarParam>> updateRadarParams(
+            @PathVariable @NotBlank String platformId,
+            @RequestBody @Valid List<RadarParam> radarParams) {
+        logger.info("更新平台 {} 的雷达参数", platformId);
+        try {
+            List<RadarParam> updated = radarStatusService.updateRadarParams(platformId, radarParams);
+            return ResponseEntity.ok(updated);
+        } catch (Exception e) {
+            logger.error("更新雷达参数失败", e);
+            throw new ServiceException("更新雷达参数失败");
+        }
+    }
+
+    @GetMapping("/platform/{platformId}/radar-params")
+    public ResponseEntity<List<RadarParam>> getRadarParams(
+            @PathVariable @NotBlank String platformId) {
+        logger.info("获取平台 {} 的雷达参数", platformId);
+        try {
+            List<RadarParam> params = radarStatusService.getRadarParams(platformId);
+            return ResponseEntity.ok(params);
+        } catch (Exception e) {
+            logger.error("获取雷达参数失败", e);
+            throw new ServiceException("获取雷达参数失败");
+        }
+    }
+
+    @GetMapping("/platform/{platformId}/position")
+    public ResponseEntity<Position> getPositionById(
+            @PathVariable @NotBlank String platformId) {
+        try {
+            Position p = radarStatusService.getPositionById(platformId);
+            if(p==null)p = new Position();
+            return ResponseEntity.ok(p);
+        } catch (Exception e) {
+            logger.error("获取目标位置失败", e);
+            throw new ServiceException("获取目标位置失败");
+        }
+    }
+
+    @GetMapping("/platform/{platformId}/radar-targets")
+    public ResponseEntity<List<RadarTarget>> getRadarTargets(
+            @PathVariable @NotBlank String platformId) {
+        logger.info("获取平台 {} 的目标数据", platformId);
+        try {
+            List<RadarTarget> targets = radarStatusService.getRadarTargets(platformId);
+            return ResponseEntity.ok(targets);
+        } catch (Exception e) {
+            logger.error("获取目标数据失败", e);
+            throw new ServiceException("获取目标数据失败");
+        }
+    }
+
+    @PostMapping("/platform/{platformId}/radar-targets")
+    public ResponseEntity<Map<String, Object>> updateRadarTargets(
+            @PathVariable @NotBlank String platformId,
+            @RequestBody @Valid List<RadarTarget> targets) {
+        logger.info("更新平台 {} 的目标数据", platformId);
+        try {
+            List<RadarTarget> updated = radarStatusService.updateRadarTargets(platformId, targets);
+            Map<String, Object> response = new HashMap<>();
+            response.put("targets", updated);
+            response.put("queueSize", radarStatusService.getRadarTargetsCount(platformId));
+            return ResponseEntity.ok(response);
+        } catch (Exception e) {
+            logger.error("更新目标数据失败", e);
+            throw new ServiceException("更新目标数据失败");
+        }
+    }
+
+    @DeleteMapping("/platform/{platformId}/radar-targets")
+    public ResponseEntity<Void> clearRadarTargets(
+            @PathVariable @NotBlank String platformId) {
+        logger.info("清除平台 {} 的目标数据", platformId);
+        try {
+            radarStatusService.clearRadarTargets(platformId);
+            return ResponseEntity.ok().build();
+        } catch (Exception e) {
+            logger.error("清除目标数据失败", e);
+            throw new ServiceException("清除目标数据失败");
+        }
+    }
+
+    @GetMapping("/platform/{platformId}/getMsgStatus")
+    public ResponseEntity<MessageStatus> getMsgStatus(
+            @PathVariable @NotBlank String platformId) {
+        logger.info("获取平台 {} 的目标数据", platformId);
+        try {
+            MessageStatus m = radarStatusService.getMsgStatusById(platformId);
+            return ResponseEntity.ok(m);
+        } catch (Exception e) {
+            logger.error("获取通信状态失败", e);
+            throw new ServiceException("获取通信状态失败");
+        }
+    }
+
+    @PostMapping("/platform/{platformId}/setMsgStatus")
+    public ResponseEntity<Void> setMsgStatus(
+            @PathVariable @NotBlank String platformId,
+            @RequestBody @Valid MessageStatus messageStatus) {
+        logger.info("更新平台 {} 的通信状态", platformId);
+        try {
+            radarStatusService.setMsgStatusById(platformId,messageStatus);
+            return ResponseEntity.ok().build();
+        } catch (Exception e) {
+            logger.error("更新通信状态失败", e);
+            throw new ServiceException("更新通信状态失败");
+        }
+    }
+
+    @GetMapping("/platform/{platformId}/getMsgList")
+    public ResponseEntity<List<Message>> getMsgList(
+            @PathVariable @NotBlank String platformId) {
+        logger.info("获取平台 {} 的消息数据", platformId);
+        try {
+            List<Message> list = radarStatusService.getMsgListById(platformId);
+            return ResponseEntity.ok(list);
+        } catch (Exception e) {
+            logger.error("获取消息数据失败", e);
+            throw new ServiceException("获取消息数据失败");
+        }
+    }
+
+    @GetMapping("/platform/{platformId}/getOutMsgList")
+    public ResponseEntity<List<Message>> getOutMsgList(
+            @PathVariable @NotBlank String platformId) {
+        logger.info("获取平台 {} 的消息数据", platformId);
+        try {
+            List<Message> list = radarStatusService.getOutMsgListById(platformId);
+            return ResponseEntity.ok(list);
+        } catch (Exception e) {
+            logger.error("获取消息数据失败", e);
+            throw new ServiceException("获取消息数据失败");
+        }
+    }
+
+    @PostMapping("/platform/{platformId}/sendMsg")
+    public ResponseEntity<Void> sendMsg(
+            @PathVariable @NotBlank String platformId,
+            @RequestBody @Valid Message msg) {
+        logger.info("平台 {} 发送消息", platformId);
+        try {
+            radarStatusService.sendMessageToOther(platformId, msg,msg.getRecivier(),radarStatusService.msgToNumber(msg.getTopic()));
+            return ResponseEntity.ok().build();
+        } catch (Exception e) {
+            logger.error("发送消息失败", e);
+            throw new ServiceException("发送消息失败");
+        }
+    }
+
+    @PostMapping("/platform/{platformId}/sendRadarPulseMsg")
+    public ResponseEntity<Void> sendRadarPulseMsg(
+            @PathVariable @NotBlank String platformId,
+            @RequestBody @Valid radarPulseMsg msg) {
+        logger.info("平台 {} 发送消息", platformId);
+        try {
+            radarStatusService.sendRadarPulseMsg(platformId, msg,msg.getRecivier());
+            return ResponseEntity.ok().build();
+        } catch (Exception e) {
+            logger.error("发送消息失败", e);
+            throw new ServiceException("发送消息失败");
+        }
+    }
+
+    @PostMapping("/platform/{platformId}/sendDisturbMsg")
+    public ResponseEntity<Void> sendDisturbMsg(
+            @PathVariable @NotBlank String platformId,
+            @RequestBody @Valid disturbMsg msg) {
+        logger.info("平台 {} 发送消息", platformId);
+        try {
+            radarStatusService.sendDisturbMsg(platformId, msg,msg.getRecivier());
+            return ResponseEntity.ok().build();
+        } catch (Exception e) {
+            logger.error("发送消息失败", e);
+            throw new ServiceException("发送消息失败");
+        }
+    }
+
+    @PostMapping("/platform/{platformId}/sendCompMsg")
+    public ResponseEntity<Void> sendCompMsg(
+            @PathVariable @NotBlank String platformId,
+            @RequestBody @Valid compMsg msg) {
+        logger.info("平台 {} 发送消息", platformId);
+        try {
+            radarStatusService.sendCompMsg(platformId, msg,msg.getRecivier());
+            return ResponseEntity.ok().build();
+        } catch (Exception e) {
+            logger.error("发送消息失败", e);
+            throw new ServiceException("发送消息失败");
+        }
+    }
+
+    @GetMapping("/platform/{platformId}/getECMStatusByID")
+    public ResponseEntity<ecmStatus> getEMCStatusByID(
+            @PathVariable @NotBlank String platformId) {
+        logger.info("获取平台 {} 的电子攻击状态", platformId);
+        try {
+            ecmStatus ecmStatus = radarStatusService.getECMStatusByID(platformId);
+            return ResponseEntity.ok(ecmStatus);
+        } catch (Exception e) {
+            logger.error("获取电子攻击状态失败", e);
+            throw new ServiceException("获取电子攻击状态失败");
+        }
+    }
+
+    @GetMapping("/platform/{platformId}/getECMParamsByID")
+    public ResponseEntity<List<ecmParams>> getECMParamsByID(
+            @PathVariable @NotBlank String platformId) {
+        logger.info("获取平台 {} 的干扰列表数据", platformId);
+        try {
+            List<ecmParams> list = radarStatusService.getECMParamsByID(platformId);
+            return ResponseEntity.ok(list);
+        } catch (Exception e) {
+            logger.error("获取干扰列表数据失败", e);
+            throw new ServiceException("获取干扰列表数据失败");
+        }
+    }
+}

+ 252 - 0
src/main/java/com/example/backend/dds/DataReaderListenerImpl.java

@@ -0,0 +1,252 @@
+package com.example.backend.dds;/*
+ *
+ *
+ * Distributed under the OpenDDS License.
+ * See: http://www.opendds.org/license.html
+ */
+
+import DDS.*;
+import OpenDDS.DCPS.*;
+import OpenDDS.DCPS.transport.*;
+import com.example.backend.model.Position;
+import org.omg.CORBA.StringSeqHolder;
+import Messenger.*;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class DataReaderListenerImpl extends DDS._DataReaderListenerLocalBase {
+
+    private int num_msgs = 0;
+    public int isInit = 0;
+    public int isRecall = 0;
+    public String text = "";
+    private static final int N_EXPECTED = 40;
+    private ArrayList<Boolean> counts = new ArrayList<Boolean>(N_EXPECTED);
+    public Map<String, Position> positionMap = new HashMap<>();
+    public final Map<String, List<com.example.backend.model.Message>> messageList = new ConcurrentHashMap<>();
+
+    private void initialize_counts() {
+        if (counts.size() > 0) {
+          return;
+        }
+
+        for (int i = 0; i < N_EXPECTED; ++i) {
+            counts.add(false);
+        }
+    }
+
+    public synchronized void on_data_available(DDS.DataReader reader) {
+
+        initialize_counts();
+
+        MessageDataReader mdr = MessageDataReaderHelper.narrow(reader);
+        if (mdr == null) {
+            System.err.println("ERROR: read: narrow failed.");
+            return;
+        }
+
+        MessageHolder mh = new MessageHolder(new Message());
+        SampleInfoHolder sih = new SampleInfoHolder(new SampleInfo(0, 0, 0,
+            new DDS.Time_t(), 0, 0, 0, 0, 0, 0, 0, false, 0));
+        int status = mdr.take_next_sample(mh, sih);
+
+        if (status == RETCODE_OK.value) {
+
+            System.out.println("SampleInfo.sample_rank = "
+                                + sih.value.sample_rank);
+            System.out.println("SampleInfo.instance_state = "
+                                + sih.value.instance_state);
+
+            if (sih.value.valid_data) {
+
+                String prefix = "";
+                boolean invalid_count = false;
+                if (mh.value.count < 0 || mh.value.count >= counts.size()) {
+                    invalid_count = true;
+                }
+                else {
+                    if (counts.get(mh.value.count) == false){
+                        counts.set(mh.value.count, true);
+                    }
+                    else {
+                        prefix = "ERROR: Repeat ";
+                    }
+                }
+                System.out.println(prefix + "Message: subject    = " + mh.value.subject);
+                System.out.println("         subject_id = "
+                                   + mh.value.subject_id);
+                System.out.println("         from       = " + mh.value.from);
+                System.out.println("         count      = " + mh.value.count);
+                System.out.println("         text       = " + mh.value.text);
+                System.out.println("SampleInfo.sample_rank = "
+                                   + sih.value.sample_rank);
+                text = mh.value.text;
+                LocalDateTime now = LocalDateTime.now();
+
+                // 定义格式(例如:yyyy-MM-dd HH:mm:ss)
+                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+                // 格式化时间
+                String formattedDateTime = now.format(formatter);
+                if(mh.value.subject.equals("1")){
+                    if(isInit==1){
+                        System.out.println("已完成初始化,丢弃");
+                        return;
+                    }
+                    //收到初始化消息 完成初始化
+                    isInit = 1;
+                    String message = mh.value.text;
+                    String[] messageList = message.split("\n");
+                    String[] countList = messageList[0].split(" ");
+                    int count = Integer.parseInt(countList[0]);
+                    for(int i=1;i<=count;i++){
+                        String[] s = messageList[i].split(" ");
+                        Position p = new Position();
+                        p.coopID = s[1];
+                        p.jaming = s[2];
+                        p.isReal = s[3];
+                        p.x = Double.parseDouble(s[4]);
+                        p.y = Double.parseDouble(s[5]);
+                        p.z = Double.parseDouble(s[6]);
+                        positionMap.put(s[0],p);
+                    }
+                    //回复初始化应答
+                    isRecall = 1;
+                }
+                if(mh.value.subject.equals("3")){
+                    //收到平台位置信息
+                    if(isInit==0){
+                        System.out.println("未完成初始化,丢弃");
+                        return;
+                    }
+                    String message = mh.value.text;
+                    String[] messageList = message.split("\n");
+                    for(int i=1;i<messageList.length;i++){
+                        String[] s = messageList[i].split(" ");
+                        Position p = new Position();
+                        p.coopID = positionMap.get(s[0]).coopID;
+                        p.jaming = positionMap.get(s[0]).jaming;
+                        p.isReal = positionMap.get(s[0]).isReal;
+                        p.x = Double.parseDouble(s[1]);
+                        p.y = Double.parseDouble(s[2]);
+                        p.z = Double.parseDouble(s[3]);
+                        positionMap.put(s[0],p);
+                    }
+                }
+                if(mh.value.subject.equals("2")){
+                    if(mh.value.text.equals("4")){
+                        resetAll();
+                    }
+                }
+                if(mh.value.subject.equals("5")){
+                    String[] s = mh.value.from.split(" ");
+                    String recivier = s[2];
+                    String sender = s[0];
+                    List<com.example.backend.model.Message> list = messageList.get(recivier)==null ? new ArrayList<>() : messageList.get(recivier);
+                    list.add(new com.example.backend.model.Message(formattedDateTime,sender,"雷达脉冲",mh.value.text,"0"));
+                    messageList.put(recivier,list);
+
+                }
+                if(mh.value.subject.equals("6")){
+                    String[] s = mh.value.from.split(" ");
+                    String recivier = s[2];
+                    String sender = s[0];
+                    List<com.example.backend.model.Message> list = messageList.get(recivier)==null ? new ArrayList<>() : messageList.get(recivier);
+                    list.add(new com.example.backend.model.Message(formattedDateTime,sender,"电子干扰",mh.value.text,"0"));
+                    messageList.put(recivier,list);
+
+                }
+                if(mh.value.subject.equals("7")){
+                    String[] s = mh.value.from.split(" ");
+                    String recivier = s[2];
+                    String sender = s[0];
+                    List<com.example.backend.model.Message> list = messageList.get(recivier)==null ? new ArrayList<>() : messageList.get(recivier);
+                    list.add(new com.example.backend.model.Message(formattedDateTime,sender,"综合情报",mh.value.text,"0"));
+                    messageList.put(recivier,list);
+
+                }
+                if (invalid_count == true) {
+                    System.out.println("ERROR: Invalid message.count (" + mh.value.count + ")");
+                }
+                if (!mh.value.from.equals("Comic Book Guy") && !mh.value.from.equals("OpenDDS-Java")) {
+                    System.out.println("ERROR: Invalid message.from (" + mh.value.from + ")");
+                }
+                if (!mh.value.subject.equals("Review")) {
+                    System.out.println("ERROR: Invalid message.subject (" + mh.value.subject + ")");
+                }
+                if (!mh.value.text.equals("Worst. Movie. Ever.")) {
+                    System.out.println("ERROR: Invalid message.text (" + mh.value.text + ")");
+                }
+                if (mh.value.subject_id != 99) {
+                    System.out.println("ERROR: Invalid message.subject_id (" + mh.value.subject_id + ")");
+                }
+            }
+            else if (sih.value.instance_state ==
+                     NOT_ALIVE_DISPOSED_INSTANCE_STATE.value) {
+                System.out.println("instance is disposed");
+            }
+            else if (sih.value.instance_state ==
+                     NOT_ALIVE_NO_WRITERS_INSTANCE_STATE.value) {
+                System.out.println("instance is unregistered");
+            }
+            else {
+                System.out.println("DataReaderListenerImpl::on_data_available: "
+                                   + "ERROR: received unknown instance state "
+                                   + sih.value.instance_state);
+            }
+
+        } else if (status == RETCODE_NO_DATA.value) {
+            System.err.println("ERROR: reader received DDS::RETCODE_NO_DATA!");
+        } else {
+            System.err.println("ERROR: read Message: Error: " + status);
+        }
+    }
+
+    public void on_requested_deadline_missed(DDS.DataReader reader, DDS.RequestedDeadlineMissedStatus status) {
+        System.err.println("DataReaderListenerImpl.on_requested_deadline_missed");
+    }
+
+    public void on_requested_incompatible_qos(DDS.DataReader reader, DDS.RequestedIncompatibleQosStatus status) {
+        System.err.println("DataReaderListenerImpl.on_requested_incompatible_qos");
+    }
+
+    public void on_sample_rejected(DDS.DataReader reader, DDS.SampleRejectedStatus status) {
+        System.err.println("DataReaderListenerImpl.on_sample_rejected");
+    }
+
+    public void on_liveliness_changed(DDS.DataReader reader, DDS.LivelinessChangedStatus status) {
+        System.err.println("DataReaderListenerImpl.on_liveliness_changed");
+    }
+
+    public void on_subscription_matched(DDS.DataReader reader, DDS.SubscriptionMatchedStatus status) {
+        System.err.println("DataReaderListenerImpl.on_subscription_matched");
+    }
+
+    public void on_sample_lost(DDS.DataReader reader, DDS.SampleLostStatus status) {
+        System.err.println("DataReaderListenerImpl.on_sample_lost");
+    }
+
+    public void resetAll(){
+        this.positionMap.clear();
+        this.isInit = 0;
+        this.isRecall = 0;
+    }
+
+    public void report_validity() {
+        int count = 0;
+        int missed_counts = 0;
+        for (Boolean val : counts) {
+            if (val == false)
+                ++missed_counts;
+        }
+        if (missed_counts > 0) {
+            System.out.println("ERROR: Missing " + missed_counts + " messages");
+        }
+    }
+}

+ 241 - 0
src/main/java/com/example/backend/dds/TestPublisher.java

@@ -0,0 +1,241 @@
+package com.example.backend.dds;/*
+ *
+ *
+ * Distributed under the OpenDDS License.
+ * See: http://www.opendds.org/license.html
+ */
+
+import DDS.*;
+import OpenDDS.DCPS.*;
+import org.omg.CORBA.StringSeqHolder;
+import Messenger.*;
+
+import java.util.concurrent.*;
+
+public class TestPublisher {
+
+    private static final int N_MSGS = 20;
+    private int count = 0;
+    private DomainParticipantFactory dpf;
+    private DomainParticipant dp;
+    private MessageTypeSupportImpl servant;
+    private Topic top;
+    private Publisher pub;
+    private DataWriterQos dw_qos;
+    private DataWriterQosHolder qosh;
+    private DataReaderListenerImpl listener;
+    private DataWriter dw ;
+    private StatusCondition sc;
+    private WaitSet ws;
+    private PublicationMatchedStatusHolder matched;
+    private Duration_t timeout;
+    private MessageDataWriter mdw;
+    private int instanceHandle;
+    private BlockingQueue<Message> messageQueue = new LinkedBlockingQueue<>();
+    private volatile boolean isInitialized = false;
+    private final ExecutorService executor = Executors.newSingleThreadExecutor();
+    private volatile boolean running = true;
+    public TestPublisher() throws Exception {
+        String[] s = new String[4];
+        s[0] = "-DCPSBit";
+        s[1] = "0";
+        s[2] = "-DCPSConfigFile";
+        s[3] = "D:/dds/open-dds_3.16/OpenDDS-3.16/OpenDDS-3.16/java/tests/messenger/tcp.ini";
+        executor.submit(() -> initialize(s)); // 初始化放在后台线程
+    }
+    public static boolean checkReliable(String[] args) {
+        for (int i = 0; i < args.length; ++i) {
+            if (args[i].equals("-r")) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean checkWaitForAcks(String[] args) {
+        for (int i = 0; i < args.length; ++i) {
+            if (args[i].equals("-w")) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void initialize(String[] args) {
+        try {
+            // ... 原有初始化代码到创建DataWriter为止...
+            System.out.println("Start Publisher");
+            boolean reliable = checkReliable(args);
+            boolean waitForAcks = checkWaitForAcks(args);
+
+            dpf =
+                    TheParticipantFactory.WithArgs(new StringSeqHolder(args));
+            if (dpf == null) {
+                System.err.println("ERROR: Domain Participant Factory not found");
+                return;
+            }
+            dp = dpf.create_participant(4,
+                    PARTICIPANT_QOS_DEFAULT.get(), null, DEFAULT_STATUS_MASK.value);
+            if (dp == null) {
+                System.err.println("ERROR: Domain Participant creation failed");
+                return;
+            }
+
+            servant = new MessageTypeSupportImpl();
+            if (servant.register_type(dp, "") != RETCODE_OK.value) {
+                System.err.println("ERROR: register_type failed");
+                return;
+            }
+
+            top = dp.create_topic("Movie Discussion List",
+                    servant.get_type_name(),
+                    TOPIC_QOS_DEFAULT.get(),
+                    null,
+                    DEFAULT_STATUS_MASK.value);
+            if (top == null) {
+                System.err.println("ERROR: Topic creation failed");
+                return;
+            }
+
+            pub = dp.create_publisher(PUBLISHER_QOS_DEFAULT.get(), null,
+                    DEFAULT_STATUS_MASK.value);
+            if (pub == null) {
+                System.err.println("ERROR: Publisher creation failed");
+                return;
+            }
+
+            // Use the default transport configuration (do nothing)
+
+            dw_qos = new DataWriterQos();
+            dw_qos.durability = new DurabilityQosPolicy();
+            dw_qos.durability.kind = DurabilityQosPolicyKind.from_int(0);
+            dw_qos.durability_service = new DurabilityServiceQosPolicy();
+            dw_qos.durability_service.history_kind = HistoryQosPolicyKind.from_int(0);
+            dw_qos.durability_service.service_cleanup_delay = new Duration_t();
+            dw_qos.deadline = new DeadlineQosPolicy();
+            dw_qos.deadline.period = new Duration_t();
+            dw_qos.latency_budget = new LatencyBudgetQosPolicy();
+            dw_qos.latency_budget.duration = new Duration_t();
+            dw_qos.liveliness = new LivelinessQosPolicy();
+            dw_qos.liveliness.kind = LivelinessQosPolicyKind.from_int(0);
+            dw_qos.liveliness.lease_duration = new Duration_t();
+            dw_qos.reliability = new ReliabilityQosPolicy();
+            dw_qos.reliability.kind = ReliabilityQosPolicyKind.from_int(0);
+            dw_qos.reliability.max_blocking_time = new Duration_t();
+            dw_qos.destination_order = new DestinationOrderQosPolicy();
+            dw_qos.destination_order.kind = DestinationOrderQosPolicyKind.from_int(0);
+            dw_qos.history = new HistoryQosPolicy();
+            dw_qos.history.kind = HistoryQosPolicyKind.from_int(0);
+            dw_qos.resource_limits = new ResourceLimitsQosPolicy();
+            dw_qos.transport_priority = new TransportPriorityQosPolicy();
+            dw_qos.lifespan = new LifespanQosPolicy();
+            dw_qos.lifespan.duration = new Duration_t();
+            dw_qos.user_data = new UserDataQosPolicy();
+            dw_qos.user_data.value = new byte[0];
+            dw_qos.ownership = new OwnershipQosPolicy();
+            dw_qos.ownership.kind = OwnershipQosPolicyKind.from_int(0);
+            dw_qos.ownership_strength = new OwnershipStrengthQosPolicy();
+            dw_qos.writer_data_lifecycle = new WriterDataLifecycleQosPolicy();
+            dw_qos.representation = new DataRepresentationQosPolicy();
+            dw_qos.representation.value = new short[0];
+
+            qosh = new DataWriterQosHolder(dw_qos);
+            pub.get_default_datawriter_qos(qosh);
+            qosh.value.history.kind = HistoryQosPolicyKind.KEEP_ALL_HISTORY_QOS;
+            if (reliable) {
+                qosh.value.reliability.kind =
+                        ReliabilityQosPolicyKind.RELIABLE_RELIABILITY_QOS;
+            }
+            dw = pub.create_datawriter(top,
+                    qosh.value,
+                    null,
+                    DEFAULT_STATUS_MASK.value);
+            if (dw == null) {
+                System.err.println("ERROR: DataWriter creation failed");
+                return;
+            }
+            System.out.println("Publisher Created DataWriter");
+
+            sc = dw.get_statuscondition();
+            sc.set_enabled_statuses(PUBLICATION_MATCHED_STATUS.value);
+            ws = new WaitSet();
+            ws.attach_condition(sc);
+            matched =
+                    new PublicationMatchedStatusHolder(new PublicationMatchedStatus());
+            timeout = new Duration_t(DURATION_INFINITE_SEC.value,
+                    DURATION_INFINITE_NSEC.value);
+
+
+
+            ws.detach_condition(sc);
+
+            mdw = MessageDataWriterHelper.narrow(dw);
+            // 等待匹配的逻辑保持原样
+            while (running) {
+                System.out.println("等待match中");
+                final int result = dw.get_publication_matched_status(matched);
+                if (result != RETCODE_OK.value) {
+                    System.err.println("ERROR: get_publication_matched_status()" +
+                            "failed.");
+                    return;
+                }
+                // 原有匹配等待逻辑...
+                if (matched.value.current_count >= 1) {
+                    System.out.println("Publisher Matched");
+                    isInitialized = true;
+                    break;
+                }
+                // 修改等待时间为有限等待
+                Duration_t timeout = new Duration_t(1, 0);
+                ConditionSeqHolder cond = new ConditionSeqHolder(new Condition[]{});
+                ws.wait(cond, timeout);
+            }
+
+            // 创建消息模板
+            Message template = new Message();
+            template.subject_id = 99;
+            instanceHandle = mdw.register_instance(template);
+
+            // 启动消息处理线程
+            executor.submit(this::processMessageQueue);
+
+        } catch (Exception e) {
+            // 异常处理...
+        }
+    }
+    public void publishMessage(String from, String subject, String text) {
+        if (!isInitialized) {
+            throw new IllegalStateException("Publisher not initialized");
+        }
+
+        Message msg = new Message();
+        msg.subject_id = 99;
+        msg.from = from;
+        msg.subject = subject;
+        msg.text = text;
+        msg.count = count++; // 根据需求调整
+
+        messageQueue.offer(msg); // 非阻塞式添加
+    }
+
+    private void processMessageQueue() {
+        try {
+            while (running) {
+                Message msg = messageQueue.poll(1, TimeUnit.SECONDS); // 带超时的获取
+                if (msg != null) {
+                    int ret;
+                    do {
+                        ret = mdw.write(msg, instanceHandle);
+                        if (ret != RETCODE_OK.value) {
+                            Thread.sleep(100); // 失败时短暂等待
+                        }
+                    } while (running && ret == RETCODE_TIMEOUT.value);
+                }
+            }
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+        }
+    }
+
+
+}

+ 189 - 0
src/main/java/com/example/backend/dds/TestSubscriber.java

@@ -0,0 +1,189 @@
+package com.example.backend.dds;/*
+ *
+ *
+ * Distributed under the OpenDDS License.
+ * See: http://www.opendds.org/license.html
+ */
+
+import DDS.*;
+import OpenDDS.DCPS.*;
+import org.omg.CORBA.StringSeqHolder;
+import Messenger.*;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class TestSubscriber {
+    private DomainParticipantFactory dpf;
+    private DomainParticipant dp;
+    private MessageTypeSupportImpl servant;
+    private Topic top;
+    private Subscriber sub;
+    private DataReaderQos dr_qos;
+    private DataReaderQosHolder qosh;
+    public DataReaderListenerImpl listener;
+    private DataReader dr;
+    private StatusCondition sc;
+    private WaitSet ws;
+    private SubscriptionMatchedStatusHolder matched;
+    private Duration_t timeout;
+    // 添加线程控制相关成员
+    private final ExecutorService executor = Executors.newSingleThreadExecutor();
+    private volatile boolean running = true;
+
+    public static boolean checkReliable(String[] args) {
+        for (int i = 0; i < args.length; ++i) {
+            if (args[i].equals("-r")) {
+                return true;
+            }
+        }
+        return false;
+    }
+    public TestSubscriber() throws Exception {
+        String[] s = new String[4];
+        s[0] = "-DCPSBit";
+        s[1] = "0";
+        s[2] = "-DCPSConfigFile";
+        s[3] = "D:/dds/open-dds_3.16/OpenDDS-3.16/OpenDDS-3.16/java/tests/messenger/tcp.ini";
+        executor.submit(() -> initialize(s));
+    }
+    public String getText(){
+        return listener.text;
+    }
+    private void initialize(String[] args) {
+        try {
+            // ... 保持原有初始化代码到创建DataReader为止...
+
+            System.out.println("Start Subscriber");
+            boolean reliable = checkReliable(args);
+
+            dpf =
+                    TheParticipantFactory.WithArgs(new StringSeqHolder(args));
+            if (dpf == null) {
+                System.err.println("ERROR: Domain Participant Factory not found");
+                return;
+            }
+            dp = dpf.create_participant(4,
+                    PARTICIPANT_QOS_DEFAULT.get(), null, DEFAULT_STATUS_MASK.value);
+            if (dp == null) {
+                System.err.println("ERROR: Domain Participant creation failed");
+                return;
+            }
+
+            servant = new MessageTypeSupportImpl();
+            if (servant.register_type(dp, "") != RETCODE_OK.value) {
+                System.err.println("ERROR: register_type failed");
+                return;
+            }
+            top = dp.create_topic("Movie Discussion List",
+                    servant.get_type_name(),
+                    TOPIC_QOS_DEFAULT.get(),
+                    null,
+                    DEFAULT_STATUS_MASK.value);
+            if (top == null) {
+                System.err.println("ERROR: Topic creation failed");
+                return;
+            }
+
+            sub = dp.create_subscriber(SUBSCRIBER_QOS_DEFAULT.get(),
+                    null, DEFAULT_STATUS_MASK.value);
+            if (sub == null) {
+                System.err.println("ERROR: Subscriber creation failed");
+                return;
+            }
+
+            // Use the default transport (do nothing)
+
+            dr_qos = new DataReaderQos();
+            dr_qos.durability = new DurabilityQosPolicy();
+            dr_qos.durability.kind = DurabilityQosPolicyKind.from_int(0);
+            dr_qos.deadline = new DeadlineQosPolicy();
+            dr_qos.deadline.period = new Duration_t();
+            dr_qos.latency_budget = new LatencyBudgetQosPolicy();
+            dr_qos.latency_budget.duration = new Duration_t();
+            dr_qos.liveliness = new LivelinessQosPolicy();
+            dr_qos.liveliness.kind = LivelinessQosPolicyKind.from_int(0);
+            dr_qos.liveliness.lease_duration = new Duration_t();
+            dr_qos.reliability = new ReliabilityQosPolicy();
+            dr_qos.reliability.kind = ReliabilityQosPolicyKind.from_int(0);
+            dr_qos.reliability.max_blocking_time = new Duration_t();
+            dr_qos.destination_order = new DestinationOrderQosPolicy();
+            dr_qos.destination_order.kind = DestinationOrderQosPolicyKind.from_int(0);
+            dr_qos.history = new HistoryQosPolicy();
+            dr_qos.history.kind = HistoryQosPolicyKind.from_int(0);
+            dr_qos.resource_limits = new ResourceLimitsQosPolicy();
+            dr_qos.user_data = new UserDataQosPolicy();
+            dr_qos.user_data.value = new byte[0];
+            dr_qos.ownership = new OwnershipQosPolicy();
+            dr_qos.ownership.kind = OwnershipQosPolicyKind.from_int(0);
+            dr_qos.time_based_filter = new TimeBasedFilterQosPolicy();
+            dr_qos.time_based_filter.minimum_separation = new Duration_t();
+            dr_qos.reader_data_lifecycle = new ReaderDataLifecycleQosPolicy();
+            dr_qos.reader_data_lifecycle.autopurge_nowriter_samples_delay = new Duration_t();
+            dr_qos.reader_data_lifecycle.autopurge_disposed_samples_delay = new Duration_t();
+            dr_qos.representation = new DataRepresentationQosPolicy();
+            dr_qos.representation.value = new short[0];
+
+            qosh = new DataReaderQosHolder(dr_qos);
+            sub.get_default_datareader_qos(qosh);
+            if (reliable) {
+                qosh.value.reliability.kind =
+                        ReliabilityQosPolicyKind.RELIABLE_RELIABILITY_QOS;
+            }
+            qosh.value.history.kind = HistoryQosPolicyKind.KEEP_ALL_HISTORY_QOS;
+
+            listener = new DataReaderListenerImpl();
+            dr = sub.create_datareader(top,
+                    qosh.value,
+                    listener,
+                    DEFAULT_STATUS_MASK.value);
+            if (dr == null) {
+                System.err.println("ERROR: DataReader creation failed");
+                return;
+            }
+
+            sc = dr.get_statuscondition();
+            sc.set_enabled_statuses(SUBSCRIPTION_MATCHED_STATUS.value);
+            ws = new WaitSet();
+            ws.attach_condition(sc);
+            matched =
+                    new SubscriptionMatchedStatusHolder(new SubscriptionMatchedStatus());
+
+//        timeout = new Duration_t(DURATION_INFINITE_SEC.value,
+//                DURATION_INFINITE_NSEC.value);
+
+            boolean matched_pub = false;
+
+
+             timeout = new Duration_t(1, 0); // 1秒超时
+
+            while (running) {
+                final int result = dr.get_subscription_matched_status(matched);
+                if (result != RETCODE_OK.value) {
+                    System.err.println("ERROR: get_subscription_matched_status() failed");
+                    break;
+                }
+
+                if (matched.value.current_count > 0) {
+                    System.out.println("Subscriber Matched");
+                    break;
+                }
+
+                ConditionSeqHolder cond = new ConditionSeqHolder(new Condition[]{});
+                if (ws.wait(cond, timeout) != RETCODE_OK.value && running) {
+                    System.err.println("ERROR: wait() failed");
+                    break;
+                }
+            }
+
+            System.out.println("Subscriber initialization completed");
+
+        } catch (Exception e) {
+            if (running) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+}

+ 57 - 0
src/main/java/com/example/backend/exception/GlobalExceptionHandler.java

@@ -0,0 +1,57 @@
+package com.example.backend.exception;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.context.request.WebRequest;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@RestControllerAdvice
+public class GlobalExceptionHandler {
+    
+    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+    
+    @ExceptionHandler(Exception.class)
+    public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex, WebRequest request) {
+        logger.error("未预期的错误", ex);
+        ErrorResponse error = new ErrorResponse(
+            HttpStatus.INTERNAL_SERVER_ERROR.value(),
+            "服务器内部错误",
+            ex.getMessage()
+        );
+        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
+    }
+    
+    @ExceptionHandler(ServiceException.class)
+    public ResponseEntity<ErrorResponse> handleServiceException(ServiceException ex) {
+        logger.error("服务异常", ex);
+        ErrorResponse error = new ErrorResponse(
+            HttpStatus.BAD_REQUEST.value(),
+            "服务异常",
+            ex.getMessage()
+        );
+        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
+    }
+    
+    @ExceptionHandler(ResourceNotFoundException.class)
+    public ResponseEntity<ErrorResponse> handleResourceNotFound(ResourceNotFoundException ex) {
+        ErrorResponse error = new ErrorResponse(
+            HttpStatus.NOT_FOUND.value(),
+            "资源未找到",
+            ex.getMessage()
+        );
+        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
+    }
+    
+    @Data
+    @AllArgsConstructor
+    public static class ErrorResponse {
+        private int status;
+        private String message;
+        private String details;
+    }
+}

+ 12 - 0
src/main/java/com/example/backend/exception/ResourceNotFoundException.java

@@ -0,0 +1,12 @@
+package com.example.backend.exception;
+
+public class ResourceNotFoundException extends RuntimeException {
+    
+    public ResourceNotFoundException(String message) {
+        super(message);
+    }
+    
+    public ResourceNotFoundException(String message, Throwable cause) {
+        super(message, cause);
+    }
+} 

+ 11 - 0
src/main/java/com/example/backend/exception/ServiceException.java

@@ -0,0 +1,11 @@
+package com.example.backend.exception;
+
+public class ServiceException extends RuntimeException {
+    public ServiceException(String message) {
+        super(message);
+    }
+    
+    public ServiceException(String message, Throwable cause) {
+        super(message, cause);
+    }
+} 

+ 69 - 0
src/main/java/com/example/backend/model/Message.java

@@ -0,0 +1,69 @@
+package com.example.backend.model;
+
+public class Message {
+    String Time;
+
+    public String getTime() {
+        return Time;
+    }
+
+    public Message(String time, String send, String topic, String text, String isSend) {
+        Time = time;
+        this.send = send;
+        this.topic = topic;
+        this.text = text;
+        this.isSend = isSend;
+    }
+
+    public void setTime(String time) {
+        Time = time;
+    }
+
+    public String getSend() {
+        return send;
+    }
+
+    public void setSend(String send) {
+        this.send = send;
+    }
+
+    public String getTopic() {
+        return topic;
+    }
+
+    public void setTopic(String topic) {
+        this.topic = topic;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public void setText(String text) {
+        this.text = text;
+    }
+
+    String send;
+    String topic;
+    String text;
+
+    public String getRecivier() {
+        return recivier;
+    }
+
+    public void setRecivier(String recivier) {
+        this.recivier = recivier;
+    }
+
+    String recivier;
+
+    public String getIsSend() {
+        return isSend;
+    }
+
+    public void setIsSend(String isSend) {
+        this.isSend = isSend;
+    }
+
+    String isSend = "0";
+}

+ 32 - 0
src/main/java/com/example/backend/model/MessageStatus.java

@@ -0,0 +1,32 @@
+package com.example.backend.model;
+
+public class MessageStatus {
+    public String startUp = "开";//链路开关状态
+
+    public String getStartUp() {
+        return startUp;
+    }
+
+    public void setStartUp(String startUp) {
+        this.startUp = startUp;
+    }
+
+    public String getQuite() {
+        return quite;
+    }
+
+    public void setQuite(String quite) {
+        this.quite = quite;
+    }
+
+    public String getMode() {
+        return mode;
+    }
+
+    public void setMode(String mode) {
+        this.mode = mode;
+    }
+
+    public String quite = "非静默";//静默状态
+    public String mode = "实时性";//传输模式
+}

+ 22 - 0
src/main/java/com/example/backend/model/Platform.java

@@ -0,0 +1,22 @@
+package com.example.backend.model;
+
+public class Platform {
+    public String getPlatformID() {
+        return platformID;
+    }
+
+    public void setPlatformID(String platformID) {
+        this.platformID = platformID;
+    }
+
+    public String getPlatformName() {
+        return platformName;
+    }
+
+    public void setPlatformName(String platformName) {
+        this.platformName = platformName;
+    }
+
+    public String platformID;
+    public String platformName;
+}

+ 59 - 0
src/main/java/com/example/backend/model/Position.java

@@ -0,0 +1,59 @@
+package com.example.backend.model;
+
+public class Position {
+    public double getX() {
+        return x;
+    }
+
+    public void setX(double x) {
+        this.x = x;
+    }
+
+    public double getY() {
+        return y;
+    }
+
+    public void setY(double y) {
+        this.y = y;
+    }
+
+    public double getZ() {
+        return z;
+    }
+
+    public void setZ(double z) {
+        this.z = z;
+    }
+
+    public double x=1;
+    public double y=1;
+    public double z=1;
+    public String coopID;
+
+    public String getCoopID() {
+        return coopID;
+    }
+
+    public void setCoopID(String coopID) {
+        this.coopID = coopID;
+    }
+
+    public String getJaming() {
+        return jaming;
+    }
+
+    public void setJaming(String jaming) {
+        this.jaming = jaming;
+    }
+
+    public String getIsReal() {
+        return isReal;
+    }
+
+    public void setIsReal(String isReal) {
+        this.isReal = isReal;
+    }
+
+    public String jaming;
+    public String isReal;
+}

+ 13 - 0
src/main/java/com/example/backend/model/RadarParam.java

@@ -0,0 +1,13 @@
+package com.example.backend.model;
+
+import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class RadarParam {
+    private String key;
+    private String value;
+} 

+ 169 - 0
src/main/java/com/example/backend/model/RadarStatus.java

@@ -0,0 +1,169 @@
+package com.example.backend.model;
+
+import java.util.Objects;
+import java.util.List;
+
+public class RadarStatus {
+    private String model;
+    private String serialNumber;
+    private String type;
+    private String connectionType;
+    private String startupTime;
+    private double detectionProbability;
+    private double falseAlarmRate;
+    private int scanCycle;
+    private int beamAzimuth;
+    private int beamElevation;
+    private double antennaGain;
+    private double sideLobeGain;
+    private String platformId;
+
+    // Getters and Setters
+
+    public String getModel() {
+        return model;
+    }
+
+    public void setModel(String model) {
+        this.model = model;
+    }
+
+    public String getSerialNumber() {
+        return serialNumber;
+    }
+
+    public void setSerialNumber(String serialNumber) {
+        this.serialNumber = serialNumber;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getConnectionType() {
+        return connectionType;
+    }
+
+    public void setConnectionType(String connectionType) {
+        this.connectionType = connectionType;
+    }
+
+    public String getStartupTime() {
+        return startupTime;
+    }
+
+    public void setStartupTime(String startupTime) {
+        this.startupTime = startupTime;
+    }
+
+    public double getDetectionProbability() {
+        return detectionProbability;
+    }
+
+    public void setDetectionProbability(double detectionProbability) {
+        this.detectionProbability = detectionProbability;
+    }
+
+    public double getFalseAlarmRate() {
+        return falseAlarmRate;
+    }
+
+    public void setFalseAlarmRate(double falseAlarmRate) {
+        this.falseAlarmRate = falseAlarmRate;
+    }
+
+    public int getScanCycle() {
+        return scanCycle;
+    }
+
+    public void setScanCycle(int scanCycle) {
+        this.scanCycle = scanCycle;
+    }
+
+    public int getBeamAzimuth() {
+        return beamAzimuth;
+    }
+
+    public void setBeamAzimuth(int beamAzimuth) {
+        this.beamAzimuth = beamAzimuth;
+    }
+
+    public int getBeamElevation() {
+        return beamElevation;
+    }
+
+    public void setBeamElevation(int beamElevation) {
+        this.beamElevation = beamElevation;
+    }
+
+    public double getAntennaGain() {
+        return antennaGain;
+    }
+
+    public void setAntennaGain(double antennaGain) {
+        this.antennaGain = antennaGain;
+    }
+
+    public double getSideLobeGain() {
+        return sideLobeGain;
+    }
+
+    public void setSideLobeGain(double sideLobeGain) {
+        this.sideLobeGain = sideLobeGain;
+    }
+
+    public String getPlatformId() {
+        return platformId;
+    }
+
+    public void setPlatformId(String platformId) {
+        this.platformId = platformId;
+    }
+
+    @Override
+    public String toString() {
+        return "RadarStatus{" +
+                "model='" + model + '\'' +
+                ", serialNumber='" + serialNumber + '\'' +
+                ", type='" + type + '\'' +
+                ", connectionType='" + connectionType + '\'' +
+                ", startupTime='" + startupTime + '\'' +
+                ", detectionProbability=" + detectionProbability +
+                ", falseAlarmRate=" + falseAlarmRate +
+                ", scanCycle=" + scanCycle +
+                ", beamAzimuth=" + beamAzimuth +
+                ", beamElevation=" + beamElevation +
+                ", antennaGain=" + antennaGain +
+                ", sideLobeGain=" + sideLobeGain +
+                '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        RadarStatus that = (RadarStatus) o;
+        return Double.compare(that.detectionProbability, detectionProbability) == 0 &&
+                Double.compare(that.falseAlarmRate, falseAlarmRate) == 0 &&
+                scanCycle == that.scanCycle &&
+                beamAzimuth == that.beamAzimuth &&
+                beamElevation == that.beamElevation &&
+                Double.compare(that.antennaGain, antennaGain) == 0 &&
+                Double.compare(that.sideLobeGain, sideLobeGain) == 0 &&
+                model.equals(that.model) &&
+                serialNumber.equals(that.serialNumber) &&
+                type.equals(that.type) &&
+                connectionType.equals(that.connectionType) &&
+                startupTime.equals(that.startupTime);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(model, serialNumber, type, connectionType, startupTime, detectionProbability,
+                falseAlarmRate, scanCycle, beamAzimuth, beamElevation, antennaGain, sideLobeGain);
+    }
+}

+ 20 - 0
src/main/java/com/example/backend/model/RadarTarget.java

@@ -0,0 +1,20 @@
+package com.example.backend.model;
+
+import lombok.Data;
+import lombok.AllArgsConstructor;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class RadarTarget {
+    private String simTime;
+    private Integer targetId;
+    private String enemyPro;
+    private String flightState;
+    private String lightQuality;
+    private double targetAzi;
+    private double targetEle;
+    private double targetDistance;
+    private double targetRSpeed;
+} 

+ 51 - 0
src/main/java/com/example/backend/model/compMsg.java

@@ -0,0 +1,51 @@
+package com.example.backend.model;
+
+public class compMsg {
+    String topic;
+    String priority;
+
+    public String getTopic() {
+        return topic;
+    }
+
+    public void setTopic(String topic) {
+        this.topic = topic;
+    }
+
+    public String getPriority() {
+        return priority;
+    }
+
+    public void setPriority(String priority) {
+        this.priority = priority;
+    }
+
+    public String getIsBroadcast() {
+        return isBroadcast;
+    }
+
+    public void setIsBroadcast(String isBroadcast) {
+        this.isBroadcast = isBroadcast;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public void setText(String text) {
+        this.text = text;
+    }
+
+    public String getRecivier() {
+        return recivier;
+    }
+
+    public void setRecivier(String recivier) {
+        this.recivier = recivier;
+    }
+
+    String isBroadcast;
+    String text;
+    String recivier;
+}
+

+ 77 - 0
src/main/java/com/example/backend/model/disturbMsg.java

@@ -0,0 +1,77 @@
+package com.example.backend.model;
+
+public class disturbMsg {
+    String jaming;
+    String env;
+    String area;
+    String jamingPolicy;
+    String target;
+    String isCoop;
+    String PRI;
+
+    public String getJaming() {
+        return jaming;
+    }
+
+    public void setJaming(String jaming) {
+        this.jaming = jaming;
+    }
+
+    public String getEnv() {
+        return env;
+    }
+
+    public void setEnv(String env) {
+        this.env = env;
+    }
+
+    public String getArea() {
+        return area;
+    }
+
+    public void setArea(String area) {
+        this.area = area;
+    }
+
+    public String getJamingPolicy() {
+        return jamingPolicy;
+    }
+
+    public void setJamingPolicy(String jamingPolicy) {
+        this.jamingPolicy = jamingPolicy;
+    }
+
+    public String getTarget() {
+        return target;
+    }
+
+    public void setTarget(String target) {
+        this.target = target;
+    }
+
+    public String getIsCoop() {
+        return isCoop;
+    }
+
+    public void setIsCoop(String isCoop) {
+        this.isCoop = isCoop;
+    }
+
+    public String getPRI() {
+        return PRI;
+    }
+
+    public void setPRI(String PRI) {
+        this.PRI = PRI;
+    }
+
+    public String getRecivier() {
+        return recivier;
+    }
+
+    public void setRecivier(String recivier) {
+        this.recivier = recivier;
+    }
+
+    String recivier;
+}

+ 59 - 0
src/main/java/com/example/backend/model/ecmParams.java

@@ -0,0 +1,59 @@
+package com.example.backend.model;
+
+public class ecmParams {
+    String beginTime;
+    String invesStatus;
+
+    public String getBeginTime() {
+        return beginTime;
+    }
+
+    public void setBeginTime(String beginTime) {
+        this.beginTime = beginTime;
+    }
+
+    public String getInvesStatus() {
+        return invesStatus;
+    }
+
+    public void setInvesStatus(String invesStatus) {
+        this.invesStatus = invesStatus;
+    }
+
+    public String getJaming() {
+        return jaming;
+    }
+
+    public void setJaming(String jaming) {
+        this.jaming = jaming;
+    }
+
+    public String getParam1() {
+        return param1;
+    }
+
+    public void setParam1(String param1) {
+        this.param1 = param1;
+    }
+
+    public String getParam2() {
+        return param2;
+    }
+
+    public void setParam2(String param2) {
+        this.param2 = param2;
+    }
+
+    public String getParam3() {
+        return param3;
+    }
+
+    public void setParam3(String param3) {
+        this.param3 = param3;
+    }
+
+    String jaming;
+    String param1;
+    String param2;
+    String param3;
+}

+ 41 - 0
src/main/java/com/example/backend/model/ecmStatus.java

@@ -0,0 +1,41 @@
+package com.example.backend.model;
+
+public class ecmStatus {
+    String jamingPolicy;
+
+    public String getJamingPolicy() {
+        return jamingPolicy;
+    }
+
+    public void setJamingPolicy(String jamingPolicy) {
+        this.jamingPolicy = jamingPolicy;
+    }
+
+    public String getStartUp() {
+        return startUp;
+    }
+
+    public void setStartUp(String startUp) {
+        this.startUp = startUp;
+    }
+
+    public String getConnect() {
+        return connect;
+    }
+
+    public void setConnect(String connect) {
+        this.connect = connect;
+    }
+
+    public String getOpenTime() {
+        return openTime;
+    }
+
+    public void setOpenTime(String openTime) {
+        this.openTime = openTime;
+    }
+
+    String startUp;
+    String connect;
+    String openTime;
+}

+ 78 - 0
src/main/java/com/example/backend/model/radarPulseMsg.java

@@ -0,0 +1,78 @@
+package com.example.backend.model;
+
+public class radarPulseMsg {
+    String type;
+    String env;
+
+    public String getRecivier() {
+        return recivier;
+    }
+
+    public void setRecivier(String recivier) {
+        this.recivier = recivier;
+    }
+
+    String recivier;
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getEnv() {
+        return env;
+    }
+
+    public void setEnv(String env) {
+        this.env = env;
+    }
+
+    public String getLon() {
+        return lon;
+    }
+
+    public void setLon(String lon) {
+        this.lon = lon;
+    }
+
+    public String getLat() {
+        return lat;
+    }
+
+    public void setLat(String lat) {
+        this.lat = lat;
+    }
+
+    public String getH() {
+        return h;
+    }
+
+    public void setH(String h) {
+        this.h = h;
+    }
+
+    public String getFreq() {
+        return freq;
+    }
+
+    public void setFreq(String freq) {
+        this.freq = freq;
+    }
+
+    public String getPRI() {
+        return PRI;
+    }
+
+    public void setPRI(String PRI) {
+        this.PRI = PRI;
+    }
+
+    String lon;
+    String lat;
+    String h;
+    String freq;
+    String PRI;
+}

+ 458 - 0
src/main/java/com/example/backend/service/RadarStatusService.java

@@ -0,0 +1,458 @@
+package com.example.backend.service;
+
+import com.example.backend.dds.TestSubscriber;
+import com.example.backend.dds.TestPublisher;
+import com.example.backend.model.*;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.concurrent.*;
+
+import jakarta.annotation.PostConstruct;
+
+@Service
+public class RadarStatusService {
+
+    private static final Logger logger = LoggerFactory.getLogger(RadarStatusService.class);
+
+    ExecutorService e = Executors.newSingleThreadExecutor();
+    
+    private final Map<String, RadarStatus> platformRadarMap = new ConcurrentHashMap<>();
+    private final Map<String, List<RadarParam>> platformParamsMap = new ConcurrentHashMap<>();
+    private final Map<String, Queue<RadarTarget>> platformTargetsMap = new ConcurrentHashMap<>();
+    private final Map<String, MessageStatus> messageStatusMap = new ConcurrentHashMap<>();
+    private final Map<String, List<Message>> messageList = new ConcurrentHashMap<>();
+    private final Map<String, List<Message>> outmessageList = new ConcurrentHashMap<>();
+    private final Map<String, List<ecmParams>> ecmParamsList = new ConcurrentHashMap<>();
+    private final Map<String, ecmStatus> ecmStatusList = new ConcurrentHashMap<>();
+    public final TestSubscriber subscriber = new TestSubscriber();
+    public final TestPublisher publisher = new TestPublisher();
+
+    
+    // 设置队列最大容量
+    private static final int MAX_QUEUE_SIZE = 100;
+
+    public RadarStatusService() throws Exception {
+
+    }
+
+    @Async
+    @Scheduled(fixedRate = 6000) // 每3秒执行一次
+    public void checkInitStateTask() {
+        if (subscriber != null && subscriber.listener != null) {
+            try {//发送心跳信息
+                publisher.publishMessage(
+                        "2",
+                        "8",
+                        "这是心跳信息"
+                );
+
+            } catch (Exception e) {
+
+            }
+        synchronized (subscriber.listener) {
+            // 读写操作
+                // 根据你的具体业务逻辑判断状态
+                if(subscriber.listener.isInit==0){
+                    this.messageList.clear();
+                    this.messageStatusMap.clear();
+                    this.outmessageList.clear();
+                }
+                if (subscriber.listener.isInit==1&&subscriber.listener.isRecall==1) {
+                    try {
+                        subscriber.listener.isRecall=0;
+
+                        publisher.publishMessage(
+                                "2",
+                                "11",
+                                "这是初始化应答"
+                        );
+
+                    } catch (Exception e) {
+
+                    }  // 回复初始化应答
+                    subscriber.listener.isRecall=0;
+                    init();
+                }
+                if(subscriber.listener.isInit==0){
+                    //未初始化,发送初始化请求
+                    try {
+                        publisher.publishMessage(
+                                "2",
+                                "12",
+                                "这是初始化请求"
+                        );
+
+                    } catch (Exception e) {
+
+                    }  // 回复初始化应答
+                }
+            }
+        }
+    }
+
+    @PostConstruct
+    public void init() {
+        // 初始化默认平台的状态和参数
+        for(String key : subscriber.listener.positionMap.keySet()){
+            initializePlatform(key);
+        }
+
+    }
+
+    public Set<String> getPlatforms(){
+        return subscriber.listener.positionMap.keySet();
+    }
+
+    // 初始化平台数据
+    private void initializePlatform(String platformId) {
+        logger.info("初始化平台 {} 的数据", platformId);
+        platformRadarMap.put(platformId, initDefaultPlatform(platformId));
+        platformParamsMap.put(platformId, initDefaultParams());
+        Queue<RadarTarget> queue = new ConcurrentLinkedQueue<>();
+        queue.addAll(initDefaultTargets());
+        platformTargetsMap.put(platformId, queue);
+        MessageStatus m = new MessageStatus();
+        messageStatusMap.put(platformId,m);
+        //messageList.put(platformId,initDefaultMessage(platformId));
+        //outmessageList.put(platformId,initDefaultMessage(platformId));
+    }
+
+    public List<Map<String, Object>> getRadarStatus(String platformId) {
+        logger.info("获取平台 {} 的雷达状态", platformId);
+        RadarStatus status = platformRadarMap.computeIfAbsent(platformId, this::initDefaultPlatform);
+        return convertToKeyValueList(status);
+    }
+
+    public RadarStatus updateRadarStatus(String platformId, RadarStatus updatedStatus) {
+        if (updatedStatus == null) {
+            logger.error("尝试更新空的雷达状态");
+            throw new IllegalArgumentException("雷达状态不能为空");
+        }
+        logger.info("更新平台 {} 的雷达状态", platformId);
+        updatedStatus.setPlatformId(platformId);
+        platformRadarMap.put(platformId, updatedStatus);
+        try {
+            publisher.publishMessage(
+                    "RadarSystem",
+                    "DetectionUpdate",
+                    "XYH"
+            );
+
+        } catch (Exception e) {
+
+        }
+        return updatedStatus;
+    }
+
+    // 辅助方法,创建一个 key-value 对
+    private Map<String, Object> createKeyValue(String key, Object value) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("key", key);
+        map.put("value", value);
+        return map;
+    }
+
+    // 将雷达状态转换为前端需要的格式
+    private List<Map<String, Object>> convertToKeyValueList(RadarStatus status) {
+        List<Map<String, Object>> radarStatusList = new ArrayList<>();
+        
+        // 添加平台ID到返回数据中
+        radarStatusList.add(createKeyValue("平台编号", status.getPlatformId()));
+        
+        // 只包含雷达状态数据
+        radarStatusList.add(createKeyValue("型号", status.getModel()));
+        radarStatusList.add(createKeyValue("序号", status.getSerialNumber()));
+        radarStatusList.add(createKeyValue("类型", status.getType()));
+        radarStatusList.add(createKeyValue("连接方式", status.getConnectionType()));
+        radarStatusList.add(createKeyValue("开机时间", status.getStartupTime()));
+        radarStatusList.add(createKeyValue("发现概率(%)", status.getDetectionProbability()));
+        radarStatusList.add(createKeyValue("虚警率(%)", status.getFalseAlarmRate()));
+        radarStatusList.add(createKeyValue("扫描周期(s)", status.getScanCycle()));
+        radarStatusList.add(createKeyValue("波束指向方位角", status.getBeamAzimuth()));
+        radarStatusList.add(createKeyValue("波束指向俯仰角", status.getBeamElevation()));
+        radarStatusList.add(createKeyValue("天线最大增益(dB)", status.getAntennaGain()));
+        radarStatusList.add(createKeyValue("副瓣增益(dB)", status.getSideLobeGain()));
+        
+        return radarStatusList;
+    }
+
+    private RadarStatus initDefaultPlatform(String platformId) {
+        RadarStatus defaultStatus = new RadarStatus();
+        defaultStatus.setPlatformId(platformId);
+        defaultStatus.setModel("默认型号测试数据");
+        defaultStatus.setSerialNumber("000000");
+        defaultStatus.setType("默认类型");
+        defaultStatus.setConnectionType("TCP");
+        defaultStatus.setStartupTime("2024-01-01 00:00:00");
+        defaultStatus.setDetectionProbability(90.0);
+        defaultStatus.setFalseAlarmRate(0.1);
+        defaultStatus.setScanCycle(10);
+        defaultStatus.setBeamAzimuth(0);
+        defaultStatus.setBeamElevation(0);
+        defaultStatus.setAntennaGain(30.0);
+        defaultStatus.setSideLobeGain(-20.0);
+        return defaultStatus;
+    }
+
+    // 获取雷达参数
+    public List<RadarParam> getRadarParams(String platformId) {
+        logger.info("获取平台 {} 的雷达参数", platformId);
+        return platformParamsMap.computeIfAbsent(platformId, k -> {
+            logger.info("平台 {} 不存在,创建默认参数", platformId);
+            return initDefaultParams();
+        });
+    }
+
+    // 更新雷达参数
+    public List<RadarParam> updateRadarParams(String platformId, List<RadarParam> radarParams) {
+        if (radarParams == null || radarParams.isEmpty()) {
+            logger.error("尝试更新空的雷达参数列表");
+            throw new IllegalArgumentException("雷达参数不能为空");
+        }
+
+        logger.info("更新平台 {} 的雷达参数,参数数量: {}", platformId, radarParams.size());
+        // 验证参数的合法性
+        validateRadarParams(radarParams);
+        // 存储参数
+        platformParamsMap.put(platformId, new ArrayList<>(radarParams));
+        try {
+            publisher.publishMessage(
+                    "RadarSystem",
+                    "DetectionUpdate",
+                    "XYH"
+            );
+
+        } catch (Exception e) {
+
+        }
+        System.out.println(subscriber.getText());
+        return radarParams;
+    }
+
+    // 获取位置信息
+    public Position getPositionById(String platformId) {
+        for(String key : subscriber.listener.positionMap.keySet()){
+            if(key.equals(platformId)){
+                return subscriber.listener.positionMap.get(key);
+            }
+        }
+        return null;
+    }
+
+    // 验证雷达参数的合法性
+    private void validateRadarParams(List<RadarParam> params) {
+        if (params.stream().anyMatch(p -> p.getKey() == null || p.getKey().trim().isEmpty())) {
+            throw new IllegalArgumentException("参数键不能为空");
+        }
+        if (params.stream().anyMatch(p -> p.getValue() == null)) {
+            throw new IllegalArgumentException("参数值不能为空");
+        }
+    }
+
+    // 初始化默认参数
+    private List<RadarParam> initDefaultParams() {
+        List<RadarParam> defaultParams = new ArrayList<>();
+        defaultParams.add(new RadarParam("开关机状态", "打开"));
+        defaultParams.add(new RadarParam("抗干扰措施", "频率捷变"));
+        defaultParams.add(new RadarParam("工作模式", "搜索"));
+        defaultParams.add(new RadarParam("脉冲参数", "自动"));
+        defaultParams.add(new RadarParam("方位扫描中心(°)", "0"));
+        defaultParams.add(new RadarParam("俯仰扫描中心(°)", "0"));
+        defaultParams.add(new RadarParam("波束宽度(°)", "2"));
+        defaultParams.add(new RadarParam("方位扫描范围(°)", "10"));
+        defaultParams.add(new RadarParam("俯仰扫描范围(°)", "10"));
+        defaultParams.add(new RadarParam("发射机功率(W)", "100"));
+        return defaultParams;
+    }
+
+    // 修改获取目标数据的方法
+    public List<RadarTarget> getRadarTargets(String platformId) {
+        logger.info("获取平台 {} 的目标数据", platformId);
+        Queue<RadarTarget> queue = platformTargetsMap.computeIfAbsent(platformId, k -> {
+            logger.info("平台 {} 不存在,创建默认目标数据队列", platformId);
+            Queue<RadarTarget> newQueue = new ConcurrentLinkedQueue<>();
+            newQueue.addAll(initDefaultTargets());
+            return newQueue;
+        });
+        return new ArrayList<>(queue);
+    }
+
+    // 修改更新目标数据的方法
+    public List<RadarTarget> updateRadarTargets(String platformId, List<RadarTarget> targets) {
+        if (targets == null || targets.isEmpty()) {
+            logger.error("尝试更新空的目标数据列表");
+            throw new IllegalArgumentException("目标数据不能为空");
+        }
+
+        logger.info("更新平台 {} 的目标数据,目标数量: {}", platformId, targets.size());
+        validateRadarTargets(targets);
+
+        Queue<RadarTarget> queue = platformTargetsMap.computeIfAbsent(
+            platformId, 
+            k -> new ConcurrentLinkedQueue<>()
+        );
+
+        // 添加新数据到队列
+        for (RadarTarget target : targets) {
+            queue.offer(target);
+            // 如果队列超出最大容量,移除最旧的数据
+            while (queue.size() > MAX_QUEUE_SIZE) {
+                queue.poll();
+            }
+        }
+
+        return new ArrayList<>(queue);
+    }
+
+    // 添加清除目标数据的方法
+    public void clearRadarTargets(String platformId) {
+        logger.info("清除平台 {} 的目标数据", platformId);
+        Queue<RadarTarget> queue = platformTargetsMap.get(platformId);
+        if (queue != null) {
+            queue.clear();
+        }
+    }
+
+    // 添加获取队列大小的方法
+    public int getRadarTargetsCount(String platformId) {
+        Queue<RadarTarget> queue = platformTargetsMap.get(platformId);
+        return queue != null ? queue.size() : 0;
+    }
+
+    // 验证目标数据的合法性
+    private void validateRadarTargets(List<RadarTarget> targets) {
+        for (RadarTarget target : targets) {
+            if (target.getTargetId() == null) {
+                throw new IllegalArgumentException("目标ID不能为空");
+            }
+            if (target.getSimTime() == null || target.getSimTime().trim().isEmpty()) {
+                throw new IllegalArgumentException("仿真时间不能为空");
+            }
+        }
+    }
+
+    //获取消息数据 链路状态相关方法
+    public MessageStatus getMsgStatusById(String PlatformID){
+        return messageStatusMap.get(PlatformID);
+    }
+
+    public void setMsgStatusById(String PlatformID,MessageStatus m){
+        messageStatusMap.put(PlatformID,m);
+    }
+
+    public List<Message> getMsgListById(String PlatformID){
+        return subscriber.listener.messageList.get(PlatformID);
+    }
+
+    public void setMsgListById(String PlatformID,Message m){
+        List<Message> list = messageList.get(PlatformID);
+        list.add(m);
+        messageList.put(PlatformID,list);
+    }
+
+    public List<Message> getOutMsgListById(String PlatformID){
+        return outmessageList.get(PlatformID);
+    }
+
+    public void setOutMsgListById(String PlatformID,Message m){
+        List<Message> list = outmessageList.get(PlatformID);
+        list.add(m);
+        outmessageList.put(PlatformID,list);
+    }
+//---------------------------------
+
+    //平台发送消息给平台方法
+    public void sendMessageToOther(String platformID,Message msg,String other,String subject){
+        publisher.publishMessage(platformID+" "+"3"+" "+other,subject,msg.getTime()+" "+msg.getTopic()+" "+msg.getText());
+    }
+
+    public void sendRadarPulseMsg(String platformID, radarPulseMsg msg,String recivier){
+        publisher.publishMessage(platformID+" "+"3"+" "+recivier,"5",msg.getType()+" "+msg.getEnv()+" "+msg.getLon()+" "+msg.getLat()+" "+msg.getH()+" "+msg.getFreq()+" "+msg.getPRI());
+        List<Message> list = outmessageList.get(platformID)==null ? new ArrayList<>() : outmessageList.get(platformID);
+        LocalDateTime now = LocalDateTime.now();
+
+        // 定义格式(例如:yyyy-MM-dd HH:mm:ss)
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+        // 格式化时间
+        String formattedDateTime = now.format(formatter);
+        list.add(new Message(formattedDateTime,platformID,"雷达脉冲",msg.getType()+" "+msg.getEnv()+" "+msg.getLon()+" "+msg.getLat()+" "+msg.getH()+" "+msg.getFreq()+" "+msg.getPRI(),"1"));
+        outmessageList.put(platformID,list);
+    }
+
+    public void sendDisturbMsg(String platformID, disturbMsg msg,String recivier){
+        publisher.publishMessage(platformID+" "+"3"+" "+recivier,"6",msg.getJaming()+" "+msg.getEnv()+" "+msg.getArea()+" "+msg.getJamingPolicy()+" "+msg.getTarget()+" "+msg.getIsCoop()+" "+msg.getPRI());
+        List<Message> list = outmessageList.get(platformID)==null ? new ArrayList<>() : outmessageList.get(platformID);
+        LocalDateTime now = LocalDateTime.now();
+
+        // 定义格式(例如:yyyy-MM-dd HH:mm:ss)
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+        // 格式化时间
+        String formattedDateTime = now.format(formatter);
+        list.add(new Message(formattedDateTime,platformID,"电子干扰",msg.getJaming()+" "+msg.getEnv()+" "+msg.getArea()+" "+msg.getJamingPolicy()+" "+msg.getTarget()+" "+msg.getIsCoop()+" "+msg.getPRI(),"1"));
+        outmessageList.put(platformID,list);
+    }
+
+    public void sendCompMsg(String platformID, compMsg msg,String recivier){
+        publisher.publishMessage(platformID+" "+"3"+" "+recivier,"7",msg.getTopic()+" "+msg.getPriority()+" "+msg.getIsBroadcast()+" "+msg.getText());
+
+        List<Message> list = outmessageList.get(platformID)==null ? new ArrayList<>() : outmessageList.get(platformID);
+        LocalDateTime now = LocalDateTime.now();
+
+        // 定义格式(例如:yyyy-MM-dd HH:mm:ss)
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+        // 格式化时间
+        String formattedDateTime = now.format(formatter);
+        list.add(new Message(formattedDateTime,platformID,"综合情报",msg.getTopic()+" "+msg.getPriority()+" "+msg.getIsBroadcast()+" "+msg.getText(),"1"));
+        outmessageList.put(platformID,list);
+    }
+
+    //电子攻击相关方法\
+    public ecmStatus getECMStatusByID(String platformID){
+        return ecmStatusList.get(platformID);
+    }
+
+    public List<ecmParams> getECMParamsByID(String platformID){
+        return ecmParamsList.get(platformID);
+    }
+
+    // 初始化默认目标数据
+    private List<RadarTarget> initDefaultTargets() {
+        List<RadarTarget> defaultTargets = new ArrayList<>();
+        defaultTargets.add(new RadarTarget("14:37.15", 1, "我方", "后端数据测试", "高", 10, -50, 859, 5.4));
+        defaultTargets.add(new RadarTarget("14:33.40", 2, "未知", "后端数据测试", "低", 40, -70, 458, 10.1));
+        defaultTargets.add(new RadarTarget("14:38.55", 3, "可疑目标", "后端数据测试", "中", 120, -54, 269, 15.3));
+        defaultTargets.add(new RadarTarget("14:39.30", 4, "可疑目标", "后端数据测试", "中", 210, -60, 234, 22.5));
+        return defaultTargets;
+    }
+
+
+
+    private List<Message> initDefaultMessage(String platformID) {
+        List<Message> defaultMessage = new ArrayList<>();
+        defaultMessage.add(new Message("2025-4-1 12:00","100","综合情报","这是测试消息内容","0"));
+        defaultMessage.add(new Message("2025-4-1 12:00","100","综合情报","这是测试消息内容","1"));
+        defaultMessage.add(new Message("2025-4-1 12:00","100","综合情报","这是测试消息内容","0"));
+        return defaultMessage;
+    }
+
+
+    public String msgToNumber(String s){
+        if(s.equals("雷达脉冲")){
+            return "5";
+        }
+        else if(s.equals("电子干扰")){
+            return "6";
+        }
+        else return "7";
+    }
+}

+ 4 - 0
src/main/resources/application.properties

@@ -0,0 +1,4 @@
+spring.application.name=backend
+frontend.url=http://localhost:8082
+server.port=5100
+

+ 13 - 0
src/test/java/com/example/backend/BackendApplicationTests.java

@@ -0,0 +1,13 @@
+package com.example.backend;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+@SpringBootTest
+class BackendApplicationTests {
+
+    @Test
+    void contextLoads() {
+    }
+
+}