1
、
Struts1.x
簡單配置
a
)、配置
struts
?????? *
拷貝
struts lib
下的所有
jar
到
WEB-INF/lib
下
?????? *
修改
web.xml
文件,配置
ActionServlet
?????? *
提供
struts-config.xml
文件
??????
b)
、創建登錄項目
?????? *
創建
jsp
頁面(
login.jsp,login_success.jsp,login_error.jsp
)
?
?????? *
創建
LoginActionForm.java
?????? *
創建
LoginAction.java
?????? *
配置
struts-config.xml
文件
?
2
、
I18N
問題
??????
首先創建國際化資源文件:
MessageResources_zh_CN.properties
,如此格式,
然后在
Struts-config.xml
中配置一個
Action
處理,該編碼問題,并做如下代碼:
??????
?????? String lang = request.getParameter("lang");//
取得指定的語言
????????????? Locale currentLocale = Locale.getDefault();//
得到本地
Locale
?????????????
????????????? if("zh".equals(lang)){
???????????????????? currentLocale = new Locale("zh","CN");
????????????? }else if("en".equals(lang)){
???????????????????? currentLocale = new Locale("en","US");
????????????? }
????????????? //
修改
session
中
Globals.LOCALE_KEY
????????????? request.getSession().setAttribute(Globals.LOCALE_KEY, currentLocale);
?????????????
?
3
、采用
DispathAction
?????? *
如果覆寫
DispathAction
中的
execute
方法,必須顯示的用
super
調用
execute
方法
?????? * parameter
參數值不能是
execute
或
perform
?????? *
了解
<action>
標簽中的
parameter
的含義
?????? *
了解
DispathAction
中的
unspecified
方法的含義
?
4
、學會使用
FormBean
??????
在配置文件中配置的
ActionForm
在解析
ActionMapping
時,會以
Action
的
name
為
key
,然后在
HttpSession
中存儲該
ActionForm
的值,那么我們在整個會話中都會得到這個
Form
,而且這個
Form
在每次請求的時候都會更新。
?
5
、
ActionServlet
初始化方法
??
public
void
init()
throws
ServletException {
???????
final
String configPrefix =
"config/"
;
???????
final
int
configPrefixLength = configPrefix.length() - 1;
?
???????
// Wraps the entire initialization in a try/catch to better handle
???????
// unexpected exceptions and errors to provide better feedback
???????
// to the developer
???????
try
{
//
初始化我們系統的資源信息綁定
??????????? initInternal();
?????????
??//
初始化控制器的字符集轉換信息,通過配置
web.xml
中的
convertNull
參數來進行數據類型的轉換。通過注冊轉換器來實現。
initOther();?
//
初始化我們當前請求的
Servlet
控制器
?????????
??initServlet();
//
解析配置文件
web.xml
文件中的
chainConfig
初始化參數去配置在
CatalogFactory
中默認的
org.apache.commons.chain.Catalog
。
??????????? initChain();
//
在當前的
Servlet
上下文中使用
Globals.ACTION_SERVLET_KEY
保存當前的
ActionServlet
。
??????????? getServletContext().setAttribute(Globals.
ACTION_SERVLET_KEY
,
this
);
//
初始化
ModuleConfig
的模版工廠
??????????? initModuleConfigFactory();
?
???????
????//
初始化當前需要的
ModuleConfig,
即開始初始化
struts-config.xml
??????????? ModuleConfig moduleConfig = initModuleConfig(
""
,
config
);
??????
??? //
初始化配置文檔中的國際化資源信息,并將其存入當前的
ServletCotext
中。
??????????? initModuleMessageResources(moduleConfig);
??????
??? //
初始化配置文檔中的插件
??????????? initModulePlugIns(moduleConfig);
?????????? //
初始化
FormBeans
并建起存入
moduleConfig
中,其實是保存在當前的
HttpSession
中,每次請求替換一次該
FormBeans
??????????? initModuleFormBeans(moduleConfig);
//
初始化全局化的
Forward
將
Forward
保存在當前的
ActionConfig
或者
moduleConfig
中
??????????? initModuleForwards(moduleConfig);
//
初始化全局
Exception
將
Exception
保存在當前的
ActionConfig
或者
moduleConfig
中
??????????? initModuleExceptionConfigs(moduleConfig);
//
初始化
Action
,將當前
ActionConfig
保存在
moduleConfig
中,用路徑做為
key
??????????? initModuleActions(moduleConfig);
//
凍結當前配置模版,任何修改將會導致
IllegalStateException
。
??????????? moduleConfig.freeze();
//
取得當前
Application
的
web.xml
中的所有的初始化參數,然后在解析配置文件
??????????? Enumeration names = getServletConfig().getInitParameterNames();
?
???????????
while
(names.hasMoreElements()) {
??????????????? String name = (String) names.nextElement();
?
???????????????
if
(!name.startsWith(configPrefix)) {
???????????????????
continue
;
?
?????????????? }
?
??????????????? String prefix = name.substring(configPrefixLength);
?
??????????????? moduleConfig =
??????????????????? initModuleConfig(prefix,
??????????????????????? getServletConfig().getInitParameter(name));
??????????????? initModuleMessageResources(moduleConfig);
??????????????? initModulePlugIns(moduleConfig);
??????????????? initModuleFormBeans(moduleConfig);
??????????????? initModuleForwards(moduleConfig);
??????????????? initModuleExceptionConfigs(moduleConfig);
??????????????
?initModuleActions(moduleConfig);
??????????????? moduleConfig.freeze();
??????????? }
//
保持模版前綴的字符串數組在
ServletContext
中。使用
Globals.MODULE_PREFIXES_KEY
???????????
this
.initModulePrefixes(
this
.getServletContext());
//
溫柔的釋放我們創建的
ConfigDigester
???????????
this
.destroyConfigDigester();
??????? }
catch
(UnavailableException ex) {
???????????
throw
ex;
??????? }
catch
(Throwable t) {
???????????
// The follow error message is not retrieved from internal message
???????????
// resources as they may not have been able to have been
???????????
// initialized
???????????
log
.error(
"Unable to initialize Struts ActionServlet due to an "
??????????????? +
"unexpected exception or error thrown, so marking the "
??????????????? +
"servlet as unavailable.? Most likely, this is due to an "
??????????????? +
"incorrect or missing library dependency."
, t);
??????????
?
throw
new
UnavailableException(t.getMessage());
??????? }
??? }
??????
?
?
?
?
?
6
、
Struts
請求處理流程
??????
?????? 1
)、請求通過
doGet
或
doPost
方法委托給
ActionServlet
的
process
方法。
???
??? //
執行標準的請求處理方法,并創建相應的回復
??????
protected
void
process(HttpServletRequest request,
???????
??????? HttpServletResponse response)
???????
???????
throws
IOException, ServletException {
??????
???
??? //
根據請求選擇相應的模版信息,而且添加相應的請求屬性到當前的請求
ModuleUtils.getInstance().selectModule(request, getServletContext());
???
??? //
為選中的模版,選擇相應的模版配置信息對象
??????? ModuleConfig config = getModuleConfig(request);
???
??? //
根據當前的模版配置信息,返回一個請求處理器,如果沒有的話則返回
null
,該方法不會創建
RequestProcessor
??????? RequestProcessor processor = getProcessorForModule(config);
?????? //
如果該模版的請求處理器為
null
,則使用模版信息創建一個
RequestProcessor
???????
if
(processor ==
null
) {
??????????? processor = getRequestProcessor(config);
???
????}
?????? //
使用請求處理器來處理當前的請求,
RequestProcessor
以及
process
方法是整個
Struts
的核心對象和方法
??????? processor.process(request, response);
}
?
2
)、
RequestProcessor
的
process
方法
?
???
public
void
process(HttpServletRequest request, HttpServletResponse response)
???????
throws
IOException, ServletException {
??????? // Wrap multipart requests with a special wrapper
(用一個特效的包裝器來包裝多媒體請求,如果當前請求不是多媒體的則方法原理的請求對象)
??????? request = processMultipart(request);
?
???????
// Identify the path component we will use to select a mapping
?????? //
根據請求
URI
,選擇一個
Action Mapping
去分派請求,如果沒有則報錯或結束方法
??????? String path = processPath(request, response);
?
???????
if
(path ==
null
) {
???????????
return
;
??????? }
?
???????
if
(
log
.isDebugEnabled()) {
???????????
log
.debug(
"Processing a '"
+ request.getMethod() +
"' for path '"
??????????????? + path +
"'"
);
??????? }
?
???????
// Select a Locale
(地點)
for the current user if requested
??????? processLocale(request, response);
?
???????
// Set the content type and no-caching headers if requested
??????? processContent(request, response);
??????? processNoCache(request, response);
?
???????
// General purpose preprocessing
(預處理)
hook
,
true
則表示正常執行下面語句,否則表示已經完成處理
???????
if
(!processPreprocess(request, response)) {
???????????
return
;
??????? }
??????
//
從
session
中移除或者添加修改
Grobel.MESSAGE_KEY
或
Grobel.ERROR_KEY
???????
this
.processCachedMessages(request, response);
??????
??????? // Identify the mapping for this request
,根據
path
為
request
選擇一個
ActionMapping
,來訪問相應的
Action
。
ActionMapping
提供給
RequestProcessor
對于
Action
的各種處理信息。
??????? ActionMapping mapping = processMapping(request, response, path);
?
???????
if
(mapping ==
null
) {
???????????
return
;
??????? }
?
???????
// Check for any role required to perform this action
???????
if
(!processRoles(request, response, mapping)) {
???????????
return
;
??????? }
?
???????
// Process any ActionForm bean related to
(涉及)
this request
??????? ActionForm form = processActionForm(request, response, mapping);
//
根據
request
中的請求參數,組裝特殊的
ActionForm
??????? processPopulate(request, response, form, mapping);
?
???????
//
如果這個請求沒有取消而且這個請求的
ActionMapping
沒有取消驗證,調用指定的
ActionForm
中的
validate
方法,然后轉發到
input
路徑指定的頁面也就是錯誤發生的頁面。返回
true
我們將繼續處理,否則我們已經被控制轉發到
input
表單頁面中。
???????
try
{
???????????
if
(!processValidate(request, response, form, mapping)) {
???????????????
return
;
??????????? }
??????? }
catch
(InvalidCancelException e) {
//
詢問我們的異常處理器去處理異常。有調用的
ExceptionHandler
返回
ActionForward
實例
ActionForward forward = processException(request, response, e, form, mapping);
//
根據指定的機制轉發或者重定向到指定的目的地。
??????????? processForwardConfig(request, response, forward);
???????????
return
;
??????? }
catch
(IOException e) {
???????????
throw
e;
??????? }
catch
(ServletException e) {
???????????
throw
e;
??????? }
?
???????
// Process a forward or include specified by this mapping
???????
if
(!processForward(request, response, mapping)) {
???????????
return
;
??????? }
?
???????
if
(!processInclude(request, response, mapping)) {
???????????
return
;
??????? }
?
???????
//
返回一個用于處理當前請求的
ActionForm
實例,如果必要的話返回一個新實例
??????? Action action = processActionCreate(request, response, mapping);
?
???????
if
(action ==
null
) {
???????????
return
;
??????? }
?
??????? //
詢問指定的
Action
實例去處理當前的請求。根據調用的
Action
返回
ActionForward
實例用作以后的處理。
??????? ActionForward forward =
??????????? processActionPerform(request, response, action, form, mapping);
?
????
???//
根據指定的機制轉發或者重定向到指定的目的地。
??????? processForwardConfig(request, response, forward);
??? }