1、初始化工作
读取配置---转换器-----读取插件
当struts-config.xml配置文件加载到内存,则会创建两个map:ActionConfigs,FromBeans。这两个map都交由ModuleConfig对象管理
a、ActionConfigs的Map装载每个Action配置信息---ActionMapping
b、名为FromBeans的map装载FormBean配置信息---FormBeanConfig
 
接收请求ActionServlet的doPost方法进行处理,调用process方法,而process方法会创建RequestProcessor对象并调用其process方法
ActionServlet的doPost方法
 public void doPost(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException {
        process(request, response);
    }
ActionServlet的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);
    }
RequestProcessor对象的process方法,也是整个ActionServlet的整个核心控制流程
 public void process(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException {
        // Identify the path component we will use to select a mapping
        String path = processPath(request, response);
        if (path == null) {
            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);
    }
 
1、struts工作流程:
@@、processPath()-->截取.do前路径
RequestProcessor对象的process方法的调用processPath方法截取.do前路径
源码如下:
String path = processPath(request, response);
 

http://127.0.0.1:8080/struts_login/login.do?

username="admin"&password="admin"

path = request.getServletPath();

path=/login.do?username="admin"&password="admin"

int slash = path.lastIndexOf("/");

slash =0;

int period = path.lastIndexOf(".");

period=6;

if ((period >= 0) && (period > slash)) {

path = path.substring(0, period);

path=/login

}

return (path);

--------------------------------------------------------------------

@@、processMapping()-->根据上一步解析的路径,找到请求路径找到在actionConfigs的map里取得所对应的ActionMapping对象
核心源码如下:
protected ActionMapping processMapping(HttpServletRequest request,
        HttpServletResponse response, String path)
        throws IOException {
        // Is there a mapping for this path?
        ActionMapping mapping =
            (ActionMapping) moduleConfig.findActionConfig(path);
 
        // If a mapping is found, put it in the request and return it
        if (mapping != null) {
            request.setAttribute(Globals.MAPPING_KEY, mapping);
 
            return (mapping);
        }

<action-mappings>

<action path="/login"

type="com.struts.LoginAction"

name="loginForm"

scope="request"

validate="true"

>

<forward name="success" path="/login_success.jsp"/>

<forward name="error" path="/login_error.jsp"/>

</action>

</action-mappings>

---------------------------------------------------------------------

@@、processActionForm()--->根据解析action配置的name值找是否scope所对应的域里是否有该请求对应的actionfrom对象,没有则根据actionfrom配置的type的值反射创建actionFrom对象并存入request

protected ActionForm processActionForm(HttpServletRequest request,HttpServletResponse response, ActionMapping mapping) {

ActionForm instance = RequestUtils.createActionForm

(request, mapping, moduleConfig, servlet);

if (instance == null) {

return (null);

}

if ("request".equals(mapping.getScope())) {

request.setAttribute(mapping.getAttribute(), instance);

} else {

HttpSession session = request.getSession();

session.setAttribute(mapping.getAttribute(), instance);

}

return (instance);

}

public static ActionForm createActionForm(HttpServletRequest request,ActionMapping mapping, ModuleConfig moduleConfig,ActionServlet servlet) {

String attribute = mapping.getAttribute();

if (attribute == null) {

return (null);

}

String name = mapping.getName();

//到formBeans的Map中取得FormBeanConfig对象

FormBeanConfig config = moduleConfig.findFormBeanConfig(name);

if (config == null) {return (null);}

ActionForm instance = lookupActionForm(request, attribute, mapping.getScope());

try {if (instance != null ) {return (instance); }

return createActionForm(config, servlet);

}

private static ActionForm lookupActionForm(HttpServletRequest request, String attribute, String scope)

{// Look up any existing form bean instance

ActionForm instance = null;

HttpSession session = null;

if ("request".equals(scope)) {

instance = (ActionForm) request.getAttribute(attribute);

} else {

session = request.getSession();

instance = (ActionForm) session.getAttribute(attribute);

}

return (instance);

}

-------------------------------------------------------------------------------------------------------------------------------

@@、processPopulate()-->从request里拿出name值所对应的actionform并根据actionform配置自动收集请求参数到对象并存入request里

protected void processPopulate(HttpServletRequest req,HttpServletResponse response,

ActionForm form,

ActionMapping mapping)

throws ServletException {

if (form == null) {

return;

}

form.reset(mapping, request);//收集表单数据前对 表单bean的属性初始化

RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(),

request);

RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(),request);

public static void populate(Object bean,String prefix,String suffix,HttpServletRequest request)

throws ServletException {

HashMap properties = new HashMap();

Enumeration names = null;

names = request.getParameterNames();

while (names.hasMoreElements()) {

String name = (String) names.nextElement();

String stripped = name;

Object parameterValue = null;

parameterValue = request.getParameterValues(na

me);

properties.put(stripped, parameterValue);

}

BeanUtils.populate(bean, properties);

}

public static void populate(Object bean, Map properties)

throws IllegalAccessException, InvocationTargetException {

if ((bean == null) || (properties == null)) {

return;

}

Iterator names = properties.keySet().iterator();

while (names.hasNext()) {

String name = (String)

 

names.next();

Object value = properties.get(name);

setProperty(bean, name, value);

//收集表单数据后对表单bean的属性值进行验证

if (!processValidate(request, response, form, mapping)) {

return;

}

-------------------------------------------------------------------------

 
@@、processActionCreate()--->根据action配置type的值创建action对象.
 

processActionCreate创建action对象(这里actions是HashMap对象,用map实现创建action对象是单例,而且在创建的过程是加锁防止多个线程在用一个时刻访问同一个action请求)

源码如下:

 
protected Action processActionCreate(HttpServletRequest request,
        HttpServletResponse response, ActionMapping mapping)
        throws IOException {
        //通过maping对象获取action的类型(全类名用于反射创建对象)
        String className = mapping.getType();
        Action instance;
        //在创建action的过程中加锁确保线程同步
        synchronized (actions) {
            instance = (Action) actions.get(className);
            if (instance != null) {  
                return (instance);
            }
            try {
                instance = (Action) RequestUtils.applicationInstance(className);
            } catch (Exception e) {  
                return (null);
            }
            actions.put(className, instance);
        }
        if (instance.getServlet() == null) {
            instance.setServlet(this.servlet);
        }
        return (instance);
    }
 
---------------------------------------------------------------------------------------------------------------------------------
 

@@、processActionPerform()---->调用processActionPerform()把request,response,actionform,actionmapping参数注入action对象的execte方法.创建action对象成功则执行ActionForward forward = processActionPerform(request, response, action, form, mapping);其实质是调用execute方法并注入requst,rresponse,actionform,mapping参数并返回ActionFword的转向信息。

protected ActionForward processActionPerform(HttpServletRequest request,HttpServletResponse            response,Action action,ActionForm form,ActionMapping mapping)throws IOException, ServletException {

try {

return (action.execute(mapping, form, request, response));

} catch (Exception e) {

return (processException(request, response,

e, form, mapping));

}

}

---------------------------------------------------------------------

@@、processForwardConfig()--->执行execte方法后,返回的是ActionForward对象(封装了转向信息和转向方式),根据配置文件的forward标签里的name的值拿和path值注入actionforward对象,返回给actionservlet,actionservlet对actionforward进行分析(不写redirect则默认服务器跳转,否则是客户端跳转)转向结果页面

protected void processForwardConfig(HttpServletRequest request,

HttpServletResponse response,ForwardConfig forward)throws IOException, ServletException {

if (forward == null) { return;}

String forwardPath = forward.getPath();

String uri = null;

uri = forwardPath;

if (forward.getRedirect()) //如果为重定向

{

response.sendRedirect( uri);//客户端跳转

} else {

doForward(uri, request, response); //服务端端跳转

}

}

protected void doForward(

String uri,

HttpServletRequest request,

HttpServletResponse response)

throws IOException, ServletException {

RequestDispatcher rd = getServletContext().getRequestDispatcher(uri);

rd.forward(request, response);

}

 
 
 
 

Struts流程分析+源码分析的更多相关文章

  1. SpringMVC执行流程及源码分析

    SpringMVC流程及源码分析 前言 ​ 学了一遍SpringMVC以后,想着做一个总结,复习一下.复习写下面的总结的时候才发现,其实自己学的并不彻底.牢固.也没有学全,视频跟书本是要结合起来一起, ...

  2. Struts2请求处理流程及源码分析

    1.1 Struts2请求处理 1. 一个请求在Struts2框架中的处理步骤: a) 客户端初始化一个指向Servlet容器的请求: b) 根据Web.xml配置,请求首先经过ActionConte ...

  3. Android应用层View绘制流程与源码分析

    1  背景 还记得前面<Android应用setContentView与LayoutInflater加载解析机制源码分析>这篇文章吗?我们有分析到Activity中界面加载显示的基本流程原 ...

  4. django Rest Framework----APIView 执行流程 APIView 源码分析

    在django—CBV源码分析中,我们是分析的from django.views import View下的执行流程,这篇博客我们介绍django Rest Framework下的APIView的源码 ...

  5. Spring源码分析——源码分析环境搭建

    1.在Windows上安装Gradle gradle工具类似于maven,用于项目的构建,此处主要用于构建spring源码,以便我们将spring源码导入eclipse. 开发环境 Java:JDK8 ...

  6. java 容器(collection)--ArrayList 常用方法分析 源码分析

    ArrayList 介绍 打开jdk源码看看官方文档的介绍 粗糙的翻译下大致意思是: List接口的可调整大小的数组实现.实现了所有可选的列表操作,并允许所有元素,包括 null .除了实现List接 ...

  7. openstack cinder-backup流程与源码分析

    在现在的云计算大数据环境下,备份容灾已经变成了一个炙手可热的话题,今天,和大家一起分享一下openstack是怎么做灾备的. [首先介绍快照] snapshot可以为volume创建快照,快照中保存了 ...

  8. Django 基于类的视图(CBV)执行流程 CBV 源码分析

    一.CBV(基于类的视图) 视图是可以调用的,它接受请求并返回响应,这不仅仅是一个函数,Django提供了一些可以用作视图的类的例子,这些允许您通过继承或mixin来构建视图并重用代码. 基本示例 D ...

  9. Yarn任务提交流程(源码分析)

    关键词:yarn rm mapreduce 提交 Based on Hadoop 2.7.1 JobSubmitter addMRFrameworkToDistributedCache(Configu ...

随机推荐

  1. Appium手势密码滑动之Z字形走势(java篇)

    1.直接使用负的偏移量appium会报错,在后面加上moveto(1,1)就行了 2.直接看图说话 废话少说看代码如: List<AndroidElement> element = dri ...

  2. NPOI扩展--判断指定单元格是否为合并单元格和输出该单元格的行列跨度(维度)

    因工作需要用到跨合并单元格获取数据,所以写了个NPOI扩展类. 主要方法如下: 1.判断指定行/列索引(单元格)是否为合并单元格. 2.获取指定列索引的实际含有数据的单元格. 3.返回指定行/列索引的 ...

  3. [SinGuLaRiTy] 字节大小

    [SinGuLaRiTy-1006] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. 16位编译器 char 1个字节 char*(即指针变量 ...

  4. 老李推荐:第8章5节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-运行测试脚本

    老李推荐:第8章5节<MonkeyRunner源码剖析>MonkeyRunner启动运行过程-运行测试脚本   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化 ...

  5. 老李分享:android手机测试之适配(1)

    Android的屏幕适配一直以来都在折磨着我们这些开发者,本篇文章以Google的官方文档为基础,全面而深入的讲解了Android屏幕适配的原因.重要概念.解决方案及最佳实践,我相信如果你能认真的学习 ...

  6. Vue.js 学习笔记 一

    本文的Demo和源代码已放到GitHub,如果您觉得本篇内容不错,请点个赞,或在GitHub上加个星星! https://github.com/zwl-jasmine95/Vue_test 以下所有知 ...

  7. 整合初步--------->SSH(注解版)

    上面的一篇博客已经介绍了 Spring和Hibernate之间的整合,没看过的童鞋可以去看看,这篇博客讲解Spring+Hibernate+Struts2注解版......... 个人觉得使用注解可能 ...

  8. (iOS)sqlcipher和FMDB的使用总结(原创)

    写这篇文章的原因是之前接触到了关于sqlite数据库加密的问题,一般数据库加密,无非是数据加密和数据库文件加密,当然数据库文件加密对手机效率可能更高一些. 下面就讲一下,自己对sqlcipher和fm ...

  9. ggplot2:分面的介绍

    1.分面 分面是指在一个页面上自动摆放多幅图形的技巧,也就是说可以让不同分类的图同时展示在一张图上,这样方便于数据之间的的比较.ggplot2提供了网格型(facet_grid)和封装型(facet_ ...

  10. C#中的DateTime是值类型还是引用类型

    近期遇到了DateTime到底是值类型还是引用类型的疑惑,顺势较深入地了解一下DateTime相关的内容 结论:DateTime是值类型,因为DateTime是结构体,而结构体继承自Syste.Val ...