Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
custom-server
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lizhonghong
custom-server
Commits
17729b0b
Commit
17729b0b
authored
Jul 16, 2026
by
pfh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
定时任务,文件上传,队列转发功能迁移
parent
da5a00ac
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
918 additions
and
3 deletions
+918
-3
custom-server-app/src/main/java/com/jomalls/custom/app/handler/SyntheticServerCallbackHandler.java
+26
-0
custom-server-app/src/main/java/com/jomalls/custom/app/handler/xxljob/CustomXxlJob.java
+19
-0
custom-server-app/src/main/java/com/jomalls/custom/app/handler/xxljob/DemoXxlJob.java
+250
-0
custom-server-app/src/main/java/com/jomalls/custom/app/mq/MqTool.java
+98
-0
custom-server-app/src/main/java/com/jomalls/custom/app/utils/IdUtils.java
+89
-0
custom-server-app/src/main/java/com/jomalls/custom/app/utils/Seq.java
+79
-0
custom-server-app/src/main/java/com/jomalls/custom/app/utils/StrFormatter.java
+74
-0
custom-server-app/src/main/java/com/jomalls/custom/app/utils/StringUtils.java
+0
-0
custom-server-app/src/main/java/com/jomalls/custom/app/utils/UUID.java
+0
-0
custom-server-core/pom.xml
+8
-0
custom-server-core/src/main/java/com/jomalls/custom/enums/MqRoute.java
+28
-0
custom-server-integrate/pom.xml
+6
-0
custom-server-integrate/src/main/java/com/jomalls/custom/integrate/configuration/XxlJobConfig.java
+41
-0
custom-server-starter/src/main/java/com/jomalls/custom/CustomServerApplication.java
+2
-1
custom-server-starter/src/main/resources/application-dev.yml
+28
-0
custom-server-starter/src/main/resources/application-prod.yml
+31
-2
custom-server-starter/src/main/resources/application-test.yml
+29
-0
custom-server-starter/src/main/resources/application.yml
+3
-0
custom-server-webapp/pom.xml
+8
-0
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/rest/SyntheticServerCallbackController.java
+28
-0
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/upload/UploadController.java
+52
-0
pom.xml
+19
-0
No files found.
custom-server-app/src/main/java/com/jomalls/custom/app/handler/SyntheticServerCallbackHandler.java
0 → 100644
View file @
17729b0b
package
com
.
jomalls
.
custom
.
app
.
handler
;
import
com.jomalls.custom.app.mq.MqTool
;
import
com.jomalls.custom.enums.MqRoute
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Component
;
import
java.util.HashMap
;
/**
* 合成服务器回调
*/
@Component
public
class
SyntheticServerCallbackHandler
{
@Value
(
"${jomalls.custom.url}"
)
private
String
customUrl
;
public
void
callback
(
String
queryString
)
{
String
url
=
customUrl
+
"/api/diy/userSave/update?"
+
queryString
;
HashMap
<
String
,
Object
>
params
=
new
HashMap
<>();
params
.
put
(
"url"
,
url
);
MqTool
.
getTool
().
sendMsg
(
MqRoute
.
synthesized_image_server_callback
.
getKey
(),
params
);
}
}
custom-server-app/src/main/java/com/jomalls/custom/app/handler/xxljob/CustomXxlJob.java
0 → 100644
View file @
17729b0b
package
com
.
jomalls
.
custom
.
app
.
handler
.
xxljob
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Component
;
@Component
public
class
CustomXxlJob
{
@Value
(
"${jomalls.job.execute}"
)
private
boolean
executeJob
;
private
static
Logger
logger
=
LoggerFactory
.
getLogger
(
CustomXxlJob
.
class
);
}
custom-server-app/src/main/java/com/jomalls/custom/app/handler/xxljob/DemoXxlJob.java
0 → 100644
View file @
17729b0b
package
com
.
jomalls
.
custom
.
app
.
handler
.
xxljob
;
import
com.xxl.job.core.context.XxlJobHelper
;
import
com.xxl.job.core.handler.annotation.XxlJob
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.stereotype.Component
;
import
java.io.BufferedInputStream
;
import
java.io.BufferedReader
;
import
java.io.DataOutputStream
;
import
java.io.InputStreamReader
;
import
java.net.HttpURLConnection
;
import
java.net.URL
;
import
java.util.Arrays
;
import
java.util.concurrent.TimeUnit
;
/**
*
* 开发步骤:
* 1、任务开发:在Spring Bean实例中,开发Job方法;
* 2、注解配置:为Job方法添加注解 "@XxlJob(value="自定义jobhandler名称", init = "JobHandler初始化方法", destroy = "JobHandler销毁方法")",注解value值对应的是调度中心新建任务的JobHandler属性的值。
* 3、执行日志:需要通过 "XxlJobHelper.log" 打印执行日志;
* 4、任务结果:默认任务结果为 "成功" 状态,不需要主动设置;如有诉求,比如设置任务结果为失败,可以通过 "XxlJobHelper.handleFail/handleSuccess" 自主设置任务结果;
*
*/
@Component
public
class
DemoXxlJob
{
private
static
Logger
logger
=
LoggerFactory
.
getLogger
(
DemoXxlJob
.
class
);
/**
* 1、简单任务示例(Bean模式)
*/
@XxlJob
(
"demoJobHandler"
)
public
void
demoJobHandler
()
throws
Exception
{
XxlJobHelper
.
log
(
"XXL-JOB, Hello World."
);
System
.
out
.
println
(
"XXL-JOB, Hello World."
);
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
XxlJobHelper
.
log
(
"beat at:"
+
i
);
TimeUnit
.
SECONDS
.
sleep
(
2
);
}
// default success
}
/**
* 2、分片广播任务
*/
@XxlJob
(
"shardingJobHandler"
)
public
void
shardingJobHandler
()
throws
Exception
{
// 分片参数
int
shardIndex
=
XxlJobHelper
.
getShardIndex
();
int
shardTotal
=
XxlJobHelper
.
getShardTotal
();
XxlJobHelper
.
log
(
"分片参数:当前分片序号 = {}, 总分片数 = {}"
,
shardIndex
,
shardTotal
);
// 业务逻辑
for
(
int
i
=
0
;
i
<
shardTotal
;
i
++)
{
if
(
i
==
shardIndex
)
{
XxlJobHelper
.
log
(
"第 {} 片, 命中分片开始处理"
,
i
);
}
else
{
XxlJobHelper
.
log
(
"第 {} 片, 忽略"
,
i
);
}
}
}
/**
* 3、命令行任务
*/
@XxlJob
(
"commandJobHandler"
)
public
void
commandJobHandler
()
throws
Exception
{
String
command
=
XxlJobHelper
.
getJobParam
();
int
exitValue
=
-
1
;
BufferedReader
bufferedReader
=
null
;
try
{
// command process
ProcessBuilder
processBuilder
=
new
ProcessBuilder
();
processBuilder
.
command
(
command
);
processBuilder
.
redirectErrorStream
(
true
);
Process
process
=
processBuilder
.
start
();
//Process process = Runtime.getRuntime().exec(command);
BufferedInputStream
bufferedInputStream
=
new
BufferedInputStream
(
process
.
getInputStream
());
bufferedReader
=
new
BufferedReader
(
new
InputStreamReader
(
bufferedInputStream
));
// command log
String
line
;
while
((
line
=
bufferedReader
.
readLine
())
!=
null
)
{
XxlJobHelper
.
log
(
line
);
}
// command exit
process
.
waitFor
();
exitValue
=
process
.
exitValue
();
}
catch
(
Exception
e
)
{
XxlJobHelper
.
log
(
e
);
}
finally
{
if
(
bufferedReader
!=
null
)
{
bufferedReader
.
close
();
}
}
if
(
exitValue
==
0
)
{
// default success
}
else
{
XxlJobHelper
.
handleFail
(
"command exit value("
+
exitValue
+
") is failed"
);
}
}
/**
* 4、跨平台Http任务
* 参数示例:
* "url: http://www.baidu.com\n" +
* "method: get\n" +
* "data: content\n";
*/
@XxlJob
(
"httpJobHandler"
)
public
void
httpJobHandler
()
throws
Exception
{
// param parse
String
param
=
XxlJobHelper
.
getJobParam
();
if
(
param
==
null
||
param
.
trim
().
length
()==
0
)
{
XxlJobHelper
.
log
(
"param["
+
param
+
"] invalid."
);
XxlJobHelper
.
handleFail
();
return
;
}
String
[]
httpParams
=
param
.
split
(
"\n"
);
String
url
=
null
;
String
method
=
null
;
String
data
=
null
;
for
(
String
httpParam:
httpParams
)
{
if
(
httpParam
.
startsWith
(
"url:"
))
{
url
=
httpParam
.
substring
(
httpParam
.
indexOf
(
"url:"
)
+
4
).
trim
();
}
if
(
httpParam
.
startsWith
(
"method:"
))
{
method
=
httpParam
.
substring
(
httpParam
.
indexOf
(
"method:"
)
+
7
).
trim
().
toUpperCase
();
}
if
(
httpParam
.
startsWith
(
"data:"
))
{
data
=
httpParam
.
substring
(
httpParam
.
indexOf
(
"data:"
)
+
5
).
trim
();
}
}
// param valid
if
(
url
==
null
||
url
.
trim
().
length
()==
0
)
{
XxlJobHelper
.
log
(
"url["
+
url
+
"] invalid."
);
XxlJobHelper
.
handleFail
();
return
;
}
if
(
method
==
null
||
!
Arrays
.
asList
(
"GET"
,
"POST"
).
contains
(
method
))
{
XxlJobHelper
.
log
(
"method["
+
method
+
"] invalid."
);
XxlJobHelper
.
handleFail
();
return
;
}
boolean
isPostMethod
=
method
.
equals
(
"POST"
);
// request
HttpURLConnection
connection
=
null
;
BufferedReader
bufferedReader
=
null
;
try
{
// connection
URL
realUrl
=
new
URL
(
url
);
connection
=
(
HttpURLConnection
)
realUrl
.
openConnection
();
// connection setting
connection
.
setRequestMethod
(
method
);
connection
.
setDoOutput
(
isPostMethod
);
connection
.
setDoInput
(
true
);
connection
.
setUseCaches
(
false
);
connection
.
setReadTimeout
(
5
*
1000
);
connection
.
setConnectTimeout
(
3
*
1000
);
connection
.
setRequestProperty
(
"connection"
,
"Keep-Alive"
);
connection
.
setRequestProperty
(
"Content-Type"
,
"application/json;charset=UTF-8"
);
connection
.
setRequestProperty
(
"Accept-Charset"
,
"application/json;charset=UTF-8"
);
// do connection
connection
.
connect
();
// data
if
(
isPostMethod
&&
data
!=
null
&&
data
.
trim
().
length
()>
0
)
{
DataOutputStream
dataOutputStream
=
new
DataOutputStream
(
connection
.
getOutputStream
());
dataOutputStream
.
write
(
data
.
getBytes
(
"UTF-8"
));
dataOutputStream
.
flush
();
dataOutputStream
.
close
();
}
// valid StatusCode
int
statusCode
=
connection
.
getResponseCode
();
if
(
statusCode
!=
200
)
{
throw
new
RuntimeException
(
"Http Request StatusCode("
+
statusCode
+
") Invalid."
);
}
// result
bufferedReader
=
new
BufferedReader
(
new
InputStreamReader
(
connection
.
getInputStream
(),
"UTF-8"
));
StringBuilder
result
=
new
StringBuilder
();
String
line
;
while
((
line
=
bufferedReader
.
readLine
())
!=
null
)
{
result
.
append
(
line
);
}
String
responseMsg
=
result
.
toString
();
XxlJobHelper
.
log
(
responseMsg
);
return
;
}
catch
(
Exception
e
)
{
XxlJobHelper
.
log
(
e
);
XxlJobHelper
.
handleFail
();
return
;
}
finally
{
try
{
if
(
bufferedReader
!=
null
)
{
bufferedReader
.
close
();
}
if
(
connection
!=
null
)
{
connection
.
disconnect
();
}
}
catch
(
Exception
e2
)
{
XxlJobHelper
.
log
(
e2
);
}
}
}
/**
* 5、生命周期任务示例:任务初始化与销毁时,支持自定义相关逻辑;
*/
@XxlJob
(
value
=
"demoJobHandler2"
,
init
=
"init"
,
destroy
=
"destroy"
)
public
void
demoJobHandler2
()
throws
Exception
{
XxlJobHelper
.
log
(
"XXL-JOB, Hello World."
);
}
public
void
init
(){
logger
.
info
(
"init"
);
}
public
void
destroy
(){
logger
.
info
(
"destroy"
);
}
}
custom-server-app/src/main/java/com/jomalls/custom/app/mq/MqTool.java
0 → 100644
View file @
17729b0b
package
com
.
jomalls
.
custom
.
app
.
mq
;
import
com.alibaba.fastjson2.JSONObject
;
import
com.jomalls.custom.app.utils.IdUtils
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.amqp.core.*
;
import
org.springframework.amqp.rabbit.core.RabbitAdmin
;
import
org.springframework.amqp.rabbit.core.RabbitTemplate
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.Map
;
@Slf4j
public
final
class
MqTool
{
public
static
final
String
SUFFIX_DIRECT
=
"_direct"
;
public
static
final
String
SUFFIX_QUEUE
=
"_queue0"
;
public
static
final
String
SUFFIX_ROUTE
=
"_route0"
;
public
static
final
String
SUFFIX_BIND
=
"_bind0"
;
public
static
final
String
NAMESPACE
=
"custom"
;
private
static
MqTool
tool
=
null
;
private
final
RabbitTemplate
rabbitTemplate
;
private
MqTool
(
RabbitTemplate
rabbitTemplate
)
{
this
.
rabbitTemplate
=
rabbitTemplate
;
}
public
static
MqTool
getTool
()
{
return
tool
;
}
public
static
synchronized
Map
<
String
,
Object
>
init
(
RabbitTemplate
rabbitTemplate
,
List
<
String
>
list
)
{
if
(
tool
==
null
){
tool
=
new
MqTool
(
rabbitTemplate
);
}
AmqpAdmin
admin
=
new
RabbitAdmin
(
rabbitTemplate
.
getConnectionFactory
());
Map
<
String
,
Object
>
map
=
new
LinkedHashMap
<>();
for
(
String
key
:
list
)
{
String
exchangeKey
=
key
+
SUFFIX_DIRECT
;
String
queueKey
=
key
+
SUFFIX_QUEUE
;
String
routeKey
=
key
+
SUFFIX_ROUTE
;
String
bindKey
=
key
+
SUFFIX_BIND
;
DirectExchange
exchange
=
new
DirectExchange
(
exchangeKey
,
true
,
false
);
Queue
queue
=
new
Queue
(
queueKey
,
true
);
admin
.
declareExchange
(
exchange
);
admin
.
declareQueue
(
queue
);
Binding
bind
=
BindingBuilder
.
bind
(
queue
).
to
(
exchange
).
with
(
routeKey
);
admin
.
declareBinding
(
bind
);
map
.
put
(
exchangeKey
,
exchange
);
map
.
put
(
queueKey
,
queue
);
map
.
put
(
bindKey
,
bind
);
}
return
map
;
}
public
void
sendMsg
(
String
key
,
Map
<
String
,
Object
>
params
)
{
if
(
params
==
null
){
throw
new
RuntimeException
(
"消息发送失败,发送的消息内容不能为空。"
);
}
if
(
StringUtils
.
isEmpty
(
key
))
{
throw
new
RuntimeException
(
"消息发送失败,不能发送消息到空路由。"
);
}
if
(
params
.
containsKey
(
"namespace"
)){
throw
new
RuntimeException
(
"消息发送失败,namespace为系统关键词,请修改后重试。"
);
}
if
(
params
.
containsKey
(
"msgTime"
)){
throw
new
RuntimeException
(
"消息发送失败,msgTime为系统关键词,请修改后重试。"
);
}
if
(
params
.
containsKey
(
"routeKey"
)){
throw
new
RuntimeException
(
"消息发送失败,routeKey为系统关键词,请修改后重试。"
);
}
if
(!
params
.
containsKey
(
"msgId"
)){
params
.
put
(
"msgId"
,
IdUtils
.
simpleUUID
());
//生成msgId消息唯一标识
}
if
(!
params
.
containsKey
(
"requestId"
)){
params
.
put
(
"requestId"
,
params
.
get
(
"msgId"
));
}
params
.
put
(
"namespace"
,
NAMESPACE
);
params
.
put
(
"msgTime"
,
System
.
currentTimeMillis
());
params
.
put
(
"routeKey"
,
key
);
String
message
=
JSONObject
.
toJSONString
(
params
);
String
exchange
=
key
+
SUFFIX_DIRECT
;
String
route
=
key
+
SUFFIX_ROUTE
;
log
.
info
(
"exchange:{} route:{} message:{} requestId:{}"
,
exchange
,
route
,
message
,
params
.
get
(
"msgId"
));
this
.
rabbitTemplate
.
convertAndSend
(
exchange
,
route
,
message
);
}
}
custom-server-app/src/main/java/com/jomalls/custom/app/utils/IdUtils.java
0 → 100644
View file @
17729b0b
package
com
.
jomalls
.
custom
.
app
.
utils
;
import
org.apache.commons.lang3.StringUtils
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* ID生成器工具类
*/
public
class
IdUtils
{
/**
* 获取随机UUID
*
* @return 随机UUID
*/
public
static
String
randomUUID
()
{
return
UUID
.
randomUUID
().
toString
();
}
/**
* 简化的UUID,去掉了横线
*
* @return 简化的UUID,去掉了横线
*/
public
static
String
simpleUUID
()
{
return
UUID
.
randomUUID
().
toString
(
true
);
}
/**
* 获取随机UUID,使用性能更好的ThreadLocalRandom生成UUID
*
* @return 随机UUID
*/
public
static
String
fastUUID
()
{
return
UUID
.
fastUUID
().
toString
();
}
/**
* 简化的UUID,去掉了横线,使用性能更好的ThreadLocalRandom生成UUID
*
* @return 简化的UUID,去掉了横线
*/
public
static
String
fastSimpleUUID
()
{
return
UUID
.
fastUUID
().
toString
(
true
);
}
/**
* 将字符串的id分隔,转换成Integer数组
*/
public
static
List
<
Integer
>
idsConvertToIntegerList
(
String
ids
){
List
<
Integer
>
idsList
=
new
ArrayList
<>();
if
(
StringUtils
.
isEmpty
(
ids
)){
return
idsList
;
}
String
[]
arr
=
ids
.
split
(
","
);
for
(
String
s
:
arr
)
{
if
(
StringUtils
.
isNotEmpty
(
s
))
{
idsList
.
add
(
Integer
.
parseInt
(
s
.
trim
()));
}
}
return
idsList
;
}
public
static
List
<
String
>
idsConvertToStringList
(
String
ids
)
{
List
<
String
>
res
=
new
ArrayList
<>();
if
(
StringUtils
.
isEmpty
(
ids
)){
return
res
;
}
for
(
String
s
:
ids
.
split
(
","
))
{
res
.
add
(
s
.
trim
());
}
return
res
;
}
public
static
List
<
Long
>
idsConvertToLongList
(
String
ids
){
List
<
Long
>
idsList
=
new
ArrayList
<>();
if
(
StringUtils
.
isEmpty
(
ids
)){
return
idsList
;
}
String
[]
arr
=
ids
.
split
(
","
);
for
(
String
s
:
arr
)
{
idsList
.
add
(
Long
.
parseLong
(
s
.
trim
()));
}
return
idsList
;
}
}
custom-server-app/src/main/java/com/jomalls/custom/app/utils/Seq.java
0 → 100644
View file @
17729b0b
package
com
.
jomalls
.
custom
.
app
.
utils
;
import
java.util.concurrent.atomic.AtomicInteger
;
/**
* 序列生成类
*/
public
class
Seq
{
// 通用序列类型
public
static
final
String
commSeqType
=
"COMMON"
;
// 上传序列类型
public
static
final
String
uploadSeqType
=
"UPLOAD"
;
// 通用接口序列数
private
static
AtomicInteger
commSeq
=
new
AtomicInteger
(
1
);
// 上传接口序列数
private
static
AtomicInteger
uploadSeq
=
new
AtomicInteger
(
1
);
// 机器标识
private
static
final
String
machineCode
=
"A"
;
/**
* 获取通用序列号
*
* @return 序列值
*/
public
static
String
getId
()
{
return
getId
(
commSeqType
);
}
/**
* 默认16位序列号 yyMMddHHmmss + 一位机器标识 + 3长度循环递增字符串
*
* @return 序列值
*/
public
static
String
getId
(
String
type
)
{
AtomicInteger
atomicInt
=
commSeq
;
if
(
uploadSeqType
.
equals
(
type
))
{
atomicInt
=
uploadSeq
;
}
return
getId
(
atomicInt
,
3
);
}
/**
* 通用接口序列号 yyMMddHHmmss + 一位机器标识 + length长度循环递增字符串
*
* @param atomicInt 序列数
* @param length 数值长度
* @return 序列值
*/
public
static
String
getId
(
AtomicInteger
atomicInt
,
int
length
)
{
String
result
=
DateUtils
.
dateTimeNow
();
result
+=
machineCode
;
result
+=
getSeq
(
atomicInt
,
length
);
return
result
;
}
/**
* 序列循环递增字符串[1, 10 的 (length)幂次方), 用0左补齐length位数
*
* @return 序列值
*/
private
synchronized
static
String
getSeq
(
AtomicInteger
atomicInt
,
int
length
)
{
// 先取值再+1
int
value
=
atomicInt
.
getAndIncrement
();
// 如果更新后值>=10 的 (length)幂次方则重置为1
int
maxSeq
=
(
int
)
Math
.
pow
(
10
,
length
);
if
(
atomicInt
.
get
()
>=
maxSeq
)
{
atomicInt
.
set
(
1
);
}
// 转字符串,用0左补齐
return
StringUtils
.
padl
(
value
,
length
);
}
}
custom-server-app/src/main/java/com/jomalls/custom/app/utils/StrFormatter.java
0 → 100644
View file @
17729b0b
package
com
.
jomalls
.
custom
.
app
.
utils
;
/**
* 字符串格式化
*/
public
class
StrFormatter
{
public
static
final
String
EMPTY_JSON
=
"{}"
;
public
static
final
char
C_BACKSLASH
=
'\\'
;
public
static
final
char
C_DELIM_START
=
'{'
;
public
static
final
char
C_DELIM_END
=
'}'
;
/**
* 格式化字符串<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* 例:<br>
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param strPattern 字符串模板
* @param argArray 参数列表
* @return 结果
*/
public
static
String
format
(
final
String
strPattern
,
final
Object
...
argArray
)
{
if
(
StringUtils
.
isEmpty
(
strPattern
)
||
StringUtils
.
isEmpty
(
argArray
))
{
return
strPattern
;
}
final
int
strPatternLength
=
strPattern
.
length
();
// 初始化定义好的长度以获得更好的性能
StringBuilder
sbuf
=
new
StringBuilder
(
strPatternLength
+
50
);
int
handledPosition
=
0
;
int
delimIndex
;
// 占位符所在位置
for
(
int
argIndex
=
0
;
argIndex
<
argArray
.
length
;
argIndex
++)
{
delimIndex
=
strPattern
.
indexOf
(
EMPTY_JSON
,
handledPosition
);
if
(
delimIndex
==
-
1
)
{
if
(
handledPosition
==
0
)
{
return
strPattern
;
}
else
{
// 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果
sbuf
.
append
(
strPattern
,
handledPosition
,
strPatternLength
);
return
sbuf
.
toString
();
}
}
else
{
if
(
delimIndex
>
0
&&
strPattern
.
charAt
(
delimIndex
-
1
)
==
C_BACKSLASH
)
{
if
(
delimIndex
>
1
&&
strPattern
.
charAt
(
delimIndex
-
2
)
==
C_BACKSLASH
)
{
// 转义符之前还有一个转义符,占位符依旧有效
sbuf
.
append
(
strPattern
,
handledPosition
,
delimIndex
-
1
);
sbuf
.
append
(
Convert
.
utf8Str
(
argArray
[
argIndex
]));
handledPosition
=
delimIndex
+
2
;
}
else
{
// 占位符被转义
argIndex
--;
sbuf
.
append
(
strPattern
,
handledPosition
,
delimIndex
-
1
);
sbuf
.
append
(
C_DELIM_START
);
handledPosition
=
delimIndex
+
1
;
}
}
else
{
// 正常占位符
sbuf
.
append
(
strPattern
,
handledPosition
,
delimIndex
);
sbuf
.
append
(
Convert
.
utf8Str
(
argArray
[
argIndex
]));
handledPosition
=
delimIndex
+
2
;
}
}
}
// 加入最后一个占位符后所有的字符
sbuf
.
append
(
strPattern
,
handledPosition
,
strPattern
.
length
());
return
sbuf
.
toString
();
}
}
custom-server-app/src/main/java/com/jomalls/custom/app/utils/StringUtils.java
0 → 100644
View file @
17729b0b
This diff is collapsed.
Click to expand it.
custom-server-app/src/main/java/com/jomalls/custom/app/utils/UUID.java
0 → 100644
View file @
17729b0b
This diff is collapsed.
Click to expand it.
custom-server-core/pom.xml
View file @
17729b0b
...
@@ -62,5 +62,13 @@
...
@@ -62,5 +62,13 @@
<groupId>
com.alibaba
</groupId>
<groupId>
com.alibaba
</groupId>
<artifactId>
transmittable-thread-local
</artifactId>
<artifactId>
transmittable-thread-local
</artifactId>
</dependency>
</dependency>
<dependency>
<groupId>
org.springframework.amqp
</groupId>
<artifactId>
spring-rabbit
</artifactId>
</dependency>
<dependency>
<groupId>
org.dromara.x-file-storage
</groupId>
<artifactId>
x-file-storage-spring
</artifactId>
</dependency>
</dependencies>
</dependencies>
</project>
</project>
custom-server-core/src/main/java/com/jomalls/custom/enums/MqRoute.java
0 → 100644
View file @
17729b0b
package
com
.
jomalls
.
custom
.
enums
;
import
lombok.Getter
;
import
java.util.Arrays
;
import
java.util.List
;
import
java.util.stream.Collectors
;
@Getter
public
enum
MqRoute
{
synthesized_image_server_callback
(
"synthesized_image_server_callback"
,
"com.jomalls.worker.queue.SyntheticServerCallbackQueue"
,
"合成图像服务器回调"
),;
MqRoute
(
String
key
,
String
handleQueue
,
String
remark
)
{
this
.
key
=
key
;
this
.
handleQueue
=
handleQueue
;
this
.
remark
=
remark
;
}
private
final
String
key
;
private
final
String
handleQueue
;
private
final
String
remark
;
public
static
List
<
String
>
geList
()
{
return
Arrays
.
stream
(
MqRoute
.
values
()).
map
(
MqRoute:
:
getKey
).
collect
(
Collectors
.
toList
());
}
}
custom-server-integrate/pom.xml
View file @
17729b0b
...
@@ -46,5 +46,11 @@
...
@@ -46,5 +46,11 @@
<artifactId>
resilience4j-spring-boot3
</artifactId>
<artifactId>
resilience4j-spring-boot3
</artifactId>
<version>
2.2.0
</version>
<version>
2.2.0
</version>
</dependency>
</dependency>
<!-- xxl-job-core -->
<dependency>
<groupId>
com.xuxueli
</groupId>
<artifactId>
xxl-job-core
</artifactId>
<version>
2.4.0
</version>
</dependency>
</dependencies>
</dependencies>
</project>
</project>
custom-server-integrate/src/main/java/com/jomalls/custom/integrate/configuration/XxlJobConfig.java
0 → 100644
View file @
17729b0b
package
com
.
jomalls
.
custom
.
integrate
.
configuration
;
import
com.xxl.job.core.executor.impl.XxlJobSpringExecutor
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
@Configuration
public
class
XxlJobConfig
{
@Value
(
"${xxl.job.admin.addresses}"
)
private
String
adminAddresses
;
@Value
(
"${xxl.job.accessToken}"
)
private
String
accessToken
;
@Value
(
"${xxl.job.executor.appname}"
)
private
String
appname
;
@Value
(
"${xxl.job.executor.address}"
)
private
String
address
;
@Value
(
"${xxl.job.executor.ip}"
)
private
String
ip
;
@Value
(
"${xxl.job.executor.port}"
)
private
Integer
port
;
@Value
(
"${xxl.job.executor.logpath}"
)
private
String
logpath
;
@Value
(
"${xxl.job.executor.logretentiondays}"
)
private
Integer
logretentiondays
;
@Bean
public
XxlJobSpringExecutor
xxlJobExecutor
()
{
XxlJobSpringExecutor
xxlJobSpringExecutor
=
new
XxlJobSpringExecutor
();
xxlJobSpringExecutor
.
setAdminAddresses
(
adminAddresses
);
xxlJobSpringExecutor
.
setAccessToken
(
accessToken
);
xxlJobSpringExecutor
.
setAppname
(
appname
);
xxlJobSpringExecutor
.
setAddress
(
address
);
xxlJobSpringExecutor
.
setIp
(
ip
);
xxlJobSpringExecutor
.
setPort
(
port
);
xxlJobSpringExecutor
.
setLogPath
(
logpath
);
xxlJobSpringExecutor
.
setLogRetentionDays
(
logretentiondays
);
return
xxlJobSpringExecutor
;
}
}
\ No newline at end of file
custom-server-starter/src/main/java/com/jomalls/custom/CustomServerApplication.java
View file @
17729b0b
package
com
.
jomalls
.
custom
;
package
com
.
jomalls
.
custom
;
import
org.dromara.x.file.storage.spring.EnableFileStorage
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.context.annotation.EnableAspectJAutoProxy
;
import
org.springframework.scheduling.annotation.EnableAsync
;
import
org.springframework.scheduling.annotation.EnableAsync
;
import
org.springframework.scheduling.annotation.EnableScheduling
;
import
org.springframework.scheduling.annotation.EnableScheduling
;
...
@@ -12,6 +12,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
...
@@ -12,6 +12,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
* @author Lizh
* @author Lizh
* @date 2026-05-26 18:25:27
* @date 2026-05-26 18:25:27
*/
*/
@EnableFileStorage
@SpringBootApplication
@SpringBootApplication
@EnableAsync
@EnableAsync
@EnableScheduling
@EnableScheduling
...
...
custom-server-starter/src/main/resources/application-dev.yml
View file @
17729b0b
...
@@ -17,3 +17,31 @@ token:
...
@@ -17,3 +17,31 @@ token:
header
:
Authorization
header
:
Authorization
# 令牌密钥(兼容旧版本)
# 令牌密钥(兼容旧版本)
secret
:
custom
secret
:
custom
xxl
:
job
:
admin
:
addresses
:
http://172.16.19.99:8888/xxl-job-admin
accessToken
:
udPDEOHA1Q7rgJSVrTpNFoyXbd79Ynz09CumN9ypYlhvh5eSLZh2DMR5sQ4B5W3P5yKz8mkB77Ynz6KA3L
executor
:
appname
:
xxl-job-executor-custom
# 不同服务使用不同appname
address
:
ip
:
port
:
9060
# 不同执行器使用不同端口
logpath
:
/data/applogs/xxl-job/custom
# 不同服务使用不同日志路径
logretentiondays
:
30
jomalls
:
custom
:
url
:
https://tcustom.jomalls.com
dromara
:
x-file-storage
:
#文件存储配置
default-platform
:
aliyun-oss-1
#默认使用的存储平台
thumbnail-suffix
:
"
.min.jpg"
#缩略图后缀,例如【.min.jpg】【.png】
aliyun-oss
:
-
platform
:
aliyun-oss-1
# 存储平台标识
enable-storage
:
true
# 启用存储
access-key
:
LTAI5t9NpNn2eTVUzvDWhV3W
secret-key
:
jQLgp8mYHuV8rQkBSY4RiZQ8jpJhV4
end-point
:
oss-cn-hangzhou.aliyuncs.com
bucket-name
:
jomalls-psd
domain
:
https://jomalls-psd.oss-cn-hangzhou.aliyuncs.com/
# 访问域名,注意“/”结尾,例如:https://abc.oss-cn-shanghai.aliyuncs.com/
base-path
:
custom/
# 基础路径
custom-server-starter/src/main/resources/application-prod.yml
View file @
17729b0b
...
@@ -16,4 +16,33 @@ spring:
...
@@ -16,4 +16,33 @@ spring:
token
:
token
:
header
:
Authorization
header
:
Authorization
# 令牌密钥(兼容旧版本)
# 令牌密钥(兼容旧版本)
secret
:
custom
secret
:
custom
\ No newline at end of file
xxl
:
job
:
admin
:
addresses
:
http://120.0.0.1:8888/xxl-job-admin
accessToken
:
udPDEOHA1Q7rgJSVrTpNFoyXbd79Ynz09CumN9ypYlhvh5eSLZh2DMR5sQ4B5W3P5yKz8mkB77Ynz6KA3L
executor
:
appname
:
xxl-job-executor-custom
# 不同服务使用不同appname
address
:
ip
:
port
:
9060
# 不同执行器使用不同端口
logpath
:
/data/applogs/xxl-job/custom
# 不同服务使用不同日志路径
logretentiondays
:
30
jomalls
:
custom
:
url
:
https://custom.jomalls.com
dromara
:
x-file-storage
:
#文件存储配置
default-platform
:
aliyun-oss-1
#默认使用的存储平台
thumbnail-suffix
:
"
.min.jpg"
#缩略图后缀,例如【.min.jpg】【.png】
aliyun-oss
:
-
platform
:
aliyun-oss-1
# 存储平台标识
enable-storage
:
true
# 启用存储
access-key
:
LTAI5t9NpNn2eTVUzvDWhV3W
secret-key
:
jQLgp8mYHuV8rQkBSY4RiZQ8jpJhV4
end-point
:
oss-cn-hangzhou.aliyuncs.com
bucket-name
:
jomalls-psd
domain
:
https://jomalls-psd.oss-cn-hangzhou.aliyuncs.com/
# 访问域名,注意“/”结尾,例如:https://abc.oss-cn-shanghai.aliyuncs.com/
base-path
:
custom/
# 基础路径
\ No newline at end of file
custom-server-starter/src/main/resources/application-test.yml
View file @
17729b0b
...
@@ -17,3 +17,32 @@ token:
...
@@ -17,3 +17,32 @@ token:
header
:
Authorization
header
:
Authorization
# 令牌密钥(兼容旧版本)
# 令牌密钥(兼容旧版本)
secret
:
custom
secret
:
custom
xxl
:
job
:
admin
:
addresses
:
http://172.16.19.99:8888/xxl-job-admin
accessToken
:
udPDEOHA1Q7rgJSVrTpNFoyXbd79Ynz09CumN9ypYlhvh5eSLZh2DMR5sQ4B5W3P5yKz8mkB77Ynz6KA3L
executor
:
appname
:
xxl-job-executor-custom
# 不同服务使用不同appname
address
:
ip
:
port
:
9060
# 不同执行器使用不同端口
logpath
:
/data/applogs/xxl-job/custom
# 不同服务使用不同日志路径
logretentiondays
:
30
jomalls
:
custom
:
url
:
https://tcustom.jomalls.com
dromara
:
x-file-storage
:
#文件存储配置
default-platform
:
aliyun-oss-1
#默认使用的存储平台
thumbnail-suffix
:
"
.min.jpg"
#缩略图后缀,例如【.min.jpg】【.png】
aliyun-oss
:
-
platform
:
aliyun-oss-1
# 存储平台标识
enable-storage
:
true
# 启用存储
access-key
:
LTAI5t9NpNn2eTVUzvDWhV3W
secret-key
:
jQLgp8mYHuV8rQkBSY4RiZQ8jpJhV4
end-point
:
oss-cn-hangzhou.aliyuncs.com
bucket-name
:
jomalls-psd
domain
:
https://jomalls-psd.oss-cn-hangzhou.aliyuncs.com/
# 访问域名,注意“/”结尾,例如:https://abc.oss-cn-shanghai.aliyuncs.com/
base-path
:
custom/
# 基础路径
custom-server-starter/src/main/resources/application.yml
View file @
17729b0b
...
@@ -138,3 +138,6 @@ management:
...
@@ -138,3 +138,6 @@ management:
base-path
:
/api/v3/actuator
base-path
:
/api/v3/actuator
exposure
:
exposure
:
include
:
metrics,health
include
:
metrics,health
jomalls
:
job
:
execute
:
true
custom-server-webapp/pom.xml
View file @
17729b0b
...
@@ -38,6 +38,14 @@
...
@@ -38,6 +38,14 @@
<artifactId>
lombok
</artifactId>
<artifactId>
lombok
</artifactId>
<scope>
provided
</scope>
<scope>
provided
</scope>
</dependency>
</dependency>
<dependency>
<groupId>
org.dromara.x-file-storage
</groupId>
<artifactId>
x-file-storage-spring
</artifactId>
</dependency>
<dependency>
<groupId>
com.aliyun.oss
</groupId>
<artifactId>
aliyun-sdk-oss
</artifactId>
</dependency>
</dependencies>
</dependencies>
</project>
</project>
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/rest/SyntheticServerCallbackController.java
0 → 100644
View file @
17729b0b
package
com
.
jomalls
.
custom
.
webapp
.
controller
.
rest
;
import
com.jomalls.custom.app.handler.SyntheticServerCallbackHandler
;
import
com.jomalls.custom.utils.R
;
import
jakarta.servlet.http.HttpServletRequest
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
/**
* 合成服务器回调
*/
@RestController
@RequestMapping
(
"api/v2/rest/synthetic-server"
)
public
class
SyntheticServerCallbackController
{
@Autowired
SyntheticServerCallbackHandler
syntheticServerCallbackHandler
;
@GetMapping
(
"/callback"
)
public
R
callback
(
HttpServletRequest
request
)
{
String
queryString
=
request
.
getQueryString
();
syntheticServerCallbackHandler
.
callback
(
queryString
);
return
R
.
ok
();
}
}
custom-server-webapp/src/main/java/com/jomalls/custom/webapp/controller/upload/UploadController.java
0 → 100644
View file @
17729b0b
package
com
.
jomalls
.
custom
.
webapp
.
controller
.
upload
;
import
com.jomalls.custom.utils.R
;
import
org.dromara.x.file.storage.core.FileInfo
;
import
org.dromara.x.file.storage.core.FileStorageService
;
import
org.springframework.beans.factory.annotation.Autowired
;;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
org.springframework.web.multipart.MultipartFile
;
import
java.time.LocalDateTime
;
import
java.time.format.DateTimeFormatter
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* 上传文件
*/
@RestController
@RequestMapping
(
"api/v2/common"
)
public
class
UploadController
{
@Autowired
private
FileStorageService
fileStorageService
;
private
static
final
String
FILE_DELIMETER
=
","
;
/**
* 通用上传请求(单个)
*/
@PostMapping
(
"/upload"
)
public
R
<
Map
<
String
,
Object
>>
uploadFile
(
MultipartFile
file
){
try
{
String
filePath
=
LocalDateTime
.
now
().
format
(
DateTimeFormatter
.
ofPattern
(
"yy/MM/dd/"
));
FileInfo
fileInfo
=
fileStorageService
.
of
(
file
)
.
setPath
(
filePath
)
.
upload
();
Map
<
String
,
Object
>
map
=
new
HashMap
<>();
map
.
put
(
"url"
,
fileInfo
.
getUrl
());
map
.
put
(
"fileName"
,
fileInfo
.
getUrl
());
map
.
put
(
"newFileName"
,
fileInfo
.
getUrl
());
map
.
put
(
"originalFilename"
,
file
.
getOriginalFilename
());
return
R
.
ok
(
map
);
}
catch
(
Exception
e
)
{
return
R
.
fail
(
e
.
getMessage
());
}
}
}
pom.xml
View file @
17729b0b
...
@@ -25,6 +25,9 @@
...
@@ -25,6 +25,9 @@
<transmittable-thread-local.version>
2.14.5
</transmittable-thread-local.version>
<transmittable-thread-local.version>
2.14.5
</transmittable-thread-local.version>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
<project.reporting.outputEncoding>
UTF-8
</project.reporting.outputEncoding>
<project.reporting.outputEncoding>
UTF-8
</project.reporting.outputEncoding>
<x-file.version>
2.3.0
</x-file.version>
<aliyun-oss.version>
3.16.1
</aliyun-oss.version>
<spring-boot-starter-amqp.version>
2.5.15
</spring-boot-starter-amqp.version>
</properties>
</properties>
<dependencies>
<dependencies>
<dependency>
<dependency>
...
@@ -127,6 +130,22 @@
...
@@ -127,6 +130,22 @@
<artifactId>
transmittable-thread-local
</artifactId>
<artifactId>
transmittable-thread-local
</artifactId>
<version>
${transmittable-thread-local.version}
</version>
<version>
${transmittable-thread-local.version}
</version>
</dependency>
</dependency>
<dependency>
<groupId>
org.dromara.x-file-storage
</groupId>
<artifactId>
x-file-storage-spring
</artifactId>
<version>
${x-file.version}
</version>
</dependency>
<!-- RabbitMQ -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-amqp
</artifactId>
<version>
${spring-boot-starter-amqp.version}
</version>
</dependency>
<dependency>
<groupId>
com.aliyun.oss
</groupId>
<artifactId>
aliyun-sdk-oss
</artifactId>
<version>
${aliyun-oss.version}
</version>
</dependency>
</dependencies>
</dependencies>
</dependencyManagement>
</dependencyManagement>
<modules>
<modules>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment