版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
..StrutsPrepareAndExecuteFilter实现了Filter接口
init方法为初始化入口StrutsPrepareAndExecuteFilterinit方法
publicvoid
init<FilterConfig
filterConfig>
throws
ServletException
{
//初始化辅助类
类似一个Delegate
InitOperations
init
=
new
InitOperations<>;
try
{
//
FilterHostConfig
封装了FilterConfig参数对象
FilterHostConfig
config
=
new
FilterHostConfig<filterConfig>;
//LoggerFactory配置加载
//如果失败
使用JdkLoggerFactory//TODO
SPI
init.initLogging<config>;
//TODO
创建Dispatcher
注册加载器
执行加载器
创建容器
解析xml
Dispatcher
dispatcher
=
init.initDispatcher<config>;
init.initStaticContentLoader<config,
dispatcher>;
//预处理类
请求处理时才会真正用到//1.主要负责在每次请求
创建ActionContext
清除ActionContext//2.当接收到一个请求时
通过uri查找
ActionConfig
创建ActionMapping
prepare
=
new
PrepareOperations<filterConfig.getServletContext<>,
dispatcher>;
//处理请求
Delegate
execute
=
new
ExecuteOperations<filterConfig.getServletContext<>,
dispatcher>;
this.excludedPatterns
=
init.buildExcludedPatternsList<dispatcher>;
//空实现
留作扩展
postInit<dispatcher,
filterConfig>;
}
finally
{
init.cleanup<>;
}
}
InitOperations类似与一个Delegate主要负责实例化Dispatche
再把初始化操作转交给Dispatcheinit处理public
Dispatcher
initDispatcher<
HostConfig
filterConfig
>
{
//创建Dispatcher
Dispatcher
dispatcher
=
createDispatcher<filterConfig>;
//核心方法
Container容器的创建
xml解析在此方法发生
dispatcher.init<>;
return
dispatcher;
}
private
Dispatcher
createDispatcher<
HostConfig
filterConfig
>
{
Map<String,
String>
params
=
new
HashMap<String,
String><>;
for
<
Iterator
e
=
filterConfig.getInitParameterNames<>;
e.hasNext<>;
>
{
String
name
=
<String>
e.next<>;
String
value
=
filterConfig.getInitParameter<name>;
params.put<name,
value>;
}
returnnew
Dispatcher<filterConfig.getServletContext<>,
params>;
}
Dispatcherinit方法
1.针对配置文件注册不同的加载器保存到ConfigurationManager类中的一个变量中
2.创建容器解析xmlpublicvoid
init<>
{
//创建配置操作管理类
,
会保存元素加载器
if
<configurationManager
==
null>
{
configurationManager
=
createConfigurationManager<BeanSelectionProvider.DEFAULT_BEAN_NAME>;
}
try
{
/**初始化各种形式加载器,保存到ConfigurationManager#containerProviders
Map集合中
没有真正执行加载
解析逻辑*///org/apache/struts2/perties属性文件
里面定义了一系列struts常量
init_DefaultProperties<>;
//
[1]//web.xml配置的
config参数
[配置多个用","分开]//如果没有该参数
默认为
struts-default.xml[框架级],struts-plugin.xml[框架级],struts.xml[系统级别]//根据文件名称
创建加载器
加载xml主要有一下两个解析器//XmlConfigurationProvider[xwork.xml],//StrutsXmlConfigurationProvider[struts相关配置文件]配置元素加载器
init_TraditionalXmlConfigurations<>;
//
[2]//struts.locale
注册
init_LegacyStrutsProperties<>;
//
[3]//实例化
我们自定义的加载器
保存到containerProviders集合中//
web.xml
configProviders参数
多个用","分开
//配置器必须是ConfigurationProvider接口的实例//TODO
SPI
init_CustomConfigurationProviders<>;
//
[5]//web.xml配置的init-param参数
加载器
最终会保存到Container容器中
init_FilterInitParameters<>
;
//
[6]//TODO
根据我们在struts.xml定义的
常量
选择插件类
//比如集成spring
会用到org.apache.struts2.spring.StrutsSpringObjectFactory
init_AliasStandardObjects<>
;
//
[7]/**
执行加载器
*///TODO
创建容器
解析xml
真正执行加载器方法
Container
container
=
init_PreloadConfiguration<>;
//执行当前Dispatcher对象
依赖关系注入
container.inject<this>;
//额外动作
init_CheckConfigurationReloading<container>;
init_CheckWebLogicWorkaround<container>;
}
catch
<Exception
ex>
{
if
<LOG.isErrorEnabled<>>
LOG.error<"Dispatcher
initialization
failed",
ex>;
thrownew
StrutsException<ex>;
}
}
ConfigurationManager主要管理创建的各种加载器publicclass
ConfigurationManager
{
protectedstaticfinal
Logger
LOG
=
LoggerFactory.getLogger<ConfigurationManager.class>;
//配置元素管理器protected
Configuration
configuration;
protected
Lock
providerLock
=
new
ReentrantLock<>;
//创建的xml加载器会保存到次集合中private
List<ContainerProvider>
containerProviders
=
new
CopyOnWriteArrayList<ContainerProvider><>;
}
Dispatcher的createConfigurationManager方法protected
ConfigurationManager
createConfigurationManager<String
name>
{
//name
-
>
strutsreturnnew
ConfigurationManager<name>;
}
/r/perties
属性文件加载器privatevoid
init_DefaultProperties<>
{
//保存到ConfigurationManager加载器集合中
configurationManager.addConfigurationProvider<new
DefaultPropertiesProvider<>>;
}
2.创建struts相关文件加载器StrutsXmlConfigurationProvider
privatevoid
init_TraditionalXmlConfigurations<>
{
//web.xml
配置的config
String
configPaths
=
initParams.get<"config">;
if
<configPaths
==
null>
{
//如果没有配置
默认
struts-default.xml,struts-plugin.xml,struts.xml
configPaths
=
DEFAULT_CONFIGURATION_PATHS;
}
String[]
files
=
configPaths.split<"\\s*[,]\\s*">;
for
<String
file
:
files>
{
if
<file.endsWith<".xml">>
{
if
<"xwork.xml".equals<file>>
{
configurationManager.addConfigurationProvider<createXmlConfigurationProvider<file,
false>>;
}
else
{
//struts
xml加载器
//StrutsXmlConfigurationProvider
configurationManager.addConfigurationProvider<createStrutsXmlConfigurationProvider<file,
false,
servletContext>>;
}
}
else
{
thrownew
IllegalArgumentException<"Invalid
configuration
file
name">;
}
}
}
protected
XmlConfigurationProvider
createXmlConfigurationProvider<String
filename,
boolean
errorIfMissing>
{
returnnew
XmlConfigurationProvider<filename,
errorIfMissing>;
}
protected
XmlConfigurationProvider
createStrutsXmlConfigurationProvider<String
filename,
boolean
errorIfMissing,
ServletContext
ctx>
{
returnnew
StrutsXmlConfigurationProvider<filename,
errorIfMissing,
ctx>;
}
3.web.xml扩展的ContainerProviders加载器实例化privatevoid
init_CustomConfigurationProviders<>
{
//web.xml
中configProviders
节点
String
configProvs
=
initParams.get<"configProviders">;
if
<configProvs
!=
null>
{
String[]
classes
=
configProvs.split<"\\s*[,]\\s*">;
for
<String
cname
:
classes>
{
Class
cls
=
ClassLoaderUtils.loadClass<cname,
this.getClass<>>;
ConfigurationProvider
prov
=
<ConfigurationProvider>cls.newInstance<>;
configurationManager.addConfigurationProvider<prov>;
}
}
}
init_PreloadConfiguration
方法主要完成创建容器,解析xml动作private
Container
init_PreloadConfiguration<>
{
//创建Container
解析xml
Configuration
config
=
configurationManager.getConfiguration<>;
Container
container
=
config.getContainer<>;
boolean
reloadi18n
=
Boolean.valueOf<container.getInstance<String.class,
StrutsConstants.STRUTS_I18N_RELOAD>>;
LocalizedTextUtil.setReloadBundles<reloadi18n>;
return
container;
}
init_PreloadConfiguration方法中调用了
ConfigurationManager的getConfiguration方法publicsynchronized
Configuration
getConfiguration<>
{
//创建配置元素管理器if
<configuration
==
null>
{
//
defaultFrameworkBeanName
-
>
struts
setConfiguration<createConfiguration<defaultFrameworkBeanName>>;
try
{
//
getContainerProviders
返回注册的各种加载器
//
reloadContainer
创建Container
解析xml
configuration.reloadContainer<getContainerProviders<>>;
}
catch
<ConfigurationException
e>
{
setConfiguration<null>;
thrownew
ConfigurationException<"Unable
to
load
configuration.",
e>;
}
}
else
{
conditionalReload<>;
}
return
configuration;
}
[java]viewplaincopyprint?protected
Configuration
createConfiguration<String
beanName>
{
returnnew
DefaultConfiguration<beanName>;
}
DefaultConfiguration的reloadContainer方法会去执行已注册的各种加载器
,和创建容器publicsynchronized
List<PackageProvider>
reloadContainer<List<ContainerProvider>
providers>
throws
ConfigurationException
{
packageContexts.clear<>;
loadedFileNames.clear<>;
List<PackageProvider>
packageProviders
=
new
ArrayList<PackageProvider><>;
//
保存struts常量
ContainerProperties
props
=
new
ContainerProperties<>;
//容器构建器
ContainerBuilder
builder
=
new
ContainerBuilder<>;
for
<final
ContainerProvider
containerProvider
:
providers>
{
/**
*
初始化Document
准备解析
*
具体在XmlConfigurationProvider实现类
会处理include节点
*
处理完成之后Document会保存到XmlConfigurationProvider#documents
list集合中
*
include
file路径会保存到XmlConfigurationProvider#loadedFileUrls
set集合中
*
从代码中发现
include
file属性中
可以使用通配符
"*"
*//**
StrutsXmlConfigurationProvider
是
XmlConfigurationProvider的子类
*//**
StrutsXmlConfigurationProvider
struts*.xml
*/
containerProvider.init<this>;
//针对"bean","constant","unknown-handler-stack"节点
不包括"package"节点
解析xml
//每一个bean
对应一个LocatableFactory
LocatableFactory保存了bean的定义//bean定义
保存到ContainerBuilder#factories
map集合中
//配置文件中定义的常量
保存到props中
containerProvider.register<builder,
props>;
}
//将常量保存到ContainerBuilder#factories
map集合中
//每一个常量对应一个LocatableConstantFactory
props.setConstants<builder>;
builder.factory<Configuration.class,
new
Factory<Configuration><>
{
public
Configuration
create<Context
context>
throws
Exception
{
return
DefaultConfiguration.this;
}
}>;
ActionContext
oldContext
=
ActionContext.getContext<>;
try
{
//创建辅助容器
ContainerImpl并且
实例化
struts一些核心类
Container
bootstrap
=
createBootstrapContainer<>;
setContext<bootstrap>;
//主容器
这是一个全局变量
container
=
builder.create<false>;
setContext<container>;
objectFactory
=
container.getInstance<ObjectFactory.class>;
//
Process
the
configuration
providers
firstfor
<final
ContainerProvider
containerProvider
:
providers>
{
if
<containerProvider
instanceof
PackageProvider>
{
//viders.XmlConfigurationProvider#setObjectFactory<ObjectFactory>
container.inject<containerProvider>;
//解析
xml
package节点//保存packageContexts
map集合中//viders.XmlConfigurationProvider
line
481
<<PackageProvider>
containerProvider>.loadPackages<>;
packageProviders.add<<PackageProvider>
containerProvider>;
}
}
//
Then
process
any
package
providers
from
the
plugins
Set<String>
packageProviderNames
=
container.getInstanceNames<PackageProvider.class>;
if
<packageProviderNames
!=
null>
{
for
<String
name
:
packageProviderNames>
{
PackageProvider
provider
=
container.getInstance<PackageProvider.class,
name>;
provider.init<this>;
provider.loadPackages<>;
packageProviders.add<provider>;
}
}
//TODO
rebuildRuntimeConfiguration<>;
}
finally
{
if
<oldContext
==
null>
{
ActionContext.setContext<null>;
}
}
return
packageProviders;
}
StrutsXmlConfigurationProvider的init方法具体在父类XmlConfigurationProvider中实现publicvoid
init<Configuration
configuration>
{
this.configuration
=
configuration;
this.includedFileNames
=
configuration.getLoadedFileNames<>;
//
configFileName
->struts.xml//1.递归处理include节点//2.生成Document
集合
loadDocuments<configFileName>;
}
loadDocuments方法中调用了loadConfigurationFiles方法
返回一个Document集合privatevoid
loadDocuments<String
configFileName>
{
loadedFileUrls.clear<>;
//List<Document>
documents
documents
=
loadConfigurationFiles<configFileName,
null>;
}
loadConfigurationFiles方法递归处理include节点最终生成Document集合private
List<Document>
loadConfigurationFiles<String
fileName,
Element
includeElement>
{
List<Document>
docs
=
new
ArrayList<Document><>;
List<Document>
finalDocs
=
new
ArrayList<Document><>;
//防止include重复引入if
<!includedFileNames.contains<fileName>>
{
if
<LOG.isDebugEnabled<>>
{
LOG.debug<"Loading
action
configurations
from:
"
+
fileName>;
}
includedFileNames.add<fileName>;
Iterator<URL>
urls
=
null;
InputStream
is
=
null;
IOException
ioException
=
null;
try
{
urls
=
getConfigurationUrls<fileName>;
}
catch
<IOException
ex>
{
ioException
=
ex;
}
if
<urls
==
null
||
!urls.hasNext<>>
{
if
<errorIfMissing>
{
thrownew
ConfigurationException<"Could
not
open
files
of
the
name
"
+
fileName,
ioException>;
}
else
{
LOG.info<"Unable
to
locate
configuration
files
of
the
name
"
+
fileName
+
",
skipping">;
return
docs;
}
}
URL
url
=
null;
while
<urls.hasNext<>>
{
try
{
url
=
urls.next<>;
is
=
FileManager.loadFile<url>;
InputSource
in
=
new
InputSource<is>;
in.setSystemId<url.toString<>>;
//生成Document对象
docs.add<DomHelper.parse<in,
dtdMappings>>;
}
catch
<XWorkException
e>
{
if
<includeElement
!=
null>
{
thrownew
ConfigurationException<"Unable
to
load
"
+
url,
e,
includeElement>;
}
else
{
thrownew
ConfigurationException<"Unable
to
load
"
+
url,
e>;
}
}
catch
<Exception
e>
{
final
String
s
=
"Caught
exception
while
loading
file
"
+
fileName;
thrownew
ConfigurationException<s,
e,
includeElement>;
}
finally
{
if
<is
!=
null>
{
try
{
is.close<>;
}
catch
<IOException
e>
{
LOG.error<"Unable
to
close
input
stream",
e>;
}
}
}
}
//sort
the
documents,
according
to
the
"order"
attribute
Collections.sort<docs,
new
Comparator<Document><>
{
publicint
compare<Document
doc1,
Document
doc2>
{
return
XmlHelper.getLoadOrder<doc1>.compareTo<XmlHelper.getLoadOrder<doc2>>;
}
}>;
for
<Document
doc
:
docs>
{
Element
rootElement
=
doc.getDocumentElement<>;
NodeList
children
=
rootElement.getChildNodes<>;
int
childSize
=
children.getLength<>;
for
<int
i
=
0;
i
<
childSize;
i++>
{
Node
childNode
=
children.item<i>;
if
<childNode
instanceof
Element>
{
Element
child
=
<Element>
childNode;
final
String
nodeName
=
child.getNodeName<>;
if
<"include".equals<nodeName>>
{
String
includeFileName
=
child.getAttribute<"file">;
//可以使用通配符匹配
if
<includeFileName.indexOf<'*'>
!=
-1>
{
ClassPathFinder
wildcardFinder
=
new
ClassPathFinder<>;
wildcardFinder.setPattern<includeFileName>;
Vector<String>
wildcardMatches
=
wildcardFinder.findMatches<>;
for
<String
match
:
wildcardMatches>
{
//递归处理include节点
finalDocs.addAll<loadConfigurationFiles<match,
child>>;
}
}
else
{
//递归处理include节点finalDocs.addAll<loadConfigurationFiles<includeFileName,
child>>;
}
}
}
}
finalDocs.add<doc>;
loadedFileUrls.add<url.toString<>>;
}
}
return
finalDocs;
}
StrutsXmlConfigurationProvider的register方法主要在父类XmlConfigurationProvider中实现1.遍历init方法中生成的Document
集合
解析xml文件中定义的bean,constant常量节点不会处理package节点2.解析bean节点的值包装成LocatableFactory对象
注册到ContainerBuilder中factoriesmap集合中3.解析constant节点的值保存到ContainerProperties对象中
XmlConfigurationProvider的register
这里只解析bean
,constant节点publicvoid
register<ContainerBuilder
containerBuilder,
LocatableProperties
props>
throws
ConfigurationException
{
Map<String,
Node>
loadedBeans
=
new
HashMap<String,
Node><>;
for
<Document
doc
:
documents>
{
Element
rootElement
=
doc.getDocumentElement<>;
NodeList
children
=
rootElement.getChildNodes<>;
int
childSize
=
children.getLength<>;
for
<int
i
=
0;
i
<
childSize;
i++>
{
Node
childNode
=
children.item<i>;
if
<childNode
instanceof
Element>
{
Element
child
=
<Element>
childNode;
final
String
nodeName
=
child.getNodeName<>;
//解析bean节点if
<"bean".equals<nodeName>>
{
String
type
=
child.getAttribute<"type">;
String
name
=
child.getAttribute<"name">;
String
impl
=
child.getAttribute<"class">;
String
onlyStatic
=
child.getAttribute<"static">;
String
scopeStr
=
child.getAttribute<"scope">;
boolean
optional
=
"true".equals<child.getAttribute<"optional">>;
Scope
scope
=
Scope.SINGLETON;
if
<"default".equals<scopeStr>>
{
scope
=
Scope.DEFAULT;
}
elseif
<"request".equals<scopeStr>>
{
scope
=
Scope.REQUEST;
}
elseif
<"session".equals<scopeStr>>
{
scope
=
Scope.SESSION;
}
elseif
<"singleton".equals<scopeStr>>
{
scope
=
Scope.SINGLETON;
}
elseif
<"thread".equals<scopeStr>>
{
scope
=
Scope.THREAD;
}
if
<StringUtils.isEmpty<name>>
{
name
=
Container.DEFAULT_NAME;
}
try
{
Class
cimpl
=
ClassLoaderUtil.loadClass<impl,
getClass<>>;
Class
ctype
=
cimpl;
if
<StringUtils.isNotEmpty<type>>
{
ctype
=
ClassLoaderUtil.loadClass<type,
getClass<>>;
}
if
<"true".equals<onlyStatic>>
{
//
Force
loading
of
class
to
detect
no
class
def
found
exceptions
cimpl.getDeclaredClasses<>;
containerBuilder.injectStatics<cimpl>;
}
else
{
//
beanName
+
class
构成唯一约束
if
<containerBuilder.contains<ctype,
name>>
{
//用loadedBeans
map集合检查是否有重复配置的beanLocation
loc
=
LocationUtils.getLocation<loadedBeans.get<ctype.getName<>
+
name>>;
if
<throwExceptionOnDuplicateBeans>
{
thrownew
ConfigurationException<"Bean
type
"
+
ctype
+
"
with
the
name
"
+
name
+
"
has
already
been
loaded
by
"
+
loc,
child>;
}
}
//
Force
loading
of
class
to
detect
no
class
def
found
exceptions
cimpl.getDeclaredConstructors<>;
if
<LOG.isDebugEnabled<>>
{
LOG.debug<"Loaded
type:"
+
type
+
"
name:"
+
name
+
"
impl:"
+
impl>;
}
//LocatableFactory
类似spring中
BeanDefinition
//bean定义
保存到ContainerBuilder#factories
map集合中//目前为止
并未真正实例化beancontainerBuilder.factory<ctype,
name,
new
LocatableFactory<name,
ctype,
cimpl,
scope,
childNode>,
scope>;
}
//loadedBeans
检查重复配置的bean
loadedBeans.put<ctype.getName<>
+
name,
child>;
}
catch
<Throwable
ex>
{
if
<!optional>
{
thrownew
ConfigurationException<"Unable
to
load
bean:
type:"
+
type
+
"
class:"
+
impl,
ex,
childNode>;
}
else
{
LOG.debug<"Unable
to
load
optional
class:
"
+
ex>;
}
}
//constant常量节点
}
elseif
<"constant".equals<nodeName>>
{
String
name
=
child.getAttribute<"name">;
String
value
=
child.getAttribute<"value">;
//ContainerProperties
->props
props.setProperty<name,
value,
childNode>;
}
elseif
<nodeName.equals<"unknown-handler-stack">>
{
List<UnknownHandlerConfig>
unknownHandlerStack
=
new
ArrayList<UnknownHandlerConfig><>;
NodeList
unknownHandlers
=
child.getElementsByTagName<"unknown-handler-ref">;
int
unknownHandlersSize
=
unknownHandlers.getLength<>;
for
<int
k
=
0;
k
<
unknownHandlersSize;
k++>
{
Element
unknownHandler
=
<Element>
unknownHandlers.item<k>;
unknownHandlerStack.add<new
UnknownHandlerConfig<unknownHandler.getAttribute<"name">>>;
}
if
<!unknownHandlerStack.isEmpty<>>
configuration.setUnknownHandlerStack<unknownHandlerStack>;
}
}
}
}
}
XmlConfigurationProvider的loadPackages方法
解析package节点下的所有子节点interceptor
,ResultType等等
保存到DefaultConfigurationpackageContextsmap集合中publicvoid
loadPackages<>
throws
ConfigurationException
{
List<Element>
reloads
=
new
ArrayList<Element><>;
for
<Document
doc
:
documents>
{
Element
rootElement
=
doc.getDocumentElement<>;
NodeList
children
=
rootElement.getChildNodes<>;
int
childSize
=
children.getLength<>;
for
<int
i
=
0;
i
<
childSize;
i++>
{
Node
childNode
=
children.item<i>;
if
<childNode
instanceof
Element>
{
Element
child
=
<Element>
childNode;
final
String
nodeName
=
child.getNodeName<>;
if
<"package".equals<nodeName>>
{
//解析package节点
包装成PackageConfig对象
PackageConfig
cfg
=
addPackage<child>;
if
<cfg.isNeedsRefresh<>>
{
reloads.add<child>;
}
}
}
}
//空实现
扩展时用
loadExtraConfiguration<doc>;
}
if
<reloads.size<>
>
0>
{
reloadRequiredPackages<reloads>;
}
for
<Document
doc
:
documents>
{
//空实现
扩展时用
loadExtraConfiguration<doc>;
}
documents.clear<>;
configuration
=
null;
}
package节点下的所有子节点protected
PackageConfig
addPackage<Element
packageElement>
throws
ConfigurationException
{PackageConfig.Builder
newPackage
=
buildPackageContext<packageElement>;
if
<newPackage.isNeedsRefresh<>>
{
return
newPackage.build<>;
}
//处理所有的ResultType
包括自定义的
,
strust-default.xml中定义的
addResultTypes<newPackage,
packageElement>;
//interceptor节点
loadInterceptors<newPackage,
packageElement>;
//default-interceptor-ref
loadDefaultInterceptorRef<newPackage,
packageElement>;
//default-class-ref节点
loadDefaultClassRef<newPackage,
packageElement>;
//全局result
global-results节点
loadGlobalResults<newPackage,
packageElement>;
//global-exception-mappings节点
异常处理
loadGobalExceptionMappings<newPackage,
packageElement>;
NodeList
actionList
=
packageElement.getElementsByTagName<"action">;
for
<int
i
=
0;
i
<
actionList.getLength<>;
i++>
{
Element
actionElement
=
<Element>
actionList.item<i>;
//
action节点
result节点处理
addAction<actionElement,
newPackage>;
}
//default-action-ref
loadDefaultActionRef<newPackage,
packageElement>;
PackageConfig
cfg
=
newPackage.build<>;
//TODO
保存到Map<string
packageconfig="">
packageContexts
集合中
configuration.addPackageConfig<cfg.getName<>,
cfg>;
return
cfg;
}</string>
最后整理解析的ActionConfigMap集合[DefaultConfiguration#packageContexts]
最终已Map<nameSpace,Map<actionName,ActionConfig>>形式存储publicvoid
rebuildRuntimeConfiguration<>
{
runtimeConfiguration
=
buildRuntimeConfiguration<>;
}
[java]protectedsynchronized
RuntimeConfiguration
buildRuntimeConfiguration<>
throws
ConfigurationException
{
Map<String,
Map<String,
ActionConfig>>
namespaceActionConfigs
=
new
LinkedHashMap<String,
Map<String,
ActionConfig>><>;
Map<String,
String>
namespaceConfigs
=
new
LinkedHashMap<String,
String><>;
for
<PackageConfig
packageConfi
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年度大型仓储物流中心智能通风系统合同2篇
- 2024年度教育公司与海外院校关于国际合作与交流的合同2篇
- 2024年度原创音乐作品委托创作合同样本3篇
- 2024年度品牌策划推广合同.3篇
- 2024年度广告发布合同广告项目合作意向书
- 2024年标准产品采购合同模板版
- 2024年度水利围堰设计与施工一体化服务合同2篇
- 2024版个人财产反担保合同示范书3篇
- 2024年度有机农业抚育承包管理合同3篇
- 2024年度合肥软件开发项目委托合同6篇
- 乳品加工工(中级)理论考试复习题库(含答案)
- 《教材循环利用》课件
- 学生思想政治工作工作证明材料
- 2023水性环氧树脂涂层钢筋
- 湘少版六年级英语上册《Unit 12 第二课时(Part CPart D)》课堂教学课件公开课
- 国开《Windows网络操作系统管理》形考任务2-配置本地帐户与活动目录域服务实训
- 环保设施安全风险评估报告
- 配位化学-本科生版智慧树知到课后章节答案2023年下兰州大学
- 数字逻辑与计算机组成 习题答案 袁春风 第3章作业批改总结
- 设备考察报告怎么写(共8篇)
- 涉酒案件警示教育心得体会范文(通用4篇)
评论
0/150
提交评论