提交 96886500 作者: lixiaojuan

Initial commit

上级
/mvnw text eol=lf
*.cmd text eol=crlf
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/
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip
# 镜像仓库
## 版本 T1.0.0: T为测试版,R为稳定版
version="T1.0.0" # 可自定义
## 镜像仓库地址
domain="swr.cn-southwest-2.myhuaweicloud.com"
## 镜像分组,按部门区分
namespace="wd"
# 服务配置
## 部署节点的内网IP
internal_ip=server-1-95-14-24.ciglobal.cn
## 数据挂载根目录
root_dir="/zzsn"
## 需根据日志配置填写,比如:logback-spring.xml
svc_logs="/workspace/logs"
## 环境变量 test or prod
svc_env="test"
## 服务名
svc_name="excel-export-service"
## 服务端口
svc_port="8089"
# nacos配置
## 往nacos注册IP,配置文件使用变量 NACOS_REGISTER_IP
## nacos服务地址, 配置文件使用 NACOS_SERVER
nacos_server="server-1-95-77-159.ciglobal.cn:8848"
## nacos命名空间, 配置文件使用 NACOS_NAMESPACE
nacos_namespace="smartTest"
# 资源限制
## cpu
limit_cpu=1.0
limit_mem=2g
#!/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.4
#
# 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:]'
}
scriptDir="$(dirname "$0")"
scriptName="$(basename "$0")"
# 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 <"$scriptDir/.mvn/wrapper/maven-wrapper.properties"
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.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${scriptName#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
# Find the actual extracted directory name (handles snapshots where filename != directory name)
actualDistributionDir=""
# First try the expected directory name (for regular distributions)
if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then
if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then
actualDistributionDir="$distributionUrlNameMain"
fi
fi
# If not found, search for any directory with the Maven executable (for snapshots)
if [ -z "$actualDistributionDir" ]; then
# enable globbing to iterate over items
set +f
for dir in "$TMP_DOWNLOAD_DIR"/*; do
if [ -d "$dir" ]; then
if [ -f "$dir/bin/$MVN_CMD" ]; then
actualDistributionDir="$(basename "$dir")"
break
fi
fi
done
set -f
fi
if [ -z "$actualDistributionDir" ]; then
verbose "Contents of $TMP_DOWNLOAD_DIR:"
verbose "$(ls -la "$TMP_DOWNLOAD_DIR")"
die "Could not find Maven distribution directory in extracted archive"
fi
verbose "Found extracted Maven distribution directory: $actualDistributionDir"
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url"
mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
clean || :
exec_maven "$@"
<# : 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.4
@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 -eq $False) { "/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_M2_PATH = "$HOME/.m2"
if ($env:MAVEN_USER_HOME) {
$MAVEN_M2_PATH = "$env:MAVEN_USER_HOME"
}
if (-not (Test-Path -Path $MAVEN_M2_PATH)) {
New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null
}
$MAVEN_WRAPPER_DISTS = $null
if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) {
$MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists"
} else {
$MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists"
}
$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain"
$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::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
# Find the actual extracted directory name (handles snapshots where filename != directory name)
$actualDistributionDir = ""
# First try the expected directory name (for regular distributions)
$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain"
$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD"
if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) {
$actualDistributionDir = $distributionUrlNameMain
}
# If not found, search for any directory with the Maven executable (for snapshots)
if (!$actualDistributionDir) {
Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object {
$testPath = Join-Path $_.FullName "bin/$MVN_CMD"
if (Test-Path -Path $testPath -PathType Leaf) {
$actualDistributionDir = $_.Name
}
}
}
if (!$actualDistributionDir) {
Write-Error "Could not find Maven distribution directory in extracted archive"
}
Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir"
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -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"
<?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>3.2.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.zzsn</groupId>
<artifactId>excel-export-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>excel-export-service</name>
<description>excel-export-service</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
<spring-boot.version>3.2.4</spring-boot.version>
<spring-cloud.version>2023.0.1</spring-cloud.version>
<spring-cloud-alibaba.version>2023.0.1.0</spring-cloud-alibaba.version>
<spring-cloud-openfeign.version>4.1.0</spring-cloud-openfeign.version>
<fastjson.version>2.0.22</fastjson.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud Alibaba -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud OpenFeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-openfeign</artifactId>
<version>${spring-cloud-openfeign.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Cloud Alibaba Nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- Spring Cloud OpenFeign (必须显式引入) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- LoadBalancer (Feign需要) -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.1.2</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-spring-boot3-starter</artifactId>
<version>1.5.34</version>
</dependency>
<!--配置文件加密-->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
package com.zzsn.excelexportservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients(basePackages = "com.zzsn.excelexportservice.feign")
public class ExcelExportServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ExcelExportServiceApplication.class, args);
}
}
package com.zzsn.excelexportservice.config;
import feign.Request;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@Configuration
public class FeignConfig implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes == null) {
return; // 当前不是来自前端请求时(比如定时任务)就不加
}
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
String token = request.getHeader("Accesstoken"); // 或者 "token"
if (token != null) {
template.header("Accesstoken", token);
}
}
@Value("${feign.client.config.default.connectTimeout}")
private int connectTimeout;
@Value("${feign.client.config.default.readTimeout}")
private int readTimeout;
@Bean
public Request.Options options() {
return new Request.Options(
connectTimeout,
readTimeout
);
}
}
package com.zzsn.excelexportservice.controller;
import com.zzsn.excelexportservice.dto.ExportReq;
import com.zzsn.excelexportservice.service.ExcelExportService;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Author: lxj
* @Date: 2025/9/18 11:09
*/
@RestController
@RequestMapping("/export")
@RequiredArgsConstructor
public class ExcelExportController {
@Resource
private ExcelExportService excelExportService;
@PostMapping("/excel")
public void exportExcel(@RequestBody List<ExportReq> exportReqList, HttpServletRequest request, HttpServletResponse response) {
excelExportService.export(exportReqList,request, response);
}
}
package com.zzsn.excelexportservice.dto;
import lombok.Data;
import java.util.List;
/**
* @author bhl
* @date 2025-01-16 16:59:29
*/
@Data
public class AeiModuleVo {
private String searchWord;
/**
* 1 是一带一路 2 不是一带一路
*/
private String bri;
/**
* CONSTRUCTION:建设 INVESTMENT:投资
*/
private List<String> type;
private List<Integer> years;
/**
* 国家
*/
private String country;
/**
* sector
*/
private String sector;
private Integer pageSize;
private Integer currentPage;
private String sortField;
private String sortRule;
}
package com.zzsn.excelexportservice.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ColumnParamSeniorVo {
private String id;
private List<String> ids;
//专题id
private String subjectId;
//文章链接
private String url;
//专题标题
private String title;
//专题摘要
private String summary;
//内容
private String content;
//作者
private String author;
//发布时间
private String publishDate;
//来源
private String origin;
//得分
private String score;
//企业名称
private String enterpriseName;
//信息类型
private String InfoType;
//专题库类型
private String libraryType;
//置顶标识(0取消置顶 1置顶)
private Integer type;
private String sourceAddress;
//开始时间
private String startTime;
//结束时间
private String endTime;
//专题库类型(1:政策;2:领导讲话;3:专家观点;4:企业案例)
private Integer classificationType;
//审核操作(0:未审核 1:审核通过 2:审核未通过 3:暂定 默认值为0)
private List<Integer> checkStatusList;
private Integer checkStatus;
//删除标记(1:删除;0:保留)
private Integer deleteFlag = 0;
//用户id
private String userId;
//项目id、栏目id、栏目组id
private String columnId;
//是否音频、视频
private String video = "";
//搜索内容
private String searchInfo = "";
//排序的列 ["score"(相关性),"publishDate"(发布时间) "all"(综合)]
private String column = "publishDate";
//排序字段 [desc|asc]默认desc
private String order = "desc";
//页码
private Integer pageNo = 1;
//页大小
private Integer pageSize = 10;
//是否所有
private String ynAll = "";
//是否是栏目
private String ynChannel = "1";
//是否是项目
private String ynProject = "0";
//筛选的栏目id
private String channelId = "";
/**标签*/
List<Label> labels;
//关键词检索范围 [1标题 2正文 3 全部]
private Integer searchScope;
//精确度["精确"| --]
private String searchAccuracy;
//专家搜索类型(1全部、2姓名、3机构 4标签 5领域 6资讯)通过字典接口获取
private Integer searchType;
//操作类型 add .update
private String action;
//日期最大值
private String maxValue;
//字段
private String fields;
//倾向性
private String orientation;
//是否支持组合查询
private Boolean multiLabel =false;
//专家部门
private String department;
//专家部门
private String expertType;
//去除前几条
private Integer from = 0;
//栏目编码
private String flagCode;
//数据索引
private String index;
//专家分类id
private List<String> typeId;
//专家审核状态(默认查询待审核与审核通过)
private List<String> auditStatus = Arrays.asList("2");
//查询关键词
private String keyWords;
//人物id
private String uid;
//标签集合
private Map<String,List<LinkedHashMap>> tagList;
//是否核心
private Boolean ynCore = true;
//queryType 0 -500强 1-重点企业 2-智能写作专题 3-reits专题 4-栏目查询(四期服务参数要求)
private String queryType="4";
//开始日期
private String startDate="1900-01-01T00:00:00";
//查询资讯数量
private Integer articleNum;
//结束日期
private String endDate;
//查询热词个数
private Integer count;
//选中的资讯id集合
private List<String> articleIds;
/*
* 关键词
* */
private String keyword;
//图谱相关参数-节点层级、每种节点数量、每种节点占比
private String nodeId;
private String nodeLabel;
private String nodeName;
private Integer level = 1;
private Integer expertNodeNumber = 5;
private Integer institutionNodeNumber = 5;
private Integer keywordNodeNumber = 5;
private Integer researchAreaNodeNumber = 5;
private Integer expertNodeRatio = 20;
private Integer institutionNodeRatio = 20;
private Integer keywordNodeRatio = 20;
private Integer researchAreaNodeRatio = 20;
}
package com.zzsn.excelexportservice.dto;
import lombok.Data;
/**
* @Author: lxj
* @Date: 2025/4/28 10:20
*/
@Data
public class CountryReq {
private String country;
public CountryReq(String country) {
this.country = country;
}
// private List<Integer> yearList;
}
package com.zzsn.excelexportservice.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
import java.util.List;
/**
* @Author: lxj
* @Date: 2025/9/18 14:13
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ExportDataResponse<T> {
private int code;
private String msg;
private List<Header> headers;
private List<T> dataList;
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Header {
private String field;
private String title;
}
}
package com.zzsn.excelexportservice.dto;
import lombok.Data;
import java.util.Map;
/**
* @Author: lxj
* @Date: 2025/9/18 09:50
*/
@Data
public class ExportReq {
private String serviceName; // 要调用的业务服务名:order-service, user-service
private String apiPath; // 数据接口路径,例如 /user/list
private String fileName;
private String sheetName;
private String base64Img; // 图片base64编码
private Map<String, Object> queryParams; // 查询参数
}
\ No newline at end of file
package com.zzsn.excelexportservice.dto;
import lombok.Data;
/**
* 基础信息打上标签的实体对象
*/
@Data
public class Label {
//命中标识
private String hitRemarks;
//标签标识
private String labelMark;
//标签备注
private String labelRemarks;
//项目标签id
private String projectLabelId;
//关联标签id
private String relationId;
//关联标签名称
private String relationName;
//审核状态
private Integer status;
//得分
private Float score;
}
package com.zzsn.excelexportservice.dto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* @Author: lxj
* @Date: 2025/9/19 17:13
*/
public class RequestParamHelper {
private static final Logger log = LoggerFactory.getLogger(RequestParamHelper.class);
/**
* 安全获取 Map 参数,带默认值
*
* @param params 请求参数 Map
* @param key 参数 key
* @param <T> 返回类型
* @return 参数值或默认值
*/
@SuppressWarnings("unchecked")
public static <T> T getParam(Map<String, Object> params, String key) {
if (params == null || !params.containsKey(key)) {
return null;
}
Object val = params.get(key);
if (val == null) {
return null;
}
try {
return (T) val;
} catch (ClassCastException e) {
log.warn("参数 {} 类型不正确,期望 {}, 实际 {}", key, val.getClass().getName(), e.getMessage());
return null;
}
}
public static List<String> getListParam(Map<String, Object> params, String key) {
if (params == null || !params.containsKey(key)) {
return Collections.emptyList();
}
Object val = params.get(key);
// 如果已经是List类型,直接返回
if (val instanceof List) {
return (List<String>) val;
}
// 如果是字符串,尝试按逗号分割成列表
if (val instanceof String) {
String str = (String) val;
if (str.trim().isEmpty()) {
return Collections.emptyList();
}
return Arrays.asList(str.split(","));
}
// 其他情况返回空列表
return Collections.emptyList();
}
public static Integer getIntegerParam(Map<String, Object> params, String key) {
if (params == null || !params.containsKey(key)) {
return null;
}
Object val = params.get(key);
// 如果已经是List类型,直接返回
if (val instanceof Integer) {
return (Integer) val;
}
// 如果是字符串,尝试按逗号分割成列表
if (val instanceof String) {
String str = (String) val;
if (str.trim().isEmpty()) {
return Integer.valueOf(str);
}
return Integer.valueOf(str);
}
// 其他情况返回空列表
return null;
}
}
package com.zzsn.excelexportservice.dto;
import lombok.Data;
import java.io.Serializable;
/**
* @author kongliufeng
* @create 2021-11-08
*/
@Data
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
private int errorcode = 0;
private String msg;
private T model;
public Result() {
}
public static<T> Result<T> OK() {
Result<T> r = new Result<T>();
r.setErrorcode(0);
r.setMsg("success");
return r;
}
public static<T> Result<T> OK(T data) {
Result<T> r = new Result<T>();
r.setErrorcode(0);
r.setMsg("success");
r.setModel(data);
return r;
}
public static<T> Result<T> OK(String msg, T data) {
Result<T> r = new Result<T>();
r.setErrorcode(0);
r.setMsg(msg);
r.setModel(data);
return r;
}
public static<T> Result<T> error() {
Result<T> r = new Result<T>();
r.setErrorcode(1);
r.setMsg("fail");
return r;
}
public static<T> Result<T> error(String msg) {
Result<T> r = new Result<T>();
r.setErrorcode(1);
r.setMsg(msg);
return r;
}
public static<T> Result<T> error(String msg, T data) {
Result<T> r = new Result<T>();
r.setErrorcode(0);
r.setMsg(msg);
r.setModel(data);
return r;
}
}
package com.zzsn.excelexportservice.dto;
import lombok.Data;
import java.util.List;
/**
* @date 2022/6/20 16:50
*/
@Data
public class WorldTopAnalysis {
/**
*/
private String ids;
/**
*/
private String years;
/**
*/
private String industrys;
/**
*/
private String indexCode;
private List<String> socialCreditCode;
private String industries;
private Integer quarter;
private String typeId;
private List<String> year;
}
package com.zzsn.excelexportservice.exportStrategys;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zzsn.excelexportservice.dto.ColumnParamSeniorVo;
import com.zzsn.excelexportservice.dto.ExportDataResponse;
import com.zzsn.excelexportservice.dto.ExportReq;
import com.zzsn.excelexportservice.dto.RequestParamHelper;
import com.zzsn.excelexportservice.feign.CharacterFeign;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: lxj
* @Date: 2025/9/26 11:53
*/
@Component
public class CharacterStrategy implements ExportStrategy {
@Autowired
private CharacterFeign characterFeign;
private final Map<String, TriFunction<HttpServletRequest, Map<String, Object>, ExportReq, ExportDataResponse<?>>> pathMapping = new HashMap<>();
private final ObjectMapper mapper = new ObjectMapper();
@PostConstruct
public void init() {
register("/character/characterAnalysis/expertKeyWordsCloud/export/excel",
(request, queryParams, exportReq) ->
characterFeign.queryExportExcel(
mapper.convertValue(queryParams, ColumnParamSeniorVo.class)
));
register("/character/characterAnalysis/expertGraph/export/excel",
(request, queryParams, exportReq) ->
characterFeign.expertGraph(
mapper.convertValue(queryParams, ColumnParamSeniorVo.class)
));
register("/character/characterAnalysis/getExpertAcademicInformation/export/excel",
(request, queryParams, exportReq) ->{
String clbToken = request.getHeader("x-access-token");
if (clbToken == null || clbToken.isEmpty()) {
return new ExportDataResponse<>(2, "x-access-token 不能为空", Collections.emptyList(), Collections.emptyList());
}
return characterFeign.getExpertAcademicInformationExport(
RequestParamHelper.getParam(queryParams, "uid"),
request.getHeader("x-access-token"));
});
}
private void register(String path,
TriFunction<HttpServletRequest, Map<String, Object>, ExportReq, ExportDataResponse<?>> func) {
pathMapping.put(path, (request, queryParams, exportReq) -> {
try {
return func.apply(request, queryParams, exportReq);
} catch (Exception e) {
// Feign 调用异常或其他不可预期异常统一处理
return new ExportDataResponse<>(2, "调用 Character 接口失败:" + e.getMessage(),
Collections.emptyList(), Collections.emptyList());
}
});
}
@Override
public String getServiceName() {
return "character-analysis";
}
@Override
public String getApiPath() {
return null; // 所有接口由本策略处理
}
@Override
public ExportDataResponse<?> execute(HttpServletRequest request, Map<String, Object> queryParams, ExportReq exportReq) {
TriFunction<HttpServletRequest, Map<String, Object>, ExportReq, ExportDataResponse<?>> func =
pathMapping.get(exportReq.getApiPath());
if (func == null) {
return new ExportDataResponse<>(404, "未找到匹配的接口: " + exportReq.getApiPath(),
Collections.emptyList(), Collections.emptyList());
}
return func.apply(request, queryParams, exportReq);
}
}
package com.zzsn.excelexportservice.exportStrategys;
import com.alibaba.fastjson2.JSONObject;
import com.zzsn.excelexportservice.dto.ExportDataResponse;
import com.zzsn.excelexportservice.dto.ExportReq;
import com.zzsn.excelexportservice.dto.RequestParamHelper;
import com.zzsn.excelexportservice.service.CmsSearch;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* @Author: lxj
* @Date: 2025/9/25 16:51
*/
@Component
public class CmsSubjectRelationInfoStrategy implements ExportStrategy {
@Resource
private CmsSearch cmsSearch;
private final Map<String, TriFunction<HttpServletRequest, Map<String, Object>, ExportReq, ExportDataResponse<?>>> pathMapping = new HashMap<>();
@PostConstruct
public void init() {
register("/cms/cmsSubject/getSubjectRelationInfo/export/excel",
(request, queryParams, exportReq) -> {
String accesstoken = request.getHeader("Accesstoken");
String s = cmsSearch.getLdjh(
accesstoken,
RequestParamHelper.getParam(queryParams, "operationType"),
RequestParamHelper.getParam(queryParams, "leaderId"),
RequestParamHelper.getParam(queryParams, "subjectId"),
RequestParamHelper.getParam(queryParams, "pStartTime"),
RequestParamHelper.getParam(queryParams, "pEndTime"),
RequestParamHelper.getParam(queryParams, "limitNumber")
);
JSONObject jsonObject = JSONObject.parseObject(s);
if (jsonObject.getInteger("code") != 0) {
return new ExportDataResponse<>(jsonObject.getInteger("code"), jsonObject.getString("message"),
Collections.emptyList(), Collections.emptyList());
}
JSONObject model = jsonObject.getJSONObject("data").getJSONObject("model");
if (model == null || model.getJSONArray("rows") == null) {
return new ExportDataResponse<>(1, "接口返回数据为空", Collections.emptyList(), Collections.emptyList());
}
List<Object> rows = model.getJSONArray("rows");
List<ExportDataResponse.Header> headers = new ArrayList<>();
headers.add(new ExportDataResponse.Header("name", "热词"));
headers.add(new ExportDataResponse.Header("value", "词频"));
return new ExportDataResponse<>(0, "success", headers, rows);
});
// 以后可以继续 put 其他 CMS 导出接口
}
private void register(String path,
TriFunction<HttpServletRequest, Map<String, Object>, ExportReq, ExportDataResponse<?>> func) {
pathMapping.put(path, (request, queryParams, exportReq) -> {
try {
return func.apply(request, queryParams, exportReq);
} catch (com.dtflys.forest.exceptions.ForestRuntimeException fre) {
// Forest 调用异常,比如 token 过期或连接失败
return new ExportDataResponse<>(2, "调用 CMS 接口失败:" + fre.getMessage(),
Collections.emptyList(), Collections.emptyList());
} catch (Exception e) {
// 其他不可预期的异常
return new ExportDataResponse<>(3, "导出内部错误:" + e.getMessage(),
Collections.emptyList(), Collections.emptyList());
}
});
}
@Override
public String getServiceName() {
return "cms-server";
}
@Override
public String getApiPath() {
return null; // 所有接口由本策略处理
}
@Override
public ExportDataResponse<?> execute(HttpServletRequest request, Map<String, Object> queryParams, ExportReq exportReq) {
TriFunction<HttpServletRequest, Map<String, Object>, ExportReq, ExportDataResponse<?>> func =
pathMapping.get(exportReq.getApiPath());
if (func == null) {
return new ExportDataResponse<>(404, "未找到匹配的接口: " + exportReq.getApiPath(),
Collections.emptyList(), Collections.emptyList());
}
return func.apply(request, queryParams, exportReq);
}
}
package com.zzsn.excelexportservice.exportStrategys;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zzsn.excelexportservice.dto.*;
import com.zzsn.excelexportservice.feign.EnterpriseFeign;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author: lxj
* @Date: 2025/9/26 14:52
*/
@Component
public class EnterpriseStrategy implements ExportStrategy {
@Autowired
private EnterpriseFeign enterpriseFeign;
private final Map<String, TriFunction<HttpServletRequest, Map<String, Object>, ExportReq, ExportDataResponse<?>>> pathMapping = new HashMap<>();
private final ObjectMapper mapper = new ObjectMapper();
@PostConstruct
public void init() {
// 映射接口
register("/company/enterprise/detail/indexQuery/export/excel",
(request, queryParams, exportReq) -> enterpriseFeign.enterpriseIndexQueryExport(
RequestParamHelper.getParam(queryParams, "socialCreditCode"),
RequestParamHelper.getParam(queryParams, "indexType"),
RequestParamHelper.getParam(queryParams, "indexNames")
));
register("/company/enterpriseData/getOnListRecord/export/excel",
(request, queryParams, exportReq) -> enterpriseFeign.getOnListRecordExport(
RequestParamHelper.getParam(queryParams, "socialCreditCodes"),
RequestParamHelper.getParam(queryParams, "yearList"),
RequestParamHelper.getParam(queryParams, "lists"),
RequestParamHelper.getParam(queryParams, "type")
));
register("/company/finance_new/indexCompare/export/excel",
(request, queryParams, exportReq) -> enterpriseFeign.indexCompareExport(
RequestParamHelper.getListParam(queryParams, "socialCreditCode"),
RequestParamHelper.getListParam(queryParams, "year"),
RequestParamHelper.getParam(queryParams, "quarter"),
RequestParamHelper.getParam(queryParams, "indexCode")
));
register("/company/enterprise/rankList/getWorldTopAnalysis/export/excel",
(request, queryParams, exportReq) -> enterpriseFeign.getWorldTopAnalysis(
mapper.convertValue(queryParams, WorldTopAnalysis.class)
));
register("/company/finance_new/indexCompareByIndustry/export/excel",
(request, queryParams, exportReq) -> enterpriseFeign.indexCompareByIndustryExport(
mapper.convertValue(queryParams, WorldTopAnalysis.class),
RequestParamHelper.getParam(queryParams, "socialCreditCode"),
RequestParamHelper.getParam(queryParams, "year"),
RequestParamHelper.getParam(queryParams, "quarter"),
RequestParamHelper.getParam(queryParams, "industries"),
RequestParamHelper.getParam(queryParams, "indexCode")
));
register("/company/finance_new/coreIndexCompareByIndustry/export/excel",
(request, queryParams, exportReq) -> enterpriseFeign.coreIndexCompareByIndustryExport(
RequestParamHelper.getListParam(queryParams, "socialCreditCode"),
RequestParamHelper.getListParam(queryParams, "year"),
RequestParamHelper.getParam(queryParams, "industries"),
RequestParamHelper.getParam(queryParams, "indexName"),
RequestParamHelper.getParam(queryParams, "type")
));
register("/company/enterprise/rankList/getEnterpriseBenchmarking/export/excel",
(request, queryParams, exportReq) -> enterpriseFeign.getEnterpriseBenchmarkingExport(
mapper.convertValue(queryParams, WorldTopAnalysis.class),
RequestParamHelper.getParam(queryParams, "ids"),
RequestParamHelper.getParam(queryParams, "years"),
RequestParamHelper.getParam(queryParams, "industrys"),
RequestParamHelper.getParam(queryParams, "indexCode")
));
register("/company/enterprise/rankList/getTransnationalCompany/export/excel",
(request, queryParams, exportReq) -> enterpriseFeign.getTransnationalCompanyExport(
mapper.convertValue(queryParams, WorldTopAnalysis.class),
RequestParamHelper.getParam(queryParams, "ids"),
RequestParamHelper.getParam(queryParams, "years"),
RequestParamHelper.getParam(queryParams, "industrys"),
RequestParamHelper.getParam(queryParams, "indexCode")
));
register("/company/aei/pageList/export/excel",
(request, queryParams, exportReq) -> enterpriseFeign.getPageAndTotalExport(
RequestParamHelper.getParam(queryParams, "pageSize"),
RequestParamHelper.getParam(queryParams, "currentPage"),
mapper.convertValue(queryParams, AeiModuleVo.class)
));
}
private void register(String path,
TriFunction<HttpServletRequest, Map<String, Object>, ExportReq, ExportDataResponse<?>> func) {
pathMapping.put(path, (request, queryParams, exportReq) -> {
try {
return func.apply(request, queryParams, exportReq);
} catch (Exception e) {
// 返回统一业务错误码,前端可以显示提示
return new ExportDataResponse<>(2, "调用企业接口失败:" + e.getMessage(),
Collections.emptyList(), Collections.emptyList());
}
});
}
@Override
public String getServiceName() {
return "enterprise-service";
}
@Override
public String getApiPath() {
return null; // 所有接口由本策略处理
}
@Override
public ExportDataResponse<?> execute(HttpServletRequest request, Map<String, Object> queryParams, ExportReq exportReq) {
TriFunction<HttpServletRequest, Map<String, Object>, ExportReq, ExportDataResponse<?>> func =
pathMapping.get(exportReq.getApiPath());
if (func == null) {
return new ExportDataResponse<>(404, "未找到匹配的接口: " + exportReq.getApiPath(),
Collections.emptyList(), Collections.emptyList());
}
return func.apply(request, queryParams, exportReq);
}
}
package com.zzsn.excelexportservice.exportStrategys;
import com.zzsn.excelexportservice.dto.ExportDataResponse;
import com.zzsn.excelexportservice.dto.ExportReq;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Map;
/**
* @Author: lxj
* @Date: 2025/9/25 16:45
*/
public interface ExportStrategy {
/**
* 当前策略支持的 serviceName
*/
String getServiceName();
/**
* 当前策略支持的 apiPath
* - 如果返回 null,表示该 serviceName 下所有 apiPath 都交给它处理
* - 如果返回具体字符串,就只处理对应的 apiPath
*/
default String getApiPath() {
return null;
}
/**
* 执行导出逻辑
*/
ExportDataResponse<?> execute(HttpServletRequest request, Map<String, Object> queryParams, ExportReq exportReq);
}
package com.zzsn.excelexportservice.exportStrategys;
import com.zzsn.excelexportservice.dto.CountryReq;
import com.zzsn.excelexportservice.dto.ExportDataResponse;
import com.zzsn.excelexportservice.dto.ExportReq;
import com.zzsn.excelexportservice.feign.InternationalFeign;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.*;
/**
* @Author: lxj
* @Date: 2025/9/25 16:52
*/
@Component
public class InternationalStrategy implements ExportStrategy {
@Autowired
private InternationalFeign internationalFeign;
private final Map<String, TriFunction<HttpServletRequest, Map<String, Object>, ExportReq, ExportDataResponse<?>>> pathMapping = new HashMap<>();
@PostConstruct
public void init() {
List<String> postApiPaths = Arrays.asList(
"/international/country/merchandise/export/excel",
"/international/country/getTradeServ/export/excel",
"/international/country/getTradeServ/category/export/excel",
"/international/country/getTradeIndices/export/excel",
"/international/country/getEconomic/export/excel",
"/international/country/getEconomic/Expenditure/export/excel",
"/international/country/getFdiAndExternal/export/excel",
"/international/country/getFdiAndExternal/capitalFlow/export/excel",
"/international/country/getGoodsAndServ/export/excel",
"/international/country/getGoodsAndServ/openness/export/excel",
"/international/country/getLivingArea/export/excel",
"/international/country/getOther/export/excel",
"/international/country/getOther/economy/export/excel"
);
for (String path : postApiPaths) {
pathMapping.put(path, (request, queryParams, exportReq) -> {
try {
CountryReq req = new CountryReq((String) queryParams.get("country"));
switch (path) {
case "/international/country/merchandise/export/excel":
return internationalFeign.merchandiseExport(req);
case "/international/country/getTradeServ/export/excel":
return internationalFeign.getTradeServExport(req);
case "/international/country/getTradeServ/category/export/excel":
return internationalFeign.getTradeServCategoryExport(req);
case "/international/country/getTradeIndices/export/excel":
return internationalFeign.getTradeIndicesExport(req);
case "/international/country/getEconomic/export/excel":
return internationalFeign.getEconomicExport(req);
case "/international/country/getEconomic/Expenditure/export/excel":
return internationalFeign.getEconomicExpenditureExport(req);
case "/international/country/getFdiAndExternal/export/excel":
return internationalFeign.getFdiAndExternal(req);
case "/international/country/getFdiAndExternal/capitalFlow/export/excel":
return internationalFeign.getFdiAndExternalCapitalFlowExport(req);
case "/international/country/getGoodsAndServ/export/excel":
return internationalFeign.getGoodsAndServExport(req);
case "/international/country/getGoodsAndServ/openness/export/excel":
return internationalFeign.getGoodsAndServOpennessExport(req);
case "/international/country/getLivingArea/export/excel":
return internationalFeign.getLivingAreaExport(req);
case "/international/country/getOther/export/excel":
return internationalFeign.getOtherExport(req);
case "/international/country/getOther/economy/export/excel":
return internationalFeign.getOtherEconomyExport(req);
default:
return new ExportDataResponse<>(404, "未找到匹配的接口", Collections.emptyList(), Collections.emptyList());
}
} catch (Exception e) {
// 不抛 500,返回业务错误码 2,前端可以根据 msg 显示提示
return new ExportDataResponse<>(2, "调用国际接口失败:" + e.getMessage(), Collections.emptyList(), Collections.emptyList());
}
});
}
// 特殊接口:@RequestParam String country
pathMapping.put("/international/country/generalInfo/export/excel",
(request, queryParams, exportReq) -> {
try {
String country = (String) queryParams.get("country");
return internationalFeign.getCountryInfoExport(country);
} catch (Exception e) {
return new ExportDataResponse<>(2, "调用国际化接口失败:" + e.getMessage(), Collections.emptyList(), Collections.emptyList());
}
});
}
@Override
public String getServiceName() {
return "international-operation";
}
/**
* 返回 null,表示所有 apiPath 由本类处理
*/
@Override
public String getApiPath() {
return null;
}
@Override
public ExportDataResponse<?> execute(HttpServletRequest request, Map<String, Object> queryParams, ExportReq exportReq) {
TriFunction<HttpServletRequest, Map<String, Object>, ExportReq, ExportDataResponse<?>> func =
pathMapping.get(exportReq.getApiPath());
if (func == null) {
throw new IllegalArgumentException("No mapping for apiPath: " + exportReq.getApiPath());
}
return func.apply(request, queryParams, exportReq);
}
}
package com.zzsn.excelexportservice.exportStrategys;
import com.alibaba.fastjson2.JSONObject;
import com.zzsn.excelexportservice.dto.ExportDataResponse;
import com.zzsn.excelexportservice.dto.ExportReq;
import com.zzsn.excelexportservice.dto.RequestParamHelper;
import com.zzsn.excelexportservice.feign.ResearchFeign;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: lxj
* @Date: 2025/9/25 16:50
*/
@Component
public class ResearchStrategy implements ExportStrategy {
@Autowired
private ResearchFeign zdqyFeign;
private final Map<String, TriFunction<HttpServletRequest, Map<String, Object>, ExportReq, ExportDataResponse<?>>> pathMapping = new HashMap<>();
@PostConstruct
public void init() {
// 热词趋势导出
register("/research/benchmark/analyse/getHotKeywordTendency/export/excel",
(request, queryParams, exportReq) -> zdqyFeign.getHotKeywordTendency(
RequestParamHelper.getParam(queryParams, "tid"),
RequestParamHelper.getParam(queryParams, "kids"),
RequestParamHelper.getParam(queryParams, "coids"),
RequestParamHelper.getParam(queryParams, "countryNames"),
RequestParamHelper.getParam(queryParams, "industryNames"),
RequestParamHelper.getParam(queryParams, "countryType"),
RequestParamHelper.getParam(queryParams, "topKids"),
RequestParamHelper.getParam(queryParams, "startDate"),
RequestParamHelper.getParam(queryParams, "endDate"),
RequestParamHelper.getParam(queryParams, "dateType"),
RequestParamHelper.getParam(queryParams, "weeks"),
RequestParamHelper.getParam(queryParams, "labels"),
RequestParamHelper.getParam(queryParams, "articleNum"),
RequestParamHelper.getParam(queryParams, "count"),
RequestParamHelper.getParam(queryParams, "queryType"),
RequestParamHelper.getParam(queryParams, "flagCode"),
RequestParamHelper.getParam(queryParams, "rankings"),
RequestParamHelper.getParam(queryParams, "columnId")
));
// 特殊关键词集导出
register("/research/special/universal/getKeyWordsSetById/export/excel",
(request, queryParams, exportReq) -> zdqyFeign.getKeyWordsSetById(
RequestParamHelper.getParam(queryParams, "id"),
RequestParamHelper.getParam(queryParams, "limitNumber"),
RequestParamHelper.getParam(queryParams, "keyWordsNum"),
RequestParamHelper.getParam(queryParams, "title")
));
// 热词列表导出
register("/research/benchmark/analyse/getHotKeywordList/export/excel",
(request, queryParams, exportReq) -> zdqyFeign.getHotKeywordListExport(
// String类型参数使用getStringParam避免类型转换错误
RequestParamHelper.getParam(queryParams, "tid"),
RequestParamHelper.getParam(queryParams, "kids"),
RequestParamHelper.getParam(queryParams, "coids"),
RequestParamHelper.getParam(queryParams, "countryNames"),
RequestParamHelper.getParam(queryParams, "industryNames"),
RequestParamHelper.getParam(queryParams, "labels"),
// Integer类型参数保持不变
RequestParamHelper.getIntegerParam(queryParams, "countryType"),
RequestParamHelper.getParam(queryParams, "startDate"),
RequestParamHelper.getParam(queryParams, "endDate"),
RequestParamHelper.getIntegerParam(queryParams, "dateType"),
RequestParamHelper.getIntegerParam(queryParams, "count"),
RequestParamHelper.getParam(queryParams, "queryType"),
RequestParamHelper.getParam(queryParams, "flagCode"),
RequestParamHelper.getParam(queryParams, "rankings"),
RequestParamHelper.getParam(queryParams, "columnId")
));
// 通用接口导出
register("/research/interface/query/export/excel",
(request, queryParams, exportReq) -> zdqyFeign.queryExportExcel(new JSONObject(queryParams)));
}
private void register(String path,
TriFunction<HttpServletRequest, Map<String, Object>, ExportReq, ExportDataResponse<?>> func) {
pathMapping.put(path, (request, queryParams, exportReq) -> {
try {
return func.apply(request, queryParams, exportReq);
} catch (Exception e) {
// Feign 调用异常或其他不可预期异常统一处理
return new ExportDataResponse<>(2, "调用 Research 接口失败:" + e.getMessage(),
Collections.emptyList(), Collections.emptyList());
}
});
}
@Override
public String getServiceName() {
return "research-center-fourth-server";
}
@Override
public String getApiPath() {
return null; // 所有接口由本策略处理
}
@Override
public ExportDataResponse<?> execute(HttpServletRequest request, Map<String, Object> queryParams, ExportReq exportReq) {
TriFunction<HttpServletRequest, Map<String, Object>, ExportReq, ExportDataResponse<?>> func =
pathMapping.get(exportReq.getApiPath());
if (func == null) {
return new ExportDataResponse<>(404, "未找到匹配的接口: " + exportReq.getApiPath(),
Collections.emptyList(), Collections.emptyList());
}
return func.apply(request, queryParams, exportReq);
}
}
\ No newline at end of file
package com.zzsn.excelexportservice.exportStrategys;
/**
* @Author: lxj
* @Date: 2025/9/25 17:10
*/
@FunctionalInterface
public interface TriFunction<T, U, V, R> {
R apply(T t, U u, V v);
}
package com.zzsn.excelexportservice.factorys;
import com.zzsn.excelexportservice.exportStrategys.ExportStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author: lxj
* @Date: 2025/9/25 17:11
*/
@Component
public class ExportStrategyFactory {
private final Map<String, ExportStrategy> strategyMap = new HashMap<>();
@Autowired
public ExportStrategyFactory(List<ExportStrategy> strategies) {
for (ExportStrategy strategy : strategies) {
String key;
if (strategy.getApiPath() == null) {
// 该 serviceName 下所有 apiPath 都由它处理
key = strategy.getServiceName();
} else {
key = strategy.getServiceName() + "#" + strategy.getApiPath();
}
strategyMap.put(key, strategy);
}
}
public ExportStrategy getStrategy(String serviceName, String apiPath) {
// 优先查具体路径
ExportStrategy strategy = strategyMap.get(serviceName + "#" + apiPath);
if (strategy != null) {
return strategy;
}
// 退化查 serviceName 级别(表示该 serviceName 全部交给某个策略)
return strategyMap.get(serviceName);
}
}
package com.zzsn.excelexportservice.feign;
/**
* @Author: lxj
* @Date: 2025/9/26 11:46
*/
import com.zzsn.excelexportservice.dto.ColumnParamSeniorVo;
import com.zzsn.excelexportservice.dto.ExportDataResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.cloud.openfeign.SpringQueryMap;
import org.springframework.web.bind.annotation.*;
/**
* @Author: lxj
* @Date: 2025/9/26 11:46
*/
@FeignClient(name = "character-analysis"
, url = "${excel.export.services.character-analysis.data-url}"
)
public interface CharacterFeign {
@PostMapping("/character/characterAnalysis/expertKeyWordsCloud/export/excel")
ExportDataResponse queryExportExcel(@RequestBody ColumnParamSeniorVo columnParamVO);
@PostMapping("/character/characterAnalysis/expertGraph/export/excel")
ExportDataResponse expertGraph(@RequestBody ColumnParamSeniorVo columnParamVO);
@GetMapping("/character/characterAnalysis/getExpertAcademicInformation/export/excel")
ExportDataResponse<?> getExpertAcademicInformationExport(
@RequestParam("uid") String uid,
@RequestHeader("x-access-token") String clbToken
);
}
package com.zzsn.excelexportservice.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
/**
* @Author: lxj
* @Date: 2025/9/26 14:09
*/
//@FeignClient(name = "research-center-fourth-server"
//// , url = "${excel.export.services.research-center-fourth-server.data-url}"
//)
//public interface ClbColumFeign {
// @PostMapping("/channel/datapull/column/getEnterpriseDynamicNum")
//}
package com.zzsn.excelexportservice.feign;
import com.zzsn.excelexportservice.dto.AeiModuleVo;
import com.zzsn.excelexportservice.dto.ExportDataResponse;
import com.zzsn.excelexportservice.dto.WorldTopAnalysis;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
/**
* @Author: lxj
* @Date: 2025/9/26 14:14
*/
@FeignClient(name = "enterprise-service"
, url = "${excel.export.services.enterprise-service.data-url}"
)
public interface EnterpriseFeign {
@GetMapping("/company/enterprise/detail/indexQuery/export/excel")
ExportDataResponse enterpriseIndexQueryExport(
@RequestParam("socialCreditCode") String socialCreditCode,
@RequestParam("indexType") Integer indexType,
@RequestParam(value = "indexNames", required = false) String indexNames
);
@GetMapping("/company/enterpriseData/getOnListRecord/export/excel")
ExportDataResponse<?> getOnListRecordExport(
@RequestParam("socialCreditCodes") String socialCreditCodes,
@RequestParam("yearList") String yearList,
@RequestParam("lists") String lists,
@RequestParam("type") String type
);
@GetMapping("/company/finance_new/indexCompare/export/excel")
ExportDataResponse<?> indexCompareExport(
@RequestParam("socialCreditCode") List<String> socialCreditCodes,
@RequestParam("year") List<String> years,
@RequestParam("quarter") Integer quarter,
@RequestParam("indexCode") String indexCode
);
@PostMapping("/company/enterprise/rankList/getWorldTopAnalysis/export/excel")
ExportDataResponse<?> getWorldTopAnalysis(
@RequestBody WorldTopAnalysis worldTopAnalysis
);
@PostMapping("/company/finance_new/indexCompareByIndustry/export/excel")
ExportDataResponse<?> indexCompareByIndustryExport(
@RequestBody(required = false) WorldTopAnalysis worldTopAnalysis,
@RequestParam(value = "socialCreditCode", required = false) List<String> socialCreditCodes,
@RequestParam(value = "year", required = false) List<String> years,
@RequestParam(value = "quarter", required = false) Integer quarter,
@RequestParam(value = "industries", required = false) String industry,
@RequestParam(value = "indexCode", required = false) String indexCode
);
@GetMapping("/company/finance_new/coreIndexCompareByIndustry/export/excel")
ExportDataResponse<?> coreIndexCompareByIndustryExport(
@RequestParam(value = "socialCreditCode", required = false) List<String> socialCreditCodes,
@RequestParam("year") List<String> years,
@RequestParam(value = "industries", required = false) String industry,
@RequestParam("indexName") String indexName,
@RequestParam("type") String type
);
@PostMapping("/company/enterprise/rankList/getEnterpriseBenchmarking/export/excel")
ExportDataResponse getEnterpriseBenchmarkingExport(
@RequestBody WorldTopAnalysis worldTopAnalysis,
@RequestParam("ids") String ids,
@RequestParam("years") String years,
@RequestParam("industrys") String industrys,
@RequestParam("indexCode") String indexCode
);
@PostMapping("/company/enterprise/rankList/getTransnationalCompany/export/excel")
ExportDataResponse getTransnationalCompanyExport(
@RequestBody WorldTopAnalysis worldTopAnalysis,
@RequestParam("ids") String ids,
@RequestParam("years") String years,
@RequestParam("industrys") String industrys,
@RequestParam("indexCode") String indexCode
);
@PostMapping("/company/aei/pageList/export/excel")
ExportDataResponse getPageAndTotalExport(
@RequestParam("pageSize") Integer pageSize,
@RequestParam( "currentPage") Integer currentPage,
@RequestBody AeiModuleVo aeiModuleVo
);
}
package com.zzsn.excelexportservice.feign;
import com.zzsn.excelexportservice.dto.CountryReq;
import com.zzsn.excelexportservice.dto.ExportDataResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @Author: lxj
* @Date: 2025/9/25 16:15
*/
@FeignClient(name = "international-operation"
, url = "${excel.export.services.international-operation.data-url}"
)
public interface InternationalFeign {
@GetMapping("/international/country/generalInfo/export/excel")
ExportDataResponse getCountryInfoExport(@RequestParam("country") String country);
@PostMapping("/international/country/merchandise/export/excel")
ExportDataResponse merchandiseExport(@RequestBody CountryReq req);
@PostMapping("/international/country/getTradeServ/export/excel")
ExportDataResponse getTradeServExport(@RequestBody CountryReq req);
@PostMapping("/international/country/getTradeServ/category/export/excel")
ExportDataResponse getTradeServCategoryExport(@RequestBody CountryReq req);
@PostMapping("/international/country/getTradeIndices/export/excel")
ExportDataResponse getTradeIndicesExport(@RequestBody CountryReq req);
@PostMapping("/international/country/getEconomic/export/excel")
ExportDataResponse getEconomicExport(@RequestBody CountryReq req);
@PostMapping("/international/country/getEconomic/Expenditure/export/excel")
ExportDataResponse getEconomicExpenditureExport(@RequestBody CountryReq req);
@PostMapping("/international/country/getFdiAndExternal/export/excel")
ExportDataResponse getFdiAndExternal(@RequestBody CountryReq req);
@PostMapping("/international/country/getFdiAndExternal/capitalFlow/export/excel")
ExportDataResponse getFdiAndExternalCapitalFlowExport(@RequestBody CountryReq req);
@PostMapping("/international/country/getGoodsAndServ/export/excel")
ExportDataResponse getGoodsAndServExport(@RequestBody CountryReq req);
@PostMapping("/international/country/getGoodsAndServ/openness/export/excel")
ExportDataResponse getGoodsAndServOpennessExport(@RequestBody CountryReq req);
@PostMapping("/international/country/getLivingArea/export/excel")
ExportDataResponse getLivingAreaExport(@RequestBody CountryReq req);
@PostMapping("/international/country/getOther/export/excel")
ExportDataResponse getOtherExport(@RequestBody CountryReq req);
@PostMapping("/international/country/getOther/economy/export/excel")
ExportDataResponse getOtherEconomyExport(@RequestBody CountryReq req);
}
package com.zzsn.excelexportservice.feign;
import com.alibaba.fastjson2.JSONObject;
import com.zzsn.excelexportservice.dto.ExportDataResponse;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @Author: lxj
* @Date: 2025/9/18 10:45
*/
@FeignClient(name = "research-center-fourth-server"
// , url = "${excel.export.services.research-center-fourth-server.data-url}"
)
public interface ResearchFeign {
@PostMapping("/benchmark/analyse/getHotKeywordTendency/export/excel")
ExportDataResponse getHotKeywordTendency(
@RequestParam("tid") String tid,
@RequestParam("kids") String kids,
@RequestParam("coids") String coids,
@RequestParam("countryNames") String countryNames,
@RequestParam("industryNames") String industryNames,
@RequestParam(value = "countryType") Integer countryType,
@RequestParam("topKids") String topKids,
@RequestParam("startDate") String startDate,
@RequestParam("endDate") String endDate,
@RequestParam("dateType") Integer dateType,
@RequestParam("weeks") Integer weeks,
@RequestParam("labels") String labels,
@RequestParam(value = "articleNum") Integer articleNum,
@RequestParam(value = "count") Integer count,
@RequestParam(value = "queryType") String queryType,
@RequestParam("flagCode") String flagCode,
@RequestParam("rankings") String rankings,
@RequestParam(value = "columnId") String columnId
);
@GetMapping("/special/universal/getKeyWordsSetById/export/excel")
ExportDataResponse getKeyWordsSetById(
@RequestParam("id") String id,
@RequestParam("limitNumber") Integer limitNumber,
@RequestParam("keyWordsNum") Integer keyWordsNum,
@RequestParam("title") String title
);
@PostMapping("/benchmark/analyse/getHotKeywordList/export/excel")
ExportDataResponse<?> getHotKeywordListExport(
@RequestParam("tid") String tid,
@RequestParam("kids") String kids,
@RequestParam("coids") String coids,
@RequestParam("countryNames") String countryNames,
@RequestParam("industryNames") String industryNames,
@RequestParam("labels") String labels,
@RequestParam(value = "countryType", defaultValue = "0") Integer countryType,
@RequestParam("startDate") String startDate,
@RequestParam("endDate") String endDate,
@RequestParam("dateType") Integer dateType,
@RequestParam(value = "count", defaultValue = "20") Integer count,
@RequestParam(value = "queryType", defaultValue = "0") String queryType,
@RequestParam("flagCode") String flagCode,
@RequestParam("rankings") String rankings,
@RequestParam(value = "columnId", required = false) String columnId
);
@PostMapping("/interface/query/export/excel")
ExportDataResponse queryExportExcel(
@RequestBody JSONObject jsonObject);
}
package com.zzsn.excelexportservice.service;
import com.dtflys.forest.annotation.*;
/**
* @Author: lxj
* @Date: 2025/9/23 17:30
*/
public interface CmsSearch {
@Post(
url = "${cmsQuestionUrl}",
connectTimeout = 10000,
readTimeout = 10000,
contentType = "application/json"
)
String getLdjh(
@Header("accesstoken") String accessToken,
@Query("operationType") String operationType,
@Query("leaderId") String leaderId,
@Query("subjectId") String subjectId,
@Query("pStartTime") String pStartTime,
@Query("pEndTime") String pEndTime,
@Query("limitNumber") String limitNumber);
}
package com.zzsn.excelexportservice.service;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.zzsn.excelexportservice.dto.*;
import com.zzsn.excelexportservice.exportStrategys.ExportStrategy;
import com.zzsn.excelexportservice.factorys.ExportStrategyFactory;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;
import com.zzsn.excelexportservice.dto.ExportDataResponse.Header;
/**
* @Author: lxj
* @Date: 2025/9/18 11:07
*/
@Service
@Slf4j
@RequiredArgsConstructor
public class ExcelExportService {
@Resource
private CmsSearch cmsSearch;
private final ExportStrategyFactory exportStrategyFactory;
public void export(List<ExportReq> exportReqList, HttpServletRequest request, HttpServletResponse response) {
if (exportReqList == null || exportReqList.isEmpty()) {
sendError(response, "导出失败: 入参为空");
return;
}
SXSSFWorkbook workbook = new SXSSFWorkbook(1000);
workbook.setCompressTempFiles(true);
for (ExportReq exportReq : exportReqList) {
ExportDataResponse resp = null;
String serviceName = exportReq.getServiceName();
Map<String, Object> queryParams = exportReq.getQueryParams();
ExportStrategy strategy = exportStrategyFactory.getStrategy(serviceName, exportReq.getApiPath());
if (strategy == null) {
log.error("No strategy found for service: {}, path: {}", serviceName, exportReq.getApiPath());
sendError(response, "导出失败: 未找到匹配的服务策略");
return;
}
resp = strategy.execute(request, queryParams, exportReq);
if (resp == null || resp.getCode() != 0) {
log.error("导出数据失败, serviceName: {}, apiPath: {}, errorMsg: {}",
serviceName, exportReq.getApiPath(), resp != null ? resp.getMsg() : "null");
sendError(response, resp != null ? resp.getMsg() : "导出失败: 未知错误");
return;
}
// 创建 sheet
Sheet sheet = workbook.createSheet(
StringUtils.isNotBlank(exportReq.getSheetName())
? exportReq.getSheetName()
: "Sheet_" + serviceName);
int startRow = 0;
int endCol = 13;
// 判断是否有图片
if (StringUtils.isNotBlank(exportReq.getBase64Img())) {
log.info("开始插入图片------->" + System.currentTimeMillis());
drawImg(workbook, sheet, exportReq.getBase64Img(), startRow, endCol);
startRow++; // 图片占用一行,从下一行开始写标题
}
List<Map<String, Object>> dataList = resp.getDataList();
List<Header> headers = resp.getHeaders();
// 写标题
log.info("开始插入标题------->" + System.currentTimeMillis());
handlerExcelTitle(workbook, sheet, startRow, headers);
// 写数据
log.info("开始写入数据------->" + System.currentTimeMillis());
handlerExcelData(workbook, sheet, startRow + 1, headers, dataList);
}
// 最后写到 response
log.info("生成excel结束------->" + System.currentTimeMillis());
writeExcelToResponse("导出", workbook, response);
}
@SuppressWarnings("unchecked")
private <T> T getParam(Map<String, Object> params, String key, T defaultVal) {
Object val = params.get(key);
if (val == null) {
return defaultVal;
}
try {
return (T) val;
} catch (ClassCastException e) {
log.warn("参数 {} 类型不正确,期望 {}, 实际 {}", key, defaultVal.getClass(), val.getClass());
return defaultVal;
}
}
private static void sendError(HttpServletResponse response, String msg) {
response.reset();
response.setStatus(1);
response.setContentType("text/plain;charset=UTF-8");
try {
response.getWriter().write(msg != null ? msg : "未知错误");
} catch (IOException e) {
e.printStackTrace();
}
}
// 插入图片(Base64)
private void drawImg(SXSSFWorkbook workbook, Sheet sheet, String base64Img, int rowIndex, int endCol) {
Row firstRow = sheet.createRow(rowIndex);
for (int i = 0; i < endCol; i++) {
firstRow.createCell(i);
}
firstRow.setHeightInPoints(230);
// 合并单元格
sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 0, endCol));
if (base64Img != null && !base64Img.isBlank()) {
int start = base64Img.indexOf(",");
if (start != -1) {
base64Img = base64Img.substring(start + 1);
}
byte[] imgBytes = Base64.getDecoder().decode(base64Img);
Drawing<?> drawingPatriarch = sheet.createDrawingPatriarch();
ClientAnchor anchor = drawingPatriarch.createAnchor(0, 0, 0, 0, 0, rowIndex, endCol, rowIndex + 1);
int pictureIdx = workbook.addPicture(imgBytes, Workbook.PICTURE_TYPE_PNG);
drawingPatriarch.createPicture(anchor, pictureIdx);
}
}
// 写入标题
private void handlerExcelTitle(Workbook workbook, Sheet sheet, int rowIndex, List<Header> headers) {
Row row = sheet.createRow(rowIndex);
CellStyle titleStyle = getTitleStyle(workbook);
if (headers != null && !headers.isEmpty()) {
for (int i = 0; i < headers.size(); i++) {
Cell cell = row.createCell(i);
cell.setCellStyle(titleStyle);
cell.setCellValue(headers.get(i).getTitle());
}
}
}
// Title 样式
private CellStyle getTitleStyle(Workbook workbook) {
Font font = workbook.createFont();
font.setFontName("Courier New");
font.setBold(true);
CellStyle style = workbook.createCellStyle();
style.setFont(font);
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
return style;
}
// 写入数据
private void handlerExcelData(Workbook workbook, Sheet sheet, int startRowIndex,
List<Header> headers, List<Map<String, Object>> dataList) {
CellStyle dataStyle = getDataStyle(workbook);
if (headers != null && !headers.isEmpty() && dataList != null && !dataList.isEmpty()) {
for (int j = 0; j < dataList.size(); j++) {
Row row = sheet.createRow(startRowIndex + j);
Map<String, Object> dataMap = dataList.get(j);
for (int i = 0; i < headers.size(); i++) {
Cell cell = row.createCell(i);
cell.setCellStyle(dataStyle);
Object value = dataMap.get(headers.get(i).getField());
cell.setCellValue(value == null ? "" : value.toString());
}
}
}
}
// 数据样式
private CellStyle getDataStyle(Workbook workbook) {
Font font = workbook.createFont();
font.setFontName("Courier New");
CellStyle style = workbook.createCellStyle();
style.setFont(font);
style.setAlignment(HorizontalAlignment.CENTER);
style.setVerticalAlignment(VerticalAlignment.CENTER);
return style;
}
// 将数据写入 HttpServletResponse(流式,不占用内存)
private void writeExcelToResponse(String fileNamePrefix, SXSSFWorkbook workbook, HttpServletResponse response) {
try {
response.reset();
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-disposition",
"attachment;filename=" + URLEncoder.encode(fileNamePrefix + System.currentTimeMillis() + ".xlsx", "UTF-8"));
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
workbook.write(response.getOutputStream());
response.getOutputStream().flush();
} catch (IOException e) {
sendError(response, "导出 Excel 异常:" + e.getMessage());
} finally {
// 清理临时文件
try {
workbook.close();
} catch (IOException ignored) {
}
workbook.dispose();
}
}
}
spring:
config:
import: optional:nacos:1.95.77.159:8848
cloud:
nacos:
discovery:
server-addr: 1.95.77.159:8848
username: nacos
password: Nacos@Smart20
namespace: smartTest
config:
enabled: false # 禁用配置中心功能
# ?????????????????????
excel:
export:
services:
international-operation:
data-url: http://server-1-95-77-159.ciglobal.cn:10089
character-analysis:
data-url: http://server-1-95-77-159.ciglobal.cn:10089
enterprise-service:
data-url: http://server-1-95-77-159.ciglobal.cn:10089
#
forest:
connect-timeout: 600000 # HTTP请求连接超时时间
read-timeout: 600000 # HTTP请求读取超时时间
variables:
cmsQuestionUrl: http://1.95.77.159:10089/api/v4/cms/cmsSubject/getSubjectRelationInfo
\ No newline at end of file
spring:
config:
import: optional:nacos:${NACOS_SERVER}
cloud:
nacos:
discovery:
server-addr: ${NACOS_SERVER}
username: ZZSN(ZIgriRlkxZ2g3SxM9x6sVYcMQe2QVxXx0/l4BAivWsTeVPkAYERSKxlHxzUwHF5M)
password: ZZSN(zB38iUSsp2RptT9HMrjJ0qGdSJ5iwq3jToor7ozqfMOYTiC6RwOvAxdayF7x9qm/)
namespace: ${NACOS_NAMESPACE}
config:
enabled: false # 禁用配置中心功能
# ?????????????????????
excel:
export:
services:
international-operation:
data-url: https://sasac-rc.com
character-analysis:
data-url: https://sasac-rc.com
enterprise-service:
data-url: https://sasac-rc.com
#
forest:
connect-timeout: 600000 # HTTP请求连接超时时间
read-timeout: 600000 # HTTP请求读取超时时间
variables:
cmsQuestionUrl: https://sasac-rc.com/api/v4/cms/cmsSubject/getSubjectRelationInfo
\ No newline at end of file
spring:
config:
import: optional:nacos:${NACOS_SERVER}
cloud:
nacos:
discovery:
server-addr: ${NACOS_SERVER}
username: ZZSN(ZIgriRlkxZ2g3SxM9x6sVYcMQe2QVxXx0/l4BAivWsTeVPkAYERSKxlHxzUwHF5M)
password: ZZSN(zB38iUSsp2RptT9HMrjJ0qGdSJ5iwq3jToor7ozqfMOYTiC6RwOvAxdayF7x9qm/)
namespace: ${NACOS_NAMESPACE}
config:
enabled: false # 禁用配置中心功能
# ?????????????????????
excel:
export:
services:
international-operation:
data-url: http://server-1-95-77-159.ciglobal.cn:10089
character-analysis:
data-url: http://server-1-95-77-159.ciglobal.cn:10089
enterprise-service:
data-url: http://server-1-95-77-159.ciglobal.cn:10089
#
forest:
connect-timeout: 600000 # HTTP请求连接超时时间
read-timeout: 600000 # HTTP请求读取超时时间
variables:
cmsQuestionUrl: http://1.95.77.159:10089/api/v4/cms/cmsSubject/getSubjectRelationInfo
\ No newline at end of file
server:
port: 8082
spring:
application:
name: excel-export-service
profiles:
active: local
jasypt:
encryptor:
property:
prefix: ZZSN(
suffix: )
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 10000
package com.zzsn.excelexportservice;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ExcelExportServiceApplicationTests {
@Test
void contextLoads() {
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论