Struts1的处理流程
本文从收到一个请求开始讲述,忽略之前的filter等工作.
处理工作的主要承担者为RequestProcessor
1.处理请求的url. RequestProcessor.processPath(request,response)
String path = processPath(request, response);
1 protected String processPath(HttpServletRequest request, 2 HttpServletResponse response) 3 throws IOException { 4 5 String path = null; 6 7 // For prefix matching, match on the path info (if any) 8 path = (String) request.getAttribute(INCLUDE_PATH_INFO); 9 if (path == null) { 10 path = request.getPathInfo(); 11 } 12 if ((path != null) && (path.length() > 0)) { 13 return (path); 14 } 15 16 // For extension matching, strip the module prefix and extension 17 path = (String) request.getAttribute(INCLUDE_SERVLET_PATH); 18 if (path == null) { 19 path = request.getServletPath(); 20 } 21 String prefix = moduleConfig.getPrefix(); 22 if (!path.startsWith(prefix)) { 23 String msg = getInternal().getMessage("processPath"); 24 25 log.error(msg + " " + request.getRequestURI()); 26 response.sendError(HttpServletResponse.SC_BAD_REQUEST, msg); 27 28 return null; 29 } 30 31 path = path.substring(prefix.length()); 32 int slash = path.lastIndexOf("/"); 33 int period = path.lastIndexOf("."); 34 if ((period >= 0) && (period > slash)) { 35 path = path.substring(0, period); 36 } 37 return (path); 38 39 }
从request中获取请求的url.path = request.getPathInfo();
在对获取的path进行处理:
1 path = path.substring(prefix.length()); 2 int slash = path.lastIndexOf("/"); 3 int period = path.lastIndexOf("."); 4 if ((period >= 0) && (period > slash)) { 5 path = path.substring(0, period); 6 } 7 return (path);
2.根据获取的url-path来构建ActionMapping
ActionMapping mapping = processMapping(request, response, path);
1 protected ActionMapping processMapping(HttpServletRequest request, 2 HttpServletResponse response, 3 String path) 4 throws IOException { 5 6 // Is there a mapping for this path? 7 ActionMapping mapping = (ActionMapping) 8 moduleConfig.findActionConfig(path); 9 10 // If a mapping is found, put it in the request and return it 11 if (mapping != null) { 12 request.setAttribute(Globals.MAPPING_KEY, mapping); 13 return (mapping); 14 } 15 16 // Locate the mapping for unknown paths (if any) 17 ActionConfig configs[] = moduleConfig.findActionConfigs(); 18 for (int i = 0; i < configs.length; i++) { 19 if (configs[i].getUnknown()) { 20 mapping = (ActionMapping) configs[i]; 21 request.setAttribute(Globals.MAPPING_KEY, mapping); 22 return (mapping); 23 } 24 } 25 26 // No mapping can be found to process this request 27 String msg = getInternal().getMessage("processInvalid"); 28 log.error(msg + " " + path); 29 response.sendError(HttpServletResponse.SC_NOT_FOUND, msg); 30 31 return null; 32 }
这个过程主要是从struts-config.xml中读取<action-mapping>结点的action信息,将所有的<action>结点保存到ActionMapping中.
3.获取ActionForm,
ActionForm form = processActionForm(request, response, mapping);
上一步通过url已经定位到了相应的action,然后通过 String name = mapping.getName(); 获取actionform(该项在<form-beans>中获取),同时设置该action的作用域(request/session默认session).再将创建号的actionform放到request/session中.
4.从actionform中获取相应的值,完成相应数据的赋值,这其中包括类型的转换,使用了第三方的工具类BeanUtils.
5.创建相应的action
protected Action processActionCreate(HttpServletRequest request,HttpServletResponse response,ActionMapping mapping)
actionform信息存在于actionmapping中。首先根据action类的完整名称(<action>标签下面的type),如果已经存在直接返回;否则再使用反射机制创建action。
6.最终执行action的execute方法。
ActionForward forward =processActionPerform(request, response,action, form, mapping);
从中执行action的execute方法,返回actinforward,再根据返回的actionforward来实现转发/转向。
具体的处理流程如下图:
附件一 struts-config.xml
<struts-config> <form-beans> <form-bean name="loginactionform" type="com.volshell.actionform.LoginActionForm"/> </form-beans> <action-mappings> <action path="/login" name="loginactionform" type="com.volshell.action.LoginAction" scope="request"> <forward name="error" path="/login_fail.jsp"></forward> <forward name="success" path="/login_success.jsp"></forward> </action> </action-mappings> </struts-config>