Struts流程分析+源码分析

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

}

 
 
 
 
上一篇:深入浅出Mybatis系列(九)---强大的动态SQL


下一篇:深入浅出Mybatis系列十-SQL执行流程分析(源码篇)