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. Android Studio项目构建常见问题解决

    1. 创建或导入项目后编译时一直在等待 问题: 原因:AS连网去下载gradle了,但是网络不好或不通 解决:禁用网络,AS就会立即自动终止下载进入到主界面了.此时再去指定离线的gradle版本进行编 ...

  2. 早期练手:功能相对比较完善的 js 计算器

    第一次发博客,就先发一个自己早期,刚开始学前端时,用js写的一个计算器吧,计算功能比较少,只有 + - * / ,不过其他功能还是比较完善的,比如: 输出结果后,连续按"=",可以 ...

  3. 一步操作配置Word环境

    我们在开始编辑Word文档的时候,会发现有些事情我们总需要预先操作一下,比如100%普通视图.显示隐藏特殊标记.显示标尺.最大化窗口.显示导航窗格啥的,每次去操作,感觉很烦,那么通过下面这个宏代码可以 ...

  4. 老李分享:持续集成学好jenkins之解答疑问

    老李分享:持续集成学好jenkins之解答疑问   poptest(www.poptest.cn)在培训的过程中使用jenkins搭建持续集成环境,让学员真正交流持续集成到底是什么,怎么去做的. Je ...

  5. Java并发编程:Java线程池

    转载自:http://www.cnblogs.com/dolphin0520/p/3932921.html 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题 ...

  6. git clone时出现 error:inflate:data stream error(incorrect data check)

    git clone时出现 error:inflate:data stream error(incorrect data check) fatal:serrious inflate inconsiste ...

  7. Entity Framework快速入门--ModelFirst

    Entity Framework带给我们的不仅仅是操作上的方便,而且使用上也很是考虑了用户的友好交互,EF4.0与vs2010的完美融合也是我们选择它的一个理由吧.相比Nhibernate微软这方面做 ...

  8. 写出稳定的Modbus代码之点滴经验

    1.引言 Modbus是工业领域重要的协议,物理层有常见的RS485双绞线和TCP,所以又常说Modbus 485开发和Modbus TCP开发. 前者就是串口通信,比较简单.后者涉及到网络协议,复杂 ...

  9. 使用mysql索引技巧及注意事项

    一.索引的作用 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,所以查询语句的优化显然是重中之重. 在数据 ...

  10. Java Script 数组操作

    常用几种数组操作方法: concat() join() toString() pop() push() shift() unshift() slice() splice() sort() revers ...