ActionServlet通过调用process方法处理http请求,具体声明如下:
protected void process(HttpServletRequest request,HttpServletResponse response)
throws IOException, ServletException:
该方法主要调用了两个方法,RequestUtils.selectModule(request, getServletContext()); 和
getRequestProcessor(getModuleConfig(request)).process(request, response);
下面分别介绍:
1. RequestUtils.selectModule(request, getServletContext()):
该方法主要是通过截取request的ServletPath的路径,并在ServletContext中查找所有已经配置的子模块(即:prefix不是空字符串””的所有的ModuleConfigImpl)中的prefix是否有与截取的ServletPath路径相等的,如果存在则返回该子模块的prefix,否则返回默认模块的prefix,即空字符串””;代码如下:
String prefix = ""; // Initialize prefix before we try lookup
String prefixes[] = getModulePrefixes(context); // Get all other possible prefixes
int lastSlash = 0; // Initialize before loop
/* 如果当前请求的ServletPath匹配到某个特定的前缀,则会选定该前缀模块;
* 否则选定默认模块 */
while (prefix.equals("") && ((lastSlash = matchPath.lastIndexOf("/")) > 0)) {
// We may be in a non-default module. Try to get it's prefix.
matchPath = matchPath.substring(0, lastSlash);
// Match against the list of module prefixes
for (int i = 0; i < prefixes.length; i++) {
if (matchPath.equals(prefixes[i])) {
prefix = prefixes[i];
break;
}
}
}
return prefix;
确定ModuleConfigImpl对象后,将该对象以及相应的消息资源对象放进request的属性中,代码如下:
ModuleConfig config = (ModuleConfig) context.getAttribute(Globals.MODULE_KEY + prefix);
if (config != null) {
request.setAttribute(Globals.MODULE_KEY, config);
} else {
request.removeAttribute(Globals.MODULE_KEY);
}
MessageResources resources =
(MessageResources) context.getAttribute(Globals.MESSAGES_KEY + prefix);
if (resources != null) {
request.setAttribute(Globals.MESSAGES_KEY, resources);
} else {
request.removeAttribute(Globals.MESSAGES_KEY);
}
2. getRequestProcessor(getModuleConfig(request)).process(request, response):
该方法主要是调用了RequestProcessor类的
public void process(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException 方法,该方法的主要流程如下:
2.1 request = processMultipart(request);判断参数request是否是multipart,如果是则将request封装成MultipartRequestWrapper类,否则直接返回request;
2.2 String path = processPath(request, response);获取当前请求的path,以便用来匹配当前ModuleConfigImpl的action标记;
2.3 processLocale(request, response);将request的Locale放进Session变量中;
2.4 processContent(request, response);将response的content type 设置为配置文件中controller标记中的contentType属性的设置值,默认为”text/html”;
2.5 processNoCache(request, response);如果controller标记的nocache属性设置为true,则设置response不缓存,默认设置为false;
2.6 ActionMapping mapping = processMapping(request, response, path);查找该ModuleConfigImpl对象中对应该path的ActionMapping对象,如果找不到则查找默认的ActionMapping,即unknown属性为true的ActionMapping;
2.7 processRoles(request, response, mapping);JAAS相关
2.8 ActionForm form = processActionForm(request, response, mapping);该方法主要根据mapping的attribute属性或name属性查找request或session(根据mapping的scope属性决定)的属性中是否已经存在该ActionForm对象,如果存在则直接返回,否则根据mapping的attribute或name属性值查找ModuleConfigImpl的FormBeanConfig对象,然后根据FormBeanConfig对象的type属性值动态创建一个ActionForm实例;
2.9 processPopulate(request, response, form, mapping);此步主要是根据表单的输入参数对ActionForm进行属性赋值,其中ActionForm的属性名称与表单参数名称截去ActionMapping的prefix和suffix的属性值标示的前缀和后缀后的字符串一致;利用表单进行上传(即request的content type属性以multipart/form-data开头)的情况以后详述;
2.10 processValidate(request, response, form, mapping);该方法主要通过调用ActionForm的form.validate(mapping, request)方法,如果返回结果不为null,则将跳转到mapping的input属性标记的uri,如果此时未标明input属性则出错;执行ActionForm的validate方法的前提是mapping的validate属性为true,否则将不检验;
2.11 processForward(request, response, mapping);如果mapping的forward属性不为null,则将请求和相应转发到mapping的forward属性表示的uri处理,并返回;
2.12 processInclude(request, response, mapping); 如果mapping的include属性不为null,则将请求和相应转发到mapping的include属性表示的uri处理,并返回;
2.13 Action action = processActionCreate(request, response, mapping);根据mapping的type属性值在一个HashMap变量中查找相应的对象实例,如果不存在则动态创建并存入HashMap变量以提高以后的读取效率;
2.14 ActionForward forward =processActionPerform( request, response, action, form, mapping);
该方法主要是执行action的execute方法,并将该方法返回的ActionForward对象获取下一步的forward;
2.15 processForwardConfig(request, response, forward);该方法主要是将请求和响应转发给forward的path属性标示的uri处理;