框架-struts2
一:struts2概要
以WebWork優(yōu)秀設(shè)計(jì)思想為核心,吸收了struts1的部分優(yōu)點(diǎn)。
二:struts2詳解
主要就是詳解struts2與struts1之間的區(qū)別,以及為什么要采用webwork重新設(shè)計(jì)新框架,以及吸收了struts1的哪部分優(yōu)點(diǎn)。
首先將區(qū)別:

首先的從核心控制器談起,struts2的FilterDispatcher,這里我們知道是一個filter而不是一個servlet,講到這里很多人還不是很清楚web.xml里它們之間的聯(lián)系,先簡短講一下它們的加載順序,context-param(應(yīng)用范圍的初始化參數(shù))-->listener(監(jiān)聽?wèi)?yīng)用端的任何修改通知)-->filter(過濾)-->servlet。
filter在執(zhí)行servlet之間就以及調(diào)用了,所以才有可能解脫完全依賴servlet的局面,那我們來看看這個filter做了什么事情:
/**
以WebWork優(yōu)秀設(shè)計(jì)思想為核心,吸收了struts1的部分優(yōu)點(diǎn)。
二:struts2詳解
主要就是詳解struts2與struts1之間的區(qū)別,以及為什么要采用webwork重新設(shè)計(jì)新框架,以及吸收了struts1的哪部分優(yōu)點(diǎn)。
首先將區(qū)別:
- 最大的區(qū)別是與servlet成功解耦,不在依賴容器來初始化HttpServletRequest和HttpServletResponse
struts1里依賴的核心控制器為ActionServlet而struts2依賴ServletDispatcher,一個是servlet一個是filter,正是采用了filter才不至于和servlet耦合,所有的數(shù)據(jù) 都是通過攔截器來實(shí)現(xiàn),如下圖顯示:

- web層表現(xiàn)層的豐富,struts2已經(jīng)可以使用jsp、velocity、freemarker
- 線程模式方面:struts1的action是單例模式而且必須是線程安全或同步的,是struts2的action對每一個請求都產(chǎn)生一個新的實(shí)例,因此沒有線程安全問 題。
- 封裝請求參數(shù):是struts1采用ActionForm封裝請求參數(shù),都必須繼承ActionForm基類,而struts2通過bean的屬性封裝,大大降低了耦合。
- 類型轉(zhuǎn)換:struts1封裝的ActionForm都是String類型,采用Commons- Beanutils進(jìn)行類型轉(zhuǎn)換,每個類一個轉(zhuǎn)換器;struts2采用OGNL進(jìn)行類型轉(zhuǎn) 換,支持基本數(shù)據(jù)類型和封裝類型的自動轉(zhuǎn)換。
- 數(shù)據(jù)校驗(yàn):struts1在ActionForm中重寫validate方法;struts2直接重寫validate方法,直接在action里面重寫即可,不需要繼承任何基類,實(shí)際的調(diào)用順序是,validate()-->execute(),會在執(zhí)行execute之前調(diào)用validate,也支持xwork校驗(yàn)框架來校驗(yàn)。
首先的從核心控制器談起,struts2的FilterDispatcher,這里我們知道是一個filter而不是一個servlet,講到這里很多人還不是很清楚web.xml里它們之間的聯(lián)系,先簡短講一下它們的加載順序,context-param(應(yīng)用范圍的初始化參數(shù))-->listener(監(jiān)聽?wèi)?yīng)用端的任何修改通知)-->filter(過濾)-->servlet。
filter在執(zhí)行servlet之間就以及調(diào)用了,所以才有可能解脫完全依賴servlet的局面,那我們來看看這個filter做了什么事情:
/**
* Process an action or handle a request a static resource.
* <p/>
* The filter tries to match the request to an action mapping.
* If mapping is found, the action processes is delegated to the dispatcher's serviceAction method.
* If action processing fails, doFilter will try to create an error page via the dispatcher.
* <p/>
* Otherwise, if the request is for a static resource,
* the resource is copied directly to the response, with the appropriate caching headers set.
* <p/>
* If the request does not match an action mapping, or a static resource page,
* then it passes through.
*
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
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
ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
ActionContext ctx = new ActionContext(stack.getContext());
ActionContext.setContext(ctx);
UtilTimerStack.push(timerKey);
request = prepareDispatcherAndWrapRequest(request, response);
ActionMapping mapping;
try {
mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager());
} catch (Exception ex) {
log.error("error getting ActionMapping", ex);
dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
return;
}
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)) {
staticResourceLoader.findStaticResource(resourcePath, request, response);
} else {
// this is a normal request, let it pass through
chain.doFilter(request, response);
}
// The framework did its job here
return;
}
dispatcher.serviceAction(request, response, servletContext, mapping);//過濾用戶請求,攔截器執(zhí)行,把對應(yīng)的action請求轉(zhuǎn)到業(yè)務(wù)action執(zhí)行 }
finally {
try {
ActionContextCleanUp.cleanUp(req);
} finally {
UtilTimerStack.pop(timerKey);
}
}
}
對應(yīng)的action參數(shù)由攔截器獲取。
解耦servlet是struts2采用webwork思路的最重要的一個原因,也迎合了整個技術(shù)的一個發(fā)展方向,解耦一直貫穿于整個框架。
* <p/>
* The filter tries to match the request to an action mapping.
* If mapping is found, the action processes is delegated to the dispatcher's serviceAction method.
* If action processing fails, doFilter will try to create an error page via the dispatcher.
* <p/>
* Otherwise, if the request is for a static resource,
* the resource is copied directly to the response, with the appropriate caching headers set.
* <p/>
* If the request does not match an action mapping, or a static resource page,
* then it passes through.
*
* @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
*/
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
ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
ActionContext ctx = new ActionContext(stack.getContext());
ActionContext.setContext(ctx);
UtilTimerStack.push(timerKey);
request = prepareDispatcherAndWrapRequest(request, response);
ActionMapping mapping;
try {
mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager());
} catch (Exception ex) {
log.error("error getting ActionMapping", ex);
dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
return;
}
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)) {
staticResourceLoader.findStaticResource(resourcePath, request, response);
} else {
// this is a normal request, let it pass through
chain.doFilter(request, response);
}
// The framework did its job here
return;
}
dispatcher.serviceAction(request, response, servletContext, mapping);//過濾用戶請求,攔截器執(zhí)行,把對應(yīng)的action請求轉(zhuǎn)到業(yè)務(wù)action執(zhí)行 }
finally {
try {
ActionContextCleanUp.cleanUp(req);
} finally {
UtilTimerStack.pop(timerKey);
}
}
}
對應(yīng)的action參數(shù)由攔截器獲取。
解耦servlet是struts2采用webwork思路的最重要的一個原因,也迎合了整個技術(shù)的一個發(fā)展方向,解耦一直貫穿于整個框架。