Struts流程分析+源码分析
1、初始化工作 讀取配置---轉換器-----讀取插件 當struts-config.xml配置文件加載到內存,則會創建兩個map:ActionConfigs,FromBeans。這兩個map都交由ModuleConfig對象管理 a、ActionConfigs的Map裝載每個Action配置信息---ActionMapping b、名為FromBeans的map裝載FormBean配置信息---FormBeanConfig ? 接收請求ActionServlet的doPost方法進行處理,調用process方法,而process方法會創建RequestProcessor對象并調用其process方法 ActionServlet的doPost方法 public?void?doPost(HttpServletRequest?request,?HttpServletResponse?response) throws?IOException,?ServletException?{ ?process(request,?response); } ActionServlet的process方法 ?protected?void?process(HttpServletRequest?request,HttpServletResponse?response)throws?IOException,?ServletException?{ ModuleUtils.getInstance().selectModule(request,?getServletContext()); ModuleConfig?config?=?getModuleConfig(request); ?RequestProcessor?processor?=?getProcessorForModule(config); if?(processor?==?null)?{ processor?=?getRequestProcessor(config); } ?processor.process(request,?response); } RequestProcessor對象的process方法,也是整個ActionServlet的整個核心控制流程 public?void?process(HttpServletRequest?request,?HttpServletResponse?response) ????????throws?IOException,?ServletException?{ //?Identify?the?path?component?we?will?use?to?select?a?mapping ???String?path?=?processPath(request,?response); if?(path?==?null)?{ return; } this.processCachedMessages(request,?response); //?Identify?the?mapping?for?this?request ??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); processPopulate(request,?response,?form,?mapping); //?Validate?any?fields?of?the?ActionForm?bean,?if?applicable try?{ if?(!processValidate(request,?response,?form,?mapping))?{ return; } }?catch?(InvalidCancelException?e)?{ 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; } //?Create?or?acquire?the?Action?instance?to?process?this?request ???Action?action?=?processActionCreate(request,?response,?mapping); if?(action?==?null)?{ return; } //?Call?the?Action?instance?itself ActionForward?forward?= ????????????processActionPerform(request,?response,?action,?form,?mapping); //?Process?the?returned?ActionForward?instance ??processForwardConfig(request,?response,?forward); } 1、struts工作流程: @@、processPath()-->截取.do前路徑 RequestProcessor對象的process方法的調用processPath方法截取.do前路徑
源碼如下: String?path?=?processPath(request,?response);
http://127.0.0.1:8080/struts_login/login.do?
username="admin"&password="admin"
path = request.getServletPath();
path=/login.do?username="admin"&password="admin"
int slash = path.lastIndexOf("/");
slash =0;
int period = path.lastIndexOf(".");
period=6;
if ((period >= 0) && (period > slash)) {
????????????path = path.substring(0, period);
????????????path=/login ???
?}
?return (path);
?
-------------------------------------------------------------------- @@、processMapping()-->根據上一步解析的路徑,找到請求路徑找到在actionConfigs的map里取得所對應的ActionMapping對象 核心源碼如下: protected?ActionMapping?processMapping(HttpServletRequest?request, ????????HttpServletResponse?response,?String?path) ????????throws?IOException?{ ????????//?Is?there?a?mapping?for?this?path? ????????ActionMapping?mapping?= ????????????(ActionMapping)?moduleConfig.findActionConfig(path); ? ????????//?If?a?mapping?is?found,?put?it?in?the?request?and?return?it ????????if?(mapping?!=?null)?{ ????????????request.setAttribute(Globals.MAPPING_KEY,?mapping); ? ????????????return?(mapping); ????????}?
<action-mappings>
<action path="/login"
???????type="com.struts.LoginAction"
???????name="loginForm"
???????scope="request"
???????validate="true"
>
<forward name="success" path="/login_success.jsp"/>
<forward name="error" path="/login_error.jsp"/>
</action>
</action-mappings>
--------------------------------------------------------------------- @@、processActionForm()--->根據解析action配置的name值找是否scope所對應的域里是否有該請求對應的actionfrom對象,沒有則根據actionfrom配置的type的值反射創建actionFrom對象并存入requestprotected ActionForm processActionForm(HttpServletRequest request,HttpServletResponse response, ActionMapping mapping) {
?ActionForm instance = RequestUtils.createActionForm
????????????(request, mapping, moduleConfig, servlet);
????????if (instance == null) {
????????????return (null);
????????}
if ("request".equals(mapping.getScope())) {
????????????request.setAttribute(mapping.getAttribute(), instance);
????????} else {
????????????HttpSession session = request.getSession();
????????????session.setAttribute(mapping.getAttribute(), instance);
????????}
????????return (instance);
}
public static ActionForm createActionForm(HttpServletRequest request,ActionMapping mapping,?ModuleConfig moduleConfig,ActionServlet servlet) {
????????String attribute = mapping.getAttribute();
????????if (attribute == null) {
????????????return (null);
????????}
? ? ? ? String name = mapping.getName();
????????//到formBeans的Map中取得FormBeanConfig對象
? ? ? ? FormBeanConfig config = moduleConfig.findFormBeanConfig(name);
? ? ? ? if (config == null) {return (null);}
? ? ? ? ActionForm instance = lookupActionForm(request, attribute, mapping.getScope());
? ? ? ? try {if (instance != null ) {return (instance); }
? ? ? ? return createActionForm(config, servlet);
}
?
private static ActionForm?lookupActionForm(HttpServletRequest request, String attribute, String scope)
????{// Look up any existing form bean instance
????????ActionForm instance = null;
????????HttpSession session = null;
????????if ("request".equals(scope)) {
????????????instance = (ActionForm) request.getAttribute(attribute);
????????} else {
????????????session = request.getSession();
????????????instance = (ActionForm) session.getAttribute(attribute);
????????}
????????return (instance);
????}
?
?-------------------------------------------------------------------------------------------------------------------------------
@@、processPopulate()-->從request里拿出name值所對應的actionform并根據actionform配置自動收集請求參數到對象并存入request里protected void processPopulate(HttpServletRequest req,HttpServletResponse response,
???????????????????????????????????ActionForm form,
???????????????????????????????????ActionMapping mapping)
throws ServletException {
if (form == null) {
????????????return;
????????}
form.reset(mapping, request);//收集表單數據前對 表單bean的屬性初始化
RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(),
??????????????????????????????request);
?
RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(),request);
public static void populate(Object bean,String prefix,String suffix,HttpServletRequest request)
????????????throws ServletException {
????????HashMap properties = new HashMap();
????????Enumeration names = null;
????????names = request.getParameterNames();
?????while (names.hasMoreElements()) {
????????????String name = (String) names.nextElement();
????????????String stripped = name;
????????????Object parameterValue = null;
????????????parameterValue = request.getParameterValues(na
me);
properties.put(stripped, parameterValue);
}
BeanUtils.populate(bean, properties);
}
?
public static void populate(Object bean, Map properties)
????????throws IllegalAccessException, InvocationTargetException {
????????if ((bean == null) || (properties == null)) {
????????????return;
????????}
Iterator names = properties.keySet().iterator();
????????while (names.hasNext()) {
????????????String name = (String)
names.next();
???Object value = properties.get(name);?
setProperty(bean, name, value);
?
//收集表單數據后對表單bean的屬性值進行驗證
if (!processValidate(request, response, form, mapping)) {
????????????return;
????????}
?
------------------------------------------------------------------------- @@、processActionCreate()--->根據action配置type的值創建action對象.processActionCreate創建action對象(這里actions是HashMap對象,用map實現創建action對象是單例,而且在創建的過程是加鎖防止多個線程在用一個時刻訪問同一個action請求)
源碼如下:protected?Action?processActionCreate(HttpServletRequest?request, ????????HttpServletResponse?response,?ActionMapping?mapping) ????????throws?IOException?{ ? ? ? ? //通過maping對象獲取action的類型(全類名用于反射創建對象) ????????String?className?=?mapping.getType(); ????????Action?instance; ? ? ? ? //在創建action的過程中加鎖確保線程同步 ????????synchronized?(actions)?{ ????????????instance?=?(Action)?actions.get(className); ????????????if?(instance?!=?null)?{?? ????????????????return?(instance); ????????????} ????????????try?{ ????????????????instance?=?(Action)?RequestUtils.applicationInstance(className); ????????????}?catch?(Exception?e)?{?? ????????????????return?(null); ????????????} ????????????actions.put(className,?instance); ????????} ????????if?(instance.getServlet()?==?null)?{ ????????????instance.setServlet(this.servlet); ????????} ????????return?(instance); ????} --------------------------------------------------------------------------------------------------------------------------------- @@、processActionPerform()---->調用processActionPerform()把request,response,actionform,actionmapping參數注入action對象的execte方法.創建action對象成功則執行ActionForward?forward?=?processActionPerform(request,?response,?action,?form,?mapping);其實質是調用execute方法并注入requst,rresponse,actionform,mapping參數并返回ActionFword的轉向信息。
protected ActionForward?processActionPerform(HttpServletRequest request,HttpServletResponse ? ? ? ? ? ?response,Action action,ActionForm form,ActionMapping mapping)throws IOException, ServletException {
????????try {
????????????return (action.execute(mapping, form, request, response));
????????} catch (Exception e) {
????????????return (processException(request, response,
?????????????????????????????????????e, form, mapping));
????????}
????}
--------------------------------------------------------------------- @@、processForwardConfig()--->執行execte方法后,返回的是ActionForward對象(封裝了轉向信息和轉向方式),根據配置文件的forward標簽里的name的值拿和path值注入actionforward對象,返回給actionservlet,actionservlet對actionforward進行分析(不寫redirect則默認服務器跳轉,否則是客戶端跳轉)轉向結果頁面protected void processForwardConfig(HttpServletRequest request,
????HttpServletResponse response,ForwardConfig forward)throws IOException, ServletException {
if (forward == null) { return;}
String forwardPath = forward.getPath();
String uri = null;
uri = forwardPath;
if (forward.getRedirect())?//如果為重定向
{
response.sendRedirect(?uri);//客戶端跳轉
} else {
?doForward(uri, request, response);?//服務端端跳轉
????????}
}
protected void doForward(
????????String uri,
????????HttpServletRequest request,
????????HttpServletResponse response)
????????throws IOException, ServletException {
RequestDispatcher rd = getServletContext().getRequestDispatcher(uri);
rd.forward(request, response);
}轉載于:https://www.cnblogs.com/xwlhyy1072552712/p/5820278.html
總結
以上是生活随笔為你收集整理的Struts流程分析+源码分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: zabbix3.0.4 部署之一 (简介
- 下一篇: tar 压缩去除目录