/** * <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); }

评论