/**
* <p>
* Process an <code>HttpServletRequest</code> and create the corresponding
* <code>HttpServletResponse</code>.
* </p>
*
* @param request
* The servlet request we are processing
* @param response
* The servlet response we are creating
*
* @exception IOException
* if an input/output error occurs
* @exception ServletException
* if a processing exception occurs
*/
public void process(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
/*
* 如果request请求是POST方法并且contentType为"multipart/form-data",则标准request将被转换成
* org.apache.struts.upload.MultipartRequestWrapper.它是HttpServletRequest的一个子类,然后
* 返回MultipartRequestWrapper;如果request请求是GET方法或contentType不是"multipart/form-data",
* 则传入的request被原样返回.
*/
request = processMultipart(request);
/*
* 获取request的路径信息.用于选取合适的action.
*/
String path = processPath(request, response);
if (path == null) {
return;
}
if (log.isDebugEnabled()) {
log.debug("Processing a '" + request.getMethod() + "' for path '"
+ path + "'");
}
/*
* 根据<controller>元素的locale属性配置,决定是否将一个Locale对象保存到用户的HttpSession中.
*/
processLocale(request, response);
// Set the content type and no-caching headers if requested
// 确定contentType,预设是 text/html
processContent(request, response);
// 判断<controller>属性nocache是否被设定
// 若是,在 response 中加入header参数,包括Pragma, Cache-Control, and
// Expires以防止浏览器网页被快取
processNoCache(request, response);
/*
* processPreprocess(request, response)前置处理,预设返回
* true,子类可以重新定义它以决定要不要继续处理下面的代码
* 因为此方法在Action被调用前执行,所以比较适合在此处检查用户session里是否含有合适的session值,
* 如果此方法返回true,则继续执行,否则终止process()
*/
if (!processPreprocess(request, response)) {
return;
}
/*
* 從URI路徑確定ActionMapping 如果没有找到ActionMapping,则一个错误的response将被返回
*/
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;
}
/*
* 处理ActionForm,如果没有就新增一个,之后一直使用它 Call the processActionForm() method to
* determine if an ActionForm is configured for the ActionMapping. If an
* ActionForm has been configured for the mapping, an attempt will be
* made to find an existing instance in the appropriate scope. Once an
* ActionForm is either found or created, it will be stored within the
* proper scope using a key that is configured in the name attribute for
* the mapping. If a new ActionForm instance needs to be created, the
* reset() method will be called on it.
*/
ActionForm form = processActionForm(request, response, mapping);
// 将表单的域值填入ActionForm
processPopulate(request, response, form, mapping);
/*
* The processValidate() method is called and if an ActionForm has been
* configured and if the validate attribute is set to true for the
* mapping, then call the validate() method on the ActionForm. If the
* validate() method detects errors, it will store an ActionErrors
* object into the request scope and the request is automatically
* forwarded to the resource specified by the input attribute for the
* mapping. If no errors were detected from the validate() method or
* there wasn’t an ActionForm for the mapping, processing of the request
* will continue.
*/
if (!processValidate(request, response, form, mapping)) {
return;
}
/*
* 判断 <action> 卷标的 forward 或 include 卷标是不是被设定 这两个卷标在设定一个路径,其与 type
* 属性是互斥的,当设定 其中一个属性时,调用 RequestDispatcher 的 forward() 或 include()
* ,其作用与设定ForwardAction或IncludeAction相同 直接绕送而不再使用Action对象进行接下来的处理
*/
if (!processForward(request, response, mapping)) {
return;
}
if (!processInclude(request, response, mapping)) {
return;
}
// 处理Action,如果没有就生成一个,之后一直使用它
Action action = processActionCreate(request, response, mapping);
if (action == null) {
return;
}
// 呼叫Action的execute()或perform()方法,并返回ActionForward
ActionForward forward = processActionPerform(request, response, action,
form, mapping);
// 跳转到processActionPerform()方法返回的ActionForward
processForwardConfig(request, response, forward);
}
评论