第一篇:典型相關(guān)分析SAS代碼
data fit;input X1 X2 X3 X4 X5 Y1 Y2 Y3;cards;14651000 3446 98.8 2094.51 104.2 2555.14 2637.67 179.76 13985000 3339 113.8 2305.2233 133.8 2462.45 2670.99 161.74 15162900 3093 108.9 2494.6668 93.8 2831.87 3015.04 186 14275800 3084 99.6 2770.48 99.8 2957.2 2259.86 210.3 13966000 3040 101.6 3224.05 142.4 2767.25 2169.47 206.16 13947000 2978 112.4086 3690.34 123.8 2935 2307 218.36 14632000 2952 102.5 3980.44 79.1 3119.91 2332.38 232.33 14123200 2761 106.2 4543.41 97.9 3230.04 2344.04 241.53 14299300 2703 107.3469 5231.33 143.2 3195.12 2411.98 239.79 14849000 2644 111.3 6007.5498 90.8 3342.09 2466.6 252.5 15218000 2604 103.8 6790.899 97.2 3456.7 2471.53 261.34 15344000 2567 99 7565 95.7 3518 2360.31 266.29 run;ods rtf file='F:結(jié)果.doc';proccancorr data=fit all vprefix=YING vname='yingxiang' wprefix=CHAN wname='shengchan';var X1 X2 X3 X4 X5;with Y1 Y2 Y3;run;ods rtf close;
第二篇:SAS如何實(shí)現(xiàn)典型相關(guān)分析
SAS實(shí)現(xiàn)典型相關(guān)分析
data ex20_1(type=corr);input _name_$3.x1 x2 y1-y4;_type_='corr';cards;x1 1.0 0.8491 0.5106 0.2497 0.5285 0.3019 x2 0.8491 1.0 0.8062 0.5438 0.7887 0.6064 y1 0.5106 0.8062 1.0 0.7833 0.9284 0.8364 y2 0.2497 0.5438 0.7833 1.0 0.6457 0.9051 y3 0.5285 0.7887 0.9284 0.6457 1.0 0.7097 y4 0.3019 0.6064 0.8364 0.9051 0.7097 1.0;proc cancorr edf=102;var x1 x2;with y1-y4;run;
data ex20_2(type=corr);input _name_$ x1-x9 y1-y5;_type_='corr';cards;x1 1-0.027 0.052 0.037 0.003 0.009-0.030 0.014 0.020 0.034 0.071 0.054-0.022 0.012 x2-0.027 1-0.065-0.057-0.016 0.014 0.053-0.080-0.067-0.023 0.019 0.046-0.034 0.012 x3 0.052-0.065 1 0.772 0.018 0.042-0.094 0.279 0.163 0.221 0.093-0.030 0.040-0.118 x4 0.037-0.057 0.772 1 0.003 0.044-0.080 0.098 0.040 0.224 0.116-0.013-0.013-0.096 x5 0.003-0.016 0.018 0.003 1-0.017-0.030 0.019 0.025-0.044-0.021 0.002-0.019 0.002 x6 0.009 0.014 0.042 0.044-0.017 1-0.020 0.009-0.018 0.032 0.047 0.009-0.037-0.015 x7-0.030 0.053-0.094-0.080-0.030-0.020 1-0.057 0.013 0.009-0.032 0.089 0.027 0.014 x8 0.014-0.080 0.279 0.098 0.019 0.009-0.057 1 0.447-0.018-0.036-0.031 0.156-0.041 x9 0.020-0.067 0.163 0.040 0.025-0.018 0.013 0.447 1-0.063-0.017-0.027 0.117-0.019 y1 0.034-0.023 0.221 0.224-0.044 0.032 0.009-0.018-0.063 1 0.156-0.070-0.070-0.116
y2 0.071 0.019 0.093 0.116-0.021 0.047-0.032-0.036-0.017 0.156 1-0.039-0.046-0.052 y3 0.054 0.046-0.030-0.013 0.002 0.009 0.089-0.031-0.027-0.070-0.039 1 0.001 0.013 y4-0.022-0.034 0.040-0.013-0.019-0.037 0.027 0.156 0.117-0.070-0.046 0.001 1-0.019 y5 0.012 0.012-0.118-0.096 0.002-0.015 0.014-0.041-0.019-0.116-0.052 0.013-0.019 1;proc cancorr data=ex20_2 edf=1494 red;var x1-x9;with y1-y5;run;
data ex21_1;input group num;do i=1 to num;input value@@;output;end;cards;1 25 6.5 13.5 12.8 6.2 13.9 14.7 9.5 9.0 6.9 16.8 13.3 10.8 12.2 14.9 13.7 12.8 5.3 11.8 12.4 7.6 13.3 11.9 11.2 12.3 12.7 0 20 8.5 6.4 4.6 1.7 9.7 5.3 4.9 5.7 3.8 6.5 6.3 5.4 3.3 4.7 8.6 6.3 5.9 4.8 4.5 5.2;proc logistic descending;model group=value/scale=none outroc=roc1;run;proc print;run;proc gplot;plot _SENSIT_*_1MSPEC_;run;
第三篇:典型相關(guān)分析的SAS實(shí)現(xiàn)
典型相關(guān)分析的SAS實(shí)現(xiàn)
data ex20_1(type=corr);input _name_$3.x1 x2 y1-y4;_type_='corr';cards;x1 1.0 0.8491 0.5106 0.2497 0.5285 0.3019 x2 0.8491 1.0 0.8062 0.5438 0.7887 0.6064 y1 0.5106 0.8062 1.0 0.7833 0.9284 0.8364 y2 0.2497 0.5438 0.7833 1.0 0.6457 0.9051 y3 0.5285 0.7887 0.9284 0.6457 1.0 0.7097 y4 0.3019 0.6064 0.8364 0.9051 0.7097 1.0;proc cancorr edf=102;var x1 x2;with y1-y4;run;
data ex20_2(type=corr);input _name_$ x1-x9 y1-y5;_type_='corr';cards;x1 1-0.027 0.052 0.037 0.003 0.009-0.030 0.014 0.020 0.034 0.071 0.054-0.022 0.012 x2-0.027 1-0.065-0.057-0.016 0.014 0.053-0.080-0.067-0.023 0.019 0.046-0.034 0.012 x3 0.052-0.065 1 0.772 0.018 0.042-0.094 0.279 0.163 0.221 0.093-0.030 0.040-0.118 x4 0.037-0.057 0.772 1 0.003 0.044-0.080 0.098 0.040 0.224 0.116-0.013-0.013-0.096 x5 0.003-0.016 0.018 0.003 1-0.017-0.030 0.019 0.025-0.044-0.021 0.002-0.019 0.002 x6 0.009 0.014 0.042 0.044-0.017 1-0.020 0.009-0.018 0.032 0.047 0.009-0.037-0.015 x7-0.030 0.053-0.094-0.080-0.030-0.020 1-0.057 0.013 0.009-0.032 0.089 0.027 0.014 x8 0.014-0.080 0.279 0.098 0.019 0.009-0.057 1 0.447-0.018-0.036-0.031 0.156-0.041 x9 0.020-0.067 0.163 0.040 0.025-0.018 0.013 0.447 1-0.063-0.017-0.027 0.117-0.019 y1 0.034-0.023 0.221 0.224-0.044 0.032 0.009-0.018-0.063 1 0.156-0.070-0.070-0.116
y2 0.071 0.019 0.093 0.116-0.021 0.047-0.032-0.036-0.017 0.156 1-0.039-0.046-0.052 y3 0.054 0.046-0.030-0.013 0.002 0.009 0.089-0.031-0.027-0.070-0.039 1 0.001 0.013 y4-0.022-0.034 0.040-0.013-0.019-0.037 0.027 0.156 0.117-0.070-0.046 0.001 1-0.019 y5 0.012 0.012-0.118-0.096 0.002-0.015 0.014-0.041-0.019-0.116-0.052 0.013-0.019 1;proc cancorr data=ex20_2 edf=1494 red;var x1-x9;with y1-y5;run;
data ex21_1;input group num;do i=1 to num;input value@@;output;end;cards;1 25 6.5 13.5 12.8 6.2 13.9 14.7 9.5 9.0 6.9 16.8 13.3 10.8 12.2 14.9 13.7 12.8 5.3 11.8 12.4 7.6 13.3 11.9 11.2 12.3 12.7 0 20 8.5 6.4 4.6 1.7 9.7 5.3 4.9 5.7 3.8 6.5 6.3 5.4 3.3 4.7 8.6 6.3 5.9 4.8 4.5 5.2;proc logistic descending;model group=value/scale=none outroc=roc1;run;proc print;run;proc gplot;plot _SENSIT_*_1MSPEC_;run;
第四篇:struts2代碼分析
1.Struts2架構(gòu)圖和請求處理流程
請求首先通過Filter chain,F(xiàn)ilter主要包括ActionContextCleanUp,它主要清理當(dāng)前線程的ActionContext和Dispatcher;FilterDispatcher主要通過AcionMapper來決定需要調(diào)用哪個Action。
ActionMapper取得了ActionMapping后,在Dispatcher的serviceAction方法里創(chuàng)建ActionProxy,ActionProxy創(chuàng)建ActionInvocation,然后ActionInvocation調(diào)用Interceptors,執(zhí)行Action本身,創(chuàng)建Result并返回,當(dāng)然,如果要在返回之前做些什么,可以實(shí)現(xiàn)PreResultListener。
2.Struts2部分類介紹
這部分從Struts2參考文檔中翻譯就可以了。
ActionMapper
ActionMapper其實(shí)是HttpServletRequest和Action調(diào)用請求的一個映射,它屏蔽了Action對于Request等java Servlet類的依賴。Struts2中它的默認(rèn)實(shí)現(xiàn)類是DefaultActionMapper,ActionMapper很大的用處可以根據(jù)自己的需要來設(shè)計(jì)url格式,它自己也有Restful的實(shí)現(xiàn),具體可以參考文檔的docs¥actionmapper.html。
ActionProxy&ActionInvocation
Action的一個代理,由ActionProxyFactory創(chuàng)建,它本身不包括Action實(shí)例,默認(rèn)實(shí)現(xiàn)DefaultActionProxy是由ActionInvocation持有Action實(shí)例。ActionProxy作用是如何取得Action,無論是本地還是遠(yuǎn)程。而ActionInvocation的作用是如何執(zhí)行Action,攔截器的功能就是在ActionInvocation中實(shí)現(xiàn)的。
ConfigurationProvider&Configuration
ConfigurationProvider就是Struts2中配置文件的解析器,Struts2中的配置文件主要是尤其實(shí)現(xiàn)類XmlConfigurationProvider及其子類StrutsXmlConfigurationProvider來解析。
3.Struts2請求流程
1、客戶端發(fā)送請求
2、請求先通過ActionContextCleanUp-->FilterDispatcher
3、FilterDispatcher通過ActionMapper來決定這個Request需要調(diào)用哪個Action
4、如果ActionMapper決定調(diào)用某個Action,F(xiàn)ilterDispatcher把請求的處理交給ActionProxy,這兒已經(jīng)轉(zhuǎn)到它的Delegate--Dispatcher來執(zhí)行
5、ActionProxy根據(jù)ActionMapping和ConfigurationManager找到需要調(diào)用的Action類
6、ActionProxy創(chuàng)建一個ActionInvocation的實(shí)例
7、ActionInvocation調(diào)用真正的Action,當(dāng)然這涉及到相關(guān)攔截器的調(diào)用
8、Action執(zhí)行完畢,ActionInvocation創(chuàng)建Result并返回,當(dāng)然,如果要在返回之前做些什么,可以實(shí)現(xiàn)PreResultListener。添加PreResultListener可以在Interceptor中實(shí)現(xiàn)。
首先強(qiáng)調(diào)一下struts2的線程程安全,在Struts2中大量采用ThreadLocal線程局部變量的方法來保證線程的安全,像Dispatcher等都是通過ThreadLocal來保存變量值,使得每個線程都有自己獨(dú)立的實(shí)例變量,互不相干.接下來就從Dispatcher開始看起,先看其構(gòu)造函數(shù):
//創(chuàng)建Dispatcher,此類是一個Delegate,它是真正完成根據(jù)url解析轉(zhuǎn)向,讀取對應(yīng)Action的地方
public Dispatcher(ServletContext servletContext, Map
this.servletContext = servletContext;
//配置在web.xml中的param參數(shù)
this.initParams = initParams;
}
//創(chuàng)建Dispatcher,此類是一個Delegate,它是真正完成根據(jù)url解析轉(zhuǎn)向,讀取對應(yīng)Action的地方
public Dispatcher(ServletContext servletContext, Map
this.servletContext = servletContext;
//配置在web.xml中的param參數(shù)
this.initParams = initParams;
}
我們再看在FilterDispatcher創(chuàng)建Dispatcher的:
protected Dispatcher createDispatcher(FilterConfig filterConfig){
Map
for(Enumeration e = filterConfig.getInitParameterNames();e.hasMoreElements();){
String name =(String)e.nextElement();
String value = filterConfig.getInitParameter(name);
params.put(name, value);
}
都可以從FilterConfig中得到
return new Dispatcher(filterConfig.getServletContext(), params);
}
protected Dispatcher createDispatcher(FilterConfig filterConfig){
Map
for(Enumeration e = filterConfig.getInitParameterNames();e.hasMoreElements();){
String name =(String)e.nextElement();
String value = filterConfig.getInitParameter(name);
params.put(name, value);
}
都可以從FilterConfig中得到
return new Dispatcher(filterConfig.getServletContext(), params);
}
分七步載入各種配置屬性,都是通過ConfigurationProvider接口進(jìn)行的,這個接口提供init(),destroy(),register()等方法.將各種ConfigurationProvider初始化之后將實(shí)例添加到ConfigurationManager的List里面.最后通過循環(huán)調(diào)用List里的這些destroy(),register()等方法實(shí)現(xiàn)對配置文件的屬性進(jìn)行注冊和銷毀等功能.下面將分析這七層功夫是怎樣一步步練成的.首先是init_DefaultProperties()
創(chuàng)建Dispatcher之后,來看init()方法
init()方法是用來Load用戶配置文件,資源文件以及默認(rèn)的配置文件.主要分七步走,看下面注釋
public void init(){
if(configurationManager == null){
//設(shè)置ConfigurationManager的defaultFrameworkBeanName.//這里DEFAULT_BEAN_NAME為struts,這是xwork框架的內(nèi)容,Framework可以是xwork,struts,webwork等
configurationManager
=
new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
}
//讀取properties信息,默認(rèn)的default.properties,init_DefaultProperties();// [1]
//讀取xml配置文件
init_TraditionalXmlConfigurations();// [2]
//讀取用戶自定義的struts.properties
init_LegacyStrutsProperties();// [3]
//自定義的configProviders
init_CustomConfigurationProviders();// [5]
//載入FilterDispatcher傳進(jìn)來的initParams
init_FilterInitParameters();// [6]
//將配置文件中的bean與具體的類映射
init_AliasStandardObjects();// [7]
//構(gòu)建一個用于依賴注射的Container對象
//在這里面會循環(huán)調(diào)用上面七個ConfigurationProvider的register方法
//其中的重點(diǎn)就是DefaultConfiguration的#reload()方法
Container container = init_PreloadConfiguration();
container.inject(this);
init_CheckConfigurationReloading(container);
init_CheckWebLogicWorkaround(container);
if(!dispatcherListeners.isEmpty()){
for(DispatcherListener l : dispatcherListeners){
l.dispatcherInitialized(this);
}
}
}
public void init(){
if(configurationManager == null){
//設(shè)置ConfigurationManager的defaultFrameworkBeanName.//這里DEFAULT_BEAN_NAME為struts,這是xwork框架的內(nèi)容,Framework可以是xwork,struts,webwork等
configurationManager
=
new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
}
//讀取properties信息,默認(rèn)的default.properties,init_DefaultProperties();// [1]
//讀取xml配置文件
init_TraditionalXmlConfigurations();// [2]
//讀取用戶自定義的struts.properties
init_LegacyStrutsProperties();// [3]
//自定義的configProviders
init_CustomConfigurationProviders();// [5]
//載入FilterDispatcher傳進(jìn)來的initParams
init_FilterInitParameters();// [6]
//將配置文件中的bean與具體的類映射
init_AliasStandardObjects();// [7]
//構(gòu)建一個用于依賴注射的Container對象
//在這里面會循環(huán)調(diào)用上面七個ConfigurationProvider的register方法
//其中的重點(diǎn)就是DefaultConfiguration的#reload()方法
Container container = init_PreloadConfiguration();
container.inject(this);
init_CheckConfigurationReloading(container);
init_CheckWebLogicWorkaround(container);
if(!dispatcherListeners.isEmpty()){
for(DispatcherListener l : dispatcherListeners){
l.dispatcherInitialized(this);
}
}
}
分七步載入各種配置屬性,都是通過ConfigurationProvider接口進(jìn)行的,這個接口提供init(),destroy(),register()等方法.將各種ConfigurationProvider初始化之后將實(shí)例添加到ConfigurationManager的List里面.最后通過循環(huán)調(diào)用List里的這些destroy(),register()等方法實(shí)現(xiàn)對配置文件的屬性進(jìn)行注冊和銷毀等功能.下面將分析這七層功夫是怎樣一步步練成的.首先是init_DefaultProperties()
private void init_DefaultProperties(){
configurationManager.addConfigurationProvider(new DefaultPropertiesProvider());
}
接來看DefaultPropertiesProvider好了,DefaultPropertiesProvider實(shí)際上只是實(shí)現(xiàn)了register()方法
public void register(ContainerBuilder builder, LocatableProperties props)
throws ConfigurationException {
Settings defaultSettings = null;
try {
defaultSettings = new PropertiesSettings(“org/apache/struts2/default”);
} catch(Exception e){
throw
}
loadSettings(props, defaultSettings);
}
private void init_DefaultProperties(){
configurationManager.addConfigurationProvider(new DefaultPropertiesProvider());
}
接來看DefaultPropertiesProvider好了,DefaultPropertiesProvider實(shí)際上只是實(shí)現(xiàn)了register()方法
public void register(ContainerBuilder builder, LocatableProperties props)
throws ConfigurationException {
Settings defaultSettings = null;
try {
defaultSettings = new PropertiesSettings(“org/apache/struts2/default”);
} catch(Exception e){
new
ConfigurationException(“Could
not
find
or
error
in org/apache/struts2/default.properties”, e);
throw
}
new ConfigurationException(“Could not find or error in org/apache/struts2/default.properties”, e);
loadSettings(props, defaultSettings);
}
//PropertiesSettings構(gòu)造方法
//讀取org/apache/struts2/default.properties的配置信息,如果項(xiàng)目中需要覆蓋,可以在classpath里的struts.properties里覆寫
public PropertiesSettings(String name){
URL settingsUrl = ClassLoaderUtils.getResource(name + “.properties”, getClass());
if(settingsUrl == null){
LOG.debug(name + “.properties missing”);
settings = new LocatableProperties();
return;
}
settings
// Load settings
InputStream in = null;
try {
in = settingsUrl.openStream();
settings.load(in);
} catch(IOException e){
throw new StrutsException(“Could not load ” + name + “.properties:” + e, e);
} finally {
if(in!= null){
try {
=
new
LocatableProperties(new
LocationImpl(null, settingsUrl.toString()));
in.close();
} catch(IOException io){
LOG.warn(“Unable to close input stream”, io);
}
}
}
}
//loadSettings主要是將progerty的value和Locale從上面PropertiesSettings中取得并存放到LocatableProperties props
//這個props是register的一個入?yún)?protected void loadSettings(LocatableProperties props, final Settings settings){
// We are calling the impl methods to get around the single instance of Settings that is expected
for(Iterator i = settings.listImpl();i.hasNext();){
String name =(String)i.next();
props.setProperty(name, settings.getLocationImpl(name));
}
}
//PropertiesSettings構(gòu)造方法
//讀取org/apache/struts2/default.properties的配置信息,如果項(xiàng)目中需要覆蓋,可以在classpath里的struts.properties里覆寫
public PropertiesSettings(String name){
URL settingsUrl = ClassLoaderUtils.getResource(name + “.properties”, getClass());
if(settingsUrl == null){
LOG.debug(name + “.properties missing”);
settings = new LocatableProperties();
return;
}
settings =
new
LocatableProperties(new
LocationImpl(null, settingsUrl.toString()));
settings.getImpl(name),// Load settings
InputStream in = null;
try {
in = settingsUrl.openStream();
settings.load(in);
} catch(IOException e){
throw new StrutsException(“Could not load ” + name + “.properties:” + e, e);
} finally {
if(in!= null){
try {
in.close();
} catch(IOException io){
LOG.warn(“Unable to close input stream”, io);
}
}
}
}
//loadSettings主要是將progerty的value和Locale從上面PropertiesSettings中取得并存放到LocatableProperties props
//這個props是register的一個入?yún)?protected void loadSettings(LocatableProperties props, final Settings settings){
// We are calling the impl methods to get around the single instance of Settings that is expected
for(Iterator i = settings.listImpl();i.hasNext();){
String name =(String)i.next();
props.setProperty(name, settings.getLocationImpl(name));
}
}
再來看第二步:init_TraditionalXmlConfigurations()
private void init_TraditionalXmlConfigurations(){
settings.getImpl(name), //首先讀取web.xml中的config初始參數(shù)值
//如果
沒
有
配
置
就
使
用
默
認(rèn)的DEFAULT_CONFIGURATION_PATHS:“struts-default.xml,struts-plugin.xml,struts.xml”,//這兒就可以看出為什么默認(rèn)的配置文件必須取名為這三個名稱了
//如果不想使用默認(rèn)的名稱,直接在web.xml中配置config初始參數(shù)即可
String configPaths = initParams.get(“config”);
if(configPaths == null){
configPaths = DEFAULT_CONFIGURATION_PATHS;
}
String[] files = configPaths.split(“¥¥s*[,]¥¥s*”);
for(String file : files){
if(file.endsWith(“.xml”)){
if(“xwork.xml”.equals(file)){
//XmlConfigurationProvider負(fù)責(zé)解析xwork.xml
configurationManager.addConfigurationProvider(new XmlConfigurationProvider(file, false));
} else {
//其它xml都是由StrutsXmlConfigurationProvider來解析
configurationManager.addConfigurationProvider(new StrutsXmlConfigurationProvider(file, false, servletContext));
}
} else {
throw new IllegalArgumentException(“Invalid configuration file name”);
}
}
}
private void init_TraditionalXmlConfigurations(){
//首先讀取web.xml中的config初始參數(shù)值
//如果
沒
有
配
置
就
使
用
默
認(rèn)的DEFAULT_CONFIGURATION_PATHS:“struts-default.xml,struts-plugin.xml,struts.xml”,//這兒就可以看出為什么默認(rèn)的配置文件必須取名為這三個名稱了
//如果不想使用默認(rèn)的名稱,直接在web.xml中配置config初始參數(shù)即可
String configPaths = initParams.get(“config”);
if(configPaths == null){
configPaths = DEFAULT_CONFIGURATION_PATHS;
}
String[] files = configPaths.split(“¥¥s*[,]¥¥s*”);
for(String file : files){
if(file.endsWith(“.xml”)){
if(“xwork.xml”.equals(file)){
//XmlConfigurationProvider負(fù)責(zé)解析xwork.xml
configurationManager.addConfigurationProvider(new XmlConfigurationProvider(file, false));
} else {
//其它xml都是由StrutsXmlConfigurationProvider來解析
configurationManager.addConfigurationProvider(new StrutsXmlConfigurationProvider(file, false, servletContext));
}
} else {
throw new IllegalArgumentException(“Invalid configuration file name”);
}
}
}
對于其它配置文件只用接口。
類XmlConfigurationProvider負(fù)責(zé)配置文件的讀取和解析,首先通過init()中的loadDocuments(configFileName);利用DomHelper中的
public static Document parse(InputSource inputSource, Map
addAction()方法負(fù)責(zé)讀取
loadInterceptorStack()方法負(fù)責(zé)將
StrutsXmlConfigurationProvider,此類繼承XmlConfigurationProvider,而XmlConfigurationProvider又實(shí)現(xiàn)ConfigurationProviderloadInterceptorStacks()方法負(fù)責(zé)將
而上面的方法最終會被addPackage()方法調(diào)用,addPackage又會被Provider的loadPackages()調(diào)用,將所讀取到的數(shù)據(jù)匯集到PackageConfig對象中。
protected PackageConfig
addPackage(Element
packageElement)
throws ConfigurationException {
PackageConfig.Builder newPackage = buildPackageContext(packageElement);
if(newPackage.isNeedsRefresh()){
return newPackage.build();
}
// add result types(and default result)to this package
addResultTypes(newPackage, packageElement);
// load the interceptors and interceptor stacks for this package
loadInterceptors(newPackage, packageElement);
// load the default interceptor reference for this package
loadDefaultInterceptorRef(newPackage, packageElement);
// load the default class ref for this package
loadDefaultClassRef(newPackage, packageElement);
// load the global result list for this package
loadGlobalResults(newPackage, packageElement);
// load the global exception handler list for this package
loadGobalExceptionMappings(newPackage, packageElement);
// get actions
NodeList actionList = packageElement.getElementsByTagName(“action”);
for(int i = 0;i < actionList.getLength();i++){
Element actionElement =(Element)actionList.item(i);
addAction(actionElement, newPackage);
}
// load the default action reference for this package
loadDefaultActionRef(newPackage, packageElement);
PackageConfig cfg = newPackage.build();
configuration.addPackageConfig(cfg.getName(), cfg);
return cfg;
}
loadConfigurationFiles解析讀取xml中的內(nèi)容
private List
loadConfigurationFiles(String
fileName,Element includeElement){
...//通過DomHelper調(diào)用SAX進(jìn)行解析xml
doc = DomHelper.parse(in, dtdMappings);
...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”);
//解析每個action配置是,對于include文件可以使用通配符*來進(jìn)行配置
//如Struts.xml中可配置成
if(includeFileName.indexOf('*')!=-1){
ClassPathFinder wildcardFinder = new ClassPathFinder();
wildcardFinder.setPattern(includeFileName);
Vector
for(String match : wildcardMatches){
//遞歸Load子file中的
docs.addAll(loadConfigurationFiles(match, child));
}
} else {
docs.addAll(loadConfigurationFiles(includeFileName, child));
}
}
}
}
docs.add(doc);
loadedFileUrls.add(url.toString());
...return docs;
}
首先強(qiáng)調(diào)一下struts2的線程程安全,在Struts2中大量采用ThreadLocal線程局部變量的方法來保證線程的安全,像Dispatcher等都是通過ThreadLocal來保存變量值,使得每個線程都有自己獨(dú)立的實(shí)例變量,互不相干.接下來就從Dispatcher開始看起,先看其構(gòu)造函數(shù):
//創(chuàng)建Dispatcher,此類是一個Delegate,它是真正完成根據(jù)url解析轉(zhuǎn)向,讀取對應(yīng)Action的地方
public Dispatcher(ServletContext servletContext, Map
this.servletContext = servletContext;
//配置在web.xml中的param參數(shù)
this.initParams = initParams;
}
//創(chuàng)建Dispatcher,此類是一個Delegate,它是真正完成根據(jù)url解析轉(zhuǎn)向,讀取對應(yīng)Action的地方
public Dispatcher(ServletContext servletContext, Map
this.servletContext = servletContext;
//配置在web.xml中的param參數(shù)
this.initParams = initParams;
}
我們再看在FilterDispatcher創(chuàng)建Dispatcher的:
protected Dispatcher createDispatcher(FilterConfig filterConfig){
Map
for(Enumeration e = filterConfig.getInitParameterNames();e.hasMoreElements();){
String name =(String)e.nextElement();
String value = filterConfig.getInitParameter(name);
params.put(name, value);
}
都可以從FilterConfig中得到
return new Dispatcher(filterConfig.getServletContext(), params);
}
protected Dispatcher createDispatcher(FilterConfig filterConfig){
Map
for(Enumeration e = filterConfig.getInitParameterNames();e.hasMoreElements();){
String name =(String)e.nextElement();
String value = filterConfig.getInitParameter(name);
params.put(name, value);
}
都可以從FilterConfig中得到
return new Dispatcher(filterConfig.getServletContext(), params);
}
分七步載入各種配置屬性,都是通過ConfigurationProvider接口進(jìn)行的,這個接口提供init(),destroy(),register()等方法.將各種ConfigurationProvider初始化之后將實(shí)例添加到ConfigurationManager的List里面.最后通過循環(huán)調(diào)用List里的這些destroy(),register()等方法實(shí)現(xiàn)對配置文件的屬性進(jìn)行注冊和銷毀等功能.下面將分析這七層功夫是怎樣一步步練成的.首先是init_DefaultProperties()
創(chuàng)建Dispatcher之后,來看init()方法
init()方法是用來Load用戶配置文件,資源文件以及默認(rèn)的配置文件.主要分七步走,看下面注釋
public void init(){
if(configurationManager == null){
//設(shè)置ConfigurationManager的defaultFrameworkBeanName.//這里DEFAULT_BEAN_NAME為struts,這是xwork框架的內(nèi)容,Framework可以是xwork,struts,webwork等
configurationManager = ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
}
//讀取properties信息,默認(rèn)的default.properties,init_DefaultProperties();// [1]
//讀取xml配置文件
init_TraditionalXmlConfigurations();// [2]
//讀取用戶自定義的struts.properties
init_LegacyStrutsProperties();// [3]
//自定義的configProviders
init_CustomConfigurationProviders();// [5]
//載入FilterDispatcher傳進(jìn)來的initParams
init_FilterInitParameters();// [6]
//將配置文件中的bean與具體的類映射
init_AliasStandardObjects();// [7]
//構(gòu)建一個用于依賴注射的Container對象
//在這里面會循環(huán)調(diào)用上面七個ConfigurationProvider的register方法
//其中的重點(diǎn)就是DefaultConfiguration的#reload()方法
Container container = init_PreloadConfiguration();
container.inject(this);
init_CheckConfigurationReloading(container);
init_CheckWebLogicWorkaround(container);
if(!dispatcherListeners.isEmpty()){
for(DispatcherListener l : dispatcherListeners){
l.dispatcherInitialized(this);
}
}
new
}
public void init(){
if(configurationManager == null){
//設(shè)置ConfigurationManager的defaultFrameworkBeanName.//這里DEFAULT_BEAN_NAME為struts,這是xwork框架的內(nèi)容,Framework可以是xwork,struts,webwork等
configurationManager = ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
}
//讀取properties信息,默認(rèn)的default.properties,init_DefaultProperties();// [1]
//讀取xml配置文件
init_TraditionalXmlConfigurations();// [2]
//讀取用戶自定義的struts.properties
init_LegacyStrutsProperties();// [3]
//自定義的configProviders
init_CustomConfigurationProviders();// [5]
//載入FilterDispatcher傳進(jìn)來的initParams
init_FilterInitParameters();// [6]
//將配置文件中的bean與具體的類映射
init_AliasStandardObjects();// [7]
//構(gòu)建一個用于依賴注射的Container對象
//在這里面會循環(huán)調(diào)用上面七個ConfigurationProvider的register方法
//其中的重點(diǎn)就是DefaultConfiguration的#reload()方法
Container container = init_PreloadConfiguration();
container.inject(this);
init_CheckConfigurationReloading(container);
init_CheckWebLogicWorkaround(container);
if(!dispatcherListeners.isEmpty()){
for(DispatcherListener l : dispatcherListeners){
l.dispatcherInitialized(this);
}
}
new
}
分七步載入各種配置屬性,都是通過ConfigurationProvider接口進(jìn)行的,這個接口提供init(),destroy(),register()等方法.將各種ConfigurationProvider初始化之后將實(shí)例添加到ConfigurationManager的List里面.最后通過循環(huán)調(diào)用List里的這些destroy(),register()等方法實(shí)現(xiàn)對配置文件的屬性進(jìn)行注冊和銷毀等功能.下面將分析這七層功夫是怎樣一步步練成的.首先是init_DefaultProperties()
private void init_DefaultProperties(){
configurationManager.addConfigurationProvider(new DefaultPropertiesProvider());
}
接來看DefaultPropertiesProvider好了,DefaultPropertiesProvider實(shí)際上只是實(shí)現(xiàn)了register()方法
public void register(ContainerBuilder builder, LocatableProperties props)
throws ConfigurationException {
Settings defaultSettings = null;
try {
defaultSettings = new PropertiesSettings(“org/apache/struts2/default”);
} catch(Exception e){
throw
}
loadSettings(props, defaultSettings);
}
private void init_DefaultProperties(){
configurationManager.addConfigurationProvider(new DefaultPropertiesProvider());
}
接來看DefaultPropertiesProvider好了,DefaultPropertiesProvider實(shí)際上只是實(shí)現(xiàn)了new
ConfigurationException(“Could
not
find
or
error
in org/apache/struts2/default.properties”, e);
register()方法
public void register(ContainerBuilder builder, LocatableProperties props)
throws ConfigurationException {
Settings defaultSettings = null;
try {
defaultSettings = new PropertiesSettings(“org/apache/struts2/default”);
} catch(Exception e){
throw
}
loadSettings(props, defaultSettings);
}
//PropertiesSettings構(gòu)造方法
//讀取org/apache/struts2/default.properties的配置信息,如果項(xiàng)目中需要覆蓋,可以在classpath里的struts.properties里覆寫
public PropertiesSettings(String name){
URL settingsUrl = ClassLoaderUtils.getResource(name + “.properties”, getClass());
if(settingsUrl == null){
LOG.debug(name + “.properties missing”);
settings = new LocatableProperties();
return;
}
settings
// Load settings
InputStream in = null;
try {
=
new
LocatableProperties(new
LocationImpl(null, settingsUrl.toString()));
new
ConfigurationException(“Could
not
find
or
error
in org/apache/struts2/default.properties”, e);
in = settingsUrl.openStream();
settings.load(in);
} catch(IOException e){
throw new StrutsException(“Could not load ” + name + “.properties:” + e, e);
} finally {
if(in!= null){
try {
in.close();
} catch(IOException io){
LOG.warn(“Unable to close input stream”, io);
}
}
}
}
//loadSettings主要是將progerty的value和Locale從上面PropertiesSettings中取得并存放到LocatableProperties props
//這個props是register的一個入?yún)?protected void loadSettings(LocatableProperties props, final Settings settings){
// We are calling the impl methods to get around the single instance of Settings that is expected
for(Iterator i = settings.listImpl();i.hasNext();){
String name =(String)i.next();
props.setProperty(name, settings.getLocationImpl(name));
}
}
//PropertiesSettings構(gòu)造方法
//讀取org/apache/struts2/default.properties的配置信息,如果項(xiàng)目中需要覆蓋,可以在classpath里的struts.properties里覆寫
public PropertiesSettings(String name){
URL settingsUrl = ClassLoaderUtils.getResource(name + “.properties”, getClass());
settings.getImpl(name),if(settingsUrl == null){
LOG.debug(name + “.properties missing”);
settings = new LocatableProperties();
return;
}
settings
// Load settings
InputStream in = null;
try {
in = settingsUrl.openStream();
settings.load(in);
} catch(IOException e){
throw new StrutsException(“Could not load ” + name + “.properties:” + e, e);
} finally {
if(in!= null){
try {
in.close();
} catch(IOException io){
LOG.warn(“Unable to close input stream”, io);
}
}
}
}
//loadSettings主要是將progerty的value和Locale從上面PropertiesSettings中取得并存放到LocatableProperties props
//這個props是register的一個入?yún)?protected void loadSettings(LocatableProperties props, final Settings settings){
// We are calling the impl methods to get around the single instance of Settings that is expected
for(Iterator i = settings.listImpl();i.hasNext();){
String name =(String)i.next();
=
new
LocatableProperties(new
LocationImpl(null, settingsUrl.toString()));
props.setProperty(name, settings.getLocationImpl(name));
}
}
再來看第二步:init_TraditionalXmlConfigurations()
private void init_TraditionalXmlConfigurations(){
//首先讀取web.xml中的config初始參數(shù)值
//如果
沒
有
配
置
就
使
settings.getImpl(name),用默認(rèn)的DEFAULT_CONFIGURATION_PATHS:“struts-default.xml,struts-plugin.xml,struts.xml”,//這兒就可以看出為什么默認(rèn)的配置文件必須取名為這三個名稱了
//如果不想使用默認(rèn)的名稱,直接在web.xml中配置config初始參數(shù)即可
String configPaths = initParams.get(“config”);
if(configPaths == null){
configPaths = DEFAULT_CONFIGURATION_PATHS;
}
String[] files = configPaths.split(“¥¥s*[,]¥¥s*”);
for(String file : files){
if(file.endsWith(“.xml”)){
if(“xwork.xml”.equals(file)){
//XmlConfigurationProvider負(fù)責(zé)解析xwork.xml
configurationManager.addConfigurationProvider(new XmlConfigurationProvider(file, false));
} else {
//其它xml都是由StrutsXmlConfigurationProvider來解析
configurationManager.addConfigurationProvider(new StrutsXmlConfigurationProvider(file, false, servletContext));
}
} else {
throw new IllegalArgumentException(“Invalid configuration file name”);
}
}
}
private void init_TraditionalXmlConfigurations(){
//首先讀取web.xml中的config初始參數(shù)值
//如果
沒
有
配
置
就
使
用
默
認(rèn)的DEFAULT_CONFIGURATION_PATHS:“struts-default.xml,struts-plugin.xml,struts.xml”,//這兒就可以看出為什么默認(rèn)的配置文件必須取名為這三個名稱了
//如果不想使用默認(rèn)的名稱,直接在web.xml中配置config初始參數(shù)即可
String configPaths = initParams.get(“config”);
if(configPaths == null){
configPaths = DEFAULT_CONFIGURATION_PATHS;
}
String[] files = configPaths.split(“¥¥s*[,]¥¥s*”);
for(String file : files){
if(file.endsWith(“.xml”)){
if(“xwork.xml”.equals(file)){
//XmlConfigurationProvider負(fù)責(zé)解析xwork.xml
configurationManager.addConfigurationProvider(new XmlConfigurationProvider(file, false));
} else {
//其它xml都是由StrutsXmlConfigurationProvider來解析
configurationManager.addConfigurationProvider(new StrutsXmlConfigurationProvider(file, false, servletContext));
}
} else {
throw new IllegalArgumentException(“Invalid configuration file name”);
}
}
}
對于其它配置文件只用接口。
類XmlConfigurationProvider負(fù)責(zé)配置文件的讀取和解析,首先通過init()中的loadDocuments(configFileName);利用DomHelper中的
public static Document parse(InputSource inputSource, Map
addAction()方法負(fù)責(zé)讀取
loadInterceptorStack()方法負(fù)責(zé)將
loadInterceptorStacks()方法負(fù)責(zé)將
而上面的方法最終會被addPackage()方法調(diào)用,addPackage又會被Provider的loadPackages()調(diào)用,將所讀取到的數(shù)據(jù)匯集到PackageConfig對象中。
protected PackageConfig
addPackage(Element
packageElement)
throws ConfigurationException {
PackageConfig.Builder newPackage = buildPackageContext(packageElement);
if(newPackage.isNeedsRefresh()){
return newPackage.build();
}
// add result types(and default result)to this package
addResultTypes(newPackage, packageElement);
// load the interceptors and interceptor stacks for this package
loadInterceptors(newPackage, packageElement);
// load the default interceptor reference for this package
loadDefaultInterceptorRef(newPackage, packageElement);
// load the default class ref for this package
loadDefaultClassRef(newPackage, packageElement);
// load the global result list for this package
loadGlobalResults(newPackage, packageElement);
// load the global exception handler list for this package
loadGobalExceptionMappings(newPackage, packageElement);
// get actions
NodeList actionList = packageElement.getElementsByTagName(“action”);
for(int i = 0;i < actionList.getLength();i++){
Element actionElement =(Element)actionList.item(i);
addAction(actionElement, newPackage);
}
// load the default action reference for this package
loadDefaultActionRef(newPackage, packageElement);
PackageConfig cfg = newPackage.build();
configuration.addPackageConfig(cfg.getName(), cfg);
return cfg;
}
loadConfigurationFiles解析讀取xml中的內(nèi)容
private List
loadConfigurationFiles(String
fileName, includeElement){
...//通過DomHelper調(diào)用SAX進(jìn)行解析xml
doc = DomHelper.parse(in, dtdMappings);
...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”);
//解析每個action配置是,對于include文件可以使用通配符*來進(jìn)行配置
//如Struts.xml中可配置成
if(includeFileName.indexOf('*')!=-1){
ClassPathFinder wildcardFinder = new ClassPathFinder();
wildcardFinder.setPattern(includeFileName);
Element
Vector
for(String match : wildcardMatches){
//遞歸Load子file中的
docs.addAll(loadConfigurationFiles(match, child));
}
} else {
docs.addAll(loadConfigurationFiles(includeFileName, child));
}
}
}
}
docs.add(doc);
loadedFileUrls.add(url.toString());
...return docs;
}
接下來第三步:init_LegacyStrutsProperties()調(diào)用的是調(diào)用的是LegacyPropertiesConfigurationProvider 通過比較前
面
DefaultPropertiesProvider
與
調(diào)
用的是LegacyPropertiesConfigurationProvider.發(fā)現(xiàn)DefaultPropertiesProvider繼承自后者,但重寫了register()方法,主要是生成PropertiesSetting的不同,前者是根據(jù)org/apache/struts2/default.properties 后者是根據(jù)struts.properties 我們展開register()中的Settings.getInstance(),最后是調(diào)用getDefaultInstance()
private static Settings getDefaultInstance(){
if(defaultImpl == null){
// Create bootstrap implementation
//不帶參數(shù)的DefaultSettings(),區(qū)別與DefaultPropertiesProvider中直接帶default.properties參數(shù)
//不帶參數(shù)就是默認(rèn)為struts.propertes,并且加載struts.custom.properties所定義的properties文件
defaultImpl = new DefaultSettings();
// Create default implementation
try {
//STRUTS_CONFIGURATION為:struts.configuration
//在struts.proterties中查找struts.configuration的值,這個值必須是org.apache.struts2.config.Configuration接口的實(shí)現(xiàn)類
//所以我有個困惑就是在下面的轉(zhuǎn)換當(dāng)中怎么將Configuration轉(zhuǎn)換成Setting類型的...//這一點(diǎn)先放下了,有時間再研究
String className = get(StrutsConstants.STRUTS_CONFIGURATION);
if(!className.equals(defaultImpl.getClass().getName())){
try {
// singleton instances shouldn't be built accessing request or session-specific context data
defaultImpl oader().loadClass(className), null);
} catch(Exception e){
LOG.error(“Settings:
}
}
} catch(IllegalArgumentException ex){
// ignore
}
private static Settings getDefaultInstance(){
if(defaultImpl == null){
// Create bootstrap implementation
//不帶參數(shù)的DefaultSettings(),區(qū)別與DefaultPropertiesProvider中直接帶default.properties參數(shù)
//不帶參數(shù)就是默認(rèn)為struts.propertes,并且加載struts.custom.properties所定義的properties文件
defaultImpl = new DefaultSettings();
// Create default implementation
try {
//STRUTS_CONFIGURATION為:struts.configuration
//在struts.proterties中查找struts.configuration的值,這個值必須是
Could
not
instantiate
the struts.configuration object, substituting the default implementation.”, e);
=
(Settings)ObjectFactory.getObjectFactory().buildBean(Thread.currentThread().getContextClassLorg.apache.struts2.config.Configuration接口的實(shí)現(xiàn)類
//所以我有個困惑就是在下面的轉(zhuǎn)換當(dāng)中怎么將Configuration轉(zhuǎn)換成Setting類型的...//這一點(diǎn)先放下了,有時間再研究
String className = get(StrutsConstants.STRUTS_CONFIGURATION);
if(!className.equals(defaultImpl.getClass().getName())){
try {
// singleton instances shouldn't be built accessing request or session-specific context data
defaultImpl oader().loadClass(className), null);
} catch(Exception e){
LOG.error(“Settings:
}
}
} catch(IllegalArgumentException ex){
// ignore
}
在2.1.6中去掉了第四步:init_ZeroConfiguration();第五步是自定義的configProviders
private void init_CustomConfigurationProviders(){
//從這里可以看到可以將自定義的Provider定義在web.xml中FilterDispatcher的param中:configProviders
String configProvs = initParams.get(”configProviders“);
if(configProvs!= null){
String[] classes = configProvs.split(”¥¥s*[,]¥¥s*“);
for(String cname : classes){
try {
Class cls = ClassLoaderUtils.loadClass(cname, this.getClass());
ConfigurationProvider(ConfigurationProvider)cls.newInstance();
configurationManager.addConfigurationProvider(prov);
prov
=
Could
not
instantiate
the struts.configuration object, substituting the default implementation.”, e);
=
(Settings)ObjectFactory.getObjectFactory().buildBean(Thread.currentThread().getContextClassL
}
...}
}
}
private void init_CustomConfigurationProviders(){
//從這里可以看到可以將自定義的Provider定義在web.xml中FilterDispatcher的param中:configProviders
String configProvs = initParams.get(“configProviders”);
if(configProvs!= null){
String[] classes = configProvs.split(“¥¥s*[,]¥¥s*”);
for(String cname : classes){
try {
Class cls = ClassLoaderUtils.loadClass(cname, this.getClass());
ConfigurationProvider(ConfigurationProvider)cls.newInstance();
configurationManager.addConfigurationProvider(prov);
}
...}
}
}
第六步:init_FilterInitParameters
//從這里可以看出struts.properties中的屬性不僅可以在struts.xml中以constant形式定義,而且可以在FilterDispatcher的param中定義
private void init_FilterInitParameters(){
configurationManager.addConfigurationProvider(new ConfigurationProvider(){
public void destroy(){}
public
void
init(Configuration
configuration)
throws ConfigurationException {}
public void loadPackages()throws ConfigurationException {}
public boolean needsReload(){ return false;}
prov
=
public void register(ContainerBuilder builder, LocatableProperties props)throws ConfigurationException {
props.putAll(initParams);//在這里實(shí)現(xiàn)滴~
}
});
}
//從這里可以看出struts.properties中的屬性不僅可以在struts.xml中以constant形式定義,而且可以在FilterDispatcher的param中定義
private void init_FilterInitParameters(){
configurationManager.addConfigurationProvider(new ConfigurationProvider(){
public void destroy(){}
public
void
init(Configuration
configuration)
throws ConfigurationException {}
public void loadPackages()throws ConfigurationException {}
public boolean needsReload(){ return false;}
public void register(ContainerBuilder builder, LocatableProperties props)throws ConfigurationException {
props.putAll(initParams);//在這里實(shí)現(xiàn)滴~
}
});
}
第七步:init_AliasStandardObjects,使用BeanSelectionProvider 這是將配置文件中定義的
接下來是看怎樣調(diào)用這些ConfigurationProviders 展開init_PreloadConfiguration()
private Container init_PreloadConfiguration(){
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;
}
//再看getConfiguration()
public synchronized Configuration getConfiguration(){
if(configuration == null){
setConfiguration(new DefaultConfiguration(defaultFrameworkBeanName));
try {
//重點(diǎn)就是這個reloadContainer
configuration.reloadContainer(getContainerProviders());
} catch(ConfigurationException e){
setConfiguration(null);
throw new ConfigurationException(“Unable to load configuration.”, e);
}
} else {
conditionalReload();
}
return configuration;
}
private Container init_PreloadConfiguration(){
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;
}
//再看getConfiguration()
public synchronized Configuration getConfiguration(){
if(configuration == null){
setConfiguration(new DefaultConfiguration(defaultFrameworkBeanName));
try {
//重點(diǎn)就是這個reloadContainer
configuration.reloadContainer(getContainerProviders());
} catch(ConfigurationException e){
setConfiguration(null);
throw new ConfigurationException(“Unable to load configuration.”, e);
}
} else {
conditionalReload();
}
return configuration;
}
展開DefaultConfiguration中的reloadContainer
public synchronized List
reloadContainer(List
packageContexts.clear();
loadedFileNames.clear();
List
packageProviders = new ArrayList
();
//Struts2(xwork2)用Container來完成依賴注入的功能
//首先初始化一個ContainerBuilder,再由builder來保存接口與實(shí)現(xiàn)類或工廠類的對應(yīng)關(guān)系
//然后通過builder.create(boolean)方法產(chǎn)生container
//由container.getInstance(Class);就可以得到接口的實(shí)現(xiàn)實(shí)例了
//這一部分比較復(fù)雜,后面研究完成了,會單獨(dú)拿出來講,這里先弄清楚Xwork依賴注入的實(shí)現(xiàn)步驟就可以了
ContainerProperties props = new ContainerProperties();
ContainerBuilder builder = new ContainerBuilder();
for(final ContainerProvider containerProvider : providers)
{
//循環(huán)調(diào)用ConfigurationProvider的init和register方法,明白了吧,在這里統(tǒng)一循環(huán)調(diào)用
containerProvider.init(this);
containerProvider.register(builder, props);
}
props.setConstants(builder);
//注入依賴關(guān)系,在這里并不產(chǎn)生實(shí)例
builder.factory(Configuration.class, new Factory
public Configuration create(Context context)throws Exception {
return DefaultConfiguration.this;
}
});
ActionContext oldContext = ActionContext.getContext();
try {
// Set the bootstrap container for the purposes of factory creation
Container bootstrap = createBootstrapContainer();
setContext(bootstrap);
//create已經(jīng)注入依賴關(guān)系的Container
container = builder.create(false);
setContext(container);
objectFactory = container.getInstance(ObjectFactory.class);
// Process the configuration providers first
for(final ContainerProvider containerProvider : providers)
{
if(containerProvider instanceof PackageProvider){
container.inject(containerProvider);
//調(diào)用PackageProvider的loadPackages()方法,這里主要是針對XmlConfigurationProvider和StrutsXmlConfigurationProvider
((PackageProvider)containerProvider).loadPackages();
packageProviders.add((PackageProvider)containerProvider);
}
}
// Then process any package providers from the plugins
Set
packageProviderNames
= container.getInstanceNames(PackageProvider.class);
if(packageProviderNames!= null){
for(String name : packageProviderNames){
PackageProvider
provider.init(this);
provider.loadPackages();
packageProviders.add(provider);
}
}
rebuildRuntimeConfiguration();
} finally {
if(oldContext == null){
ActionContext.setContext(null);
}
}
return packageProviders;
}
Dispatcher已經(jīng)在之前講過,這就好辦了。FilterDispatcher是Struts2的核心控制器,首先看一下init()方法。
public void init(FilterConfig filterConfig)throws ServletException {
try {
this.filterConfig = filterConfig;
initLogging();
//創(chuàng)建dispatcher,前面都已經(jīng)講過啰
dispatcher = createDispatcher(filterConfig);
dispatcher.init();
//注入將FilterDispatcher中的變量通過container注入,如下面的staticResourceLoader
dispatcher.getContainer().inject(this);
//StaticContentLoader在BeanSelectionProvider中已經(jīng)被注入了依賴關(guān)系:DefaultStaticContentLoader
//可以在struts-default.xml中的
staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig));
} finally {
provider
= container.getInstance(PackageProvider.class, name);
ActionContext.setContext(null);
}
}
public void init(FilterConfig filterConfig)throws ServletException {
try {
this.filterConfig = filterConfig;
initLogging();
//創(chuàng)建dispatcher,前面都已經(jīng)講過啰
dispatcher = createDispatcher(filterConfig);
dispatcher.init();
//注入將FilterDispatcher中的變量通過container注入,如下面的staticResourceLoader
dispatcher.getContainer().inject(this);
//StaticContentLoader在BeanSelectionProvider中已經(jīng)被注入了依賴關(guān)系:DefaultStaticContentLoader
//可以在struts-default.xml中的
staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig));
} finally {
ActionContext.setContext(null);
}
}
//下面來看DefaultStaticContentLoader的setHostConfig
public void setHostConfig(HostConfig filterConfig){
//讀取初始參數(shù)
pakages,調(diào)用
parse(),解析成類似/org/apache/struts2/static,/template的數(shù)組
String param = filterConfig.getInitParameter(“packages”);
//“org.apache.struts2.static org.apache.struts2.interceptor.debugging static”
String packages = getAdditionalPackages();
if(param!= null){
packages = param + “ ” + packages;
}
this.pathPrefixes = parse(packages);
initLogging(filterConfig);
}
template //下面來看DefaultStaticContentLoader的setHostConfig
public void setHostConfig(HostConfig filterConfig){
//讀取初始參數(shù)
pakages,調(diào)用
parse(),解析成類似/org/apache/struts2/static,/template的數(shù)組
String param = filterConfig.getInitParameter(“packages”);
//“org.apache.struts2.static org.apache.struts2.interceptor.debugging static”
String packages = getAdditionalPackages();
if(param!= null){
packages = param + “ ” + packages;
}
this.pathPrefixes = parse(packages);
initLogging(filterConfig);
}
現(xiàn)在回去doFilter的方法,每當(dāng)有一個Request,都會調(diào)用這些Filters的doFilter方法
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)throws IOException, ServletException {
HttpServletRequest request =(HttpServletRequest)req;
HttpServletResponse response =(HttpServletResponse)res;
ServletContext servletContext = getServletContext();
String timerKey = “FilterDispatcher_doFilter: ”;
try {
// FIXME: this should be refactored better to not duplicate work with the action invocation
//先看看ValueStackFactory所注入的實(shí)現(xiàn)類OgnlValueStackFactory
//new OgnlValueStack
ValueStack
stack
= dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
ActionContext ctx = new ActionContext(stack.getContext());
ActionContext.setContext(ctx);
template
UtilTimerStack.push(timerKey);
//如果是multipart/form-data就用MultiPartRequestWrapper進(jìn)行包裝
//MultiPartRequestWrapper
是
StrutsRequestWrapper的子類,兩者都是HttpServletRequest實(shí)現(xiàn)
//此時在MultiPartRequestWrapper中就會把Files給解析出來,用于文件上傳
//所有request都會StrutsRequestWrapper進(jìn)行包裝,StrutsRequestWrapper是可以訪問ValueStack
//下面是參見Dispatcher的wrapRequest
// String content_type = request.getContentType();
//if(content_type!= null&&content_type.indexOf(“multipart/form-data”)!=-1){
//MultiPartRequest multi =getContainer().getInstance(MultiPartRequest.class);
//request MultiPartRequestWrapper(multi,request,getSaveDir(servletContext));
//} else {
//
request = new StrutsRequestWrapper(request);
// }
request = prepareDispatcherAndWrapRequest(request, response);
ActionMapping mapping;
try {
//根據(jù)url取得對應(yīng)的Action的配置信息
//看一下注入的DefaultActionMapper的getMapping()方法.Action的配置信息存儲在 ActionMapping對象中
mapping
=
actionMapper.getMapping(request, dispatcher.getConfigurationManager());
} catch(Exception ex){
log.error(“error getting ActionMapping”, ex);
dispatcher.sendError(request,return;
}
//如果找不到對應(yīng)的action配置,則直接返回。比如你輸入***.jsp等等
//這兒有個例外,就是如果path是以“/struts”開頭,則到初始參數(shù)packages配置的包路徑去查找對應(yīng)的靜態(tài)資源并輸出到頁面流中,當(dāng)然.class文件除外。如果再沒有則跳轉(zhuǎn)到
response,servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
=new 404
if(mapping == null){
// there is no action in this request, should we look for a static resource?
String resourcePath = RequestUtils.getServletPath(request);
if(“".equals(resourcePath)&& null!= request.getPathInfo()){
resourcePath = request.getPathInfo();
}
if(staticResourceLoader.canHandle(resourcePath)){
// 在DefaultStaticContentLoader
中
:return
serveStatic
&&(resourcePath.startsWith(”/struts“)|| resourcePath.startsWith(”/static“));
staticResourceLoader.findStaticResource(resourcePath, response);
} else {
// this is a normal request, let it pass through
chain.doFilter(request, response);
}
// The framework did its job here
return;
}
//正式開始Action的方法
dispatcher.serviceAction(request, response, servletContext, mapping);
} finally {
try {
ActionContextCleanUp.cleanUp(req);
} finally {
UtilTimerStack.pop(timerKey);
}
}
}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)throws IOException, ServletException {
HttpServletRequest request =(HttpServletRequest)req;
request,HttpServletResponse response =(HttpServletResponse)res;
ServletContext servletContext = getServletContext();
String timerKey = ”FilterDispatcher_doFilter: “;
try {
// FIXME: this should be refactored better to not duplicate work with the action invocation
//先看看ValueStackFactory所注入的實(shí)現(xiàn)類OgnlValueStackFactory
//new OgnlValueStack
ValueStack
stack
= dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
ActionContext ctx = new ActionContext(stack.getContext());
ActionContext.setContext(ctx);
UtilTimerStack.push(timerKey);
//如果是multipart/form-data就用MultiPartRequestWrapper進(jìn)行包裝
//MultiPartRequestWrapperHttpServletRequest實(shí)現(xiàn)
//此時在MultiPartRequestWrapper中就會把Files給解析出來,用于文件上傳
//所有request都會StrutsRequestWrapper進(jìn)行包裝,StrutsRequestWrapper是可以訪問ValueStack
//下面是參見Dispatcher的wrapRequest
// String content_type = request.getContentType();
//if(content_type!= null&&content_type.indexOf(”multipart/form-data“)!=-1){
//MultiPartRequest multi =getContainer().getInstance(MultiPartRequest.class);
//request MultiPartRequestWrapper(multi,request,getSaveDir(servletContext));
//} else {
//
request = new StrutsRequestWrapper(request);
// }
request = prepareDispatcherAndWrapRequest(request, response);
ActionMapping mapping;
try {
=new
是
StrutsRequestWrapper的子類,兩者都是
//根據(jù)url取得對應(yīng)的Action的配置信息
//看一下注入的DefaultActionMapper的getMapping()方法.Action的配置信息存儲在 ActionMapping對象中
mapping
} catch(Exception ex){
log.error(”error getting ActionMapping“, ex);
dispatcher.sendError(request,return;
}
//如果找不到對應(yīng)的action配置,則直接返回。比如你輸入***.jsp等等
//這兒有個例外,就是如果path是以“/struts”開頭,則到初始參數(shù)packages配置的包路徑去查找對應(yīng)的靜態(tài)資源并輸出到頁面流中,當(dāng)然.class文件除外。如果再沒有則跳轉(zhuǎn)到404
if(mapping == null){
// there is no action in this request, should we look for a static resource?
String resourcePath = RequestUtils.getServletPath(request);
if(”“.equals(resourcePath)&& null!= request.getPathInfo()){
resourcePath = request.getPathInfo();
}
if(staticResourceLoader.canHandle(resourcePath)){
// 在DefaultStaticContentLoader
中
:return
serveStatic
&&(resourcePath.startsWith(”/struts“)|| resourcePath.startsWith(”/static“));
staticResourceLoader.findStaticResource(resourcePath, response);
} else {
// this is a normal request, let it pass through
chain.doFilter(request, response);
}
// The framework did its job here
return;
}
request,response,servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
=
actionMapper.getMapping(request, dispatcher.getConfigurationManager());
//正式開始Action的方法
dispatcher.serviceAction(request, response, servletContext, mapping);
} finally {
try {
ActionContextCleanUp.cleanUp(req);
} finally {
UtilTimerStack.pop(timerKey);
}
}
}
//下面是ActionMapper接口的實(shí)現(xiàn)類 DefaultActionMapper的getMapping()方法的源代碼:
public ActionMapping getMapping(HttpServletRequest request,ConfigurationManager configManager){
ActionMapping mapping = new ActionMapping();
String uri = getUri(request);//得到請求路徑的URI,如:testAtcion.action或testAction.do
int indexOfSemicolon = uri.indexOf(”;“);//修正url的帶;jsessionid 時找不到而且的bug
uri =(indexOfSemicolon >-1)? uri.substring(0, indexOfSemicolon): uri;
uri = dropExtension(uri, mapping);//刪除擴(kuò)展名,默認(rèn)擴(kuò)展名為action
if(uri == null){
return null;
}
parseNameAndNamespace(uri, mapping, configManager);//匹配Action的name和namespace
handleSpecialParameters(request, mapping);//去掉重復(fù)參數(shù)
//如果Action的name沒有解析出來,直接返回
if(mapping.getName()== null){
returnnull;
}
//下面處理形如testAction!method格式的請求路徑
if(allowDynamicMethodCalls){
// handle ”name!method“ convention.String name = mapping.getName();
int exclamation = name.lastIndexOf(”!“);//!是Action名稱和方法名的分隔符
if(exclamation!=-1){
mapping.setName(name.substring(0, exclamation));//提取左邊為name
mapping.setMethod(name.substring(exclamation + 1));//提取右邊的method
}
}
return mapping;
}
//下面是ActionMapper接口的實(shí)現(xiàn)類 DefaultActionMapper的getMapping()方法的源代碼:
public ActionMapping getMapping(HttpServletRequest request,ConfigurationManager configManager){
ActionMapping mapping = new ActionMapping();
String uri = getUri(request);//得到請求路徑的URI,如:testAtcion.action或testAction.do
int indexOfSemicolon = uri.indexOf(”;“);//修正url的帶;jsessionid 時找不到而且的bug
uri =(indexOfSemicolon >-1)? uri.substring(0, indexOfSemicolon): uri;
uri = dropExtension(uri, mapping);//刪除擴(kuò)展名,默認(rèn)擴(kuò)展名為action
if(uri == null){
return null;
}
parseNameAndNamespace(uri, mapping, configManager);//匹配Action的name和namespace
handleSpecialParameters(request, mapping);//去掉重復(fù)參數(shù)
//如果Action的name沒有解析出來,直接返回
if(mapping.getName()== null){
returnnull;
}
//下面處理形如testAction!method格式的請求路徑
if(allowDynamicMethodCalls){
// handle ”name!method“ convention.String name = mapping.getName();
int exclamation = name.lastIndexOf(”!“);//!是Action名稱和方法名的分隔符
if(exclamation!=-1){
mapping.setName(name.substring(0, exclamation));//提取左邊為name
mapping.setMethod(name.substring(exclamation + 1));//提取右邊的method
}
}
return mapping;
}
從代碼中看出,getMapping()方法返回ActionMapping類型的對象,該對象包含三個參數(shù):Action的name、namespace和要調(diào)用的方法method。
如果getMapping()方法返回ActionMapping對象為null,則FilterDispatcher認(rèn)為用戶請求不是Action,自然另當(dāng)別論,F(xiàn)ilterDispatcher會做一件非常有意思的事:如果請求以/struts開頭,會自動查找在web.xml文件中配置的 packages初始化參數(shù),就像下面這樣:
org.apache.struts2.dispatcher.FilterDispatcher
packages
com.lizanhong.action
org.apache.struts2.dispatcher.FilterDispatcher
packages
com.lizanhong.action
FilterDispatcher會將com.lizanhong.action包下的文件當(dāng)作靜態(tài)資源處理,即直接在頁面上顯示文件內(nèi)容,不過會忽略擴(kuò)展名為class的文件。比如在com.lizanhong.action包下有一個aaa.txt的文本文件,其內(nèi)容為“中華人民共和國”,訪問
http://localhost:8081/Struts2Demo/struts/aaa.txt時會輸出txt中的內(nèi)容
FilterDispatcher.findStaticResource()方法
protectedvoid findStaticResource(String
name,HttpServletRequest
request, HttpServletResponse response)throws IOException {
if(!name.endsWith(”.class“)){//忽略class文件
//遍歷packages參數(shù)
for(String pathPrefix : pathPrefixes){
InputStream is = findInputStream(name, pathPrefix);//讀取請求文件流
if(is!= null){
...// set the content-type header
String contentType = getContentType(name);//讀取內(nèi)容類型
if(contentType!= null){
response.setContentType(contentType);//重新設(shè)置內(nèi)容類型
}
...try {
//將讀取到的文件流以每次復(fù)制4096個字節(jié)的方式循環(huán)輸出
copy(is, response.getOutputStream());
} finally {
is.close();
}
return;
}
}
}
}
protectedvoid findStaticResource(String
name,HttpServletRequest
request, HttpServletResponse response)throws IOException {
if(!name.endsWith(”.class“)){//忽略class文件
//遍歷packages參數(shù)
for(String pathPrefix : pathPrefixes){
InputStream is = findInputStream(name, pathPrefix);//讀取請求文件流
if(is!= null){
...// set the content-type header
String contentType = getContentType(name);//讀取內(nèi)容類型
if(contentType!= null){
response.setContentType(contentType);//重新設(shè)置內(nèi)容類型
}
...try {
//將讀取到的文件流以每次復(fù)制4096個字節(jié)的方式循環(huán)輸出
copy(is, response.getOutputStream());
} finally {
is.close();
}
return;
}
}
}
}
如果用戶請求的資源不是以/struts開頭——可能是.jsp文件,也可能是.html文件,則通過過濾器鏈繼續(xù)往下傳送,直到到達(dá)請求的資源為止。
如果getMapping()方法返回有效的ActionMapping對象,則被認(rèn)為正在請求某個Action,將調(diào)用 Dispatcher.serviceAction(request, response, servletContext, mapping)方法,該方法是處理Action的關(guān)鍵所在。
下面就來看serviceAction,這又回到全局變量dispatcher中了
//Load Action class for mapping and invoke the appropriate Action method, or go directly to the Result.public void serviceAction(HttpServletRequest request, HttpServletResponse response, ServletContext context,ActionMapping mapping)throws ServletException {
//createContextMap方法主要把Application、Session、Request的key value值拷貝到Map中
Map
// If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
ValueStack
stack
=
(ValueStack)request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
boolean nullStack = stack == null;
if(nullStack){
ActionContext ctx = ActionContext.getContext();
if(ctx!= null){
stack = ctx.getValueStack();
}
}
if(stack!= null){
extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
}
String timerKey = ”Handling request from Dispatcher“;
try {
UtilTimerStack.push(timerKey);
String namespace = mapping.getNamespace();
String name = mapping.getName();
String method = mapping.getMethod();
Configuration config = configurationManager.getConfiguration();
//創(chuàng)建一個Action的代理對象,ActionProxyFactory是創(chuàng)建ActionProxy的工廠
//參考實(shí)現(xiàn)類:DefaultActionProxy和DefaultActionProxyFactory
ActionProxy
proxy
= config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(namespace, name, method, extraContext, true, false);
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
// if the ActionMapping says to go straight to a result, do it!
//如果是Result,則直接轉(zhuǎn)向,關(guān)于Result,ActionProxy,ActionInvocation下一講中再分析
if(mapping.getResult()!= null){
Result result = mapping.getResult();
result.execute(proxy.getInvocation());
} else {
//執(zhí)行Action
proxy.execute();
}
// If there was a previous value stack then set it back onto the request
if(!nullStack){
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
}
} catch(ConfigurationException e){
// WW-2874 Only log error if in devMode
if(devMode){
LOG.error(”Could not find action or result“, e);
}
else {
LOG.warn(”Could not find action or result“, e);
}
sendError(request, HttpServletResponse.SC_NOT_FOUND, e);
} catch(Exception e){
sendError(request,} finally {
UtilTimerStack.pop(timerKey);
}
} 下面開始講一下主菜ActionProxy了.在這之前最好先去了解一下動態(tài)Proxy的基本知識.ActionProxy是Action的一個代理類,也就是說Action的調(diào)用是通過ActionProxy實(shí)現(xiàn)的,其實(shí)就是調(diào)用了ActionProxy.execute()方法,而該方法又調(diào)用了ActionInvocation.invoke()方法。歸根到底,最后調(diào)用的是DefaultActionInvocation.invokeAction()方法。DefaultActionInvocation()->init()->createAction()。
最后
通
過
調(diào)
用ActionProxy.exute()-->ActionInvocation.invoke()-->Intercepter.intercept()-->ActionInvocation.invokeActionOnly()-->invokeAction()這里的步驟是先由ActionProxyFactory創(chuàng)建ActionInvocation和ActionProxy.public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map
ActionInvocation inv = new DefaultActionInvocation(extraContext, true);
container.inject(inv);
return }
public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map
createActionProxy(inv,namespace,actionName,methodName, executeResult, cleanupContext);
response,context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
response,context,ActionInvocation inv = new DefaultActionInvocation(extraContext, true);
container.inject(inv);
return }
下面先看DefaultActionInvocation的init方法
public void init(ActionProxy proxy){
this.proxy = proxy;
Map
// Setting this so that other classes, like object factories, can use the ActionProxy and other
// contextual information to operate
ActionContext actionContext = ActionContext.getContext();
if(actionContext!= null){
actionContext.setActionInvocation(this);
}
//創(chuàng)建Action,struts2中每一個Request都會創(chuàng)建一個新的Action
createAction(contextMap);
if(pushAction){
stack.push(action);
contextMap.put(”action“, action);
}
invocationContext = new ActionContext(contextMap);
invocationContext.setName(proxy.getActionName());
// get a new List so we don't get problems with the iterator if someone changes the list
List
interceptorList
=
new ArrayList
interceptors = interceptorList.iterator();
createActionProxy(inv,namespace,actionName,methodName, executeResult, cleanupContext);
}
protected void createAction(Map
// load action
String timerKey = ”actionCreate: “ + proxy.getActionName();
try {
UtilTimerStack.push(timerKey);
//默認(rèn)為SpringObjectFactory:struts.objectFactory=spring.這里非常巧妙,在struts.properties中可以重寫這個屬性
//在前面BeanSelectionProvider中通過配置文件為ObjectFactory設(shè)置實(shí)現(xiàn)類
//這里以Spring為例,這里會調(diào)到SpringObjectFactory的buildBean方法,可以通過ApplicationContext的getBean()方法得到Spring的Bean
action
=
objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap);
} catch(InstantiationException e){
throw new
XWorkException(”Unable
to
intantiate
Action!“,e, proxy.getConfig());
} catch(IllegalAccessException e){
throw new XWorkException(”Illegal access to constructor, is it public?", e, proxy.getConfig());
} catch(Exception e){
...} finally {
UtilTimerStack.pop(timerKey);
}
if(actionEventListener!= null){
action = actionEventListener.prepare(action, stack);
}
}
//SpringObjectFactory
public Object buildBean(String beanName, Map
Object o = null;
try {
//SpringObjectFactory
會
通
過
web.xml
中的
第五篇:SAS復(fù)習(xí)資料
SAS復(fù)習(xí)資料 2013.6.20
說明:根據(jù)老師給的Html版整理,如有錯誤、遺漏敬請?jiān)?,并及時指出,進(jìn)行改正。謝謝!
1.研究因子:對試驗(yàn)指標(biāo)有影響的,在試驗(yàn)中需要加以考察的條件。2.小機(jī)率原理:概率很小的事件,在一次試驗(yàn)中是不至于發(fā)生的。3.重復(fù):每個參試的品種或處理占有兩個或兩個以上的小區(qū)稱有重復(fù)。
4.局部控制:通過對小區(qū)的合理安排,把試驗(yàn)誤差控制在一個局部的范圍內(nèi)。5.試驗(yàn)指標(biāo):試驗(yàn)中用來衡量試驗(yàn)效果的量。
6.復(fù)因子試驗(yàn):包含兩個或兩個以上的因子的試驗(yàn)。7.集團(tuán)(總體):根據(jù)研究目的確定的,凡符合指定條件的全部觀察對象。8.偶然誤差(機(jī)誤):由于機(jī)會不等所造成的偏差。9.可量資料:能夠以測量、稱量的方法表示的資料。10.正交互作用(正連應(yīng)):某些因子綜合起來的效果大于這些因子單獨(dú)作用的效果之和。1.進(jìn)行隨機(jī)區(qū)組的統(tǒng)計(jì)分析,需用何種方差分析?:雙方面分類的方差分析 2.進(jìn)行拉丁方的統(tǒng)計(jì)分析,需用何種方差分析?:三方面分類的方差分析 3.進(jìn)行雙方面分類的方差分析,總平方和分解為多少部份?:三部分 4.進(jìn)行三方面分類的方差分析,總平方和分解為多少部份?:四部分
5.兩因素(含交互作用)的方差分析,處理組合平方和應(yīng)分解為多少部份?:四部分 6.三因素(含一級交互作用)的方差分析,處理組合平方和應(yīng)分解為多少部份?:七部分 7.在幾種常用的試驗(yàn)設(shè)計(jì)方法中,哪種精確度較高?:拉丁方 8.隨機(jī)區(qū)組設(shè)計(jì)的誤差自由度等于多少?:(m1)9.拉丁方設(shè)計(jì)的誤差自由度等于多少?:(n2)10.只有重復(fù)而末實(shí)行局部控制的試驗(yàn),應(yīng)采用何種方差分析?:單方面分類的方差分析 1.樣本標(biāo)準(zhǔn)差的功用?:反映樣本的變異程度
2.樣本平均數(shù)標(biāo)準(zhǔn)差(標(biāo)準(zhǔn)誤)的功用?:反映在同一個總體進(jìn)行抽樣,所得的樣本平均數(shù)間的差異,即抽樣誤差。
3.變異系數(shù)的功用?:用作兩類事物的變異程度作比較
4.樣本平均數(shù)的功用?:指示資料的中心位置,反映資料的一般質(zhì)量水平,作為代表值同其它資料比較
5.協(xié)方差分析的功用?:用處理前的數(shù)據(jù)(基數(shù))矯正處理后的數(shù)據(jù),提高分析的精確度。6.樣本均數(shù)差異顯著性測驗(yàn)的功用?:在一定的概率保證下,判斷事物間有否本質(zhì)差異 7.總體均數(shù)區(qū)間估計(jì)的功用?:通過抽樣,由樣本的情況估計(jì)未知總體平均數(shù)的數(shù)值范圍 8.在試驗(yàn)設(shè)計(jì)中,局部控制的作用?:減少試驗(yàn)誤差
9.在試驗(yàn)設(shè)計(jì)中,重復(fù)的作用?:減少試驗(yàn)誤差,估計(jì)試驗(yàn)誤差,擴(kuò)大試驗(yàn)的代表性 10.在試驗(yàn)設(shè)計(jì)中,隨機(jī)排列的功用?:正確估計(jì)試驗(yàn)誤差 1.何謂試驗(yàn)指標(biāo)?:在試驗(yàn)中用來衡量試驗(yàn)效果的一個量
2.什么叫保護(hù)行?:防止試驗(yàn)材料受外來因素和周邊環(huán)境影響作物行
3.某個復(fù)因子試驗(yàn)的處理組合數(shù)應(yīng)如何計(jì)算?:等于有關(guān)因子的水平數(shù)乘積 4.在常用的試驗(yàn)設(shè)計(jì)中,哪種設(shè)計(jì)方法的精確度最高?:拉丁方 5.在常用的試驗(yàn)設(shè)計(jì)中,哪種設(shè)計(jì)方法的精確度最低?:間比法 6.試驗(yàn)設(shè)計(jì)三大原則是什么?:重復(fù),局部控制,隨機(jī)排列
7.作改良對比法設(shè)計(jì)時,參試的品種或處理數(shù)一般不大于多少?:不受限制 8.作隨機(jī)區(qū)組設(shè)計(jì)時,參試的品種或處理數(shù)一般不大于多少?:不大于18 9.作配對法設(shè)計(jì)時,參試的品種或處理數(shù)一般不大于多少?:兩個
10.作拉丁方設(shè)計(jì)時,參試的品種或處理數(shù)一般不大于多少?:不大于8 1.某個因子的自由度等于多少?:等于該因子的水平數(shù)減1 2.某兩因子試驗(yàn)中,其交互作用的自由度等于多少?:等于有關(guān)因子的自由度的乘積
3.一可量資料樣本均數(shù)與總體均數(shù)差異顯箸性進(jìn)行t檢驗(yàn)時,其自由度為多少?:等于樣本含量數(shù)-1 4.正交表的總自由度等于多少?:等于參試的處理組合數(shù)-1 5.作回歸關(guān)系顯著性測驗(yàn)時,回歸項(xiàng)的自由度等于多少?:等于自變量的個數(shù) 6.作簡單相關(guān)系數(shù)顯著性測驗(yàn)時,DF等于多少?:等于N-2 7.2*2聯(lián)卡平方測驗(yàn)時,DF等于多少?:1 8.兩個配對法設(shè)計(jì)的可量資料樣本均數(shù)差異顯箸性進(jìn)行t檢驗(yàn),其自由度為多少?:試驗(yàn)資料的配對數(shù)-1 9.2*J聯(lián)卡平方測驗(yàn)時,其自由度為多少?:J-1 10.作拉丁方設(shè)計(jì)時,參試的品種或處理數(shù)一般不大于多少?:2 1.SS:平方和 2.N(0,1):標(biāo)準(zhǔn)正態(tài)分布 3.μ:總體平均數(shù)
4.CLM:平均數(shù)的置信區(qū)間 5.∑X :總和
6.VIF:方差膨脹因子 7.MSE:誤差均方 8.DF :自由度 9.CV:變異系數(shù) 10.V:方差
1.欲進(jìn)行聚類統(tǒng)計(jì)分析,需調(diào)用SAS系統(tǒng)的何種過程?:Proc cluster 2.欲進(jìn)行回歸統(tǒng)計(jì)分析,需調(diào)用SAS系統(tǒng)的何種過程?:Proc reg 3.欲進(jìn)行方差統(tǒng)計(jì)分析,需調(diào)用SAS系統(tǒng)的何種過程?:Proc anova 4.欲進(jìn)行因子統(tǒng)計(jì)分析,需調(diào)用SAS系統(tǒng)的何種過程?:Proc factor 5.欲進(jìn)行典型相關(guān)統(tǒng)計(jì)分析,需調(diào)用SAS系統(tǒng)的何種過程?:Proc cancorr 6.欲進(jìn)行基本統(tǒng)計(jì)量統(tǒng)計(jì)分析,需調(diào)用SAS系統(tǒng)的何種過程?:Proc means 7.欲進(jìn)行主成分分析,需調(diào)用SAS系統(tǒng)的何種過程?:Proc princomp 8.欲進(jìn)行成組法T測驗(yàn),需調(diào)用SAS系統(tǒng)的何種過程?:Proc ttest 9.欲進(jìn)行正態(tài)分布檢驗(yàn),需調(diào)用SAS系統(tǒng)的何種過程?:Procunivariate 10.欲進(jìn)行作相關(guān)點(diǎn)式圖,需調(diào)用SAS系統(tǒng)的何種過程?:Proc plot 1.單因子隨機(jī)區(qū)組的方差分析模型(MODEL)是:Y=BLOCK T 2.單因子隨機(jī)區(qū)組協(xié)方差分析的模型是(MODEL):Y=BLOCK T X 3.三元線性回歸分析的模型是(MODEL):Y=X1 X2 X3 4.單方面分類的方差分析模型(MODEL)是:Y=T
5.兩個因子變量的反應(yīng)面分析的模型(MODEL)是:Y=X1 X2
6.單因子隨機(jī)區(qū)組的多元方差分析的模型(MODEL)是:X1 X2 X3 =BLOCK T 7.3*4 復(fù)因子試驗(yàn)的方差分析模型(MODEL)是:Y=BLOCK A B A*B 8.拉丁方設(shè)計(jì)的方差分析模型(MODEL)是:Y=A B T 9.3*2*3復(fù)因子試驗(yàn)的方差分析模型(MODEL)是:Y=BLOCK A B C A*B A*C B*C A*B*C 10.正交隨機(jī)區(qū)組(不考查交互作用)的統(tǒng)計(jì)分析模型(MODEL)是:Y=BLOCK A B C D 1.協(xié)方差分析的功用?:用處理前的數(shù)據(jù)(基數(shù))矯正處理后的數(shù)據(jù),提高分析的精確度 2.主成分分析的功用?:將個數(shù)眾多、相互有關(guān)聯(lián)的變量,轉(zhuǎn)化為少數(shù)幾個相互獨(dú)立的變量 3.聚類分析的功用?:把樣本或變量進(jìn)行分類分
4.典型相關(guān)系數(shù)的功用?:反映兩組不同性質(zhì)的變量之間的關(guān)系密切程度 5.樣本平均數(shù)的功用?:反映資料的一般質(zhì)量水平,指示資料的中心位置 6.樣本平均數(shù)標(biāo)準(zhǔn)差(標(biāo)準(zhǔn)誤)的功用?:估計(jì)抽樣誤差
7.在回歸分析中,殘差的作用:反映實(shí)測值與預(yù)測值之間的偏差程度 8.在試驗(yàn)設(shè)計(jì)中,局部控制的作用?:減少試驗(yàn)誤差 9.在試驗(yàn)設(shè)計(jì)中,重復(fù)的作用?:估計(jì)試驗(yàn)誤差
10.變異系數(shù)的功用:用于兩組資料的變異程度作比較
1.多重比較的方法有很多種,課本介紹了其中的三種: 第一種、最小顯著差數(shù)法(Least Significant difference---LSD法或t測驗(yàn)法)第二種、Q測驗(yàn)法(最高顯著差數(shù)法═Tukey測驗(yàn)法)
第三種、新復(fù)極差法(Shortest Significant Range---SSR法或Duncan法)哪種測驗(yàn)法的精確度較高?TUKEY法
2.不服從正態(tài)分布的數(shù)據(jù)不能直接作方差分析,必須進(jìn)行數(shù)據(jù)轉(zhuǎn)換,數(shù)據(jù)轉(zhuǎn)換常用的方法有:(1)、平方根代換(2)、對數(shù)代換(3)、反正弦代換
問如果數(shù)據(jù)為二項(xiàng)分布的百分率,即可數(shù)百分?jǐn)?shù),且大于70%或小于30%,應(yīng)采用何種代換?反正弦代換
3.計(jì)算步驟為:
第一步、將數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化; 第二步,求相關(guān)矩陣;
第三步,求相關(guān)矩陣的特征根、特征向量、各特征根的方差貢獻(xiàn)率和累計(jì)方差貢獻(xiàn)。第四步,根據(jù)特征根的累計(jì)方差貢獻(xiàn)率保留前幾個公共因子。
第五步,用前幾個特征根的平方根乘相應(yīng)的特征向量,構(gòu)成因子載荷陣; 第六步,求相關(guān)系數(shù)矩陣的逆陣;
第七步,用因子載荷陣與相關(guān)矩陣的逆陣相乘,得回歸系數(shù)陣; 第八步,用回歸系數(shù)與標(biāo)準(zhǔn)化數(shù)據(jù)相乘得因子得分值。問這是何種統(tǒng)計(jì)分析方法?因子分析
4.計(jì)算步驟為:
第一步,將數(shù)據(jù)進(jìn)行中心化; 第二步,求方差協(xié)方差矩陣; 第三步,求方差協(xié)方差矩陣的特征根、特征向量、各特征根的方差貢獻(xiàn)率和累計(jì)方差貢獻(xiàn)率。第四步,根據(jù)特征根的累計(jì)方差貢獻(xiàn)率保留前幾個主成分。
第五步,用中心化數(shù)據(jù)與前三個特征向量相乘,求得前三個主成分得分。
第六步,如果覺得有必要,用前三個特征根的平方根(即前幾個主成分的標(biāo)準(zhǔn)差,)除前幾個主成分得分值,得標(biāo)準(zhǔn)化主成分得分。第七步,如果有必要的話,利用這些標(biāo)準(zhǔn)化主成分得分作進(jìn)一步的分析。問這是何種統(tǒng)計(jì)分析方法?主成分分析
5.計(jì)算步驟為:
第一步,計(jì)算X、Y、X*Y項(xiàng)的各種平方和(X為基數(shù),Y為處理后的實(shí)測值;
第二步,進(jìn)行X與Y項(xiàng)的回歸關(guān)系顯著性測驗(yàn),若相關(guān)不顯著,則進(jìn)行一般的方差分析; 第三步,若相關(guān)顯著,則扣除回歸關(guān)系后,再進(jìn)行方差分析; 第四步,用回歸系數(shù)矯正處理后的數(shù)據(jù)測驗(yàn),再進(jìn)行多重比較。問這是何種統(tǒng)計(jì)分析方法?協(xié)方差分析
6.計(jì)算步驟為:
第一步,計(jì)算出k個類別的方差協(xié)方差矩陣的逆陣。
第二步,計(jì)算出各個訓(xùn)練樣本到這k個類別的馬氏距離,比較這k個距離,把訓(xùn)練樣本歸到距離最短的類中。
第三步,計(jì)算在第二步中判別錯誤的樣本數(shù)占總樣本數(shù)的百分率。第四步,如果還有新的待判樣本,計(jì)算各個新樣本到這k個類別的馬氏距離,比較k個距離,把各個新樣本歸到距離最短的類中,再計(jì)算在待判樣本中判別錯誤的樣本數(shù)占待判樣本總數(shù)的百分率。
問這是何種統(tǒng)計(jì)分析方法?判別分析
7.計(jì)算步驟為:
第一步,計(jì)算出Y的矯正數(shù)及各種平方和(Y為處理后的實(shí)測值)。第二步,列方差分析表并進(jìn)行F測驗(yàn)。第三步,若F測驗(yàn)顯著則進(jìn)行多重比較。第四步,寫出統(tǒng)計(jì)結(jié)論。
問這是何種統(tǒng)計(jì)分析方法?一元方差分析
8.計(jì)算步驟為:
第一步,按一定的原則選擇k個凝聚點(diǎn);
第二步,將所有事例點(diǎn)歸到最靠近它的凝聚點(diǎn)所代表的類中,得到k個初始分類;
第三步,按最近距離的原則對初始分類進(jìn)行修改;反復(fù)進(jìn)行,直至分類合理為止。問這是何種統(tǒng)計(jì)分析方法?動態(tài)聚類
9.計(jì)算步驟為:
第一步,將原始數(shù)據(jù)進(jìn)行中心化,按研究目的分為兩組,記變量數(shù)(m1)較少的那組為X1,記變量數(shù)(m2)較多的那組為X2。
第二步,求X1和X2的方差協(xié)方差矩陣S11、S12和S22以及S12的轉(zhuǎn)置陣S21,并利用它們構(gòu)成非對稱的方陣。
第三步,求非對稱的方陣的特征根和對應(yīng)的特征向量。
第四步,將這些特征向量除以非對稱的方陣的特征根的平方根轉(zhuǎn)換為第一組的典型系數(shù)。第五步,利用兩個典型系數(shù)的關(guān)系式求出另一組的典型系數(shù)。第六步,將中心化數(shù)據(jù)和典型系數(shù)相乘得典型相關(guān)系數(shù)。問這是何種統(tǒng)計(jì)分析方法?典型相關(guān)分析 10.用SAS系統(tǒng)作數(shù)據(jù)分析,首要的問題是如何排列數(shù)據(jù),你熟悉SAS系統(tǒng)對各種統(tǒng)計(jì)分析方法的數(shù)據(jù)排列的要求嗎?問單因子試驗(yàn)采用隨機(jī)區(qū)組設(shè)計(jì),有四個試驗(yàn)指標(biāo)時,數(shù)據(jù)應(yīng)排多少列?。6列
:平方和
乘積和
合并樣本百分?jǐn)?shù)
樣本標(biāo)準(zhǔn)差
樣本平均數(shù)標(biāo)準(zhǔn)差
兩樣本百分?jǐn)?shù)之差的總體標(biāo)準(zhǔn)差
兩樣本平均數(shù)之差的樣本標(biāo)準(zhǔn)差
總體標(biāo)準(zhǔn)差
樣本變異系數(shù)
樣本差數(shù)平均數(shù)標(biāo)準(zhǔn)差
可量資料大樣本均數(shù)與總體均數(shù)差異顯箸性測驗(yàn)
可量資料兩大樣本均數(shù)差異顯箸性測驗(yàn) 可數(shù)資料樣本百分?jǐn)?shù)與總體百分?jǐn)?shù)差異顯箸性測驗(yàn)
可數(shù)資料兩大樣本百分?jǐn)?shù)差異顯箸性測驗(yàn)
可量資料小樣本均數(shù)與總體均數(shù)差異顯箸性測驗(yàn)
可量資料兩小樣本均數(shù)差異顯箸性測驗(yàn)(配對法)
可量資料兩小樣本均數(shù)差異顯箸性測驗(yàn)(成組法)
由可量資料大樣本對總體均數(shù)進(jìn)行估計(jì)
由可量資料小樣本對總體均數(shù)進(jìn)行估計(jì)
由可數(shù)資料大樣本百分?jǐn)?shù)對總體百分?jǐn)?shù)進(jìn)行估計(jì)