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. git操作详解

    前言:一般公司git的master主干与线上代码保持一致,在使用git的时候,偶尔会发生一些莫名其妙的事情,很容易导致运营事故.so- 总结一下经常使用的git命令以及git的一些小坑,方便日后查阅 ...

  2. Java日期格式化方法

    首先获取当前系统时间的方法有两种:第一种可以用currentTimeMillis()方法获取,它其实产生的是一个当前的毫秒数,这个毫秒是自1970年1月1日0时起至现在的毫秒数,类型是long 型,可 ...

  3. VB中的GDI编程-1 设备环境DC

    p{ font-size: 15px; } .alexrootdiv>div{ background: #eeeeee; border: 1px solid #aaa; width: 99%; ...

  4. ORACLE JOB创建

    Connected Connected as focususer SQL> SQL> --JOB 需要在命令行执行: SQL> --抽数job SQL> CREATE OR R ...

  5. JAVA加密算法系列-DESCoder

    package ***; import java.security.Key; import java.security.SecureRandom; import javax.crypto.Cipher ...

  6. 打印pid,写着玩。

    #include <stdio.h> #include <string.h> #include <dirent.h> #include <limits.h&g ...

  7. 《Python基础教程》第2章读书笔记(1)

    # -*- coding:utf-8 -*- #最基本的数据结构:序列,索引从0开始 #python包括6种内建的序列 #最常用的序列包括:列表,元祖 #列表 edward = ['Edward Gu ...

  8. JS弹出框

    一.JS三种最常见的对话框 1.alert()警告框      alert是警告框,只有一个按钮"确定"无返回值,警告框经常用于确保用户可以得到某些信息.当警告框出现后,用户需要点 ...

  9. 基于MVC和Bootstrap的权限框架解决方案 一.搭建HTML

    因为某些原因,因为需要,最新要做一套客户管理系统,但是不满足于仅有的框架. 看了很多大牛写的框架,强大是强大,代码也太TM多了,乱七八糟话不多说,开始吧 随便在网上找到一套好看的HTML,看起来还不错 ...

  10. JAVA----类的继承1(extends)

    要学习类的继承,首先应当理解继承的含义: 来自新华词典的释义: ①依法承受(死者的遗产等):-权ㄧ-人. ②泛指把前人的作风.文化.知识等接受过来:-优良传统ㄧ-文化遗产. ③后人继续做前人遗留下来的 ...