国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
struts2 處理請求流程分析(結(jié)合源碼)2
2、過濾器中的doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 方法
2.1、request = prepareDispatcherAndWrapRequest(request, response);分析
我們知道JSTL默認(rèn)是從page,request,session,application這四個(gè)Scope逐次查找相應(yīng)的EL表達(dá)式所對應(yīng)的對象的值。那么如果要使用JSTL來讀取Action中的變量,就需要把Action中的變量,放到request域中才行Struts2,都使用另外一種整合方式:對HttpServletRequest進(jìn)行裝飾(StrutsRequestWrapper )這個(gè)類會(huì)在Struts2初始化的時(shí)候,替換HttpServletRequest,運(yùn)行于整個(gè)Struts2的運(yùn)行過程中,當(dāng)我們試圖調(diào)用request.getAttribute()的時(shí)候,就會(huì)執(zhí)行上面的這個(gè)方法。(這是一個(gè)典型的裝飾器模式)在執(zhí)行上面的方法時(shí),會(huì)首先調(diào)用HttpServletRequest中原本的request.getAttribute(),如果沒有找到,它會(huì)繼續(xù)到ValueStack中去查找,而action在ValueStack中,所以action中的變量通過OGNL表達(dá)式,就能找到對應(yīng)的值了。
Java代碼 
protected HttpServletRequest prepareDispatcherAndWrapRequest(
HttpServletRequest request, HttpServletResponse response)
throws ServletException {
//獲取dispatch 的單例類,是由LocalThread 保存的,保證線程的安全
Dispatcher du = Dispatcher.getInstance();
// Prepare and wrap the request if the cleanup filter hasn't already,
// cleanup filter should be
// configured first before struts2 dispatcher filter, hence when its
// cleanup filter's turn,
// static instance of Dispatcher should be null.
if (du == null) {
//如果為空的話,值保存進(jìn)LocalThread 中
Dispatcher.setInstance(dispatcher);
// prepare the request no matter what - this ensures that the proper
// character encoding
// is used before invoking the mapper (see WW-9127)
// request 編碼設(shè)置和response 本地化設(shè)置
dispatcher.prepare(request, response);
} else {
dispatcher = du;
}
try {
// Wrap request first, just in case it is multipart/form-data
// parameters might not be accessible through before encoding
// (ww-1278)
//在這里就開始包裝
request = dispatcher.wrapRequest(request, getServletContext());
} catch (IOException e) {
String message = "Could not wrap servlet request with MultipartRequestWrapper!";
LOG.error(message, e);
throw new ServletException(message, e);
}
return request;
}
簡單看下這個(gè)方法Dispatcher.getInstance();
Java代碼 
private static ThreadLocal<Dispatcher> instance = new ThreadLocal<Dispatcher>();
//other code
public static Dispatcher getInstance() {
return instance.get();
}
主要的包裝在此方法進(jìn)行request = dispatcher.wrapRequest(request, getServletContext());
Java代碼 
public HttpServletRequest wrapRequest(HttpServletRequest request, ServletContext servletContext) throws IOException {
// don't wrap more than once 如果已經(jīng)包裝了,就不用再包裝了
if (request instanceof StrutsRequestWrapper) {
return request;
}
String content_type = request.getContentType();
//非表單提交的request 封裝,主要是圖片上傳等
if (content_type != null && content_type.indexOf("multipart/form-data") != -1) {
MultiPartRequest multi = getContainer().getInstance(MultiPartRequest.class);
//如果是非表單提交則包裝成MultiPartRequestWrapper
request = new MultiPartRequestWrapper(multi, request, getSaveDir(servletContext));
} else {
//如果是普通表單提交,在此包裝
request = new StrutsRequestWrapper(request);
}
return request;
}
2.2、mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager());方法的分析
這里的分析參照了:http://zddava.javaeye.com/blog/215504
下面來看一下默認(rèn)使用的ActionMapper實(shí)現(xiàn)DefaultActionMapper的#getMapping():
Java代碼 
public ActionMapping getMapping(HttpServletRequest request,
ConfigurationManager configManager) {
ActionMapping mapping = new ActionMapping();// (1)
String uri = getUri(request);// (2)
uri = dropExtension(uri);// (3)
if (uri == null) {
return null;
}
parseNameAndNamespace(uri, mapping, configManager);// (4)
handleSpecialParameters(request, mapping);// (5)
if (mapping.getName() == null) {
return null;
}
if (allowDynamicMethodCalls) {// (6)
String name = mapping.getName();
int exclamation = name.lastIndexOf("!");
if (exclamation != -1) {
mapping.setName(name.substring(0, exclamation));
mapping.setMethod(name.substring(exclamation + 1));
}
}
return mapping;
}
主要有6處需要重點(diǎn)說明:
(1) 關(guān)于ActionMapping類,它內(nèi)部封裝了如下5個(gè)字段:
Java代碼 
private String name;// Action名
private String namespace;// Action名稱空間
private String method;// 執(zhí)行方法
private Map params;// 可以通過set方法設(shè)置的參數(shù)
private Result result;// 返回的結(jié)果
這些在配置文件中都是可設(shè)置的,確定了ActionMapping類的各個(gè)字段的值,就可以對請求的Action進(jìn)行調(diào)用了。
(2) String uri = getUri(request);
這個(gè)步驟用于獲取客戶端發(fā)送的請求的URI,源代碼如下:
Java代碼 
String getUri(HttpServletRequest request) {
// handle http dispatcher includes.
String uri = (String) request.getAttribute("javax.servlet.include.servlet_path");
if (uri != null) {
return uri;
}
uri = RequestUtils.getServletPath(request);
if (uri != null && !"".equals(uri)) {
return uri;
}
uri = request.getRequestURI();
return uri.substring(request.getContextPath().length());
}
這個(gè)方法首先判斷請求是否來自于一個(gè)jsp的include,如果是,那么請求的"javax.servlet.include.servlet_path"屬性可以獲得include的頁面uri,否則通過一般的方法獲得請求的uri,最后返回去掉ContextPath的請求路徑,比如http://127.0.0.1:8087/test/jsp/index.jsp?param=1,返回的為/jsp/index.jsp。去掉了ContextPath和查詢字符串等。
(3) uri = dropExtension(uri); 負(fù)責(zé)去掉Action的"擴(kuò)展名"(默認(rèn)為"action"),源代碼如下:
Java代碼 
String dropExtension(String name) {
//extensions 為struts2 的后綴名,可有多個(gè),默認(rèn)為action
// List extensions = new ArrayList() {{ add("action");}};
if (extensions == null) {
return name;
}
Iterator it = extensions.iterator();
//分別遍歷后去掉后綴名
while (it.hasNext()) {
String extension = "." + (String) it.next();
if (name.endsWith(extension)) {
name = name.substring(0, name.length() - extension.length());
return name;
}
}
return null;
}
注意,這個(gè)步驟對于不是以特地?cái)U(kuò)展名結(jié)尾的請求會(huì)返回一個(gè)null的uri,進(jìn)而#getMapping()也會(huì)返回null,F(xiàn)ilterDispatcher的#doFilter()就會(huì)把這次請求當(dāng)作一個(gè)普通請求對待了。
(4) parseNameAndNamespace(uri, mapping, configManager);
此方法用于解析Action的名稱和命名空間,并賦給ActionMapping對象。源代碼如下:
Java代碼 
void parseNameAndNamespace(String uri, ActionMapping mapping, ConfigurationManager configManager) {
String namespace, name;
// 例如 http://127.0.0.1:8087/teststruts/namespace/name.action?param=1
// dropExtension()后,獲得uri為/namespace/name
int lastSlash = uri.lastIndexOf("/");
if (lastSlash == -1) {
namespace = "";
name = uri;
} else if (lastSlash == 0) {
namespace = "/";
name = uri.substring(lastSlash + 1);
} else if (alwaysSelectFullNamespace) {// alwaysSelectFullNamespace默認(rèn)為false,代表是否將最后一個(gè)"/"前的字符全作為名稱空間。
namespace = uri.substring(0, lastSlash);// 獲得字符串 namespace
name = uri.substring(lastSlash + 1);// 獲得字符串 name
} else {
// 例如 http://127.0.0.1:8087/teststruts/namespace1/namespace2/actionname.action?param=1
// dropExtension()后,獲得uri為/namespace1/namespace2/actionname
Configuration config = configManager.getConfiguration();
String prefix = uri.substring(0, lastSlash);// 獲得 /namespace1/namespace2
namespace = "";
// 如果配置文件中有一個(gè)包的namespace是 /namespace1/namespace2,那么namespace為/namespace1/namespace2,name為actionname
// 如果配置文件中有一個(gè)包的namespace是 /namespace1,那么namespace為/namespace1,name為/namespace2/actionname
for (Iterator i = config.getPackageConfigs().values().iterator(); i
.hasNext();) {
String ns = ((PackageConfig) i.next()).getNamespace();
if (ns != null && prefix.startsWith(ns) && (prefix.length() == ns.length() || prefix.charAt(ns.length()) == '/')) {
if (ns.length() > namespace.length()) {
namespace = ns;
}
}
}
name = uri.substring(namespace.length() + 1);
}
if (!allowSlashesInActionNames && name != null) {// allowSlashesInActionNames代表是否允許"/"出現(xiàn)在Action的名稱中,默認(rèn)為false
int pos = name.lastIndexOf('/');
if (pos > -1 && pos < name.length() - 1) {
name = name.substring(pos + 1);
}
}// 以 name = /namespace2/actionname 為例,經(jīng)過這個(gè)if塊后,name = actionname
mapping.setNamespace(namespace);
mapping.setName(name);
}
(5) handleSpecialParameters(request, mapping); 此方法用于處理Struts框架定義的四種特殊的prefix:
下邊是struts2的javadoc里提供的例子:
Method prefix:調(diào)用baz的另外一個(gè)方法"anotherMethod"而不是"execute"
Html代碼 
<a:form action="baz">
<a:textfield label="Enter your name" name="person.name"/>
<a:submit value="Create person"/>
<a:submit name="method:anotherMethod" value="Cancel"/>
</a:form>
Action prefix:調(diào)用anotherAction的"execute"
Html代碼 
<a:form action="baz">
<a:textfield label="Enter your name" name="person.name"/>
<a:submit value="Create person"/>
<a:submit name="action:anotherAction" value="Cancel"/>
</a:form>
Redirect prefix:將請求重定向,下例中為定向到google
Html代碼 
<a:form action="baz">
<a:textfield label="Enter your name" name="person.name"/>
<a:submit value="Create person"/>
<a:submit name="redirect:www.google.com" value="Cancel"/>
</a:form>
Redirect-action prefix:重定向action,下例中為定向到dashboard.action
Html代碼 
<a:form action="baz">
<a:textfield label="Enter your name" name="person.name"/>
<a:submit value="Create person"/>
<a:submit name="redirect-action:dashboard" value="Cancel"/>
</a:form>
handleSpecialParameters的源代碼如下:
Java代碼 
public void handleSpecialParameters(HttpServletRequest request, ActionMapping mapping) {
Set<String> uniqueParameters = new HashSet<String>();
Map parameterMap = request.getParameterMap();
for (Iterator iterator = parameterMap.keySet().iterator(); iterator.hasNext();) {
String key = (String) iterator.next();
if (key.endsWith(".x") || key.endsWith(".y")) {// 去掉圖片按鈕的位置信息,具體情況我也不是很了解
key = key.substring(0, key.length() - 2);
}
// 處理四種特殊的prefix:Method prefix,Action prefix,Redirect prefix,Redirect-action prefix
if (!uniqueParameters.contains(key)) {
ParameterAction parameterAction = (ParameterAction) prefixTrie.get(key);
if (parameterAction != null) {// 當(dāng)發(fā)現(xiàn)某種特殊的predix時(shí)
parameterAction.execute(key, mapping);// 調(diào)用它的execute方法,在DefaultActionMapper的構(gòu)造函數(shù)中定義
uniqueParameters.add(key);// 下邊已經(jīng)break了為什么還要把key加入到排重的Set里呢??
break;
}
}
}
}
(6) 處理調(diào)用的不是execute方法的情況:
Struts框架也可以處理"name!method"形式的action調(diào)用,碰到這種情況,在此處將name和method分別解析出來然后賦給ActionMapping對象。
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Struts2 源碼分析——Result類實(shí)例
Struts2的工作機(jī)制及分析
struts2.x的處理流程
sturts2運(yùn)行原理
struts 2 配置方法及其技巧實(shí)例整理(一)
關(guān)于struts2中namespace和s:form action和form action 路徑問題
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服