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

    }
     
     
     
     
  • 相关阅读:
    hdu 2444 交叉染色判断二分图+二分最大匹配
    uva 交叉染色法10004
    poj 3177&&3352 求边双联通分量,先求桥,然后求分量( 临界表代码)
    poj 3177&&poj 3352加边构双联通(有重边)用tarjan 模板求的
    poj 3006水题打素数表
    POJ 3352 无向图边双连通分量,缩点,无重边
    hdu 1430 魔板 康托展开 + 很好的映射
    D. Artsem and Saunders 数学题
    vijos P1412多人背包 DP的前k优解
    1475 建设国家 DP
  • 原文地址:https://www.cnblogs.com/xwlmdd/p/5820278.html
Copyright © 2020-2023  润新知