上篇讲了Tomcat实例化一个单例的ActionServlet。依据web.xml配置文件做好对应的初始化工作。

这时client产生一个.do结尾的request请求,採用get/post方式提交之后。不论哪种方式提交,都会进入到process核心方法中。

ActionServelt

 doGet()和doPost()方法

      public void <strong>doGet</strong>(HttpServletRequest request,	HttpServletResponse response)
throws IOException, ServletException { <strong>process</strong>(request, response); } public void <strong>doPost</strong>(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException { <strong>process</strong>(request, response); }

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

  这种方法主要有两个作用:

  首先调用org.apache.struts.util.ModuleUtils类的selectModule()方法。这种方法依据请求对象和servletContext选择负责处理当前请求所属的模块。然后把与该模块相关的ModuleConfig和MessageResources对象存储倒request范围中,这使得框架的其余组件能够方便地从request范围中读取这些对象,从而获取应用配置信息和消息资源。

  其次, 实例化RequestProcessor类。然后调用RequestProcessor类的process()方法,来完毕十几的预处理请求操作。

RequestProcessor

 process()方法

public void process(HttpServletRequest request,                        HttpServletResponse response)
throws IOException, ServletException { // Wrap multipart requests with a special wrapper
request = processMultipart(request); // Identify the path component we will use to select a mapping
String path = processPath(request, response);
if (path == null) {
return;
} if (log.isDebugEnabled()) {
log.debug("Processing a '" + request.getMethod() +
"' for path '" + path + "'");
} // Select a Locale for the current user if requested
processLocale(request, response); // Set the content type and no-caching headers if requested
processContent(request, response);
processNoCache(request, response); // General purpose preprocessing hook
if (!processPreprocess(request, response)) {
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); }

依照process()方法的运行流程,

  一、processMultipart();

   1、首先推断是否为post方式。假设不是post方式,则肯定不是上传请求。则直接返回request对象

	if (!"POST".equalsIgnoreCase(request.getMethod())) {
return (request); }

   2、获取request对象的ContentType,假设ContentType为multipart/form-datade 话则 new 一个 MultipartRequestWrapper 对象返回。

否则直接返回request。

 String contentType = request.getContentType();        if ((contentType != null)
&& contentType.startsWith("multipart/form-data")) {
return (new MultipartRequestWrapper(request));
} else {
return (request);
}

   这里简答的来说,是用来推断是否有上传功能的需求。假设有上传功能的需求。那么必须把form的contentType改为multipart/form-data。而这种方法就是来解析并打包成一个实现HttpServletRequest的包,为上传文件服务的。

  二、 processPath()

        String path = processPath(request, response);
if (path == null) {
return;
}
if (log.isDebugEnabled()) {
log.debug("Processing a '" + request.getMethod() +
"' for path '" + path + "'");
}

   通过调用processPath方法。获得訪问的详细action的名字

  三、processLocale()

protected void processLocale(HttpServletRequest request,HttpServletResponse response) {

	        // Are we configured to select the Locale automatically?

if (!moduleConfig.getControllerConfig().getLocale()) {
return;
}
// Has a Locale already been selected?
HttpSession session = request.getSession();
if (session.getAttribute(Globals.LOCALE_KEY) != null) {
return;
}
// Use the Locale returned by the servlet container (if any)
Locale locale = request.getLocale();
if (locale != null) {
if (log.isDebugEnabled()) {
log.debug(" Setting user locale '" + locale + "'");
}
session.setAttribute(Globals.LOCALE_KEY, locale);
}
}

   

   是本地服务还是国际化服务,这是依据浏览器的设置的(确切的说是依据操作系统设置的)

  四、processContent();processNoCache();

   当中processContent用来确定内容类型和编码类型

   processNoCache依据配置文件里的配置属性来确定某些内容是否进行缓存

  五、 processMapping()

   依据request。response和action的名字去Struts.config.xml中获取相应的actionmapping,也就是将我们配置好的request要请求的action放入到ActionMapping对象中去。

  1、首先去配置文件中找对应的配置信息

// Is there a mapping for this path?

ActionMapping mapping = (ActionMapping) moduleConfig.findActionConfig(path);

  2、假设有配置则把它放入request。并返回。

        // If a mapping is found, put it in the request and return it
if (mapping != null) {
request.setAttribute(Globals.MAPPING_KEY, mapping);
return (mapping);
}

  3、找到“未知的映射路径(假设有的话)”。相同找到了就放到request里并返回他。

        // Locate the mapping for unknown paths (if any)
ActionConfig[] configs = moduleConfig.findActionConfigs();
for (int i = 0; i < configs.length; i++) {
if (configs[i].getUnknown()) {
mapping = (ActionMapping) configs[i];
request.setAttribute(Globals.MAPPING_KEY, mapping);
return (mapping);
} }

  4、假设还是没有找到mapping信息则发送错误消息。并返回null

        // No mapping can be found to process this request
String msg = getInternal().getMessage("processInvalid");
log.error(msg + " " + path);
response.sendError(HttpServletResponse.SC_NOT_FOUND, msg); return null;

  此时。ActionMapping元素包括了如Action类的名称及在请求中用到的ActionForm的信息,另外还有配置在当前ActionMapping的里的ActionForwards信息。

  六、processActionForm()

	 protected ActionForm processActionForm(HttpServletRequest request,
HttpServletResponse response,
ActionMapping mapping) { // Create (if necessary) a form bean to use
ActionForm instance = RequestUtils.createActionForm
(request, mapping, moduleConfig, servlet);
if (instance == null) {
return (null);
} // Store the new instance in the appropriate scope
if (log.isDebugEnabled()) {
log.debug(" Storing ActionForm bean instance in scope '" +
mapping.getScope() + "' under attribute key '" +
mapping.getAttribute() + "'");
}
if ("request".equals(mapping.getScope())) {
request.setAttribute(mapping.getAttribute(), instance);
} else {
HttpSession session = request.getSession();
session.setAttribute(mapping.getAttribute(), instance);
}
return (instance); }

   查看mapping里是否配置name属性或attribute属性来指定ActionForm,假设配置了ActionForm就到session或是Request中进行查找,查到后进行返回;假设没有找到。依据ActionForm的路径进行创建并放入到scope域中。

  七、processPopulate()

 protected void processPopulate(HttpServletRequest request,
HttpServletResponse response,
ActionForm form,
ActionMapping mapping)
throws ServletException { if (form == null) {
return;
}
// Populate the bean properties of this ActionForm instance
if (log.isDebugEnabled()) {
log.debug(" Populating bean properties from this request");
}
form.setServlet(this.servlet);
form.reset(mapping, request); if (mapping.getMultipartClass() != null) {
request.setAttribute(Globals.MULTIPART_KEY,
mapping.getMultipartClass());
}
RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(),
request); // Set the cancellation request attribute if appropriate
if ((request.getParameter(Constants.CANCEL_PROPERTY) != null) ||
(request.getParameter(Constants.CANCEL_PROPERTY_X) != null)) {
request.setAttribute(Globals.CANCEL_KEY, Boolean.TRUE);
}
}

   这种方法主要是用来为ActionForm 填充数据,运行ActionForm的reset重置方法,之后获取到表单全部输入域的名称。依据request.getParameter获取输入域名称所相应的值,然后将输入域名称和值以键值对形式放入到map中,之后调用一个比較重要的第三方组件BeanUtils来实现属性的转换和拷贝到详细的ActionForm中

  八、processValidate()

   验证表单数据合法性,这个可用可不用的。假设使用了Struts的验证,这里会自己主动的运行该方法进行验证。

  九、processForward()

   处理mapping指定的forward 和 include,Struts检查<action>元素的forward和include属性的值。假如有配置。则把forward和include 请求放在配置的页面内,之后转发到详细的ActionServlet中进行详细业务逻辑的处理。

小结

  至此,RequestProcessor的核心方法process运行完成。之后会到详细的Action中运行业务相关的操作。

纵观整个运行流程,其基本的方法无外乎两个,一个是AcionServlet中的process方法,还有一个是RequestProcessor的process()方法,至于其它的截取请求路径,填充actionForm。国际化等方法也都被用于外观模式封装在了process方法中。

SSH框架之Struts(3)——Struts的执行流程之核心方法的更多相关文章

  1. 利用SSH框架开发时遇到的各种Bug及解决方法

    .hibernate自动生成的配置文件 hibernate.cfg.xml 有时候是有问题的,会出现 org.hibernate.HibernateException: Could not parse ...

  2. SSH框架之Struts(4)——Struts查漏补缺BeanUtils在Struts1中

    在上篇博客SSH框架之Struts(3)--Struts的执行流程之核心方法,我们提到RequestProcessor中的processPopulate()是用来为为ActionForm 填充数据.它 ...

  3. SSH 框架学习之初识Java中的Action、Dao、Service、Model-收藏

    SSH 框架学习之初识Java中的Action.Dao.Service.Model-----------------------------学到就要查,自己动手动脑!!!   基础知识目前不够,有感性 ...

  4. 用一天的时间学习Java EE中的SSH框架

    首先说明一下,本人目前主要从事.NET领域的工作,但对于C++.Java.OC等语言也略知一二,周末闲来无事,特花费一天的时间学习了一下Java中的SSH框架,希望把学习过程中的心得体会与园友们进行分 ...

  5. 说说你对用SSH框架进行开发的理解

    SSH框架指的是Struts,Spring,Hibernate.其中,Struts主要用于流程控制:Spring的控制反转能祈祷解耦合的作用:Hibernate主要用于数据持久化.

  6. SSM框架和SSH框架的区别

    SSH和SSM定义 SSH 通常指的是 Struts2 做控制器(controller),spring 管理各层的组件,hibernate 负责持久化层. SSM 则指的是 SpringMVC 做控制 ...

  7. 基于SSH框架开发的《高校大学生选课系统》的质量属性的实现

    基于SSH框架开发的<高校大学生选课系统>的质量属性的实现 对于可用性采取的是错误预防战术,即阻止错误演变为故障:在本系统主要体现在以下两个方面:(1)对于学生登录模块,由于初次登陆,学生 ...

  8. SSH框架分模块开发

    ------------------siwuxie095 SSH 框架分模块开发 1.在 Spring 核心配置文件中配置多个内容,容易造成 配置混乱,不利于维护 「分模块开发主要针对 Spring ...

  9. javaWeb项目(SSH框架+AJAX+百度地图API+Oracle数据库+MyEclipse+Tomcat)之一 基础Struts框架搭建篇

    即将开始着手写这个项目,所以希望通过这篇博客来记录自己学习的过程 今天开学第一天,就上了软件工程实践课,自己也开始着手做这个大作业了.首先我的项目名称叫做智能班车管理系统. 项目的概况: 该软件产品是 ...

随机推荐

  1. [Swift通天遁地]九、拔剑吧-(10)快速创建美观的聊天界面:可发送文字、表情、图片

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  2. Spring.net(v1.3.2) 官网API-第一章 前言

    虽然有很好的工具和技术,但是开发软件应用仍然是很困难的.Spring为构建企业级应用提供了一个轻量级的解决方案,Spring提供了一个统一的.透明的方式去配置你的应用,和将AOP集成到你的软件中.Sp ...

  3. ios9-NSLayoutAnchor和UILayoutGuide实现自动布局

    @interface ViewController () { NSLayoutConstraint *yellowViewTopConstraint; NSLayoutConstraint *blue ...

  4. js indexOf 列表筛选

    先来一堆效果图:  代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...

  5. CNN结构:色彩特征提取-从RGB空间到HSV空间(色彩冷暖判断)

      转自知乎和百度百科:从零开始学后期             文章: 冷暖色区分?冷暖肤色适用于那些色系的彩妆?    文章:干货 |如何判断人体色冷暖?如何判断色彩冷暖?(值得收藏研读!) -蒜苗 ...

  6. jstree CHECKBOX PLUGIN

    The checkbox plugin makes multiselection possible using three-state checkboxes. Configuration overri ...

  7. 深入理解Three.js(WebGL)贴图(纹理映射)和UV映射

    本文将详细描述如何使用Three.js给3D对象添加贴图(Texture Map,也译作纹理映射,“贴图”的翻译要更直观,而“纹理映射”更准确.).为了能够查看在线演示效果,你需要有一个兼容WebGL ...

  8. NFS指定端口,NFS缓存(转载)

    nfs服务端: #编辑/etc/nfsmount.conf,在末尾添加: #RQUOTAD_PORT=30001#LOCKD_TCPPORT=30002#LOCKD_UDPPORT=30002#MOU ...

  9. Java对象的创建及使用

    Java对象的创建及使用 对象是类的具体实例(instance),是真实存在的个体:

  10. redis在linux下安装以及扩展

    安装过redis后发现回头忘了,今天重新安装记录下 首先 我是在home下创建redis文件   mkdir  redis 然后直接用wget安装 wget http://download.redis ...