Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wecloud_im_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
hewei
wecloud_im_server
Commits
a7892caa
Commit
a7892caa
authored
Jan 26, 2022
by
lixiaozhong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加actionMapping,将websocket的服务写法模仿springmvc。
parent
49239792
Hide whitespace changes
Inline
Side-by-side
Showing
52 changed files
with
2883 additions
and
6 deletions
+2883
-6
config/src/main/resources/config/application-dev.yml
+8
-6
config/src/main/resources/config/application.yml
+3
-0
core/src/main/java/com/wecloud/dispatch/ActionContext.java
+97
-0
core/src/main/java/com/wecloud/dispatch/ActionDispatcher.java
+305
-0
core/src/main/java/com/wecloud/dispatch/WsTestAction.java
+50
-0
core/src/main/java/com/wecloud/dispatch/annotation/ActionMapping.java
+26
-0
core/src/main/java/com/wecloud/dispatch/common/ActionMethod.java
+67
-0
core/src/main/java/com/wecloud/dispatch/common/ApplyInfo.java
+28
-0
core/src/main/java/com/wecloud/dispatch/common/RequestVO.java
+40
-0
core/src/main/java/com/wecloud/dispatch/config/ActionConfigurer.java
+16
-0
core/src/main/java/com/wecloud/dispatch/exception/ActionNotFoundException.java
+17
-0
core/src/main/java/com/wecloud/dispatch/exception/MappingException.java
+17
-0
core/src/main/java/com/wecloud/dispatch/extend/ActionBox.java
+21
-0
core/src/main/java/com/wecloud/dispatch/extend/ActionInterceptor.java
+21
-0
core/src/main/java/com/wecloud/dispatch/extend/ActionMessage.java
+17
-0
core/src/main/java/com/wecloud/dispatch/extend/ActionMethodInterceptor.java
+29
-0
core/src/main/java/com/wecloud/dispatch/extend/ActionRequest.java
+18
-0
core/src/main/java/com/wecloud/dispatch/extend/ActionResponse.java
+9
-0
core/src/main/java/com/wecloud/dispatch/extend/ArgumentBox.java
+15
-0
core/src/main/java/com/wecloud/dispatch/extend/ArgumentDefaultValueBuilder.java
+16
-0
core/src/main/java/com/wecloud/dispatch/extend/MethodArgumentResolver.java
+31
-0
core/src/main/java/com/wecloud/dispatch/extend/impl/DefaultActionBox.java
+41
-0
core/src/main/java/com/wecloud/dispatch/extend/impl/DefaultActionMessage.java
+42
-0
core/src/main/java/com/wecloud/dispatch/extend/impl/DefaultArgumentBox.java
+31
-0
core/src/main/java/com/wecloud/dispatch/extend/impl/DefaultArgumentDefaultValueBuilder.java
+84
-0
core/src/main/java/com/wecloud/dispatch/extend/impl/DefaultMethodArgumentResolver.java
+60
-0
core/src/main/java/com/wecloud/dispatch/factory/AbstractFactory.java
+107
-0
core/src/main/java/com/wecloud/dispatch/factory/ObjectFactory.java
+74
-0
core/src/main/java/com/wecloud/dispatch/general/GeneralMessageHandler.java
+54
-0
core/src/main/java/com/wecloud/dispatch/general/config/DispatcherConfig.java
+46
-0
core/src/main/java/com/wecloud/dispatch/general/config/GeneralActionConfigurerAdapter.java
+15
-0
core/src/main/java/com/wecloud/dispatch/general/config/GeneralActionDefaultConfigurer.java
+17
-0
core/src/main/java/com/wecloud/dispatch/general/config/GeneralActionDispatcher.java
+56
-0
core/src/main/java/com/wecloud/dispatch/general/config/GeneralActionDispatcherProperties.java
+214
-0
core/src/main/java/com/wecloud/dispatch/general/extend/ActionMessageResolver.java
+21
-0
core/src/main/java/com/wecloud/dispatch/general/extend/impl/ActionMessageResolverImpl.java
+33
-0
core/src/main/java/com/wecloud/dispatch/general/impl/GeneralActionBox.java
+37
-0
core/src/main/java/com/wecloud/dispatch/general/impl/GeneralActionInterceptor.java
+22
-0
core/src/main/java/com/wecloud/dispatch/general/impl/GeneralActionMethodValidInterceptor.java
+124
-0
core/src/main/java/com/wecloud/dispatch/general/impl/GeneralMethodArgumentResolver.java
+213
-0
core/src/main/java/com/wecloud/dispatch/registry/ActionBoxRegistry.java
+29
-0
core/src/main/java/com/wecloud/dispatch/registry/ActionInterceptorRegistry.java
+22
-0
core/src/main/java/com/wecloud/dispatch/registry/ActionMethodInterceptorRegistry.java
+22
-0
core/src/main/java/com/wecloud/dispatch/registry/ActionRegistry.java
+317
-0
core/src/main/java/com/wecloud/dispatch/registry/ArgumentDefaultValueBuilderRegistry.java
+33
-0
core/src/main/java/com/wecloud/dispatch/registry/MethodArgumentResolverRegistry.java
+45
-0
core/src/main/java/com/wecloud/dispatch/util/ClassScaner.java
+167
-0
core/src/main/java/com/wecloud/dispatch/util/ClassUtil.java
+32
-0
core/src/main/java/com/wecloud/im/netty/core/WsReadHandler.java
+6
-0
core/src/main/java/com/wecloud/im/ws/ImConstant.java
+2
-0
core/src/main/java/com/wecloud/im/ws/sender/ChannelSender.java
+14
-0
core/src/main/java/com/wecloud/utils/JsonUtils.java
+52
-0
No files found.
config/src/main/resources/config/application-dev.yml
View file @
a7892caa
...
@@ -15,9 +15,9 @@ spring-boot-plus:
...
@@ -15,9 +15,9 @@ spring-boot-plus:
spring
:
spring
:
datasource
:
datasource
:
url
:
jdbc:mysql://
localhost:3306/wecloud_
im?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
url
:
jdbc:mysql://
192.168.1.51:3306/wecloud-
im?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
username
:
root
username
:
mysql
password
:
123
password
:
mysql
#//测试外网
#//测试外网
# url: jdbc:mysql://18.136.207.16:3306/wecloud_im?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
# url: jdbc:mysql://18.136.207.16:3306/wecloud_im?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
...
@@ -27,14 +27,14 @@ spring:
...
@@ -27,14 +27,14 @@ spring:
# Redis配置
# Redis配置
redis
:
redis
:
database
:
0
database
:
0
host
:
localhost
host
:
192.168.1.51
password
:
password
:
port
:
6379
port
:
6379
cloud
:
cloud
:
nacos
:
nacos
:
discovery
:
discovery
:
server-addr
:
localhost
:8848
server-addr
:
192.168.1.51
:8848
dubbo
:
dubbo
:
...
@@ -42,7 +42,9 @@ dubbo:
...
@@ -42,7 +42,9 @@ dubbo:
port
:
20881
port
:
20881
name
:
dubbo
name
:
dubbo
registry
:
registry
:
address
:
nacos://localhost:8848?username=nacos&password=nacos
address
:
nacos://192.168.1.51:8848?username=nacos&password=nacos
provider
:
cluster
:
channelRouterCluster
# 打印SQL语句和结果集,本地开发环境可开启,线上注释掉
# 打印SQL语句和结果集,本地开发环境可开启,线上注释掉
mybatis-plus
:
mybatis-plus
:
...
...
config/src/main/resources/config/application.yml
View file @
a7892caa
...
@@ -396,3 +396,6 @@ info:
...
@@ -396,3 +396,6 @@ info:
project-knife4j
:
http://${spring-boot-plus.server-ip}:${server.port}${server.servlet.context-path}/doc.html
project-knife4j
:
http://${spring-boot-plus.server-ip}:${server.port}${server.servlet.context-path}/doc.html
############################## Spring boot admin end ###############################
############################## Spring boot admin end ###############################
websocket
:
action
:
scan-package
:
com.wecloud
core/src/main/java/com/wecloud/dispatch/ActionContext.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
;
import
com.wecloud.dispatch.annotation.ActionMapping
;
import
com.wecloud.dispatch.config.ActionConfigurer
;
import
com.wecloud.dispatch.extend.ActionBox
;
import
com.wecloud.dispatch.extend.impl.DefaultActionBox
;
import
com.wecloud.dispatch.registry.ActionBoxRegistry
;
import
com.wecloud.dispatch.registry.ActionInterceptorRegistry
;
import
com.wecloud.dispatch.registry.ActionMethodInterceptorRegistry
;
import
com.wecloud.dispatch.registry.ActionRegistry
;
import
com.wecloud.dispatch.registry.ArgumentDefaultValueBuilderRegistry
;
import
com.wecloud.dispatch.registry.MethodArgumentResolverRegistry
;
import
com.wecloud.dispatch.util.ClassScaner
;
import
lombok.extern.slf4j.Slf4j
;
import
java.util.Set
;
/**
* @author lixiaozhong
*/
@Slf4j
public
class
ActionContext
{
private
final
ActionRegistry
actionRegistry
=
new
ActionRegistry
();
private
final
ActionBoxRegistry
actionBoxRegistry
=
new
ActionBoxRegistry
();
private
final
ActionMethodInterceptorRegistry
actionMethodInterceptorRegistry
=
new
ActionMethodInterceptorRegistry
();
private
final
MethodArgumentResolverRegistry
methodArgumentResolverRegistry
=
new
MethodArgumentResolverRegistry
();
private
final
ActionInterceptorRegistry
actionInterceptorRegistry
=
new
ActionInterceptorRegistry
();
private
final
ActionBox
actionBox
=
new
DefaultActionBox
();
private
final
ArgumentDefaultValueBuilderRegistry
argumentDefaultValueBuilderRegistry
=
new
ArgumentDefaultValueBuilderRegistry
();
private
final
ActionDispatcher
actionDispatcher
;
public
ActionContext
(
ActionDispatcher
actionDispatcher
)
{
super
();
this
.
actionDispatcher
=
actionDispatcher
;
}
@SuppressWarnings
(
"unchecked"
)
public
void
scan
(
String
...
path
)
{
// 扫描包下面的所有被注解ActionMapping的类
Set
<
Class
<?>>
classSet
=
ClassScaner
.
scan
(
path
,
ActionMapping
.
class
);
for
(
Class
<?>
classType
:
classSet
)
{
log
.
info
(
"ActionMapping scan, find: {}"
,
classType
.
getTypeName
());
actionRegistry
.
add
(
classType
);
}
}
@SuppressWarnings
(
"unchecked"
)
public
void
cover
(
String
...
path
)
{
// 扫描xxx包下面的所有被注解ActionMapping的类
Set
<
Class
<?>>
classSet
=
ClassScaner
.
scan
(
path
,
ActionMapping
.
class
);
for
(
Class
<?>
classType
:
classSet
)
{
actionRegistry
.
cover
(
classType
);
}
}
public
void
cover
(
Class
<?>
classType
)
{
actionRegistry
.
cover
(
classType
);
}
public
void
addConfig
(
ActionConfigurer
actionConfigurer
)
{
actionConfigurer
.
addConfig
(
this
);
}
public
ActionRegistry
getActionRegistry
()
{
return
actionRegistry
;
}
public
ActionBoxRegistry
getActionBoxRegistry
()
{
return
actionBoxRegistry
;
}
public
MethodArgumentResolverRegistry
getMethodArgumentResolverRegistry
()
{
return
methodArgumentResolverRegistry
;
}
public
ActionInterceptorRegistry
getActionInterceptorRegistry
()
{
return
actionInterceptorRegistry
;
}
public
ActionBox
getActionBox
()
{
return
actionBox
;
}
public
ActionMethodInterceptorRegistry
getActionMethodInterceptorRegistry
()
{
return
actionMethodInterceptorRegistry
;
}
public
ArgumentDefaultValueBuilderRegistry
getArgumentDefaultValueBuilderRegistry
()
{
return
argumentDefaultValueBuilderRegistry
;
}
public
ActionDispatcher
getActionDispatcher
()
{
return
actionDispatcher
;
}
}
core/src/main/java/com/wecloud/dispatch/ActionDispatcher.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
;
import
com.wecloud.dispatch.common.ActionMethod
;
import
com.wecloud.dispatch.common.ApplyInfo
;
import
com.wecloud.dispatch.common.RequestVO
;
import
com.wecloud.dispatch.config.ActionConfigurer
;
import
com.wecloud.dispatch.exception.ActionNotFoundException
;
import
com.wecloud.dispatch.extend.ActionBox
;
import
com.wecloud.dispatch.extend.ActionInterceptor
;
import
com.wecloud.dispatch.extend.ActionMessage
;
import
com.wecloud.dispatch.extend.ActionMethodInterceptor
;
import
com.wecloud.dispatch.extend.ActionRequest
;
import
com.wecloud.dispatch.extend.ArgumentBox
;
import
com.wecloud.dispatch.extend.impl.DefaultActionMessage
;
import
com.wecloud.dispatch.extend.impl.DefaultArgumentBox
;
import
com.wecloud.dispatch.extend.impl.DefaultMethodArgumentResolver
;
import
com.wecloud.dispatch.registry.ActionBoxRegistry
;
import
com.wecloud.dispatch.registry.ActionInterceptorRegistry
;
import
com.wecloud.dispatch.registry.ActionRegistry
;
import
com.wecloud.dispatch.registry.MethodArgumentResolverRegistry
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.core.MethodParameter
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Modifier
;
import
java.util.List
;
/**
* @author lixiaozhong
*/
public
class
ActionDispatcher
{
protected
final
Logger
logger
=
LoggerFactory
.
getLogger
(
this
.
getClass
());
protected
ActionContext
actionContext
=
new
ActionContext
(
this
);
private
final
DefaultMethodArgumentResolver
defaultMethodArgumentResolver
=
new
DefaultMethodArgumentResolver
();
public
Object
action
(
String
action
,
RequestVO
message
)
{
ActionMessage
am
=
resolver
(
action
,
message
);
return
action
(
am
,
getArgumentBox
());
}
public
Object
action
(
String
action
,
RequestVO
message
,
ArgumentBox
argumentBox
)
{
Object
returnValue
=
null
;
ActionMessage
am
=
resolver
(
action
,
message
);
returnValue
=
action
(
am
,
argumentBox
==
null
?
getArgumentBox
()
:
argumentBox
);
return
returnValue
;
}
public
Object
action
(
ActionMessage
am
)
{
ActionRequest
request
=
getActionRequest
(
am
);
return
action
(
request
,
getArgumentBox
());
}
public
Object
action
(
ActionMessage
am
,
ArgumentBox
argumentBox
)
{
Object
returnValue
=
null
;
ActionRequest
request
=
getActionRequest
(
am
);
returnValue
=
action
(
request
,
argumentBox
);
return
returnValue
;
}
public
Object
action
(
ActionRequest
request
,
ArgumentBox
argumentBox
)
{
Object
returnValue
=
null
;
ApplyInfo
applyInfo
=
applyInterceptor
(
request
,
argumentBox
);
if
(
applyInfo
.
isApprove
())
{
returnValue
=
invokeForRequest
(
request
,
argumentBox
);
}
else
{
returnValue
=
applyInfo
.
getValue
();
}
return
returnValue
;
}
public
ActionRequest
getActionRequest
(
ActionMessage
am
)
{
String
actionCode
=
am
.
getAction
();
RequestVO
data
=
am
.
getMessage
();
ActionMethod
actionMethod
=
actionContext
.
getActionRegistry
().
getActionMethod
(
actionCode
);
if
(
null
==
actionMethod
)
{
throw
new
ActionNotFoundException
(
actionCode
+
" not found"
);
}
Object
action
=
null
;
Class
<?>
type
=
actionMethod
.
getActionClass
();
action
=
getAction
(
type
);
return
createActionRequest
(
actionCode
,
action
,
actionMethod
,
data
);
}
public
Object
getAction
(
Class
<?>
type
)
{
Object
a
=
actionContext
.
getActionBoxRegistry
().
getAction
(
type
);
if
(
a
==
null
)
{
a
=
actionContext
.
getActionBox
().
getAction
(
type
);
}
return
a
;
}
public
ActionRequest
createActionRequest
(
String
path
,
Object
action
,
Method
method
,
RequestVO
data
)
{
ActionRequest
actionRequest
=
new
ActionRequestImpl
(
path
,
action
,
new
ActionMethod
(
method
,
path
),
data
);
return
actionRequest
;
}
public
ActionRequest
createActionRequest
(
String
path
,
Object
action
,
ActionMethod
actionMethod
,
RequestVO
data
)
{
ActionRequest
actionRequest
=
new
ActionRequestImpl
(
path
,
action
,
actionMethod
,
data
);
return
actionRequest
;
}
public
ApplyInfo
applyInterceptor
(
ActionRequest
request
,
ArgumentBox
argumentBox
)
{
ApplyInfo
applyInfo
=
null
;
List
<
ActionInterceptor
>
list
=
actionContext
.
getActionInterceptorRegistry
().
getActionInterceptorList
();
if
(
null
!=
list
)
{
for
(
ActionInterceptor
ai
:
list
)
{
applyInfo
=
ai
.
previous
(
actionContext
,
request
,
argumentBox
);
if
(
null
==
applyInfo
)
{
applyInfo
=
new
ApplyInfo
();
break
;
}
else
if
(!
applyInfo
.
isApprove
())
{
break
;
}
}
}
if
(
null
==
applyInfo
)
{
applyInfo
=
new
ApplyInfo
();
applyInfo
.
setApprove
(
true
);
}
return
applyInfo
;
}
public
Object
invokeForRequest
(
ActionRequest
request
,
ArgumentBox
argumentBox
)
{
Object
[]
args
=
getMethodArgumentValues
(
request
,
argumentBox
);
if
(
logger
.
isTraceEnabled
())
{
// StringBuilder sb = new StringBuilder("Invoking [");
// logger.debug(sb.toString());
}
Object
bean
=
request
.
getAction
();
ActionMethod
actionMethod
=
request
.
getActionMethod
();
Object
returnValue
=
null
;
ApplyInfo
applyInfo
=
applyActionMethodInterceptor
(
bean
,
actionMethod
.
getMethod
(),
args
,
actionMethod
.
getMethodParameters
(),
request
,
argumentBox
);
if
(
applyInfo
.
isApprove
())
{
returnValue
=
doInvoke
(
bean
,
actionMethod
.
getMethod
(),
args
);
if
(
logger
.
isTraceEnabled
())
{
logger
.
trace
(
"Method ["
+
actionMethod
.
getMethod
().
getName
()
+
"] returned ["
+
returnValue
+
"]"
);
}
}
else
{
returnValue
=
applyInfo
.
getValue
();
}
return
returnValue
;
}
public
ApplyInfo
applyActionMethodInterceptor
(
Object
bean
,
Method
method
,
Object
[]
args
,
MethodParameter
[]
parameter
,
ActionRequest
request
,
ArgumentBox
argumentBox
)
{
ApplyInfo
applyInfo
=
null
;
List
<
ActionMethodInterceptor
>
list
=
actionContext
.
getActionMethodInterceptorRegistry
().
getList
();
if
(
null
!=
list
)
{
for
(
ActionMethodInterceptor
ai
:
list
)
{
applyInfo
=
ai
.
intercept
(
actionContext
,
bean
,
method
,
args
,
parameter
,
request
,
argumentBox
);
if
(
null
==
applyInfo
)
{
applyInfo
=
new
ApplyInfo
();
break
;
}
else
if
(!
applyInfo
.
isApprove
())
{
break
;
}
}
}
if
(
null
==
applyInfo
)
{
applyInfo
=
new
ApplyInfo
();
applyInfo
.
setApprove
(
true
);
}
return
applyInfo
;
}
public
Object
[]
getMethodArgumentValues
(
ActionRequest
request
,
ArgumentBox
argumentBox
)
{
ActionMethod
actionMethod
=
request
.
getActionMethod
();
MethodParameter
[]
parameters
=
actionMethod
.
getMethodParameters
();
Object
[]
args
=
new
Object
[
parameters
.
length
];
for
(
int
i
=
0
;
i
<
parameters
.
length
;
i
++)
{
MethodParameter
parameter
=
parameters
[
i
];
// parameter.initParameterNameDiscovery(this.parameterNameDiscoverer);
// GenericTypeResolver.resolveParameterType(parameter, getBean().getClass());
if
(
this
.
actionContext
.
getMethodArgumentResolverRegistry
().
supportsParameter
(
parameter
))
{
args
[
i
]
=
this
.
actionContext
.
getMethodArgumentResolverRegistry
().
resolveArgument
(
actionContext
,
parameter
,
request
,
argumentBox
);
continue
;
}
if
(
args
[
i
]
==
null
)
{
args
[
i
]
=
defaultMethodArgumentResolver
.
resolveArgument
(
actionContext
,
parameter
,
request
,
argumentBox
);
}
if
(
args
[
i
]
==
null
)
{
String
msg
=
(
"No suitable resolver for argument"
+
i
);
throw
new
IllegalStateException
(
msg
);
}
}
return
args
;
}
public
Object
doInvoke
(
Object
bean
,
Method
method
,
Object
...
args
)
{
try
{
makeAccessible
(
method
);
return
method
.
invoke
(
bean
,
args
);
}
catch
(
IllegalArgumentException
e
)
{
throw
e
;
}
catch
(
RuntimeException
e
)
{
throw
e
;
}
catch
(
InvocationTargetException
e
)
{
Throwable
t
=
e
.
getTargetException
();
if
(
t
instanceof
RuntimeException
)
{
throw
(
RuntimeException
)
t
;
}
String
message
=
(
e
.
getMessage
()
!=
null
?
e
.
getMessage
()
:
"方法调用异常"
);
throw
new
IllegalStateException
(
message
,
e
);
}
catch
(
IllegalAccessException
e
)
{
Throwable
t
=
e
.
getCause
();
if
(
t
instanceof
RuntimeException
)
{
throw
(
RuntimeException
)
t
;
}
String
message
=
(
e
.
getMessage
()
!=
null
?
e
.
getMessage
()
:
"非法访问"
);
throw
new
IllegalStateException
(
message
,
e
);
}
}
public
void
makeAccessible
(
Method
method
)
{
boolean
isNotAccessible
=
(!
Modifier
.
isPublic
(
method
.
getModifiers
())
||
!
Modifier
.
isPublic
(
method
.
getDeclaringClass
().
getModifiers
()))
&&
!
method
.
isAccessible
();
if
(
isNotAccessible
)
{
method
.
setAccessible
(
true
);
}
}
public
ArgumentBox
getArgumentBox
()
{
ArgumentBox
ab
=
new
DefaultArgumentBox
();
return
ab
;
}
public
ActionMessage
resolver
(
String
action
,
RequestVO
message
)
{
ActionMessage
am
=
new
DefaultActionMessage
(
action
,
message
);
return
am
;
}
public
void
scan
(
String
...
path
)
{
actionContext
.
scan
(
path
);
}
public
void
cover
(
String
...
path
)
{
actionContext
.
cover
(
path
);
}
public
void
cover
(
Class
<?>
classType
)
{
actionContext
.
cover
(
classType
);
}
public
void
addConfig
(
ActionConfigurer
actionConfigurer
)
{
actionContext
.
addConfig
(
actionConfigurer
);
}
public
ActionRegistry
getActionRegistry
()
{
return
actionContext
.
getActionRegistry
();
}
public
ActionBoxRegistry
getActionBoxRegistry
()
{
return
actionContext
.
getActionBoxRegistry
();
}
public
MethodArgumentResolverRegistry
getMethodArgumentResolverRegistry
()
{
return
actionContext
.
getMethodArgumentResolverRegistry
();
}
public
ActionInterceptorRegistry
getActionInterceptorRegistry
()
{
return
actionContext
.
getActionInterceptorRegistry
();
}
public
ActionBox
getActionBox
()
{
return
actionContext
.
getActionBox
();
}
class
ActionRequestImpl
implements
ActionRequest
{
private
ActionMethod
actionMethod
;
private
Object
action
;
private
RequestVO
data
;
private
String
path
;
ActionRequestImpl
(
String
path
,
Object
action
,
ActionMethod
actionMethod
,
RequestVO
data
)
{
this
.
path
=
path
;
this
.
action
=
action
;
this
.
actionMethod
=
actionMethod
;
this
.
data
=
data
;
}
@Override
public
Object
getAction
()
{
return
this
.
action
;
}
@Override
public
RequestVO
getData
()
{
return
this
.
data
;
}
@Override
public
ActionMethod
getActionMethod
()
{
return
this
.
actionMethod
;
}
@Override
public
String
getPath
()
{
return
path
;
}
}
}
core/src/main/java/com/wecloud/dispatch/WsTestAction.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
;
import
com.wecloud.dispatch.annotation.ActionMapping
;
import
com.wecloud.im.ws.model.WsResponse
;
import
com.wecloud.im.ws.model.request.PushVO
;
import
com.wecloud.utils.JsonUtils
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
/**
* @author lixiaozhong
*/
@Component
@ActionMapping
(
value
=
"sendtest"
)
@Slf4j
public
class
WsTestAction
{
/**
* test
* @param reqId
* @param nihao
* @param push
* @param pList
* @param pSet
* @param pMap
*/
@ActionMapping
(
value
=
"gogo"
)
public
WsResponse
<
Boolean
>
groupChat
(
String
reqId
,
@RequestParam
(
"hello"
)
String
nihao
,
PushVO
push
,
ArrayList
<
PushVO
>
pList
,
Set
<
PushVO
>
pSet
,
Map
<
String
,
String
>
pMap
)
{
log
.
info
(
reqId
);
log
.
info
(
nihao
);
log
.
info
(
JsonUtils
.
encodeJson
(
push
));
log
.
info
(
JsonUtils
.
encodeJson
(
pList
));
log
.
info
(
JsonUtils
.
encodeJson
(
pSet
));
log
.
info
(
JsonUtils
.
encodeJson
(
pMap
));
WsResponse
<
Boolean
>
wsResponse
=
new
WsResponse
<>();
wsResponse
.
setCmd
(
0
).
setData
(
true
).
setCode
(
0
).
setMsg
(
"msg"
).
setReqId
(
reqId
);
return
wsResponse
;
}
}
core/src/main/java/com/wecloud/dispatch/annotation/ActionMapping.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
annotation
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* @author lixiaozhong
*/
@Target
({
ElementType
.
METHOD
,
ElementType
.
TYPE
})
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
ActionMapping
{
/**
* Mapping映射字段
* @return
*/
String
[]
value
()
default
""
;
/**
*
* @return
*/
int
order
()
default
10
;
}
core/src/main/java/com/wecloud/dispatch/common/ActionMethod.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
common
;
import
org.springframework.core.DefaultParameterNameDiscoverer
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.core.annotation.SynthesizingMethodParameter
;
import
java.lang.reflect.Method
;
/**
* @author lixiaozhong
*/
public
class
ActionMethod
{
private
Class
<?>
actionClass
;
private
Method
method
;
private
MethodParameter
[]
methodParameters
;
private
String
methodPath
;
// public ActionMethod(Class<?> actionClass, Method method) {
// this.actionClass = actionClass;
// this.method = method;
// initialize(method);
// }
public
ActionMethod
(
Method
method
,
String
methodPath
)
{
this
.
actionClass
=
method
.
getDeclaringClass
();
this
.
method
=
method
;
this
.
methodPath
=
methodPath
;
initialize
(
method
);
}
private
void
initialize
(
Method
method
)
{
methodParameters
=
initMethodParameters
(
method
);
}
private
MethodParameter
[]
initMethodParameters
(
Method
method
)
{
int
count
=
method
.
getParameterCount
();
MethodParameter
[]
result
=
new
MethodParameter
[
count
];
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
SynthesizingMethodParameter
parameter
=
SynthesizingMethodParameter
.
forExecutable
(
method
,
i
);
parameter
.
withContainingClass
(
this
.
actionClass
);
parameter
.
initParameterNameDiscovery
(
new
DefaultParameterNameDiscoverer
());
result
[
i
]
=
parameter
;
}
return
result
;
}
public
Class
<?>
getActionClass
()
{
return
actionClass
;
}
public
Method
getMethod
()
{
return
method
;
}
public
MethodParameter
[]
getMethodParameters
()
{
return
methodParameters
;
}
public
String
getMethodPath
()
{
return
methodPath
;
}
public
void
setMethodPath
(
String
methodPath
)
{
this
.
methodPath
=
methodPath
;
}
}
core/src/main/java/com/wecloud/dispatch/common/ApplyInfo.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
common
;
/**
* @author lixiaozhong
*/
public
class
ApplyInfo
{
private
boolean
approve
;
private
Object
value
;
public
boolean
isApprove
()
{
return
approve
;
}
public
void
setApprove
(
boolean
approve
)
{
this
.
approve
=
approve
;
}
public
Object
getValue
()
{
return
value
;
}
public
void
setValue
(
Object
value
)
{
this
.
value
=
value
;
}
}
core/src/main/java/com/wecloud/dispatch/common/RequestVO.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
common
;
import
lombok.NoArgsConstructor
;
import
java.util.HashMap
;
/**
* @author lixiaozhong
*/
@NoArgsConstructor
public
class
RequestVO
extends
HashMap
<
String
,
Object
>
{
/**
* 请求的参数 action,用来寻找action类的path
*/
private
String
action
;
/**
* 请求id, 以判空是否请求成功, 服务端处理完成后 返回此id
* 由前端生成,可以用uuid,也可以用时间戳
*/
private
String
reqId
;
public
String
getAction
()
{
return
(
String
)
this
.
get
(
"action"
);
}
public
void
setAction
(
String
action
)
{
this
.
put
(
"action"
,
action
);
}
public
String
getReqId
()
{
return
(
String
)
this
.
get
(
"reqId"
);
}
public
void
setReqId
(
String
reqId
)
{
this
.
put
(
"reqId"
,
reqId
);
}
}
core/src/main/java/com/wecloud/dispatch/config/ActionConfigurer.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
config
;
import
com.wecloud.dispatch.ActionContext
;
/**
* @author lixiaozhong
*/
public
interface
ActionConfigurer
{
/**
* 为了方便将配置项写入actionContext
* @param actionContext
*/
public
void
addConfig
(
ActionContext
actionContext
);
}
core/src/main/java/com/wecloud/dispatch/exception/ActionNotFoundException.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
exception
;
/**
* @author lixiaozhong
*/
public
class
ActionNotFoundException
extends
RuntimeException
{
private
static
final
long
serialVersionUID
=
1L
;
public
ActionNotFoundException
()
{
super
();
}
public
ActionNotFoundException
(
String
message
)
{
super
(
message
);
}
}
core/src/main/java/com/wecloud/dispatch/exception/MappingException.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
exception
;
/**
* @author lixiaozhong
*/
public
class
MappingException
extends
RuntimeException
{
private
static
final
long
serialVersionUID
=
1L
;
public
MappingException
()
{
super
();
}
public
MappingException
(
String
message
)
{
super
(
message
);
}
}
core/src/main/java/com/wecloud/dispatch/extend/ActionBox.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
extend
;
/**
* @author lixiaozhong
*/
public
interface
ActionBox
{
/**
* 获取action对象
* @param type
* @return
*/
public
Object
getAction
(
Class
<?>
type
);
/**
* 获取action对象
* @param className
* @return
*/
public
Object
getAction
(
String
className
);
}
core/src/main/java/com/wecloud/dispatch/extend/ActionInterceptor.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
extend
;
import
com.wecloud.dispatch.ActionContext
;
import
com.wecloud.dispatch.common.ApplyInfo
;
/**
* @author lixiaozhong
*/
public
interface
ActionInterceptor
{
/**
*
* 执行前拦截
*
* @param actionContext
* @param request
* @param argumentBox
* @return
*/
public
ApplyInfo
previous
(
ActionContext
actionContext
,
ActionRequest
request
,
ArgumentBox
argumentBox
);
}
core/src/main/java/com/wecloud/dispatch/extend/ActionMessage.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
extend
;
import
com.wecloud.dispatch.common.RequestVO
;
/**
* @author lixiaozhong
*/
public
interface
ActionMessage
{
void
setMessage
(
RequestVO
message
);
RequestVO
getMessage
();
String
getAction
();
void
setAction
(
String
action
);
}
core/src/main/java/com/wecloud/dispatch/extend/ActionMethodInterceptor.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
extend
;
import
com.wecloud.dispatch.ActionContext
;
import
com.wecloud.dispatch.common.ApplyInfo
;
import
org.springframework.core.MethodParameter
;
import
java.lang.reflect.Method
;
/**
* 切面
* @author lixiaozhong
*/
public
interface
ActionMethodInterceptor
{
/**
*
* 方法切面
*
* @param actionContext
* @param object
* @param method
* @param array
* @param parameter
* @param request
* @param argumentBox
* @return
*/
ApplyInfo
intercept
(
ActionContext
actionContext
,
Object
object
,
Method
method
,
Object
[]
array
,
MethodParameter
[]
parameter
,
ActionRequest
request
,
ArgumentBox
argumentBox
);
}
core/src/main/java/com/wecloud/dispatch/extend/ActionRequest.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
extend
;
import
com.wecloud.dispatch.common.ActionMethod
;
import
com.wecloud.dispatch.common.RequestVO
;
/**
* @author lixiaozhong
*/
public
interface
ActionRequest
{
String
getPath
();
Object
getAction
();
RequestVO
getData
();
ActionMethod
getActionMethod
();
}
core/src/main/java/com/wecloud/dispatch/extend/ActionResponse.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
extend
;
/**
* @author lixiaozhong
*/
public
interface
ActionResponse
{
void
write
(
Object
data
);
}
core/src/main/java/com/wecloud/dispatch/extend/ArgumentBox.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
extend
;
import
java.util.Set
;
/**
* @author lixiaozhong
*/
public
interface
ArgumentBox
{
<
T
>
T
get
(
Object
key
);
void
put
(
Object
key
,
Object
object
);
Set
<
Object
>
keySet
();
}
core/src/main/java/com/wecloud/dispatch/extend/ArgumentDefaultValueBuilder.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
extend
;
/**
* @author lixiaozhong
*/
public
interface
ArgumentDefaultValueBuilder
{
/**
*
* 参数默认值创建
*
* @param classType
* @return
*/
Object
build
(
Class
<?>
classType
);
}
core/src/main/java/com/wecloud/dispatch/extend/MethodArgumentResolver.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
extend
;
import
com.wecloud.dispatch.ActionContext
;
import
org.springframework.core.MethodParameter
;
/**
* @author lixiaozhong
*/
public
interface
MethodArgumentResolver
{
/**
*
* 是否支持<br>
*
* @param parameter
* @return
*/
boolean
supportsParameter
(
MethodParameter
parameter
);
/**
*
* 解析参数<br>
*
* @param actionContext
* @param parameter
* @param request
* @param argumentBox
* @return
*/
Object
resolveArgument
(
ActionContext
actionContext
,
MethodParameter
parameter
,
ActionRequest
request
,
ArgumentBox
argumentBox
);
}
core/src/main/java/com/wecloud/dispatch/extend/impl/DefaultActionBox.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
extend
.
impl
;
import
com.wecloud.dispatch.extend.ActionBox
;
import
com.wecloud.dispatch.factory.ObjectFactory
;
import
java.util.HashMap
;
import
java.util.Map
;
/**
* @author lixiaozhong
*/
public
class
DefaultActionBox
implements
ActionBox
{
Map
<
String
,
Class
<?>>
classMap
=
new
HashMap
<>();
ObjectFactory
objectFactory
=
new
ObjectFactory
();
@Override
public
Object
getAction
(
Class
<?>
type
)
{
return
objectFactory
.
getObject
(
type
);
}
@Override
public
Object
getAction
(
String
className
)
{
Class
<?>
type
=
null
;
if
(
classMap
.
containsKey
(
className
))
{
type
=
classMap
.
get
(
className
);
}
else
{
try
{
type
=
Class
.
forName
(
className
);
classMap
.
put
(
className
,
type
);
}
catch
(
Exception
e
)
{
classMap
.
put
(
className
,
null
);
}
}
if
(
null
==
type
)
{
return
null
;
}
else
{
return
getAction
(
type
);
}
}
}
core/src/main/java/com/wecloud/dispatch/extend/impl/DefaultActionMessage.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
extend
.
impl
;
import
com.wecloud.dispatch.common.RequestVO
;
import
com.wecloud.dispatch.extend.ActionMessage
;
/**
* @author lixiaozhong
*/
public
class
DefaultActionMessage
implements
ActionMessage
{
String
action
;
RequestVO
message
;
public
DefaultActionMessage
()
{
}
public
DefaultActionMessage
(
String
action
,
RequestVO
message
)
{
this
.
message
=
message
;
this
.
action
=
action
;
}
@Override
public
RequestVO
getMessage
()
{
return
message
;
}
@Override
public
void
setMessage
(
RequestVO
message
)
{
this
.
message
=
message
;
}
@Override
public
String
getAction
()
{
return
action
;
}
@Override
public
void
setAction
(
String
action
)
{
this
.
action
=
action
;
}
}
core/src/main/java/com/wecloud/dispatch/extend/impl/DefaultArgumentBox.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
extend
.
impl
;
import
com.wecloud.dispatch.extend.ArgumentBox
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Set
;
/**
* @author lixiaozhong
*/
public
class
DefaultArgumentBox
implements
ArgumentBox
{
Map
<
Object
,
Object
>
map
=
new
HashMap
<>();
@SuppressWarnings
(
"unchecked"
)
@Override
public
<
T
>
T
get
(
Object
key
)
{
return
(
T
)
map
.
get
(
key
);
}
@Override
public
void
put
(
Object
key
,
Object
object
)
{
map
.
put
(
key
,
object
);
}
@Override
public
Set
<
Object
>
keySet
()
{
return
map
.
keySet
();
}
}
core/src/main/java/com/wecloud/dispatch/extend/impl/DefaultArgumentDefaultValueBuilder.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
extend
.
impl
;
import
com.wecloud.dispatch.extend.ArgumentDefaultValueBuilder
;
import
com.wecloud.dispatch.util.ClassUtil
;
import
java.lang.reflect.Array
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
/**
* @author lixiaozhong
*/
public
class
DefaultArgumentDefaultValueBuilder
implements
ArgumentDefaultValueBuilder
{
Map
<
Class
<?>,
Boolean
>
canNotInstanceMap
=
new
HashMap
<>();
@Override
public
Object
build
(
Class
<?>
classType
)
{
return
getValue
(
classType
);
}
private
Object
getValue
(
Class
<?>
clazz
)
{
Object
value
=
null
;
if
(
null
==
value
)
{
value
=
getDefaultValue
(
clazz
);
}
if
(
null
==
value
&&
ClassUtil
.
isCanInstance
(
clazz
)
&&
!
canNotInstanceMap
.
containsKey
(
clazz
))
{
value
=
getObject
(
clazz
);
}
return
value
;
}
private
<
T
>
Object
getObject
(
Class
<
T
>
clazz
)
{
Object
object
=
null
;
if
(
ClassUtil
.
isCanInstance
(
clazz
)
&&
!
canNotInstanceMap
.
containsKey
(
clazz
))
{
try
{
object
=
clazz
.
newInstance
();
}
catch
(
InstantiationException
|
IllegalAccessException
e
)
{
canNotInstanceMap
.
put
(
clazz
,
false
);
}
}
return
object
;
}
/**
* 对象给默认值
*
*/
@SuppressWarnings
(
"unchecked"
)
public
<
T
>
T
getDefaultValue
(
Class
<
T
>
clazz
)
{
Object
object
=
null
;
if
(
List
.
class
.
isAssignableFrom
(
clazz
))
{
object
=
new
ArrayList
<
Object
>(
0
);
}
else
if
(
Map
.
class
.
isAssignableFrom
(
clazz
))
{
object
=
new
HashMap
<
Object
,
Object
>(
0
);
}
else
if
(
Set
.
class
.
isAssignableFrom
(
clazz
))
{
object
=
new
HashSet
<
Object
>(
0
);
}
else
if
(
clazz
.
isArray
())
{
Class
<?>
componentType
=
clazz
.
getComponentType
();
object
=
Array
.
newInstance
(
componentType
,
0
);
}
else
if
(
clazz
==
int
.
class
)
{
object
=
0
;
}
else
if
(
clazz
==
long
.
class
)
{
object
=
0L
;
}
else
if
(
clazz
==
float
.
class
)
{
object
=
0.0
F
;
}
else
if
(
clazz
==
double
.
class
)
{
object
=
0.00
D
;
}
else
if
(
clazz
==
byte
.
class
)
{
object
=
(
byte
)
0
;
}
else
if
(
clazz
==
char
.
class
)
{
object
=
'\u0000'
;
}
else
if
(
clazz
==
short
.
class
)
{
object
=
0
;
}
else
if
(
clazz
==
boolean
.
class
)
{
object
=
false
;
}
return
((
T
)
object
);
}
}
core/src/main/java/com/wecloud/dispatch/extend/impl/DefaultMethodArgumentResolver.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
extend
.
impl
;
import
com.wecloud.dispatch.ActionContext
;
import
com.wecloud.dispatch.extend.ActionRequest
;
import
com.wecloud.dispatch.extend.ArgumentBox
;
import
com.wecloud.dispatch.extend.MethodArgumentResolver
;
import
org.springframework.core.MethodParameter
;
import
java.util.Set
;
/**
* @author lixiaozhong
*/
public
class
DefaultMethodArgumentResolver
implements
MethodArgumentResolver
{
@Override
public
boolean
supportsParameter
(
MethodParameter
parameter
)
{
return
true
;
}
@Override
public
Object
resolveArgument
(
ActionContext
actionContext
,
MethodParameter
parameter
,
ActionRequest
request
,
ArgumentBox
argumentBox
)
{
// Type type = parameter.getGenericParameterType();
Class
<?>
clazz
=
parameter
.
getParameterType
();
Object
data
=
null
;
if
(
null
!=
clazz
)
{
if
(
clazz
.
isAssignableFrom
(
ActionContext
.
class
))
{
data
=
actionContext
;
}
else
if
(
clazz
.
isAssignableFrom
(
ActionRequest
.
class
))
{
data
=
request
;
}
else
if
(
clazz
.
isAssignableFrom
(
ArgumentBox
.
class
))
{
data
=
argumentBox
;
}
else
{
data
=
argumentBox
.
get
(
clazz
);
if
(
null
==
data
)
{
Set
<
Object
>
keys
=
argumentBox
.
keySet
();
if
(
null
!=
keys
)
{
for
(
Object
o
:
keys
)
{
if
(
o
instanceof
Class
)
{
Class
<?>
classKey
=
(
Class
<?>)
o
;
if
(
clazz
.
isAssignableFrom
(
classKey
))
{
data
=
argumentBox
.
get
(
o
);
break
;
}
}
}
}
}
if
(
null
==
data
)
{
data
=
getValue
(
actionContext
,
clazz
);
}
}
}
return
data
;
}
private
Object
getValue
(
ActionContext
actionContext
,
Class
<?>
clazz
)
{
return
actionContext
.
getArgumentDefaultValueBuilderRegistry
().
getValue
(
clazz
);
}
}
core/src/main/java/com/wecloud/dispatch/factory/AbstractFactory.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
factory
;
import
com.wecloud.dispatch.util.ClassUtil
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
java.lang.reflect.Array
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.locks.ReentrantLock
;
/**
* @author lixiaozhong
*/
public
abstract
class
AbstractFactory
{
protected
final
Logger
logger
=
LoggerFactory
.
getLogger
(
this
.
getClass
());
private
Map
<
Class
<?>,
Object
>
objectMap
=
new
ConcurrentHashMap
<>();
private
Map
<
Class
<?>,
Boolean
>
canNotInstanceMap
=
new
ConcurrentHashMap
<>();
private
ReentrantLock
lock
=
new
ReentrantLock
();
public
<
T
>
void
put
(
Class
<
T
>
defineClass
,
T
object
)
{
objectMap
.
put
(
defineClass
,
object
);
}
/**
* 根据class获取对象,均为单列(有待验证😂)
*
* @param classType
* @return T
*/
public
<
T
>
T
getObject
(
Class
<
T
>
classType
)
{
return
getObject
(
classType
,
false
,
false
);
}
/**
*
* @param classType
* @param createNew
* @return T
*/
public
<
T
>
T
getObject
(
Class
<
T
>
classType
,
boolean
createNew
)
{
return
getObject
(
classType
,
createNew
,
false
);
}
/**
*
* @param classType :被实例化的class对象
* @param createNew :true:不管对象是否存在,都新创建对象;false:如果对象已经存在就不新建对象
* @param cover :true:如果新建了对象,则覆盖原来的对象。false:不执行覆盖操作
* @return T
*/
@SuppressWarnings
(
"unchecked"
)
public
<
T
>
T
getObject
(
Class
<
T
>
classType
,
boolean
createNew
,
boolean
cover
)
{
Object
object
=
null
;
if
(
null
!=
classType
)
{
object
=
objectMap
.
get
(
classType
);
if
(
createNew
)
{
object
=
createObject
(
classType
);
if
((
cover
)
&&
null
!=
object
)
{
objectMap
.
put
(
classType
,
object
);
}
}
else
if
(
null
==
object
)
{
final
ReentrantLock
lock
=
this
.
lock
;
lock
.
lock
();
try
{
boolean
has
=
objectMap
.
containsKey
(
classType
);
object
=
objectMap
.
get
(
classType
);
if
(!
has
)
{
object
=
createObject
(
classType
);
// 原来对象不存在,或者覆盖,并且新创建的对象不能为空
if
((
cover
)
&&
null
!=
object
)
{
objectMap
.
put
(
classType
,
object
);
}
}
}
finally
{
lock
.
unlock
();
}
}
}
return
(
T
)
object
;
}
/**
* 根据class反射创建对象
*
* @param clazz
* @return
*/
public
Object
createObject
(
Class
<?>
clazz
)
{
Object
object
=
null
;
if
(!
canNotInstanceMap
.
containsKey
(
clazz
))
{
try
{
if
(
ClassUtil
.
isCanInstance
(
clazz
))
{
object
=
clazz
.
newInstance
();
}
else
if
(
clazz
.
isArray
())
{
Class
<?>
componentType
=
clazz
.
getComponentType
();
object
=
Array
.
newInstance
(
componentType
,
0
);
}
}
catch
(
Exception
e
)
{
canNotInstanceMap
.
put
(
clazz
,
false
);
logger
.
error
(
"初始化对象失败!"
,
e
);
}
}
return
object
;
}
}
core/src/main/java/com/wecloud/dispatch/factory/ObjectFactory.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
factory
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.locks.Lock
;
import
java.util.concurrent.locks.ReentrantLock
;
/**
* 管理存放系统对象
*
* @author lixiaozhong
*/
public
class
ObjectFactory
extends
AbstractFactory
{
private
Map
<
Class
<?>,
Class
<?>>
map
=
new
ConcurrentHashMap
<
Class
<?>,
Class
<?>>();
private
Map
<
Class
<?>,
Map
<
String
,
Object
>>
multipleMap
=
new
ConcurrentHashMap
<
Class
<?>,
Map
<
String
,
Object
>>();
private
Lock
lock
=
new
ReentrantLock
();
/**
* 注册定义类和实现类的关系<br>
*
* @param defineClass
* @param instanceClass
*/
public
<
T
>
void
register
(
Class
<
T
>
defineClass
,
Class
<?
extends
T
>
instanceClass
)
{
map
.
put
(
defineClass
,
instanceClass
);
}
@Override
public
<
T
>
T
getObject
(
Class
<
T
>
classType
)
{
return
getObject
(
classType
,
false
,
false
);
}
@Override
public
<
T
>
T
getObject
(
Class
<
T
>
classType
,
boolean
createNew
)
{
return
getObject
(
classType
,
createNew
,
false
);
}
@Override
@SuppressWarnings
(
"unchecked"
)
public
<
T
>
T
getObject
(
Class
<
T
>
classType
,
boolean
createNew
,
boolean
cover
)
{
T
o
=
null
;
Class
<
T
>
clazz
=
(
Class
<
T
>)
map
.
get
(
classType
);
if
(
null
!=
clazz
)
{
o
=
super
.
getObject
(
clazz
,
createNew
,
cover
);
}
else
{
o
=
super
.
getObject
(
classType
,
createNew
,
cover
);
}
return
o
;
}
@SuppressWarnings
(
"unchecked"
)
public
<
T
>
T
getObject
(
String
key
,
Class
<
T
>
classType
)
{
Object
o
=
null
;
lock
.
lock
();
try
{
Map
<
String
,
Object
>
objectMap
=
multipleMap
.
get
(
classType
);
if
(
null
==
objectMap
)
{
objectMap
=
new
ConcurrentHashMap
<
String
,
Object
>(
16
);
multipleMap
.
put
(
classType
,
objectMap
);
}
o
=
objectMap
.
get
(
key
);
if
(
null
==
o
)
{
o
=
super
.
createObject
(
classType
);
if
(
null
!=
o
)
{
objectMap
.
put
(
key
,
o
);
}
}
}
finally
{
lock
.
unlock
();
}
return
(
T
)
o
;
}
}
core/src/main/java/com/wecloud/dispatch/general/GeneralMessageHandler.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
general
;
import
com.wecloud.dispatch.common.RequestVO
;
import
com.wecloud.dispatch.extend.ActionMessage
;
import
com.wecloud.dispatch.extend.ArgumentBox
;
import
com.wecloud.dispatch.extend.impl.DefaultArgumentBox
;
import
com.wecloud.dispatch.general.config.GeneralActionDispatcher
;
import
com.wecloud.dispatch.general.extend.ActionMessageResolver
;
import
com.wecloud.im.ws.sender.ChannelSender
;
import
com.wecloud.utils.JsonUtils
;
import
io.geekidea.springbootplus.framework.common.exception.BusinessException
;
import
io.netty.channel.ChannelHandlerContext
;
import
io.netty.channel.socket.nio.NioSocketChannel
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
/**
* @author lixiaozhong
*/
@Component
@Slf4j
public
class
GeneralMessageHandler
{
@Autowired
private
GeneralActionDispatcher
generalActionDispatcher
;
@Autowired
private
ActionMessageResolver
actionMessageResolver
;
@Autowired
private
ChannelSender
channelSender
;
public
void
doMessage
(
Long
senderClientId
,
ChannelHandlerContext
ctx
,
String
data
)
{
if
(
log
.
isDebugEnabled
())
{
log
.
debug
(
"appWS收到data: {}\n senderClientId:{}, channelId:{}"
,
data
,
senderClientId
,
ctx
.
channel
().
id
().
asLongText
());
}
// 解析jsonO
RequestVO
requestVO
=
JsonUtils
.
decodeJson
(
data
,
RequestVO
.
class
);
if
(
null
==
requestVO
||
null
==
requestVO
.
getAction
())
{
throw
new
BusinessException
(
"null == requestVO || null == requestVO.getAction()"
);
}
ActionMessage
am
=
actionMessageResolver
.
resolver
(
generalActionDispatcher
,
requestVO
);
Object
res
=
generalActionDispatcher
.
action
(
am
);
channelSender
.
sendMsgLocal
((
NioSocketChannel
)
ctx
.
channel
(),
res
);
}
public
ArgumentBox
getArgumentBox
()
{
ArgumentBox
beanBox
=
new
DefaultArgumentBox
();
return
beanBox
;
}
}
core/src/main/java/com/wecloud/dispatch/general/config/DispatcherConfig.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
general
.
config
;
import
com.wecloud.dispatch.general.impl.GeneralActionBox
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.boot.context.properties.EnableConfigurationProperties
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
java.util.Set
;
/**
* @author lixiaozhong
*/
@Configuration
@EnableConfigurationProperties
(
GeneralActionDispatcherProperties
.
class
)
public
class
DispatcherConfig
{
@Autowired
private
GeneralActionDispatcherProperties
generalActionDispatcherProperties
;
@Bean
public
GeneralActionDispatcher
generalActionDispatcher
(
GeneralActionBox
generalActionBox
)
{
Set
<
String
>
actionPackages
=
generalActionDispatcherProperties
.
getScanPackage
();
GeneralActionDispatcher
bean
=
new
GeneralActionDispatcher
();
bean
.
add
(
generalActionBox
);
if
(
null
!=
actionPackages
&&
!
actionPackages
.
isEmpty
())
{
for
(
String
path
:
actionPackages
)
{
bean
.
scan
(
path
);
}
}
else
{
bean
.
scan
(
"com.wecloud"
);
}
return
bean
;
}
@Bean
public
GeneralActionBox
generalActionBox
()
{
GeneralActionBox
bean
=
new
GeneralActionBox
();
return
bean
;
}
}
core/src/main/java/com/wecloud/dispatch/general/config/GeneralActionConfigurerAdapter.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
general
.
config
;
import
com.wecloud.dispatch.ActionContext
;
import
com.wecloud.dispatch.config.ActionConfigurer
;
/**
* @author lixiaozhong
*/
public
class
GeneralActionConfigurerAdapter
implements
ActionConfigurer
{
@Override
public
void
addConfig
(
ActionContext
actionContext
)
{
// TODO Auto-generated method stub
}
}
core/src/main/java/com/wecloud/dispatch/general/config/GeneralActionDefaultConfigurer.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
general
.
config
;
import
com.wecloud.dispatch.ActionContext
;
import
com.wecloud.dispatch.general.impl.GeneralActionMethodValidInterceptor
;
import
com.wecloud.dispatch.general.impl.GeneralMethodArgumentResolver
;
/**
* @author lixiaozhong
*/
public
class
GeneralActionDefaultConfigurer
extends
GeneralActionConfigurerAdapter
{
@Override
public
void
addConfig
(
ActionContext
actionContext
)
{
actionContext
.
getMethodArgumentResolverRegistry
().
add
(
new
GeneralMethodArgumentResolver
());
actionContext
.
getActionMethodInterceptorRegistry
().
add
(
new
GeneralActionMethodValidInterceptor
());
}
}
core/src/main/java/com/wecloud/dispatch/general/config/GeneralActionDispatcher.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
general
.
config
;
import
com.wecloud.dispatch.ActionContext
;
import
com.wecloud.dispatch.ActionDispatcher
;
import
com.wecloud.dispatch.config.ActionConfigurer
;
import
com.wecloud.dispatch.extend.ActionBox
;
import
com.wecloud.dispatch.general.impl.GeneralActionInterceptor
;
/**
* @author lixiaozhong
*/
public
class
GeneralActionDispatcher
extends
ActionDispatcher
{
private
GeneralActionDefaultConfigurer
handlerActionConfigurer
=
new
GeneralActionDefaultConfigurer
();
private
GeneralActionInterceptor
handlerActionInterceptor
=
new
GeneralActionInterceptor
();
public
GeneralActionDispatcher
()
{
this
.
initialize
();
}
public
GeneralActionDispatcher
(
ActionBox
actionBox
)
{
this
.
initialize
();
this
.
add
(
actionBox
);
}
public
GeneralActionDispatcher
(
ActionBox
actionBox
,
String
...
actionLocations
)
{
this
.
initialize
();
this
.
add
(
actionBox
);
this
.
scan
(
actionLocations
);
}
@Override
public
void
addConfig
(
ActionConfigurer
actionConfigurer
)
{
super
.
addConfig
(
actionConfigurer
);
}
private
void
initialize
()
{
this
.
addConfig
(
handlerActionConfigurer
);
this
.
addConfig
(
new
GeneralActionConfigurerAdapter
()
{
@Override
public
void
addConfig
(
ActionContext
actionContext
)
{
actionContext
.
getActionInterceptorRegistry
().
add
(
handlerActionInterceptor
);
}
});
}
public
void
add
(
ActionBox
actionBox
)
{
// "com.*.action"
this
.
addConfig
(
new
GeneralActionConfigurerAdapter
()
{
@Override
public
void
addConfig
(
ActionContext
actionContext
)
{
actionContext
.
getActionBoxRegistry
().
add
(
actionBox
);
}
});
}
}
core/src/main/java/com/wecloud/dispatch/general/config/GeneralActionDispatcherProperties.java
0 → 100644
View file @
a7892caa
/**
* Apache License Version 2.0, January 2004 http://www.apache.org/licenses/
*
* TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
*
* 1. Definitions.
*
* "License" shall mean the terms and conditions for use, reproduction, and
* distribution as defined by Sections 1 through 9 of this document.
*
* "Licensor" shall mean the copyright owner or entity authorized by the
* copyright owner that is granting the License.
*
* "Legal Entity" shall mean the union of the acting entity and all other
* entities that control, are controlled by, or are under common control with
* that entity. For the purposes of this definition, "control" means (i) the
* power, direct or indirect, to cause the direction or management of such
* entity, whether by contract or otherwise, or (ii) ownership of fifty percent
* (50%) or more of the outstanding shares, or (iii) beneficial ownership of
* such entity.
*
* "You" (or "Your") shall mean an individual or Legal Entity exercising
* permissions granted by this License.
*
* "Source" form shall mean the preferred form for making modifications,
* including but not limited to software source code, documentation source, and
* configuration files.
*
* "Object" form shall mean any form resulting from mechanical transformation or
* translation of a Source form, including but not limited to compiled object
* code, generated documentation, and conversions to other media types.
*
* "Work" shall mean the work of authorship, whether in Source or Object form,
* made available under the License, as indicated by a copyright notice that is
* included in or attached to the work (an example is provided in the Appendix
* below).
*
* "Derivative Works" shall mean any work, whether in Source or Object form,
* that is based on (or derived from) the Work and for which the editorial
* revisions, annotations, elaborations, or other modifications represent, as a
* whole, an original work of authorship. For the purposes of this License,
* Derivative Works shall not include works that remain separable from, or
* merely link (or bind by name) to the interfaces of, the Work and Derivative
* Works thereof.
*
* "Contribution" shall mean any work of authorship, including the original
* version of the Work and any modifications or additions to that Work or
* Derivative Works thereof, that is intentionally submitted to Licensor for
* inclusion in the Work by the copyright owner or by an individual or Legal
* Entity authorized to submit on behalf of the copyright owner. For the
* purposes of this definition, "submitted" means any form of electronic,
* verbal, or written communication sent to the Licensor or its representatives,
* including but not limited to communication on electronic mailing lists,
* source code control systems, and issue tracking systems that are managed by,
* or on behalf of, the Licensor for the purpose of discussing and improving the
* Work, but excluding communication that is conspicuously marked or otherwise
* designated in writing by the copyright owner as "Not a Contribution."
*
* "Contributor" shall mean Licensor and any individual or Legal Entity on
* behalf of whom a Contribution has been received by Licensor and subsequently
* incorporated within the Work.
*
* 2. Grant of Copyright License.
*
* Subject to the terms and conditions of this License, each Contributor hereby
* grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
* irrevocable copyright license to reproduce, prepare Derivative Works of,
* publicly display, publicly perform, sublicense, and distribute the Work and
* such Derivative Works in Source or Object form.
*
* 3. Grant of Patent License.
*
* Subject to the terms and conditions of this License, each Contributor hereby
* grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
* irrevocable (except as stated in this section) patent license to make, have
* made, use, offer to sell, sell, import, and otherwise transfer the Work,
* where such license applies only to those patent claims licensable by such
* Contributor that are necessarily infringed by their Contribution(s) alone or
* by combination of their Contribution(s) with the Work to which such
* Contribution(s) was submitted. If You institute patent litigation against any
* entity (including a cross-claim or counterclaim in a lawsuit) alleging that
* the Work or a Contribution incorporated within the Work constitutes direct or
* contributory patent infringement, then any patent licenses granted to You
* under this License for that Work shall terminate as of the date such
* litigation is filed.
*
* 4. Redistribution.
*
* You may reproduce and distribute copies of the Work or Derivative Works
* thereof in any medium, with or without modifications, and in Source or Object
* form, provided that You meet the following conditions:
*
* You must give any other recipients of the Work or Derivative Works a copy of
* this License; and You must cause any modified files to carry prominent
* notices stating that You changed the files; and You must retain, in the
* Source form of any Derivative Works that You distribute, all copyright,
* patent, trademark, and attribution notices from the Source form of the Work,
* excluding those notices that do not pertain to any part of the Derivative
* Works; and If the Work includes a "NOTICE" text file as part of its
* distribution, then any Derivative Works that You distribute must include a
* readable copy of the attribution notices contained within such NOTICE file,
* excluding those notices that do not pertain to any part of the Derivative
* Works, in at least one of the following places: within a NOTICE text file
* distributed as part of the Derivative Works; within the Source form or
* documentation, if provided along with the Derivative Works; or, within a
* display generated by the Derivative Works, if and wherever such third-party
* notices normally appear. The contents of the NOTICE file are for
* informational purposes only and do not modify the License. You may add Your
* own attribution notices within Derivative Works that You distribute,
* alongside or as an addendum to the NOTICE text from the Work, provided that
* such additional attribution notices cannot be construed as modifying the
* License. You may add Your own copyright statement to Your modifications and
* may provide additional or different license terms and conditions for use,
* reproduction, or distribution of Your modifications, or for any such
* Derivative Works as a whole, provided Your use, reproduction, and
* distribution of the Work otherwise complies with the conditions stated in
* this License.
*
* 5. Submission of Contributions.
*
* Unless You explicitly state otherwise, any Contribution intentionally
* submitted for inclusion in the Work by You to the Licensor shall be under the
* terms and conditions of this License, without any additional terms or
* conditions. Notwithstanding the above, nothing herein shall supersede or
* modify the terms of any separate license agreement you may have executed with
* Licensor regarding such Contributions.
*
* 6. Trademarks.
*
* This License does not grant permission to use the trade names, trademarks,
* service marks, or product names of the Licensor, except as required for
* reasonable and customary use in describing the origin of the Work and
* reproducing the content of the NOTICE file.
*
* 7. Disclaimer of Warranty.
*
* Unless required by applicable law or agreed to in writing, Licensor provides
* the Work (and each Contributor provides its Contributions) on an "AS IS"
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied, including, without limitation, any warranties or conditions of
* TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR
* PURPOSE. You are solely responsible for determining the appropriateness of
* using or redistributing the Work and assume any risks associated with Your
* exercise of permissions under this License.
*
* 8. Limitation of Liability.
*
* In no event and under no legal theory, whether in tort (including
* negligence), contract, or otherwise, unless required by applicable law (such
* as deliberate and grossly negligent acts) or agreed to in writing, shall any
* Contributor be liable to You for damages, including any direct, indirect,
* special, incidental, or consequential damages of any character arising as a
* result of this License or out of the use or inability to use the Work
* (including but not limited to damages for loss of goodwill, work stoppage,
* computer failure or malfunction, or any and all other commercial damages or
* losses), even if such Contributor has been advised of the possibility of such
* damages.
*
* 9. Accepting Warranty or Additional Liability.
*
* While redistributing the Work or Derivative Works thereof, You may choose to
* offer, and charge a fee for, acceptance of support, warranty, indemnity, or
* other liability obligations and/or rights consistent with this License.
* However, in accepting such obligations, You may act only on Your own behalf
* and on Your sole responsibility, not on behalf of any other Contributor, and
* only if You agree to indemnify, defend, and hold each Contributor harmless
* for any liability incurred by, or claims asserted against, such Contributor
* by reason of your accepting any such warranty or additional liability.
*
* END OF TERMS AND CONDITIONS
*
* APPENDIX: How to apply the Apache License to your work
*
* To apply the Apache License to your work, attach the following boilerplate
* notice, with the fields enclosed by brackets "{}" replaced with your own
* identifying information. (Don't include the brackets!) The text should be
* enclosed in the appropriate comment syntax for the file format. We also
* recommend that a file or class name and description of purpose be included on
* the same "printed page" as the copyright notice for easier identification
* within third-party archives.
*
* Copyright 2019 onlovexiahui@qq.com
*
* Licensed 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.
*
**/
package
com
.
wecloud
.
dispatch
.
general
.
config
;
import
lombok.Data
;
import
org.springframework.boot.context.properties.ConfigurationProperties
;
import
java.util.Set
;
/**
* @author lixiaozhong
*/
@Data
@ConfigurationProperties
(
"websocket.action"
)
public
class
GeneralActionDispatcherProperties
{
private
Set
<
String
>
scanPackage
;
}
core/src/main/java/com/wecloud/dispatch/general/extend/ActionMessageResolver.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
general
.
extend
;
import
com.wecloud.dispatch.ActionDispatcher
;
import
com.wecloud.dispatch.common.RequestVO
;
import
com.wecloud.dispatch.extend.ActionMessage
;
/**
* @author lixiaozhong
*/
public
interface
ActionMessageResolver
{
/**
*
* 解析消息<br>
*
* @param actionDispatcher
* @param data
* @return
*/
ActionMessage
resolver
(
ActionDispatcher
actionDispatcher
,
RequestVO
data
);
}
core/src/main/java/com/wecloud/dispatch/general/extend/impl/ActionMessageResolverImpl.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
general
.
extend
.
impl
;
import
com.wecloud.dispatch.ActionDispatcher
;
import
com.wecloud.dispatch.common.RequestVO
;
import
com.wecloud.dispatch.extend.ActionMessage
;
import
com.wecloud.dispatch.extend.impl.DefaultActionMessage
;
import
com.wecloud.dispatch.general.extend.ActionMessageResolver
;
import
org.springframework.stereotype.Component
;
/**
* @author lixiaozhong
*/
@Component
public
class
ActionMessageResolverImpl
implements
ActionMessageResolver
{
@Override
public
ActionMessage
resolver
(
ActionDispatcher
actionDispatcher
,
RequestVO
data
)
{
ActionMessage
am
=
new
DefaultActionMessage
();
am
.
setAction
(
""
);
if
(
data
==
null
)
{
return
am
;
}
String
action
=
data
.
getAction
();
String
path
=
actionDispatcher
.
getActionRegistry
().
getPath
(
action
,
null
);
am
.
setMessage
(
data
);
am
.
setAction
(
path
);
return
am
;
}
}
core/src/main/java/com/wecloud/dispatch/general/impl/GeneralActionBox.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
general
.
impl
;
import
com.wecloud.dispatch.extend.ActionBox
;
import
org.springframework.beans.BeansException
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.ApplicationContextAware
;
/**
* @author lixiaozhong
*/
public
class
GeneralActionBox
implements
ActionBox
,
ApplicationContextAware
{
private
ApplicationContext
applicationContext
=
null
;
@Override
public
Object
getAction
(
Class
<?>
type
)
{
Object
o
=
null
;
if
(
null
!=
applicationContext
)
{
o
=
applicationContext
.
getBean
(
type
);
}
return
o
;
}
@Override
public
Object
getAction
(
String
className
)
{
Object
o
=
null
;
if
(
null
!=
applicationContext
)
{
o
=
applicationContext
.
getBean
(
className
);
}
return
o
;
}
@Override
public
void
setApplicationContext
(
ApplicationContext
applicationContext
)
throws
BeansException
{
this
.
applicationContext
=
applicationContext
;
}
}
core/src/main/java/com/wecloud/dispatch/general/impl/GeneralActionInterceptor.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
general
.
impl
;
import
com.wecloud.dispatch.ActionContext
;
import
com.wecloud.dispatch.common.ApplyInfo
;
import
com.wecloud.dispatch.extend.ActionInterceptor
;
import
com.wecloud.dispatch.extend.ActionRequest
;
import
com.wecloud.dispatch.extend.ArgumentBox
;
/**
* @author lixiaozhong
*/
public
class
GeneralActionInterceptor
implements
ActionInterceptor
{
@Override
public
ApplyInfo
previous
(
ActionContext
actionContext
,
ActionRequest
request
,
ArgumentBox
argumentBox
)
{
ApplyInfo
applyInfo
=
new
ApplyInfo
();
applyInfo
.
setApprove
(
true
);
return
applyInfo
;
}
}
core/src/main/java/com/wecloud/dispatch/general/impl/GeneralActionMethodValidInterceptor.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
general
.
impl
;
import
com.wecloud.dispatch.ActionContext
;
import
com.wecloud.dispatch.common.ApplyInfo
;
import
com.wecloud.dispatch.extend.ActionMethodInterceptor
;
import
com.wecloud.dispatch.extend.ActionRequest
;
import
com.wecloud.dispatch.extend.ArgumentBox
;
import
org.springframework.beans.factory.FactoryBean
;
import
org.springframework.beans.factory.SmartFactoryBean
;
import
org.springframework.context.support.ReloadableResourceBundleMessageSource
;
import
org.springframework.core.BridgeMethodResolver
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.core.annotation.AnnotationUtils
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.validation.annotation.Validated
;
import
org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean
;
import
javax.validation.ConstraintViolation
;
import
javax.validation.ConstraintViolationException
;
import
javax.validation.Validator
;
import
javax.validation.executable.ExecutableValidator
;
import
java.lang.reflect.Method
;
import
java.util.Set
;
/**
* @author lixiaozhong
*/
public
class
GeneralActionMethodValidInterceptor
implements
ActionMethodInterceptor
{
Validator
validator
;
public
GeneralActionMethodValidInterceptor
()
{
ReloadableResourceBundleMessageSource
messageSource
=
new
ReloadableResourceBundleMessageSource
();
// messageSource.setBasename("classpath:i18n/ValidationMessages");
OptionalValidatorFactoryBean
optionalValidatorFactoryBean
=
new
OptionalValidatorFactoryBean
();
optionalValidatorFactoryBean
.
setValidationMessageSource
(
messageSource
);
optionalValidatorFactoryBean
.
afterPropertiesSet
();
validator
=
optionalValidatorFactoryBean
;
}
@Override
public
ApplyInfo
intercept
(
ActionContext
actionContext
,
Object
object
,
Method
method
,
Object
[]
array
,
MethodParameter
[]
parameter
,
ActionRequest
request
,
ArgumentBox
argumentBox
)
{
// TODO Auto-generated method stub
boolean
approve
=
true
;
Object
value
=
null
;
if
(!
isFactoryBeanMetadataMethod
(
method
))
{
Class
<?>[]
groups
=
determineValidationGroups
(
object
,
method
);
// Standard Bean Validation 1.1 API
ExecutableValidator
execVal
=
this
.
validator
.
forExecutables
();
Method
methodToValidate
=
method
;
Set
<
ConstraintViolation
<
Object
>>
result
;
try
{
result
=
execVal
.
validateParameters
(
object
,
methodToValidate
,
array
,
groups
);
}
catch
(
IllegalArgumentException
ex
)
{
// Probably a generic type mismatch between interface and impl as reported in
// SPR-12237 / HV-1011
// Let's try to find the bridged method on the implementation class...
methodToValidate
=
BridgeMethodResolver
.
findBridgedMethod
(
ClassUtils
.
getMostSpecificMethod
(
method
,
object
.
getClass
()));
result
=
execVal
.
validateParameters
(
object
,
methodToValidate
,
array
,
groups
);
}
if
(!
result
.
isEmpty
())
{
throw
new
ConstraintViolationException
(
result
);
}
if
(
null
!=
array
)
{
int
size
=
array
.
length
;
for
(
int
i
=
0
;
i
<
size
;
i
++)
{
Validated
validatedAnn
=
parameter
[
i
].
getParameterAnnotation
(
Validated
.
class
);
if
(
validatedAnn
!=
null
)
{
Class
<?>[]
gs
=
validatedAnn
.
value
();
result
=
validator
.
validate
(
array
[
i
],
gs
);
if
(!
result
.
isEmpty
())
{
throw
new
ConstraintViolationException
(
result
);
}
}
}
}
}
ApplyInfo
applyInfo
=
new
ApplyInfo
();
applyInfo
.
setApprove
(
approve
);
applyInfo
.
setValue
(
value
);
return
applyInfo
;
}
private
boolean
isFactoryBeanMetadataMethod
(
Method
method
)
{
Class
<?>
clazz
=
method
.
getDeclaringClass
();
// Call from interface-based proxy handle, allowing for an efficient check?
if
(
clazz
.
isInterface
())
{
return
((
clazz
==
FactoryBean
.
class
||
clazz
==
SmartFactoryBean
.
class
)
&&
!
"getObject"
.
equals
(
method
.
getName
()));
}
// Call from CGLIB proxy handle, potentially implementing a FactoryBean method?
Class
<?>
factoryBeanType
=
null
;
if
(
SmartFactoryBean
.
class
.
isAssignableFrom
(
clazz
))
{
factoryBeanType
=
SmartFactoryBean
.
class
;
}
else
if
(
FactoryBean
.
class
.
isAssignableFrom
(
clazz
))
{
factoryBeanType
=
FactoryBean
.
class
;
}
return
(
factoryBeanType
!=
null
&&
!
method
.
getName
().
equals
(
"getObject"
)
&&
ClassUtils
.
hasMethod
(
factoryBeanType
,
method
.
getName
(),
method
.
getParameterTypes
()));
}
/**
* Determine the validation groups to validate against for the given method
* invocation.
* <p>
* Default are the validation groups as specified in the {@link Validated}
* annotation on the containing target class of the method.
*
* @param method the current MethodInvocation
* @return the applicable validation groups as a Class array
*/
protected
Class
<?>[]
determineValidationGroups
(
Object
bean
,
Method
method
)
{
Validated
validatedAnn
=
AnnotationUtils
.
findAnnotation
(
method
,
Validated
.
class
);
if
(
validatedAnn
==
null
)
{
validatedAnn
=
AnnotationUtils
.
findAnnotation
(
bean
.
getClass
(),
Validated
.
class
);
}
return
(
validatedAnn
!=
null
?
validatedAnn
.
value
()
:
new
Class
<?>[
0
]);
}
}
core/src/main/java/com/wecloud/dispatch/general/impl/GeneralMethodArgumentResolver.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
general
.
impl
;
import
com.alibaba.fastjson.JSONArray
;
import
com.alibaba.fastjson.JSONObject
;
import
com.wecloud.dispatch.ActionContext
;
import
com.wecloud.dispatch.extend.ActionRequest
;
import
com.wecloud.dispatch.extend.ArgumentBox
;
import
com.wecloud.dispatch.extend.MethodArgumentResolver
;
import
com.wecloud.utils.JsonUtils
;
import
org.springframework.core.MethodParameter
;
import
org.springframework.core.convert.support.DefaultConversionService
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
java.lang.reflect.Array
;
import
java.lang.reflect.Modifier
;
import
java.lang.reflect.ParameterizedType
;
import
java.lang.reflect.Type
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
/**
* @author lixiaozhong
*/
public
class
GeneralMethodArgumentResolver
implements
MethodArgumentResolver
{
protected
final
DefaultConversionService
conversionService
=
new
DefaultConversionService
();
Map
<
Class
<?>,
Boolean
>
canNotInstanceMap
=
new
HashMap
<>();
@Override
public
boolean
supportsParameter
(
MethodParameter
parameter
)
{
// return parameter.hasParameterAnnotation(RequestParam.class);
return
true
;
}
@Override
public
Object
resolveArgument
(
ActionContext
actionContext
,
MethodParameter
parameter
,
ActionRequest
request
,
ArgumentBox
argumentBox
)
{
Object
object
=
null
;
RequestParam
define
=
parameter
.
getParameterAnnotation
(
RequestParam
.
class
);
// 获取属定义的名称
String
name
=
null
==
define
?
parameter
.
getParameterName
()
:
define
.
value
();
Type
t
=
parameter
.
getGenericParameterType
();
Class
<?>
clazz
=
parameter
.
getParameterType
();
Object
value
=
request
.
getData
().
get
(
name
);
if
(
value
instanceof
JSONObject
)
{
JSONObject
jo
=
(
JSONObject
)
value
;
if
(
isCustomMap
(
clazz
))
{
object
=
JSONObject
.
parseObject
(
jo
.
toJSONString
(),
clazz
);
}
else
{
object
=
jo
.
toJavaObject
(
t
);
}
}
else
if
(
value
instanceof
JSONArray
)
{
JSONArray
ja
=
(
JSONArray
)
value
;
object
=
ja
.
toJavaObject
(
t
);
}
else
if
(
value
instanceof
Map
)
{
if
(
clazz
.
isInstance
(
value
))
{
object
=
value
;
}
else
{
object
=
JsonUtils
.
mapToBean
((
Map
)
value
,
getObject
(
clazz
));
}
}
else
if
(
value
instanceof
List
)
{
if
(
clazz
.
isInstance
(
value
))
{
object
=
value
;
}
else
if
(
Set
.
class
.
isAssignableFrom
(
clazz
))
{
Set
objectSet
=
new
HashSet
();
Type
actualTypeArgument
=
((
ParameterizedType
)
parameter
.
getGenericParameterType
()).
getActualTypeArguments
()[
0
];
((
List
<
Map
<
String
,
Object
>>)
value
).
forEach
(
p
->
objectSet
.
add
(
JsonUtils
.
mapToBean
(
p
,
getObject
((
Class
)
actualTypeArgument
))));
object
=
objectSet
;
}
else
{
List
objectList
=
new
ArrayList
();
Type
actualTypeArgument
=
((
ParameterizedType
)
parameter
.
getGenericParameterType
()).
getActualTypeArguments
()[
0
];
((
List
<
Map
<
String
,
Object
>>)
value
).
forEach
(
p
->
objectList
.
add
(
JsonUtils
.
mapToBean
(
p
,
getObject
((
Class
)
actualTypeArgument
))));
object
=
objectList
;
}
}
else
if
(
null
!=
value
)
{
if
(
clazz
.
isInstance
(
value
))
{
object
=
value
;
}
else
{
if
(
conversionService
.
canConvert
(
value
.
getClass
(),
clazz
))
{
object
=
conversionService
.
convert
(
value
,
clazz
);
}
}
}
if
(
null
==
object
)
{
object
=
getDefaultValue
(
clazz
);
}
if
(
null
==
object
&&
isCanInstance
(
clazz
)
&&
!
canNotInstanceMap
.
containsKey
(
clazz
))
{
object
=
getObject
(
clazz
);
}
return
object
;
}
/**
*
* 是否可以被实例化
*
* @param classType
* @return
*/
private
boolean
isCanInstance
(
Class
<?>
classType
)
{
boolean
isAbstract
=
Modifier
.
isAbstract
(
classType
.
getModifiers
());
boolean
can
=
true
;
if
(
classType
.
isAnnotation
())
{
can
=
false
;
}
else
if
(
classType
.
isArray
())
{
can
=
false
;
}
else
if
(
classType
.
isEnum
())
{
can
=
false
;
}
else
if
(
classType
.
isInterface
())
{
can
=
false
;
}
else
if
(
isAbstract
)
{
can
=
false
;
}
return
can
;
}
private
<
T
>
Object
getObject
(
Class
<
T
>
clazz
)
{
Object
object
=
null
;
if
(
isCanInstance
(
clazz
)
&&
!
canNotInstanceMap
.
containsKey
(
clazz
))
{
try
{
object
=
clazz
.
newInstance
();
}
catch
(
InstantiationException
|
IllegalAccessException
e
)
{
canNotInstanceMap
.
put
(
clazz
,
false
);
}
}
return
object
;
}
/**
* @param clazz
* @return
*/
@SuppressWarnings
(
"unchecked"
)
public
<
T
>
T
getDefaultValue
(
Class
<
T
>
clazz
)
{
Object
object
=
null
;
if
(
List
.
class
.
isAssignableFrom
(
clazz
))
{
if
(
isCanInstance
(
clazz
))
{
object
=
getObject
(
clazz
);
}
else
{
object
=
new
ArrayList
<
Object
>(
0
);
}
}
else
if
(
Map
.
class
.
isAssignableFrom
(
clazz
))
{
if
(
isCanInstance
(
clazz
))
{
object
=
getObject
(
clazz
);
}
else
{
object
=
new
HashMap
<
Object
,
Object
>(
0
);
}
}
else
if
(
Set
.
class
.
isAssignableFrom
(
clazz
))
{
if
(
isCanInstance
(
clazz
))
{
object
=
getObject
(
clazz
);
}
else
{
object
=
new
HashSet
<
Object
>(
0
);
}
}
else
if
(
clazz
.
isArray
())
{
Class
<?>
componentType
=
clazz
.
getComponentType
();
object
=
Array
.
newInstance
(
componentType
,
0
);
}
else
if
(
clazz
==
int
.
class
)
{
object
=
0
;
}
else
if
(
clazz
==
long
.
class
)
{
object
=
0L
;
}
else
if
(
clazz
==
float
.
class
)
{
object
=
0.0
F
;
}
else
if
(
clazz
==
double
.
class
)
{
object
=
0.00
D
;
}
else
if
(
clazz
==
byte
.
class
)
{
object
=
(
byte
)
0
;
}
else
if
(
clazz
==
char
.
class
)
{
object
=
'\u0000'
;
}
else
if
(
clazz
==
short
.
class
)
{
object
=
0
;
}
else
if
(
clazz
==
boolean
.
class
)
{
object
=
false
;
}
return
((
T
)
object
);
}
/**
* 是否自定义实现Map
*
* @param clazz
* @return
*/
boolean
isCustomMap
(
Class
<?>
clazz
)
{
boolean
isMap
=
Map
.
class
.
isAssignableFrom
(
clazz
);
boolean
isSubMap
=
java
.
util
.
HashMap
.
class
==
clazz
||
java
.
util
.
Hashtable
.
class
==
clazz
||
java
.
util
.
TreeMap
.
class
==
clazz
||
java
.
util
.
IdentityHashMap
.
class
==
clazz
||
java
.
util
.
WeakHashMap
.
class
==
clazz
||
java
.
util
.
LinkedHashMap
.
class
==
clazz
;
return
isMap
&&
!
isSubMap
;
}
boolean
isCollection
(
Class
<?>
clazz
)
{
return
Collection
.
class
.
isAssignableFrom
(
clazz
);
}
}
core/src/main/java/com/wecloud/dispatch/registry/ActionBoxRegistry.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
registry
;
import
com.wecloud.dispatch.extend.ActionBox
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* @author lixiaozhong
*/
public
class
ActionBoxRegistry
{
List
<
ActionBox
>
list
=
new
ArrayList
<>();
public
void
add
(
ActionBox
actionBox
)
{
list
.
add
(
actionBox
);
}
public
Object
getAction
(
Class
<?>
type
)
{
Object
o
=
null
;
for
(
ActionBox
ab
:
list
)
{
o
=
ab
.
getAction
(
type
);
if
(
null
!=
o
)
{
return
o
;
}
}
return
null
;
}
}
core/src/main/java/com/wecloud/dispatch/registry/ActionInterceptorRegistry.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
registry
;
import
com.wecloud.dispatch.extend.ActionInterceptor
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* @author lixiaozhong
*/
public
class
ActionInterceptorRegistry
{
List
<
ActionInterceptor
>
list
=
new
ArrayList
<>();
public
void
add
(
ActionInterceptor
actionInterceptor
)
{
list
.
add
(
actionInterceptor
);
}
public
List
<
ActionInterceptor
>
getActionInterceptorList
()
{
return
list
;
};
}
core/src/main/java/com/wecloud/dispatch/registry/ActionMethodInterceptorRegistry.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
registry
;
import
com.wecloud.dispatch.extend.ActionMethodInterceptor
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* @author lixiaozhong
*/
public
class
ActionMethodInterceptorRegistry
{
List
<
ActionMethodInterceptor
>
list
=
new
ArrayList
<>();
public
void
add
(
ActionMethodInterceptor
actionInterceptor
)
{
list
.
add
(
actionInterceptor
);
}
public
List
<
ActionMethodInterceptor
>
getList
()
{
return
list
;
};
}
core/src/main/java/com/wecloud/dispatch/registry/ActionRegistry.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
registry
;
import
com.wecloud.dispatch.annotation.ActionMapping
;
import
com.wecloud.dispatch.common.ActionMethod
;
import
com.wecloud.dispatch.exception.MappingException
;
import
org.springframework.http.server.PathContainer
;
import
org.springframework.util.AntPathMatcher
;
import
org.springframework.util.StringUtils
;
import
org.springframework.web.util.pattern.PathPattern
;
import
org.springframework.web.util.pattern.PathPatternParser
;
import
java.lang.annotation.Annotation
;
import
java.lang.reflect.Method
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.stream.Collectors
;
/**
* @author lixiaozhong
*/
public
class
ActionRegistry
{
private
final
Map
<
PathPattern
,
ActionMethod
>
actionMethodMap
=
new
ConcurrentHashMap
<>(
16
);
private
String
separator
=
AntPathMatcher
.
DEFAULT_PATH_SEPARATOR
;
private
AntPathMatcher
pathMatcher
=
new
AntPathMatcher
();
private
final
PathPatternParser
patternParser
=
new
PathPatternParser
();;
/**
* 为了更快获取要执行的action,将要执行的action加入Map进行缓存
*
* @param classType
* @throws MappingException
*/
public
void
add
(
Class
<?>
classType
)
{
Annotation
[]
as
=
classType
.
getAnnotations
();
ActionMapping
am
=
null
;
for
(
Annotation
annotation
:
as
)
{
if
(
annotation
instanceof
ActionMapping
)
{
am
=
((
ActionMapping
)
annotation
);
break
;
}
}
String
[]
codes
=
null
==
am
?
new
String
[]
{
""
}
:
am
.
value
();
add
(
codes
,
classType
);
}
/**
* 获取要执行的action的方法,并且缓存
*
* @param classType
* @return
* @throws MappingException
*/
public
void
add
(
String
[]
codes
,
Class
<?>
classType
)
{
Method
[]
methods
=
classType
.
getMethods
();
if
(
null
!=
methods
&&
methods
.
length
>
0
)
{
for
(
Method
method
:
methods
)
{
add
(
codes
,
method
);
}
}
}
public
void
add
(
Method
method
)
{
if
(
null
!=
method
)
{
Annotation
[]
as
=
method
.
getDeclaringClass
().
getAnnotations
();
ActionMapping
am
=
null
;
for
(
Annotation
annotation
:
as
)
{
if
(
annotation
instanceof
ActionMapping
)
{
am
=
((
ActionMapping
)
annotation
);
break
;
}
}
String
[]
codes
=
null
==
am
?
new
String
[]
{
""
}
:
am
.
value
();
add
(
codes
,
method
);
}
}
public
void
add
(
String
[]
codes
,
Method
method
)
{
if
(
null
!=
method
)
{
codes
=
(
null
==
codes
)
?
new
String
[]
{
""
}
:
codes
;
Annotation
[]
as
=
method
.
getAnnotations
();
for
(
Annotation
a
:
as
)
{
if
(
a
instanceof
ActionMapping
)
{
ActionMapping
actionMapping
=
(
ActionMapping
)
a
;
String
[]
values
=
actionMapping
.
value
();
int
order
=
actionMapping
.
order
();
List
<
String
>
paths
=
getPaths
(
codes
,
values
);
if
(
null
!=
paths
)
{
for
(
String
path
:
paths
)
{
ActionMethod
am
=
getActionMethod
(
path
);
boolean
equals
=
false
;
if
(
null
!=
am
)
{
equals
=
null
!=
am
.
getMethodPath
()
&&
am
.
getMethodPath
().
equals
(
path
);
}
if
(
null
!=
am
&&
equals
)
{
Method
lastMethod
=
am
.
getMethod
();
if
(
method
.
equals
(
lastMethod
))
{
continue
;
}
ActionMapping
lastMapping
=
am
.
getMethod
().
getAnnotation
(
ActionMapping
.
class
);
int
lastOrder
=
lastMapping
.
order
();
if
(
order
==
lastOrder
)
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
"\n"
);
sb
.
append
(
"ActionMapping:"
);
sb
.
append
(
"\n"
);
sb
.
append
(
"["
);
sb
.
append
(
am
.
getActionClass
().
getName
());
sb
.
append
(
"]"
);
sb
.
append
(
"."
);
sb
.
append
(
"["
);
sb
.
append
(
am
.
getMethod
().
getName
());
sb
.
append
(
"]"
);
sb
.
append
(
"\n"
);
sb
.
append
(
"与"
);
sb
.
append
(
"\n"
);
sb
.
append
(
"["
);
sb
.
append
(
method
.
getDeclaringClass
().
getName
());
sb
.
append
(
"]"
);
sb
.
append
(
"."
);
sb
.
append
(
"["
);
sb
.
append
(
method
.
getName
());
sb
.
append
(
"]"
);
sb
.
append
(
"\n"
);
sb
.
append
(
"存在重复"
);
sb
.
append
(
"["
);
sb
.
append
(
path
);
sb
.
append
(
"]!"
);
throw
new
MappingException
(
sb
.
toString
());
}
else
if
(
order
<
lastOrder
)
{
put
(
path
,
new
ActionMethod
(
method
,
path
));
}
}
else
{
put
(
path
,
new
ActionMethod
(
method
,
path
));
}
}
}
break
;
}
}
}
}
public
void
cover
(
Class
<?>
classType
)
{
Annotation
[]
as
=
classType
.
getAnnotations
();
ActionMapping
am
=
null
;
for
(
Annotation
annotation
:
as
)
{
if
(
annotation
instanceof
ActionMapping
)
{
am
=
((
ActionMapping
)
annotation
);
break
;
}
}
String
[]
value
=
null
==
am
?
new
String
[]
{
""
}
:
am
.
value
();
cover
(
value
,
classType
);
}
public
void
cover
(
String
[]
codes
,
Class
<?>
classType
)
{
Method
[]
methods
=
classType
.
getMethods
();
if
(
null
!=
methods
&&
methods
.
length
>
0
)
{
for
(
Method
method
:
methods
)
{
Annotation
[]
as
=
method
.
getAnnotations
();
for
(
Annotation
a
:
as
)
{
if
(
a
instanceof
ActionMapping
)
{
String
[]
values
=
((
ActionMapping
)
a
).
value
();
List
<
String
>
paths
=
getPaths
(
codes
,
values
);
cover
(
paths
,
method
);
break
;
}
}
}
}
}
public
void
cover
(
List
<
String
>
paths
,
Method
method
)
{
if
(
null
!=
paths
&&
null
!=
method
)
{
for
(
String
path
:
paths
)
{
cover
(
path
,
method
);
}
}
}
public
void
cover
(
String
path
,
Method
method
)
{
if
(
null
!=
path
&&
null
!=
method
)
{
put
(
path
,
new
ActionMethod
(
method
,
path
));
}
}
public
void
put
(
String
path
,
ActionMethod
am
)
{
PathPattern
pattern
=
patternParser
.
parse
(
path
);
actionMethodMap
.
put
(
pattern
,
am
);
}
public
boolean
has
(
String
path
)
{
ActionMethod
method
=
path
==
null
||
path
.
isEmpty
()
?
null
:
lookupHandler
(
PathContainer
.
parsePath
(
path
));
return
null
!=
method
;
}
public
ActionMethod
lookupHandler
(
PathContainer
lookupPath
)
{
ActionMethod
am
=
null
;
List
<
PathPattern
>
matches
=
this
.
actionMethodMap
.
keySet
().
stream
()
.
filter
(
key
->
key
.
matches
(
lookupPath
))
.
collect
(
Collectors
.
toList
());
if
(
matches
.
isEmpty
())
{
return
null
;
}
if
(
matches
.
size
()
>
1
)
{
matches
.
sort
(
PathPattern
.
SPECIFICITY_COMPARATOR
);
}
PathPattern
pattern
=
matches
.
get
(
0
);
am
=
this
.
actionMethodMap
.
get
(
pattern
);
return
am
;
}
/**
* 截取不包含包名,和小写首字母的类名
*
* @param classType
* @return
*/
public
String
getSimpleNameAsProperty
(
Class
<?>
classType
)
{
String
valueName
=
classType
.
getSimpleName
();
return
valueName
=
valueName
.
substring
(
0
,
1
).
toLowerCase
()
+
valueName
.
substring
(
1
);
}
public
Class
<?>
getClass
(
String
path
)
{
ActionMethod
am
=
getActionMethod
(
path
);
return
null
==
am
?
null
:
am
.
getActionClass
();
}
public
ActionMethod
getActionMethod
(
String
path
)
{
// ActionMethod method = actionMethodMap.get(path == null ? "" : path);
ActionMethod
method
=
path
==
null
||
path
.
isEmpty
()
?
null
:
lookupHandler
(
PathContainer
.
parsePath
(
path
));
return
method
;
}
public
ActionMethod
getActionMethod
(
String
classCode
,
String
methodCode
)
{
String
path
=
getPath
(
classCode
,
methodCode
);
return
getActionMethod
(
path
);
}
public
List
<
String
>
getPaths
(
String
[]
classCodes
,
String
[]
methodCodes
)
{
classCodes
=
(
null
==
classCodes
||
classCodes
.
length
==
0
)
?
new
String
[]
{
""
}
:
classCodes
;
methodCodes
=
(
null
==
methodCodes
||
methodCodes
.
length
==
0
)
?
new
String
[]
{
""
}
:
methodCodes
;
List
<
String
>
list
=
new
ArrayList
<>();
for
(
String
classCode
:
classCodes
)
{
for
(
String
methodCode
:
methodCodes
)
{
list
.
add
(
getPath
(
classCode
,
methodCode
));
}
}
return
list
;
}
public
String
getPath
(
String
classCode
,
String
methodCode
)
{
// StringBuilder sb = new StringBuilder();
String
path
=
pathMatcher
.
combine
(
classCode
,
methodCode
);
// if (isSeparateAlways()) {
// sb.append(getSeparator());
// } else if (null != classCode && !classCode.isEmpty() && !classCode.startsWith(getSeparator())) {
// sb.append(getSeparator());
// }
// sb.append(classCode);
// if (isSeparateAlways()) {
// sb.append(getSeparator());
// } else if (!methodCode.startsWith(getSeparator())) {
// sb.append(getSeparator());
// }
// sb.append(methodCode);
path
=
prependLeadingSlash
(
path
);
return
path
;
}
private
static
String
prependLeadingSlash
(
String
pattern
)
{
String
pre
=
"/"
;
if
(
StringUtils
.
hasLength
(
pattern
)
&&
!
pattern
.
startsWith
(
pre
))
{
return
pre
+
pattern
;
}
else
{
return
pattern
;
}
}
public
Map
<
PathPattern
,
ActionMethod
>
getActionMethodMap
()
{
return
actionMethodMap
;
}
public
String
getSeparator
()
{
return
separator
;
}
public
void
setSeparator
(
String
separator
)
{
this
.
separator
=
separator
;
pathMatcher
.
setPathSeparator
(
separator
);
}
// public boolean isSeparateAlways() {
// return separateAlways;
// }
//
// public void setSeparateAlways(boolean separateAlways) {
// this.separateAlways = separateAlways;
// }
//
// public void setSeparator(String separator, boolean separateAlways) {
// this.separator = separator;
// this.separateAlways = separateAlways;
// pathMatcher.setPathSeparator(separator);
// }
}
core/src/main/java/com/wecloud/dispatch/registry/ArgumentDefaultValueBuilderRegistry.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
registry
;
import
com.wecloud.dispatch.extend.ArgumentDefaultValueBuilder
;
import
com.wecloud.dispatch.extend.impl.DefaultArgumentDefaultValueBuilder
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* @author lixiaozhong
*/
public
class
ArgumentDefaultValueBuilderRegistry
{
List
<
ArgumentDefaultValueBuilder
>
list
=
new
ArrayList
<>();
ArgumentDefaultValueBuilder
b
=
new
DefaultArgumentDefaultValueBuilder
();
public
void
add
(
ArgumentDefaultValueBuilder
builder
)
{
list
.
add
(
builder
);
}
public
Object
getValue
(
Class
<?>
type
)
{
Object
o
=
null
;
for
(
ArgumentDefaultValueBuilder
ab
:
list
)
{
o
=
ab
.
build
(
type
);
if
(
null
!=
o
)
{
return
o
;
}
}
o
=
b
.
build
(
type
);
return
o
;
}
}
core/src/main/java/com/wecloud/dispatch/registry/MethodArgumentResolverRegistry.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
registry
;
import
com.wecloud.dispatch.ActionContext
;
import
com.wecloud.dispatch.extend.ActionRequest
;
import
com.wecloud.dispatch.extend.ArgumentBox
;
import
com.wecloud.dispatch.extend.MethodArgumentResolver
;
import
org.springframework.core.MethodParameter
;
import
java.util.LinkedList
;
import
java.util.List
;
/**
* @author lixiaozhong
*/
public
class
MethodArgumentResolverRegistry
{
List
<
MethodArgumentResolver
>
list
=
new
LinkedList
<>();
public
void
add
(
MethodArgumentResolver
mar
)
{
list
.
add
(
mar
);
}
public
boolean
supportsParameter
(
MethodParameter
parameter
)
{
return
(
getArgumentResolver
(
parameter
)
!=
null
);
}
public
Object
resolveArgument
(
ActionContext
actionContext
,
MethodParameter
parameter
,
ActionRequest
request
,
ArgumentBox
argumentBox
)
{
MethodArgumentResolver
resolver
=
getArgumentResolver
(
parameter
);
if
(
resolver
==
null
)
{
throw
new
IllegalArgumentException
(
"Unknown parameter type ["
+
parameter
.
getParameterType
().
getName
()
+
"]"
);
}
return
resolver
.
resolveArgument
(
actionContext
,
parameter
,
request
,
argumentBox
);
}
private
MethodArgumentResolver
getArgumentResolver
(
MethodParameter
parameter
)
{
MethodArgumentResolver
result
=
null
;
for
(
MethodArgumentResolver
methodArgumentResolver
:
this
.
list
)
{
if
(
methodArgumentResolver
.
supportsParameter
(
parameter
))
{
result
=
methodArgumentResolver
;
break
;
}
}
return
result
;
}
}
core/src/main/java/com/wecloud/dispatch/util/ClassScaner.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
util
;
import
org.springframework.core.io.Resource
;
import
org.springframework.core.io.ResourceLoader
;
import
org.springframework.core.io.support.PathMatchingResourcePatternResolver
;
import
org.springframework.core.io.support.ResourcePatternResolver
;
import
org.springframework.core.type.classreading.CachingMetadataReaderFactory
;
import
org.springframework.core.type.classreading.MetadataReader
;
import
org.springframework.core.type.classreading.MetadataReaderFactory
;
import
org.springframework.core.type.filter.AnnotationTypeFilter
;
import
org.springframework.core.type.filter.TypeFilter
;
import
org.springframework.util.ClassUtils
;
import
org.springframework.util.SystemPropertyUtils
;
import
java.io.IOException
;
import
java.lang.annotation.Annotation
;
import
java.util.HashSet
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Set
;
/**
* @author lixiaozhong
*/
public
class
ClassScaner
{
private
ResourcePatternResolver
resourcePatternResolver
=
new
PathMatchingResourcePatternResolver
();
private
final
List
<
TypeFilter
>
includeFilters
=
new
LinkedList
<
TypeFilter
>();
private
final
List
<
TypeFilter
>
excludeFilters
=
new
LinkedList
<
TypeFilter
>();
private
MetadataReaderFactory
metadataReaderFactory
=
new
CachingMetadataReaderFactory
(
this
.
resourcePatternResolver
);
public
ClassScaner
()
{
}
public
final
ResourceLoader
getResourceLoader
()
{
return
this
.
resourcePatternResolver
;
}
public
void
addIncludeFilter
(
TypeFilter
includeFilter
)
{
this
.
includeFilters
.
add
(
includeFilter
);
}
public
void
addExcludeFilter
(
TypeFilter
excludeFilter
)
{
this
.
excludeFilters
.
add
(
0
,
excludeFilter
);
}
public
void
resetFilters
()
{
this
.
includeFilters
.
clear
();
this
.
excludeFilters
.
clear
();
}
public
Set
<
Class
<?>>
doScan
(
String
basePackage
)
{
Set
<
Class
<?>>
classes
=
new
HashSet
<
Class
<?>>();
try
{
String
packageSearchPath
=
ResourcePatternResolver
.
CLASSPATH_ALL_URL_PREFIX
+
org
.
springframework
.
util
.
ClassUtils
.
convertClassNameToResourcePath
(
SystemPropertyUtils
.
resolvePlaceholders
(
basePackage
))
+
"/**/*.class"
;
Resource
[]
resources
=
this
.
resourcePatternResolver
.
getResources
(
packageSearchPath
);
for
(
int
i
=
0
;
i
<
resources
.
length
;
i
++)
{
Resource
resource
=
resources
[
i
];
if
(
resource
.
isReadable
())
{
MetadataReader
metadataReader
=
this
.
metadataReaderFactory
.
getMetadataReader
(
resource
);
// boolean isEmpty = (includeFilters.size() == 0 && excludeFilters.size() == 0);
// if (isEmpty || matches(metadataReader)) {
if
(
matches
(
metadataReader
))
{
String
className
=
metadataReader
.
getClassMetadata
().
getClassName
();
boolean
isPresent
=
ClassUtils
.
isPresent
(
className
,
ClassScaner
.
class
.
getClassLoader
());
if
(
isPresent
)
{
Class
<?>
classType
=
getClassByName
(
className
);
if
(
null
!=
classType
)
{
classes
.
add
(
classType
);
}
}
}
}
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
return
classes
;
}
public
Class
<?>
getClassByName
(
String
className
)
{
try
{
return
Class
.
forName
(
className
);
}
catch
(
ClassNotFoundException
e
)
{
e
.
printStackTrace
();
}
return
null
;
}
public
boolean
matches
(
MetadataReader
metadataReader
)
{
for
(
TypeFilter
tf
:
this
.
excludeFilters
)
{
try
{
if
(
tf
.
match
(
metadataReader
,
this
.
metadataReaderFactory
))
{
return
false
;
}
}
catch
(
IOException
e
)
{
// TODO Auto-generated catch block
e
.
printStackTrace
();
}
}
if
(
includeFilters
.
isEmpty
())
{
return
true
;
}
for
(
TypeFilter
tf
:
this
.
includeFilters
)
{
try
{
if
(
tf
.
match
(
metadataReader
,
this
.
metadataReaderFactory
))
{
return
true
;
}
}
catch
(
IOException
e
)
{
// TODO Auto-generated catch block
e
.
printStackTrace
();
}
}
return
false
;
}
public
static
Set
<
Class
<?>>
scan
(
String
...
basePackages
)
{
ClassScaner
cs
=
new
ClassScaner
();
Set
<
Class
<?>>
classes
=
new
HashSet
<
Class
<?>>();
for
(
String
s
:
basePackages
)
{
classes
.
addAll
(
cs
.
doScan
(
s
));
}
return
classes
;
}
public
static
Set
<
Class
<?>>
scan
(
List
<
String
>
basePackages
)
{
ClassScaner
cs
=
new
ClassScaner
();
Set
<
Class
<?>>
classes
=
new
HashSet
<
Class
<?>>();
for
(
String
s
:
basePackages
)
{
classes
.
addAll
(
cs
.
doScan
(
s
));
}
return
classes
;
}
public
static
Set
<
Class
<?>>
scan
(
String
basePackage
)
{
ClassScaner
cs
=
new
ClassScaner
();
return
cs
.
doScan
(
basePackage
);
}
@SuppressWarnings
(
"unchecked"
)
public
static
Set
<
Class
<?>>
scan
(
String
basePackage
,
Class
<?
extends
Annotation
>...
annotations
)
{
ClassScaner
cs
=
new
ClassScaner
();
for
(
Class
<?
extends
Annotation
>
anno
:
annotations
)
{
cs
.
addIncludeFilter
(
new
AnnotationTypeFilter
(
anno
));
}
return
cs
.
doScan
(
basePackage
);
}
@SuppressWarnings
({
"unchecked"
})
public
static
Set
<
Class
<?>>
scan
(
String
[]
basePackages
,
Class
<?
extends
Annotation
>...
annotations
)
{
ClassScaner
cs
=
new
ClassScaner
();
for
(
Class
<?
extends
Annotation
>
anno
:
annotations
)
{
cs
.
addIncludeFilter
(
new
AnnotationTypeFilter
(
anno
));
}
Set
<
Class
<?>>
classes
=
new
HashSet
<
Class
<?>>();
for
(
String
s
:
basePackages
)
{
classes
.
addAll
(
cs
.
doScan
(
s
));
}
return
classes
;
}
}
core/src/main/java/com/wecloud/dispatch/util/ClassUtil.java
0 → 100644
View file @
a7892caa
package
com
.
wecloud
.
dispatch
.
util
;
import
java.lang.reflect.Modifier
;
/**
* @author lixiaozhong
*/
public
class
ClassUtil
{
/**
* 是否可被实例化
*
* @param classType
* @return
*/
public
static
boolean
isCanInstance
(
Class
<?>
classType
)
{
boolean
can
=
true
;
boolean
isAbstract
=
Modifier
.
isAbstract
(
classType
.
getModifiers
());
if
(
classType
.
isAnnotation
())
{
can
=
false
;
}
else
if
(
classType
.
isEnum
())
{
can
=
false
;
}
else
if
(
classType
.
isInterface
())
{
can
=
false
;
}
else
if
(
isAbstract
)
{
can
=
false
;
}
else
if
(
classType
.
isArray
())
{
can
=
false
;
}
return
can
;
}
}
core/src/main/java/com/wecloud/im/netty/core/WsReadHandler.java
View file @
a7892caa
package
com
.
wecloud
.
im
.
netty
.
core
;
package
com
.
wecloud
.
im
.
netty
.
core
;
import
com.wecloud.dispatch.general.GeneralMessageHandler
;
import
com.wecloud.im.executor.BusinessThreadPool
;
import
com.wecloud.im.executor.BusinessThreadPool
;
import
com.wecloud.im.ws.manager.ChannelManager
;
import
com.wecloud.im.ws.manager.ChannelManager
;
import
com.wecloud.im.ws.strategy.AbstractImCmdStrategy
;
import
com.wecloud.im.ws.strategy.AbstractImCmdStrategy
;
...
@@ -30,6 +31,9 @@ public class WsReadHandler extends SimpleChannelInboundHandler<TextWebSocketFram
...
@@ -30,6 +31,9 @@ public class WsReadHandler extends SimpleChannelInboundHandler<TextWebSocketFram
@Resource
@Resource
private
ChannelManager
channelManager
;
private
ChannelManager
channelManager
;
@Resource
private
GeneralMessageHandler
generalMessageHandler
;
@Override
@Override
protected
void
channelRead0
(
ChannelHandlerContext
ctx
,
TextWebSocketFrame
msg
)
{
protected
void
channelRead0
(
ChannelHandlerContext
ctx
,
TextWebSocketFrame
msg
)
{
// 读空闲的计数清零
// 读空闲的计数清零
...
@@ -70,6 +74,8 @@ public class WsReadHandler extends SimpleChannelInboundHandler<TextWebSocketFram
...
@@ -70,6 +74,8 @@ public class WsReadHandler extends SimpleChannelInboundHandler<TextWebSocketFram
}
}
AbstractImCmdStrategy
.
process
(
clientId
,
ctx
,
data
);
AbstractImCmdStrategy
.
process
(
clientId
,
ctx
,
data
);
generalMessageHandler
.
doMessage
(
clientId
,
ctx
,
data
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
log
.
error
(
"系统繁忙data:"
+
data
+
",clientId:"
+
clientId
+
log
.
error
(
"系统繁忙data:"
+
data
+
",clientId:"
+
clientId
+
...
...
core/src/main/java/com/wecloud/im/ws/ImConstant.java
View file @
a7892caa
...
@@ -64,4 +64,6 @@ public class ImConstant implements Serializable {
...
@@ -64,4 +64,6 @@ public class ImConstant implements Serializable {
*/
*/
public
static
final
String
MSG_TYPE
=
"type"
;
public
static
final
String
MSG_TYPE
=
"type"
;
public
static
final
String
CMD
=
"cmd"
;
}
}
core/src/main/java/com/wecloud/im/ws/sender/ChannelSender.java
View file @
a7892caa
...
@@ -153,6 +153,20 @@ public class ChannelSender {
...
@@ -153,6 +153,20 @@ public class ChannelSender {
* @param nioSocketChannel
* @param nioSocketChannel
* @param responseModel
* @param responseModel
*/
*/
public
void
sendMsgLocal
(
NioSocketChannel
nioSocketChannel
,
Object
responseModel
)
{
String
msgJson
=
JsonUtils
.
encodeJson
(
responseModel
);
// 本地直接下发
nioSocketChannel
.
writeAndFlush
(
new
TextWebSocketFrame
(
msgJson
));
}
/**
* 本地直接下发,限定本机有的channel
*
* @param nioSocketChannel
* @param responseModel
*/
public
void
sendMsgLocal
(
NioSocketChannel
nioSocketChannel
,
WsResponse
responseModel
)
{
public
void
sendMsgLocal
(
NioSocketChannel
nioSocketChannel
,
WsResponse
responseModel
)
{
String
msgJson
=
JsonUtils
.
encodeJson
(
responseModel
);
String
msgJson
=
JsonUtils
.
encodeJson
(
responseModel
);
...
...
core/src/main/java/com/wecloud/utils/JsonUtils.java
View file @
a7892caa
package
com
.
wecloud
.
utils
;
package
com
.
wecloud
.
utils
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.databind.DeserializationFeature
;
import
com.fasterxml.jackson.databind.JavaType
;
import
com.fasterxml.jackson.databind.JavaType
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.wecloud.im.ws.model.request.ReceiveVO
;
import
lombok.extern.slf4j.Slf4j
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.cglib.beans.BeanMap
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
/**
/**
* fasterxml 的json工具类
* fasterxml 的json工具类
...
@@ -21,6 +25,9 @@ import java.util.List;
...
@@ -21,6 +25,9 @@ import java.util.List;
public
class
JsonUtils
{
public
class
JsonUtils
{
private
static
final
ObjectMapper
OBJECT_MAPPER
=
new
ObjectMapper
();
private
static
final
ObjectMapper
OBJECT_MAPPER
=
new
ObjectMapper
();
static
{
OBJECT_MAPPER
.
configure
(
DeserializationFeature
.
FAIL_ON_UNKNOWN_PROPERTIES
,
false
);
}
/**
/**
* Json格式的字符串向JavaBean转换,传入空串将返回null
* Json格式的字符串向JavaBean转换,传入空串将返回null
...
@@ -179,4 +186,49 @@ public class JsonUtils {
...
@@ -179,4 +186,49 @@ public class JsonUtils {
return
null
;
return
null
;
}
}
}
}
/**
* 判断字符也许是JSON
*
* @param string
* @return
*/
public
static
boolean
maybeJson
(
String
string
)
{
return
maybeJsonArray
(
string
)
||
maybeJsonObject
(
string
);
}
/**
* 判断字符也许是JSONArray
*
* @param string
* @return
*/
public
static
boolean
maybeJsonArray
(
String
string
)
{
string
=
(
null
==
string
)
?
string
:
string
.
trim
();
return
string
!=
null
&&
(
"null"
.
equals
(
string
)
||
(
string
.
startsWith
(
"["
)
&&
string
.
endsWith
(
"]"
)));
}
/**
* 判断字符也许是JSONObject
*
* @param string
* @return
*/
public
static
boolean
maybeJsonObject
(
String
string
)
{
string
=
(
null
==
string
)
?
string
:
string
.
trim
();
return
string
!=
null
&&
(
"null"
.
equals
(
string
)
||
(
string
.
startsWith
(
"{"
)
&&
string
.
endsWith
(
"}"
)));
}
/**
* 将map装换为javabean对象
*
* @param map
* @param bean
* @return
*/
public
static
<
T
>
T
mapToBean
(
Map
<
String
,
Object
>
map
,
T
bean
)
{
BeanMap
beanMap
=
BeanMap
.
create
(
bean
);
beanMap
.
putAll
(
map
);
return
bean
;
}
}
}
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