Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Administrator
magic-api
Commits
02897568
Commit
02897568
authored
Dec 18, 2023
by
liang.tang
Browse files
magic-api
parents
Pipeline
#222
failed with stages
in 0 seconds
Changes
320
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1626 additions
and
0 deletions
+1626
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/exception/ValidateException.java
...g/ssssssss/magicapi/core/exception/ValidateException.java
+22
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/handler/MagicCoordinationHandler.java
...sssss/magicapi/core/handler/MagicCoordinationHandler.java
+16
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/handler/MagicDebugHandler.java
...org/ssssssss/magicapi/core/handler/MagicDebugHandler.java
+59
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/handler/MagicWebSocketDispatcher.java
...sssss/magicapi/core/handler/MagicWebSocketDispatcher.java
+121
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/handler/MagicWorkbenchHandler.java
...ssssssss/magicapi/core/handler/MagicWorkbenchHandler.java
+110
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/Authorization.java
...org/ssssssss/magicapi/core/interceptor/Authorization.java
+49
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/AuthorizationInterceptor.java
...s/magicapi/core/interceptor/AuthorizationInterceptor.java
+105
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/DefaultAuthorizationInterceptor.java
...api/core/interceptor/DefaultAuthorizationInterceptor.java
+47
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/DefaultResultProvider.java
...ssss/magicapi/core/interceptor/DefaultResultProvider.java
+41
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/MagicWebRequestInterceptor.java
...magicapi/core/interceptor/MagicWebRequestInterceptor.java
+43
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/RequestInterceptor.java
...sssssss/magicapi/core/interceptor/RequestInterceptor.java
+93
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/ResultProvider.java
...rg/ssssssss/magicapi/core/interceptor/ResultProvider.java
+112
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/logging/Formatter.java
...in/java/org/ssssssss/magicapi/core/logging/Formatter.java
+276
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/logging/Log4j2LoggerContext.java
...g/ssssssss/magicapi/core/logging/Log4j2LoggerContext.java
+64
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/logging/Log4jLoggerContext.java
...rg/ssssssss/magicapi/core/logging/Log4jLoggerContext.java
+56
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/logging/LogbackLoggerContext.java
.../ssssssss/magicapi/core/logging/LogbackLoggerContext.java
+51
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/logging/LoggerManager.java
...ava/org/ssssssss/magicapi/core/logging/LoggerManager.java
+39
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/logging/MagicLoggerContext.java
...rg/ssssssss/magicapi/core/logging/MagicLoggerContext.java
+41
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/model/ApiInfo.java
...c/main/java/org/ssssssss/magicapi/core/model/ApiInfo.java
+238
-0
magic-api/src/main/java/org/ssssssss/magicapi/core/model/Attributes.java
...ain/java/org/ssssssss/magicapi/core/model/Attributes.java
+43
-0
No files found.
magic-api/src/main/java/org/ssssssss/magicapi/core/exception/ValidateException.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.exception
;
import
org.ssssssss.magicapi.core.model.JsonCode
;
/**
* 接口验证异常
*
* @author mxd
*/
public
class
ValidateException
extends
RuntimeException
{
private
final
JsonCode
jsonCode
;
public
ValidateException
(
JsonCode
jsonCode
,
String
message
)
{
super
(
message
);
this
.
jsonCode
=
jsonCode
;
}
public
JsonCode
getJsonCode
()
{
return
jsonCode
;
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/handler/MagicCoordinationHandler.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.handler
;
import
org.ssssssss.magicapi.core.annotation.Message
;
import
org.ssssssss.magicapi.core.config.MessageType
;
import
org.ssssssss.magicapi.core.config.WebSocketSessionManager
;
import
org.ssssssss.magicapi.core.config.Constants
;
import
org.ssssssss.magicapi.core.context.MagicConsoleSession
;
public
class
MagicCoordinationHandler
{
@Message
(
MessageType
.
SET_FILE_ID
)
public
void
setFileId
(
MagicConsoleSession
session
,
String
fileId
)
{
session
.
setAttribute
(
Constants
.
WEBSOCKET_ATTRIBUTE_FILE_ID
,
fileId
);
WebSocketSessionManager
.
sendToOther
(
session
.
getClientId
(),
MessageType
.
INTO_FILE_ID
,
session
.
getAttribute
(
Constants
.
WEBSOCKET_ATTRIBUTE_CLIENT_ID
),
fileId
);
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/handler/MagicDebugHandler.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.handler
;
import
org.apache.commons.lang3.StringUtils
;
import
org.ssssssss.magicapi.core.annotation.Message
;
import
org.ssssssss.magicapi.core.config.MessageType
;
import
org.ssssssss.magicapi.core.config.WebSocketSessionManager
;
import
org.ssssssss.magicapi.core.context.MagicConsoleSession
;
import
org.ssssssss.script.MagicScriptDebugContext
;
import
java.util.Collections
;
import
java.util.stream.Collectors
;
import
java.util.stream.Stream
;
/**
* WebSocket Debug 处理器
*
* @author mxd
*/
public
class
MagicDebugHandler
{
/**
* 设置断点
* 当本机没有该Session时,通知其他机器处理
*/
@Message
(
MessageType
.
SET_BREAKPOINT
)
public
boolean
setBreakPoint
(
MagicConsoleSession
session
,
String
scriptId
,
String
breakpoints
)
{
MagicScriptDebugContext
context
=
WebSocketSessionManager
.
findMagicScriptContext
(
session
.
getClientId
()
+
scriptId
);
if
(
context
!=
null
)
{
context
.
setBreakpoints
(
Stream
.
of
(
breakpoints
.
split
(
","
)).
map
(
Integer:
:
valueOf
).
collect
(
Collectors
.
toList
()));
return
true
;
}
return
false
;
}
/**
* 恢复断点
* 当本机没有该Session时,通知其他机器处理
*/
@Message
(
MessageType
.
RESUME_BREAKPOINT
)
public
boolean
resumeBreakpoint
(
MagicConsoleSession
session
,
String
scriptId
,
String
stepInto
,
String
breakpoints
)
{
MagicScriptDebugContext
context
=
WebSocketSessionManager
.
findMagicScriptContext
(
session
.
getClientId
()
+
scriptId
);
if
(
context
!=
null
)
{
context
.
setStepInto
(
"1"
.
equals
(
stepInto
));
if
(
StringUtils
.
isNotBlank
(
breakpoints
))
{
context
.
setBreakpoints
(
Stream
.
of
(
breakpoints
.
split
(
"\\|"
)).
map
(
Integer:
:
valueOf
).
collect
(
Collectors
.
toList
()));
}
else
{
context
.
setBreakpoints
(
Collections
.
emptyList
());
}
try
{
context
.
singal
();
}
catch
(
InterruptedException
ignored
)
{
}
return
true
;
}
return
false
;
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/handler/MagicWebSocketDispatcher.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.handler
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.web.socket.CloseStatus
;
import
org.springframework.web.socket.TextMessage
;
import
org.springframework.web.socket.WebSocketSession
;
import
org.springframework.web.socket.handler.TextWebSocketHandler
;
import
org.ssssssss.magicapi.core.annotation.Message
;
import
org.ssssssss.magicapi.core.config.MessageType
;
import
org.ssssssss.magicapi.core.config.WebSocketSessionManager
;
import
org.ssssssss.magicapi.core.event.EventAction
;
import
org.ssssssss.magicapi.core.context.MagicConsoleSession
;
import
org.ssssssss.magicapi.core.model.MagicNotify
;
import
org.ssssssss.magicapi.core.service.MagicNotifyService
;
import
org.ssssssss.magicapi.utils.JsonUtils
;
import
org.ssssssss.script.reflection.MethodInvoker
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.stream.Stream
;
import
static
org
.
ssssssss
.
magicapi
.
core
.
config
.
Constants
.
EMPTY_OBJECT_ARRAY
;
/**
* WebSocket 分发器
*
* @author mxd
*/
public
class
MagicWebSocketDispatcher
extends
TextWebSocketHandler
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
MagicWebSocketDispatcher
.
class
);
private
static
final
Map
<
String
,
MethodInvoker
>
HANDLERS
=
new
HashMap
<>();
private
final
String
instanceId
;
private
final
MagicNotifyService
magicNotifyService
;
public
MagicWebSocketDispatcher
(
String
instanceId
,
MagicNotifyService
magicNotifyService
,
List
<
Object
>
websocketMessageHandlers
)
{
this
.
instanceId
=
instanceId
;
this
.
magicNotifyService
=
magicNotifyService
;
WebSocketSessionManager
.
setMagicNotifyService
(
magicNotifyService
);
WebSocketSessionManager
.
setInstanceId
(
instanceId
);
websocketMessageHandlers
.
forEach
(
websocketMessageHandler
->
Stream
.
of
(
websocketMessageHandler
.
getClass
().
getDeclaredMethods
())
.
filter
(
it
->
it
.
getAnnotation
(
Message
.
class
)
!=
null
)
.
forEach
(
method
->
HANDLERS
.
put
(
method
.
getAnnotation
(
Message
.
class
).
value
().
name
().
toLowerCase
(),
new
MethodInvoker
(
method
,
websocketMessageHandler
)))
);
}
private
static
Object
findHandleAndInvoke
(
MagicConsoleSession
session
,
String
payload
)
{
// messageType[, data][,data]
int
index
=
payload
.
indexOf
(
","
);
String
msgType
=
index
==
-
1
?
payload
:
payload
.
substring
(
0
,
index
);
MethodInvoker
invoker
=
HANDLERS
.
get
(
msgType
);
if
(
invoker
!=
null
)
{
Object
returnValue
;
try
{
Class
<?>[]
pTypes
=
invoker
.
getParameterTypes
();
int
pCount
=
pTypes
.
length
;
if
(
pCount
==
0
)
{
returnValue
=
invoker
.
invoke0
(
invoker
.
getDefaultTarget
(),
null
,
EMPTY_OBJECT_ARRAY
);
}
else
{
Object
[]
pValues
=
new
Object
[
pCount
];
for
(
int
i
=
0
;
i
<
pCount
;
i
++)
{
Class
<?>
pType
=
pTypes
[
i
];
if
(
pType
==
MagicConsoleSession
.
class
)
{
pValues
[
i
]
=
session
;
}
else
if
(
pType
==
String
.
class
)
{
int
subIndex
=
payload
.
indexOf
(
","
,
index
+
1
);
if
(
subIndex
>
-
1
)
{
pValues
[
i
]
=
payload
.
substring
(
index
+
1
,
index
=
subIndex
);
}
else
if
(
index
>
-
1
)
{
pValues
[
i
]
=
payload
.
substring
(
index
+
1
);
}
}
else
{
pValues
[
i
]
=
JsonUtils
.
readValue
(
payload
,
pType
);
}
}
returnValue
=
invoker
.
invoke0
(
invoker
.
getDefaultTarget
(),
null
,
pValues
);
}
return
returnValue
;
}
catch
(
Throwable
e
)
{
logger
.
error
(
"WebSocket消息处理出错"
,
e
);
}
}
return
null
;
}
public
static
void
processMessageReceived
(
String
clientId
,
String
payload
)
{
MagicConsoleSession
session
=
WebSocketSessionManager
.
findSession
(
clientId
);
if
(
session
!=
null
)
{
findHandleAndInvoke
(
session
,
payload
);
}
}
public
static
void
processWebSocketEventMessage
(
String
payload
)
{
findHandleAndInvoke
(
null
,
payload
);
}
@Override
public
void
afterConnectionClosed
(
WebSocketSession
session
,
CloseStatus
status
)
{
MagicConsoleSession
mcsession
=
MagicConsoleSession
.
from
(
session
);
WebSocketSessionManager
.
remove
(
mcsession
);
MagicConsoleSession
.
remove
(
session
);
if
(
mcsession
.
getClientId
()
!=
null
&&
mcsession
.
getAttributes
()
!=
null
&&
!
mcsession
.
getAttributes
().
isEmpty
()){
WebSocketSessionManager
.
sendToAll
(
MessageType
.
USER_LOGOUT
,
mcsession
.
getAttributes
());
}
}
@Override
protected
void
handleTextMessage
(
WebSocketSession
session
,
TextMessage
message
)
{
MagicConsoleSession
consoleSession
=
MagicConsoleSession
.
from
(
session
);
Object
returnValue
=
findHandleAndInvoke
(
consoleSession
,
message
.
getPayload
());
// 如果未成功处理消息,则通知其他机器去处理消息
if
(
Boolean
.
FALSE
.
equals
(
returnValue
))
{
magicNotifyService
.
sendNotify
(
new
MagicNotify
(
instanceId
,
EventAction
.
WS_C_S
,
consoleSession
.
getClientId
(),
message
.
getPayload
()));
}
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/handler/MagicWorkbenchHandler.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.handler
;
import
org.apache.commons.lang3.StringUtils
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.http.HttpHeaders
;
import
org.ssssssss.magicapi.core.annotation.Message
;
import
org.ssssssss.magicapi.core.config.Constants
;
import
org.ssssssss.magicapi.core.config.MessageType
;
import
org.ssssssss.magicapi.core.config.WebSocketSessionManager
;
import
org.ssssssss.magicapi.core.context.MagicConsoleSession
;
import
org.ssssssss.magicapi.core.context.MagicUser
;
import
org.ssssssss.magicapi.core.interceptor.AuthorizationInterceptor
;
import
org.ssssssss.magicapi.utils.IpUtils
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.Optional
;
import
java.util.stream.Collectors
;
/**
* UI上其它操作处理
*
* @author mxd
*/
public
class
MagicWorkbenchHandler
{
private
final
AuthorizationInterceptor
authorizationInterceptor
;
private
final
static
MagicUser
guest
=
new
MagicUser
(
"guest"
,
"游客"
,
"unauthorization"
);
private
final
static
Logger
logger
=
LoggerFactory
.
getLogger
(
MagicWorkbenchHandler
.
class
);
public
MagicWorkbenchHandler
(
AuthorizationInterceptor
authorizationInterceptor
)
{
this
.
authorizationInterceptor
=
authorizationInterceptor
;
}
@Message
(
MessageType
.
LOGIN
)
public
void
onLogin
(
MagicConsoleSession
session
,
String
token
,
String
clientId
)
{
session
.
setClientId
(
clientId
);
MagicUser
user
=
null
;
try
{
user
=
authorizationInterceptor
.
getUserByToken
(
token
);
}
catch
(
Exception
e
)
{
if
(!
authorizationInterceptor
.
requireLogin
()){
user
=
guest
;
}
}
if
(
user
!=
null
)
{
String
ip
=
Optional
.
ofNullable
(
session
.
getWebSocketSession
().
getRemoteAddress
()).
map
(
it
->
it
.
getAddress
().
getHostAddress
()).
orElse
(
"unknown"
);
HttpHeaders
headers
=
session
.
getWebSocketSession
().
getHandshakeHeaders
();
ip
=
IpUtils
.
getRealIP
(
ip
,
headers:
:
getFirst
,
null
);
if
(
user
.
getTimeout
()
>
0
)
{
session
.
setUser
(
user
);
session
.
setTimeout
(
user
.
getTimeout
()
*
1000
+
System
.
currentTimeMillis
());
}
session
.
setAttribute
(
Constants
.
WEBSOCKET_ATTRIBUTE_USER_ID
,
user
.
getId
());
session
.
setAttribute
(
Constants
.
WEBSOCKET_ATTRIBUTE_USER_IP
,
StringUtils
.
defaultIfBlank
(
ip
,
"unknown"
));
session
.
setAttribute
(
Constants
.
WEBSOCKET_ATTRIBUTE_USER_NAME
,
user
.
getUsername
());
session
.
setActivateTime
(
System
.
currentTimeMillis
());
synchronized
(
MagicWorkbenchHandler
.
class
){
if
(
WebSocketSessionManager
.
getConsoleSession
(
clientId
)
!=
null
){
WebSocketSessionManager
.
sendBySession
(
session
,
WebSocketSessionManager
.
buildMessage
(
MessageType
.
LOGIN_RESPONSE
,
"-1"
));
return
;
}
WebSocketSessionManager
.
add
(
session
);
}
WebSocketSessionManager
.
sendBySession
(
session
,
WebSocketSessionManager
.
buildMessage
(
MessageType
.
LOGIN_RESPONSE
,
"1"
,
session
.
getAttributes
()));
List
<
Map
<
String
,
Object
>>
messages
=
getOnlineUsers
();
if
(!
messages
.
isEmpty
()){
WebSocketSessionManager
.
sendByClientId
(
session
.
getClientId
(),
WebSocketSessionManager
.
buildMessage
(
MessageType
.
ONLINE_USERS
,
messages
));
}
WebSocketSessionManager
.
sendToMachine
(
MessageType
.
SEND_ONLINE
,
session
.
getClientId
());
WebSocketSessionManager
.
sendToOther
(
session
.
getClientId
(),
MessageType
.
USER_LOGIN
,
session
.
getAttributes
());
}
else
{
WebSocketSessionManager
.
sendBySession
(
session
,
WebSocketSessionManager
.
buildMessage
(
MessageType
.
LOGIN_RESPONSE
,
"0"
));
}
}
@Message
(
MessageType
.
SEND_ONLINE
)
public
void
sendOnline
(
String
clientId
){
List
<
Map
<
String
,
Object
>>
messages
=
getOnlineUsers
();
if
(!
messages
.
isEmpty
()){
WebSocketSessionManager
.
sendToMachineByClientId
(
clientId
,
WebSocketSessionManager
.
buildMessage
(
MessageType
.
ONLINE_USERS
,
messages
));
}
}
@Message
(
MessageType
.
PONG
)
public
String
pong
(
MagicConsoleSession
session
){
session
.
setActivateTime
(
System
.
currentTimeMillis
());
MagicUser
user
=
session
.
getUser
();
if
(
user
!=
null
&&
session
.
getTimeout
()
-
System
.
currentTimeMillis
()
<
60
*
1000
){
String
oldToken
=
user
.
getToken
();
authorizationInterceptor
.
refreshToken
(
user
);
String
newToken
=
user
.
getToken
();
session
.
setTimeout
(
System
.
currentTimeMillis
()
+
user
.
getTimeout
()
*
1000
);
if
(!
Objects
.
equals
(
newToken
,
oldToken
))
{
WebSocketSessionManager
.
sendBySession
(
session
,
WebSocketSessionManager
.
buildMessage
(
MessageType
.
REFRESH_TOKEN
,
newToken
));
}
}
return
null
;
}
private
List
<
Map
<
String
,
Object
>>
getOnlineUsers
(){
return
WebSocketSessionManager
.
getSessions
().
stream
()
.
map
(
MagicConsoleSession:
:
getAttributes
)
.
collect
(
Collectors
.
toList
());
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/Authorization.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.interceptor
;
/**
* 鉴权类型枚举
*
* @author mxd
*/
public
enum
Authorization
{
/**
* 无实际意义
*/
NONE
,
/**
* 执行保存动作
*/
SAVE
,
/**
* 执行查看详情、列表动作
*/
VIEW
,
/**
* 执行删除动作
*/
DELETE
,
/**
* 执行导出动作
*/
DOWNLOAD
,
/**
* 执行上传动作
*/
UPLOAD
,
/**
* 执行推送动作
*/
PUSH
,
/**
* 锁定动作
*/
LOCK
,
/**
* 解锁动作
*/
UNLOCK
,
/**
* 重新加载
*/
RELOAD
}
magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/AuthorizationInterceptor.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.interceptor
;
import
org.ssssssss.magicapi.core.context.MagicUser
;
import
org.ssssssss.magicapi.core.exception.MagicLoginException
;
import
org.ssssssss.magicapi.core.model.Group
;
import
org.ssssssss.magicapi.core.model.MagicEntity
;
import
org.ssssssss.magicapi.core.servlet.MagicHttpServletRequest
;
/**
* UI权限拦截器
*
* @author mxd
*/
public
interface
AuthorizationInterceptor
{
/**
* 是否需要登录
*
* @return true 需要登录, false 不需要登录
*/
default
boolean
requireLogin
()
{
return
false
;
}
/**
* 根据Token获取User对象
*
* @param token token值
* @return 登录成功后返回MagicUser对象
* @throws MagicLoginException 登录失败抛出
*/
default
MagicUser
getUserByToken
(
String
token
)
throws
MagicLoginException
{
return
null
;
}
/**
* 根据用户名,密码登录
*
* @param username 用户名
* @param password 密码
* @return 登录成功后返回MagicUser对象
* @throws MagicLoginException 登录失败抛出
*/
default
MagicUser
login
(
String
username
,
String
password
)
throws
MagicLoginException
{
return
null
;
}
/**
* 退出登录
*
* @param token token值
*/
default
void
logout
(
String
token
)
{
}
/**
* 是否拥有页面按钮的权限
*
* @param magicUser 登录的用户对象
* @param request HttpServletRequest
* @param authorization 鉴权方法
* @return true 有权限访问, false 无权限访问
*/
default
boolean
allowVisit
(
MagicUser
magicUser
,
MagicHttpServletRequest
request
,
Authorization
authorization
)
{
return
true
;
}
/**
* 是否拥有对该接口的增删改权限
*
* @param magicUser 登录的用户对象
* @param request HttpServletRequest
* @param authorization 鉴权方法
* @param entity 接口、函数、数据源信息
* @return true 有权限访问, false 无权限访问
*/
default
boolean
allowVisit
(
MagicUser
magicUser
,
MagicHttpServletRequest
request
,
Authorization
authorization
,
MagicEntity
entity
)
{
return
allowVisit
(
magicUser
,
request
,
authorization
);
}
/**
* 是否拥有对该分组的增删改权限
*
* @param magicUser 登录的用户对象
* @param request HttpServletRequest
* @param authorization 鉴权方法
* @param group 分组信息
* @return true 有权限访问, false 无权限访问
*/
default
boolean
allowVisit
(
MagicUser
magicUser
,
MagicHttpServletRequest
request
,
Authorization
authorization
,
Group
group
)
{
return
allowVisit
(
magicUser
,
request
,
authorization
);
}
/**
* 刷新 token, 重新赋值对象内的token和timeout
* @param user
* @return
*/
default
void
refreshToken
(
MagicUser
user
)
{
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/DefaultAuthorizationInterceptor.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.interceptor
;
import
org.ssssssss.magicapi.core.context.MagicUser
;
import
org.ssssssss.magicapi.core.exception.MagicLoginException
;
import
org.ssssssss.magicapi.utils.MD5Utils
;
import
java.util.Objects
;
/**
* 默认UI鉴权实现
*
* @author mxd
*/
public
class
DefaultAuthorizationInterceptor
implements
AuthorizationInterceptor
{
private
final
boolean
requireLogin
;
private
String
validToken
;
private
MagicUser
configMagicUser
;
public
DefaultAuthorizationInterceptor
(
String
username
,
String
password
)
{
if
(
this
.
requireLogin
=
username
!=
null
&&
password
!=
null
)
{
this
.
validToken
=
MD5Utils
.
encrypt
(
String
.
format
(
"%s||%s"
,
username
,
password
));
this
.
configMagicUser
=
new
MagicUser
(
username
,
username
,
this
.
validToken
);
}
}
@Override
public
boolean
requireLogin
()
{
return
this
.
requireLogin
;
}
@Override
public
MagicUser
getUserByToken
(
String
token
)
throws
MagicLoginException
{
if
(
requireLogin
&&
Objects
.
equals
(
validToken
,
token
))
{
return
configMagicUser
;
}
throw
new
MagicLoginException
(
"token无效"
);
}
@Override
public
MagicUser
login
(
String
username
,
String
password
)
throws
MagicLoginException
{
if
(
requireLogin
&&
Objects
.
equals
(
MD5Utils
.
encrypt
(
String
.
format
(
"%s||%s"
,
username
,
password
)),
this
.
validToken
))
{
return
configMagicUser
;
}
throw
new
MagicLoginException
(
"用户名或密码不正确"
);
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/DefaultResultProvider.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.interceptor
;
import
org.ssssssss.magicapi.core.model.JsonBean
;
import
org.ssssssss.magicapi.core.context.RequestEntity
;
import
org.ssssssss.magicapi.utils.ScriptManager
;
import
org.ssssssss.script.MagicScriptContext
;
/**
* 默认结果封装实现
*
* @author mxd
*/
public
class
DefaultResultProvider
implements
ResultProvider
{
private
final
String
responseScript
;
public
DefaultResultProvider
(
String
responseScript
)
{
this
.
responseScript
=
responseScript
;
}
@Override
public
Object
buildResult
(
RequestEntity
requestEntity
,
int
code
,
String
message
,
Object
data
)
{
long
timestamp
=
System
.
currentTimeMillis
();
if
(
this
.
responseScript
!=
null
)
{
MagicScriptContext
context
=
new
MagicScriptContext
();
context
.
setScriptName
(
requestEntity
.
getMagicScriptContext
().
getScriptName
());
context
.
set
(
"code"
,
code
);
context
.
set
(
"message"
,
message
);
context
.
set
(
"data"
,
data
);
context
.
set
(
"apiInfo"
,
requestEntity
.
getApiInfo
());
context
.
set
(
"request"
,
requestEntity
.
getRequest
());
context
.
set
(
"response"
,
requestEntity
.
getResponse
());
context
.
set
(
"timestamp"
,
timestamp
);
context
.
set
(
"requestTime"
,
requestEntity
.
getRequestTime
());
context
.
set
(
"executeTime"
,
timestamp
-
requestEntity
.
getRequestTime
());
return
ScriptManager
.
executeExpression
(
responseScript
,
context
);
}
else
{
return
new
JsonBean
<>(
code
,
message
,
data
,
(
int
)
(
timestamp
-
requestEntity
.
getRequestTime
()));
}
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/MagicWebRequestInterceptor.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.interceptor
;
import
org.springframework.web.method.HandlerMethod
;
import
org.ssssssss.magicapi.core.annotation.Valid
;
import
org.ssssssss.magicapi.core.config.Constants
;
import
org.ssssssss.magicapi.core.config.MagicCorsFilter
;
import
org.ssssssss.magicapi.core.exception.MagicLoginException
;
import
org.ssssssss.magicapi.core.servlet.MagicHttpServletRequest
;
import
org.ssssssss.magicapi.core.servlet.MagicHttpServletResponse
;
import
org.ssssssss.magicapi.core.web.MagicController
;
public
abstract
class
MagicWebRequestInterceptor
{
private
final
MagicCorsFilter
magicCorsFilter
;
private
final
AuthorizationInterceptor
authorizationInterceptor
;
public
MagicWebRequestInterceptor
(
MagicCorsFilter
magicCorsFilter
,
AuthorizationInterceptor
authorizationInterceptor
)
{
this
.
magicCorsFilter
=
magicCorsFilter
;
this
.
authorizationInterceptor
=
authorizationInterceptor
;
}
public
void
handle
(
Object
handler
,
MagicHttpServletRequest
request
,
MagicHttpServletResponse
response
)
throws
MagicLoginException
{
HandlerMethod
handlerMethod
;
if
(
handler
instanceof
HandlerMethod
)
{
handlerMethod
=
(
HandlerMethod
)
handler
;
handler
=
handlerMethod
.
getBean
();
if
(
handler
instanceof
MagicController
)
{
if
(
magicCorsFilter
!=
null
)
{
magicCorsFilter
.
process
(
request
,
response
);
}
Valid
valid
=
handlerMethod
.
getMethodAnnotation
(
Valid
.
class
);
boolean
requiredLogin
=
authorizationInterceptor
.
requireLogin
();
boolean
validRequiredLogin
=
(
valid
==
null
||
valid
.
requireLogin
());
if
(
requiredLogin
&&
validRequiredLogin
)
{
request
.
setAttribute
(
Constants
.
ATTRIBUTE_MAGIC_USER
,
authorizationInterceptor
.
getUserByToken
(
request
.
getHeader
(
Constants
.
MAGIC_TOKEN_HEADER
)));
}
((
MagicController
)
handler
).
doValid
(
request
,
valid
);
}
}
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/RequestInterceptor.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.interceptor
;
import
org.ssssssss.magicapi.core.context.RequestEntity
;
import
org.ssssssss.magicapi.core.model.ApiInfo
;
import
org.ssssssss.magicapi.core.servlet.MagicHttpServletRequest
;
import
org.ssssssss.magicapi.core.servlet.MagicHttpServletResponse
;
import
org.ssssssss.script.MagicScriptContext
;
/**
* 请求拦截器
*
* @author mxd
*/
public
interface
RequestInterceptor
{
/**
* 请求之前执行
*
* @param requestEntity 请求对象
* @return 当返回对象时,直接将此对象返回到页面,返回null时,继续执行后续操作
*/
default
Object
preHandle
(
RequestEntity
requestEntity
)
throws
Exception
{
return
preHandle
(
requestEntity
.
getApiInfo
(),
requestEntity
.
getMagicScriptContext
(),
requestEntity
.
getRequest
(),
requestEntity
.
getResponse
());
}
/**
* 请求之前执行
*
* @param info 接口信息
* @param context 脚本上下文
* @param request HttpServletRequest
* @param response HttpServletResponse
* @return 当返回对象时,直接将此对象返回到页面,返回null时,继续执行后续操作
* @throws Exception 处理失败时抛出的异常
*/
default
Object
preHandle
(
ApiInfo
info
,
MagicScriptContext
context
,
MagicHttpServletRequest
request
,
MagicHttpServletResponse
response
)
throws
Exception
{
return
null
;
}
/**
* 执行完毕之后执行
*
* @param info 接口信息
* @param context 脚本上下文
* @param returnValue 即将要返回到页面的值
* @param request HttpServletRequest
* @param response HttpServletResponse
* @return 返回到页面的对象, 当返回null时执行后续拦截器,否则直接返回该值,不执行后续拦截器
* @throws Exception 处理失败时抛出的异常
*/
default
Object
postHandle
(
ApiInfo
info
,
MagicScriptContext
context
,
Object
returnValue
,
MagicHttpServletRequest
request
,
MagicHttpServletResponse
response
)
throws
Exception
{
return
null
;
}
/**
* 执行完毕之后执行
*
* @param requestEntity 请求对象
* @param returnValue 即将要返回到页面的值
* @return 返回到页面的对象, 当返回null时执行后续拦截器,否则直接返回该值,不执行后续拦截器
*/
default
Object
postHandle
(
RequestEntity
requestEntity
,
Object
returnValue
)
throws
Exception
{
return
postHandle
(
requestEntity
.
getApiInfo
(),
requestEntity
.
getMagicScriptContext
(),
returnValue
,
requestEntity
.
getRequest
(),
requestEntity
.
getResponse
());
}
/**
* 接口执行完毕之后执行
*
* @param requestEntity 请求对象
* @param returnValue 即将要返回到页面的值
* @param throwable 异常对象
*/
default
void
afterCompletion
(
RequestEntity
requestEntity
,
Object
returnValue
,
Throwable
throwable
)
{
afterCompletion
(
requestEntity
.
getApiInfo
(),
requestEntity
.
getMagicScriptContext
(),
returnValue
,
requestEntity
.
getRequest
(),
requestEntity
.
getResponse
(),
throwable
);
}
/**
* 接口执行完毕之后执行
*
* @param info 接口信息
* @param context 脚本上下文
* @param returnValue 即将要返回到页面的值
* @param request HttpServletRequest
* @param response HttpServletResponse
* @param throwable 异常对象
*/
default
void
afterCompletion
(
ApiInfo
info
,
MagicScriptContext
context
,
Object
returnValue
,
MagicHttpServletRequest
request
,
MagicHttpServletResponse
response
,
Throwable
throwable
)
{
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/interceptor/ResultProvider.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.interceptor
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.ssssssss.magicapi.modules.db.model.Page
;
import
org.ssssssss.magicapi.modules.db.model.PageResult
;
import
org.ssssssss.magicapi.core.context.RequestEntity
;
import
org.ssssssss.script.exception.MagicScriptAssertException
;
import
org.ssssssss.script.exception.MagicScriptException
;
import
org.ssssssss.script.functions.ObjectConvertExtension
;
import
org.ssssssss.script.runtime.ExitValue
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Objects
;
import
static
org
.
ssssssss
.
magicapi
.
core
.
config
.
Constants
.*;
/**
* 结果构建接口
*
* @author mxd
*/
public
interface
ResultProvider
{
Logger
logger
=
LoggerFactory
.
getLogger
(
ResultProvider
.
class
);
/**
* 根据异常内容构建结果
*
* @param requestEntity 请求信息
* @param root 异常对象
*/
default
Object
buildResult
(
RequestEntity
requestEntity
,
Throwable
root
)
{
MagicScriptException
se
=
null
;
Throwable
parent
=
root
;
do
{
if
(
parent
instanceof
MagicScriptAssertException
)
{
MagicScriptAssertException
sae
=
(
MagicScriptAssertException
)
parent
;
return
buildResult
(
requestEntity
,
sae
.
getCode
(),
sae
.
getMessage
());
}
if
(
parent
instanceof
MagicScriptException
)
{
se
=
(
MagicScriptException
)
parent
;
}
}
while
((
parent
=
parent
.
getCause
())
!=
null
);
logger
.
error
(
"调用接口出错"
,
root
);
if
(
se
!=
null
)
{
return
buildException
(
requestEntity
,
se
);
}
return
buildException
(
requestEntity
,
root
);
}
/**
* 构建JSON返回结果,code和message 默认为 1 success
*
* @param requestEntity 请求相关信息
* @param data 返回内容
*/
default
Object
buildResult
(
RequestEntity
requestEntity
,
Object
data
)
{
if
(
data
instanceof
ExitValue
)
{
ExitValue
exitValue
=
(
ExitValue
)
data
;
Object
[]
values
=
exitValue
.
getValues
();
int
code
=
values
.
length
>
0
?
ObjectConvertExtension
.
asInt
(
values
[
0
],
RESPONSE_CODE_SUCCESS
)
:
RESPONSE_CODE_SUCCESS
;
String
message
=
values
.
length
>
1
?
Objects
.
toString
(
values
[
1
],
RESPONSE_MESSAGE_SUCCESS
)
:
RESPONSE_MESSAGE_SUCCESS
;
return
buildResult
(
requestEntity
,
code
,
message
,
values
.
length
>
2
?
values
[
2
]
:
null
);
}
return
buildResult
(
requestEntity
,
RESPONSE_CODE_SUCCESS
,
RESPONSE_MESSAGE_SUCCESS
,
data
);
}
/**
* 构建JSON返回结果
*
* @param requestEntity 请求相关信息
* @param code 状态码
* @param message 状态说明
*/
default
Object
buildResult
(
RequestEntity
requestEntity
,
int
code
,
String
message
)
{
return
buildResult
(
requestEntity
,
code
,
message
,
null
);
}
/**
* 构建异常返回结果
*
* @param requestEntity 请求相关信息
* @param throwable 异常信息
* @since 1.2.2
*/
default
Object
buildException
(
RequestEntity
requestEntity
,
Throwable
throwable
)
{
return
buildResult
(
requestEntity
,
RESPONSE_CODE_EXCEPTION
,
"系统内部出现错误"
);
}
/**
* 构建JSON返回结果
*
* @param requestEntity 请求相关信息
* @param code 状态码
* @param message 状态说明
* @param data 数据内容,可以通过data的类型判断是否是分页结果进行区分普通结果集和分页结果集
*/
Object
buildResult
(
RequestEntity
requestEntity
,
int
code
,
String
message
,
Object
data
);
/**
* @param requestEntity 请求相关信息
* @param page 分页对象
* @param total 总数
* @param data 数据内容
*/
default
Object
buildPageResult
(
RequestEntity
requestEntity
,
Page
page
,
long
total
,
List
<
Map
<
String
,
Object
>>
data
)
{
return
new
PageResult
<>(
total
,
data
);
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/logging/Formatter.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.logging
;
import
ch.qos.logback.classic.ClassicConstants
;
import
ch.qos.logback.core.CoreConstants
;
import
java.io.PrintWriter
;
import
java.io.StringWriter
;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
public
class
Formatter
{
private
final
static
String
[]
SPACES
=
{
" "
,
" "
,
" "
,
" "
,
// 1,2,4,8
// spaces
" "
,
// 16 spaces
" "
};
// 32 spaces
private
final
static
CachingDateFormatter
CACHING_DATE_FORMATTER
=
new
CachingDateFormatter
(
"yyyy-MM-dd HH:mm:ss.SSS"
);
private
final
static
TargetLengthBasedClassNameAbbreviator
ABBREVIATOR
=
new
TargetLengthBasedClassNameAbbreviator
(
39
);
private
StringBuilder
buf
=
new
StringBuilder
();
private
Formatter
()
{
}
public
static
Formatter
create
()
{
return
new
Formatter
();
}
private
static
void
leftPad
(
StringBuilder
buf
,
String
s
,
int
desiredLength
)
{
int
actualLen
=
0
;
if
(
s
!=
null
)
{
actualLen
=
s
.
length
();
}
if
(
actualLen
<
desiredLength
)
{
spacePad
(
buf
,
desiredLength
-
actualLen
);
}
if
(
s
!=
null
)
{
buf
.
append
(
s
);
}
}
private
static
void
rightPad
(
StringBuilder
buf
,
String
s
,
int
desiredLength
)
{
int
actualLen
=
0
;
if
(
s
!=
null
)
{
actualLen
=
s
.
length
();
}
if
(
s
!=
null
)
{
buf
.
append
(
s
);
}
if
(
actualLen
<
desiredLength
)
{
spacePad
(
buf
,
desiredLength
-
actualLen
);
}
}
/**
* Fast space padding method.
*/
private
static
void
spacePad
(
StringBuilder
sbuf
,
int
length
)
{
while
(
length
>=
32
)
{
sbuf
.
append
(
SPACES
[
5
]);
length
-=
32
;
}
for
(
int
i
=
4
;
i
>=
0
;
i
--)
{
if
((
length
&
(
1
<<
i
))
!=
0
)
{
sbuf
.
append
(
SPACES
[
i
]);
}
}
}
public
Formatter
timestamp
(
long
timestamp
)
{
buf
.
append
(
CACHING_DATE_FORMATTER
.
format
(
timestamp
));
return
this
;
}
public
Formatter
space
()
{
buf
.
append
(
SPACES
[
0
]);
return
this
;
}
public
Formatter
value
(
String
value
)
{
buf
.
append
(
value
);
return
this
;
}
public
Formatter
newline
()
{
buf
.
append
(
"\n"
);
return
this
;
}
public
Formatter
thread
(
String
value
)
{
return
alignment
(
value
,
15
,
15
,
true
,
true
);
}
public
Formatter
level
(
String
value
)
{
return
alignment
(
value
,
5
,
2147483647
,
true
,
true
);
}
public
Formatter
loggerName
(
String
value
)
{
return
alignment
(
ABBREVIATOR
.
abbreviate
(
value
),
40
,
40
,
true
,
false
);
}
@Override
public
String
toString
()
{
return
buf
.
toString
();
}
public
Formatter
throwable
(
Throwable
throwable
)
{
if
(
throwable
!=
null
)
{
this
.
newline
();
StringWriter
sw
=
new
StringWriter
(
1024
);
PrintWriter
writer
=
new
PrintWriter
(
sw
);
throwable
.
printStackTrace
(
writer
);
writer
.
close
();
buf
.
append
(
sw
.
getBuffer
());
this
.
newline
();
}
return
this
;
}
private
Formatter
alignment
(
String
value
,
int
min
,
int
max
,
boolean
leftTruncate
,
boolean
leftPad
)
{
if
(
value
==
null
)
{
if
(
0
<
min
)
{
spacePad
(
buf
,
min
);
}
}
else
{
int
len
=
value
.
length
();
if
(
len
>
max
)
{
if
(
leftTruncate
)
{
buf
.
append
(
value
.
substring
(
len
-
max
));
}
else
{
buf
.
append
(
value
,
0
,
max
);
}
}
else
if
(
len
<
min
)
{
if
(
leftPad
)
{
leftPad
(
buf
,
value
,
min
);
}
else
{
rightPad
(
buf
,
value
,
min
);
}
}
else
{
buf
.
append
(
value
);
}
}
return
this
;
}
private
static
class
CachingDateFormatter
{
final
SimpleDateFormat
sdf
;
long
lastTimestamp
=
-
1
;
String
cachedStr
=
null
;
public
CachingDateFormatter
(
String
pattern
)
{
sdf
=
new
SimpleDateFormat
(
pattern
);
}
public
final
String
format
(
long
now
)
{
// SimpleDateFormat is not thread safe.
// See also the discussion in http://jira.qos.ch/browse/LBCLASSIC-36
// DateFormattingThreadedThroughputCalculator and SelectiveDateFormattingRunnable
// are also noteworthy
// The now == lastTimestamp guard minimizes synchronization
synchronized
(
this
)
{
if
(
now
!=
lastTimestamp
)
{
lastTimestamp
=
now
;
cachedStr
=
sdf
.
format
(
new
Date
(
now
));
}
return
cachedStr
;
}
}
}
private
static
class
TargetLengthBasedClassNameAbbreviator
{
final
int
targetLength
;
public
TargetLengthBasedClassNameAbbreviator
(
int
targetLength
)
{
this
.
targetLength
=
targetLength
;
}
public
String
abbreviate
(
String
fqClassName
)
{
StringBuilder
buf
=
new
StringBuilder
(
targetLength
);
if
(
fqClassName
==
null
)
{
throw
new
IllegalArgumentException
(
"Class name may not be null"
);
}
int
inLen
=
fqClassName
.
length
();
if
(
inLen
<
targetLength
)
{
return
fqClassName
;
}
int
[]
dotIndexesArray
=
new
int
[
ClassicConstants
.
MAX_DOTS
];
// a.b.c contains 2 dots but 2+1 parts.
// see also http://jira.qos.ch/browse/LBCLASSIC-110
int
[]
lengthArray
=
new
int
[
ClassicConstants
.
MAX_DOTS
+
1
];
int
dotCount
=
computeDotIndexes
(
fqClassName
,
dotIndexesArray
);
// System.out.println();
// System.out.println("Dot count for [" + className + "] is " + dotCount);
// if there are not dots than abbreviation is not possible
if
(
dotCount
==
0
)
{
return
fqClassName
;
}
// printArray("dotArray: ", dotArray);
computeLengthArray
(
fqClassName
,
dotIndexesArray
,
lengthArray
,
dotCount
);
// printArray("lengthArray: ", lengthArray);
for
(
int
i
=
0
;
i
<=
dotCount
;
i
++)
{
if
(
i
==
0
)
{
buf
.
append
(
fqClassName
.
substring
(
0
,
lengthArray
[
i
]
-
1
));
}
else
{
buf
.
append
(
fqClassName
.
substring
(
dotIndexesArray
[
i
-
1
],
dotIndexesArray
[
i
-
1
]
+
lengthArray
[
i
]));
}
// System.out.println("i=" + i + ", buf=" + buf);
}
return
buf
.
toString
();
}
int
computeDotIndexes
(
final
String
className
,
int
[]
dotArray
)
{
int
dotCount
=
0
;
int
k
=
0
;
while
(
true
)
{
// ignore the $ separator in our computations. This is both convenient
// and sensible.
k
=
className
.
indexOf
(
CoreConstants
.
DOT
,
k
);
if
(
k
!=
-
1
&&
dotCount
<
ClassicConstants
.
MAX_DOTS
)
{
dotArray
[
dotCount
]
=
k
;
dotCount
++;
k
++;
}
else
{
break
;
}
}
return
dotCount
;
}
void
computeLengthArray
(
final
String
className
,
int
[]
dotArray
,
int
[]
lengthArray
,
int
dotCount
)
{
int
toTrim
=
className
.
length
()
-
targetLength
;
// System.out.println("toTrim=" + toTrim);
// int toTrimAvarage = 0;
int
len
;
for
(
int
i
=
0
;
i
<
dotCount
;
i
++)
{
int
previousDotPosition
=
-
1
;
if
(
i
>
0
)
{
previousDotPosition
=
dotArray
[
i
-
1
];
}
int
available
=
dotArray
[
i
]
-
previousDotPosition
-
1
;
// System.out.println("i=" + i + ", available = " + available);
len
=
(
available
<
1
)
?
available
:
1
;
// System.out.println("i=" + i + ", toTrim = " + toTrim);
if
(
toTrim
>
0
)
{
len
=
(
available
<
1
)
?
available
:
1
;
}
else
{
len
=
available
;
}
toTrim
-=
(
available
-
len
);
lengthArray
[
i
]
=
len
+
1
;
}
int
lastDotIndex
=
dotCount
-
1
;
lengthArray
[
dotCount
]
=
className
.
length
()
-
dotArray
[
lastDotIndex
];
}
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/logging/Log4j2LoggerContext.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.logging
;
import
org.apache.logging.log4j.LogManager
;
import
org.apache.logging.log4j.core.Filter
;
import
org.apache.logging.log4j.core.Layout
;
import
org.apache.logging.log4j.core.LogEvent
;
import
org.apache.logging.log4j.core.LoggerContext
;
import
org.apache.logging.log4j.core.appender.AbstractAppender
;
import
org.apache.logging.log4j.core.config.Configuration
;
import
org.apache.logging.log4j.core.config.LoggerConfig
;
import
org.apache.logging.log4j.core.config.Property
;
import
org.apache.logging.log4j.core.layout.PatternLayout
;
import
java.nio.charset.StandardCharsets
;
/**
* 对接Log4j2
*
* @author mxd
*/
public
class
Log4j2LoggerContext
implements
MagicLoggerContext
{
@Override
public
void
generateAppender
()
{
LoggerContext
context
=
(
LoggerContext
)
LogManager
.
getContext
(
false
);
Configuration
configuration
=
context
.
getConfiguration
();
LoggerConfig
logger
=
configuration
.
getRootLogger
();
PatternLayout
layout
=
PatternLayout
.
newBuilder
()
.
withCharset
(
StandardCharsets
.
UTF_8
)
.
withConfiguration
(
configuration
)
.
withPattern
(
"%d %t %p %X{TracingMsg} %c - %m%n"
)
.
build
();
MagicLog4j2Appender
appender
=
new
MagicLog4j2Appender
(
"Magic"
,
logger
.
getFilter
(),
layout
);
appender
.
start
();
configuration
.
addAppender
(
appender
);
logger
.
addAppender
(
appender
,
logger
.
getLevel
(),
logger
.
getFilter
());
context
.
updateLoggers
(
configuration
);
}
static
class
MagicLog4j2Appender
extends
AbstractAppender
{
MagicLog4j2Appender
(
String
name
,
Filter
filter
,
Layout
<
String
>
layout
)
{
super
(
name
,
filter
,
layout
,
true
,
Property
.
EMPTY_ARRAY
);
}
@Override
public
void
append
(
LogEvent
event
)
{
String
message
=
Formatter
.
create
()
.
timestamp
(
event
.
getTimeMillis
())
.
space
()
.
level
(
event
.
getLevel
().
toString
())
.
value
(
" --- ["
)
.
thread
(
event
.
getThreadName
())
.
value
(
"] "
)
.
loggerName
(
event
.
getLoggerName
())
.
value
(
": "
)
.
value
(
event
.
getMessage
().
getFormattedMessage
())
.
newline
()
.
throwable
(
event
.
getThrown
())
.
toString
();
MagicLoggerContext
.
println
(
message
);
}
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/logging/Log4jLoggerContext.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.logging
;
import
org.apache.log4j.AppenderSkeleton
;
import
org.apache.log4j.LogManager
;
import
org.apache.log4j.PatternLayout
;
import
org.apache.log4j.spi.LoggingEvent
;
import
org.apache.log4j.spi.RootLogger
;
/**
* 对接Log4j
*
* @author mxd
*/
public
class
Log4jLoggerContext
implements
MagicLoggerContext
{
@Override
public
void
generateAppender
()
{
RootLogger
logger
=
(
RootLogger
)
LogManager
.
getRootLogger
();
PatternLayout
patternLayout
=
new
PatternLayout
(
"%d %p [%c] - %m%n"
);
MagicLog4jAppender
magicLog4jAppender
=
new
MagicLog4jAppender
();
magicLog4jAppender
.
setLayout
(
patternLayout
);
logger
.
addAppender
(
magicLog4jAppender
);
}
static
class
MagicLog4jAppender
extends
AppenderSkeleton
{
@Override
protected
void
append
(
LoggingEvent
event
)
{
String
message
=
Formatter
.
create
()
.
timestamp
(
event
.
getTimeStamp
())
.
space
()
.
level
(
event
.
getLevel
().
toString
())
.
value
(
" --- ["
)
.
thread
(
event
.
getThreadName
())
.
value
(
"] "
)
.
loggerName
(
event
.
getLoggerName
())
.
value
(
": "
)
.
value
(
event
.
getRenderedMessage
())
.
newline
()
.
throwable
(
event
.
getThrowableInformation
()
==
null
?
null
:
event
.
getThrowableInformation
().
getThrowable
())
.
toString
();
MagicLoggerContext
.
println
(
message
);
}
@Override
public
void
close
()
{
}
@Override
public
boolean
requiresLayout
()
{
return
false
;
}
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/logging/LogbackLoggerContext.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.logging
;
import
ch.qos.logback.classic.LoggerContext
;
import
ch.qos.logback.classic.spi.ILoggingEvent
;
import
ch.qos.logback.classic.spi.IThrowableProxy
;
import
ch.qos.logback.classic.spi.ThrowableProxy
;
import
ch.qos.logback.core.UnsynchronizedAppenderBase
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
/**
* 对接Logback
*
* @author mxd
*/
public
class
LogbackLoggerContext
implements
MagicLoggerContext
{
@Override
public
void
generateAppender
()
{
LoggerContext
context
=
(
LoggerContext
)
LoggerFactory
.
getILoggerFactory
();
ch
.
qos
.
logback
.
classic
.
Logger
logger
=
context
.
getLogger
(
Logger
.
ROOT_LOGGER_NAME
);
MagicLogbackAppender
appender
=
new
MagicLogbackAppender
();
appender
.
setContext
(
context
);
appender
.
setName
(
LOGGER_NAME
);
appender
.
start
();
logger
.
addAppender
(
appender
);
}
static
class
MagicLogbackAppender
extends
UnsynchronizedAppenderBase
<
ILoggingEvent
>
{
@Override
protected
void
append
(
ILoggingEvent
event
)
{
Formatter
formatter
=
Formatter
.
create
()
.
timestamp
(
event
.
getTimeStamp
())
.
space
()
.
level
(
event
.
getLevel
().
toString
())
.
value
(
" --- ["
)
.
thread
(
event
.
getThreadName
())
.
value
(
"] "
)
.
loggerName
(
event
.
getLoggerName
())
.
value
(
": "
)
.
value
(
event
.
getFormattedMessage
())
.
newline
();
IThrowableProxy
proxy
=
event
.
getThrowableProxy
();
if
(
proxy
instanceof
ThrowableProxy
)
{
formatter
.
throwable
(((
ThrowableProxy
)
proxy
).
getThrowable
());
}
MagicLoggerContext
.
println
(
formatter
.
toString
());
}
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/logging/LoggerManager.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.logging
;
import
org.slf4j.ILoggerFactory
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
/**
* 日志管理
*
* @author mxd
*/
public
class
LoggerManager
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
LoggerManager
.
class
);
/**
* 创建一个新的appender至项目中,用于UI界面
*/
public
static
void
createMagicAppender
()
{
ILoggerFactory
loggerFactory
=
LoggerFactory
.
getILoggerFactory
();
String
loggerFactoryClassName
=
loggerFactory
.
getClass
().
getName
();
MagicLoggerContext
magicLoggerContext
=
null
;
// logback
if
(
"ch.qos.logback.classic.LoggerContext"
.
equalsIgnoreCase
(
loggerFactoryClassName
))
{
magicLoggerContext
=
new
LogbackLoggerContext
();
}
else
if
(
"org.apache.logging.slf4j.Log4jLoggerFactory"
.
equalsIgnoreCase
(
loggerFactoryClassName
))
{
// log4j2
magicLoggerContext
=
new
Log4j2LoggerContext
();
}
else
if
(
"org.slf4j.impl.Log4jLoggerFactory"
.
equalsIgnoreCase
(
loggerFactoryClassName
))
{
// log4j 1
magicLoggerContext
=
new
Log4jLoggerContext
();
}
if
(
magicLoggerContext
==
null
)
{
logger
.
error
(
"无法识别LoggerContext:{}"
,
loggerFactoryClassName
);
}
else
{
magicLoggerContext
.
generateAppender
();
}
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/logging/MagicLoggerContext.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.logging
;
import
org.ssssssss.magicapi.core.config.WebSocketSessionManager
;
/**
* 日志上下文
*
* @author mxd
*/
public
interface
MagicLoggerContext
{
String
LOGGER_NAME
=
"magic"
;
ThreadLocal
<
String
>
SESSION
=
new
InheritableThreadLocal
<>();
/**
* 打印日志
* re
*
* @param logInfo 日志信息
*/
static
void
println
(
String
logInfo
)
{
// 获取SessionId
String
sessionId
=
SESSION
.
get
();
if
(
sessionId
!=
null
)
{
WebSocketSessionManager
.
sendLogs
(
sessionId
,
logInfo
);
}
}
/**
* 移除ThreadLocal中的sessionId
*/
static
void
remove
()
{
SESSION
.
remove
();
}
/**
* 生成appender
*/
void
generateAppender
();
}
magic-api/src/main/java/org/ssssssss/magicapi/core/model/ApiInfo.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.model
;
import
com.fasterxml.jackson.core.type.TypeReference
;
import
org.ssssssss.magicapi.core.config.MagicConfiguration
;
import
org.ssssssss.magicapi.utils.JsonUtils
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
* 接口信息
*/
public
class
ApiInfo
extends
PathMagicEntity
{
/**
* 请求方法
*/
private
String
method
=
"GET"
;
/**
* 设置的请求参数
*/
private
List
<
Parameter
>
parameters
=
Collections
.
emptyList
();
/**
* 设置的接口选项
*/
private
List
<
Option
>
options
=
new
ArrayList
<>();
/**
* 请求体
*/
private
String
requestBody
;
/**
* 请求头
*/
private
List
<
Header
>
headers
=
Collections
.
emptyList
();
/**
* 路径变量
*/
private
List
<
Path
>
paths
=
Collections
.
emptyList
();
/**
* 输出结果
*/
private
String
responseBody
;
/**
* 接口描述
*/
private
String
description
;
/**
* 请求体属性
*/
private
BaseDefinition
requestBodyDefinition
;
/**
* 输出结果属性
*/
private
BaseDefinition
responseBodyDefinition
;
public
String
getMethod
()
{
return
method
;
}
public
void
setMethod
(
String
method
)
{
this
.
method
=
method
;
}
public
String
getResponseBody
()
{
return
responseBody
;
}
public
void
setResponseBody
(
String
responseBody
)
{
this
.
responseBody
=
responseBody
;
}
public
String
getRequestBody
()
{
return
requestBody
;
}
public
void
setRequestBody
(
String
requestBody
)
{
this
.
requestBody
=
requestBody
;
}
public
List
<
Path
>
getPaths
()
{
return
paths
;
}
public
void
setPaths
(
List
<
Path
>
paths
)
{
this
.
paths
=
paths
;
}
public
Map
<
String
,
String
>
options
()
{
Map
<
String
,
String
>
map
=
this
.
options
.
stream
()
.
collect
(
Collectors
.
toMap
(
BaseDefinition:
:
getName
,
it
->
String
.
valueOf
(
it
.
getValue
()),
(
o
,
n
)
->
n
));
MagicConfiguration
.
getMagicResourceService
().
getGroupsByFileId
(
this
.
id
)
.
stream
()
.
flatMap
(
it
->
it
.
getOptions
().
stream
())
.
forEach
(
option
->
{
if
(!
map
.
containsKey
(
option
.
getName
()))
{
map
.
put
(
option
.
getName
(),
String
.
valueOf
(
option
.
getValue
()));
}
});
return
map
;
}
// 兼容1.x处理。
public
void
setOptionMap
(
Map
<
String
,
Object
>
optionMap
)
{
}
public
String
getDescription
()
{
return
description
;
}
public
void
setDescription
(
String
description
)
{
this
.
description
=
description
;
}
public
List
<
Option
>
getOptions
()
{
return
options
;
}
public
void
setOption
(
List
<
Option
>
options
)
{
this
.
options
=
options
;
}
public
void
setOption
(
String
json
)
{
this
.
options
=
JsonUtils
.
readValue
(
Objects
.
toString
(
json
,
"[]"
),
new
TypeReference
<
List
<
Option
>>()
{
});
}
public
List
<
Parameter
>
getParameters
()
{
return
parameters
;
}
public
void
setParameters
(
List
<
Parameter
>
parameters
)
{
this
.
parameters
=
parameters
;
}
public
List
<
Header
>
getHeaders
()
{
return
headers
;
}
public
void
setHeaders
(
List
<
Header
>
headers
)
{
this
.
headers
=
headers
;
}
public
String
getOptionValue
(
Options
options
)
{
return
getOptionValue
(
options
.
getValue
());
}
public
String
getOptionValue
(
String
key
)
{
return
this
.
options
.
stream
()
.
filter
(
it
->
key
.
equals
(
it
.
getName
()))
.
findFirst
()
.
map
(
it
->
Objects
.
toString
(
it
.
getValue
(),
null
))
.
orElseGet
(()
->
MagicConfiguration
.
getMagicResourceService
().
getGroupsByFileId
(
this
.
id
)
.
stream
()
.
flatMap
(
it
->
it
.
getOptions
().
stream
())
.
filter
(
it
->
key
.
equals
(
it
.
getName
()))
.
findFirst
()
.
map
(
it
->
Objects
.
toString
(
it
.
getValue
(),
null
)).
orElse
(
null
)
);
}
public
BaseDefinition
getRequestBodyDefinition
()
{
return
requestBodyDefinition
;
}
public
void
setRequestBodyDefinition
(
BaseDefinition
requestBodyDefinition
)
{
this
.
requestBodyDefinition
=
requestBodyDefinition
;
}
public
BaseDefinition
getResponseBodyDefinition
()
{
return
responseBodyDefinition
;
}
public
void
setResponseBodyDefinition
(
BaseDefinition
responseBodyDefinition
)
{
this
.
responseBodyDefinition
=
responseBodyDefinition
;
}
public
ApiInfo
simple
()
{
ApiInfo
target
=
new
ApiInfo
();
super
.
simple
(
target
);
target
.
setMethod
(
this
.
getMethod
());
return
target
;
}
@Override
public
boolean
equals
(
Object
o
)
{
if
(
this
==
o
)
return
true
;
if
(
o
==
null
||
getClass
()
!=
o
.
getClass
())
return
false
;
ApiInfo
apiInfo
=
(
ApiInfo
)
o
;
return
Objects
.
equals
(
id
,
apiInfo
.
id
)
&&
Objects
.
equals
(
method
,
apiInfo
.
method
)
&&
Objects
.
equals
(
path
,
apiInfo
.
path
)
&&
Objects
.
equals
(
script
,
apiInfo
.
script
)
&&
Objects
.
equals
(
name
,
apiInfo
.
name
)
&&
Objects
.
equals
(
paths
,
apiInfo
.
paths
)
&&
Objects
.
equals
(
groupId
,
apiInfo
.
groupId
)
&&
Objects
.
equals
(
parameters
,
apiInfo
.
parameters
)
&&
Objects
.
equals
(
options
,
apiInfo
.
options
)
&&
Objects
.
equals
(
requestBody
,
apiInfo
.
requestBody
)
&&
Objects
.
equals
(
headers
,
apiInfo
.
headers
)
&&
Objects
.
equals
(
description
,
apiInfo
.
description
)
&&
Objects
.
equals
(
requestBodyDefinition
,
apiInfo
.
requestBodyDefinition
)
&&
Objects
.
equals
(
responseBodyDefinition
,
apiInfo
.
responseBodyDefinition
);
}
@Override
public
int
hashCode
()
{
return
Objects
.
hash
(
id
,
method
,
path
,
script
,
name
,
groupId
,
parameters
,
options
,
requestBody
,
headers
,
description
,
requestBodyDefinition
,
responseBodyDefinition
);
}
@Override
public
ApiInfo
copy
()
{
ApiInfo
info
=
new
ApiInfo
();
copyTo
(
info
);
info
.
setMethod
(
this
.
method
);
info
.
setParameters
(
this
.
parameters
);
info
.
setRequestBody
(
this
.
requestBody
);
info
.
setOption
(
this
.
options
);
info
.
setHeaders
(
this
.
headers
);
info
.
setResponseBody
(
this
.
responseBody
);
info
.
setDescription
(
this
.
description
);
info
.
setPaths
(
this
.
paths
);
info
.
setRequestBodyDefinition
(
this
.
requestBodyDefinition
);
info
.
setResponseBodyDefinition
(
this
.
responseBodyDefinition
);
return
info
;
}
}
magic-api/src/main/java/org/ssssssss/magicapi/core/model/Attributes.java
0 → 100644
View file @
02897568
package
org.ssssssss.magicapi.core.model
;
import
java.beans.Transient
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* 属性信息
*
* @param <T>
* @author mxd
*/
public
class
Attributes
<
T
>
{
protected
Map
<
String
,
T
>
properties
=
new
HashMap
<>();
/**
* 设置属性
*
* @param key key
* @param value value
*/
public
void
setAttribute
(
String
key
,
T
value
)
{
properties
.
put
(
key
,
value
);
}
/**
* 获取属性
*
* @param key key
*/
public
Object
getAttribute
(
String
key
)
{
return
properties
.
get
(
key
);
}
public
Map
<
String
,
T
>
getProperties
()
{
return
properties
;
}
public
void
setProperties
(
Map
<
String
,
T
>
properties
)
{
this
.
properties
=
properties
;
}
}
Prev
1
…
5
6
7
8
9
10
11
12
13
…
16
Next
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