zoukankan      html  css  js  c++  java
  • Struts1 部分源码学习

      Struts1工作原理 
       1.系统初始化(读取配置):初始化ModuleConfig对象 
          Struts框架是一个总控制器(ActionServlet)是一个Servlet,在web.xml中配置成自动启动的Servlet。 
       读取配置文件的配置信息,为不同的struts模块初始化相应的ModuleConfig对象(ActionConfig、 
       ControlConfig、FormBeanConfig、ForwardConfig、MessageResponseConfig)。 
       
       2.发送请求 
       3.填充Form(实例化、复位、填充数据、校验):请求时ActionServlet为我们填充。如果有对应的FormBean实例化并填充http的请求数据,并保存在Servlet Context中(request或session),这样就可以被其他Action或jsp调用。 
       4.派发请求:控制器根据配置信息ActionConfig将请求派发给具体的Action,相应的FormBean一并派发。 
       5.处理业务:Action的execute。 
       6.返回响应:完毕后返回一个ActionForward对象。 
       7.查找响应(翻译响应):总控制器根据Action返回的目标响应对象,查找对应的资源对象。 
       8.响应用户:目标响应对象将结果展现给用户 

    工作流程: 
    jsp请求,服务器servlet mapping(*.do),前端控制器(ActionServlet)响应,封装FormBean,派发请求,Action execute,完毕后返回一个ActionForward对象,查找响应,响应用户


    自己用Struts 写一个登入项目

          类: LoginAction(继承action)

                  LoginActionForm(继承ActionForm)

                  manager(设计成单例 里面写具体的login方法)

           jsp:login (写个表单)

                   success

                   erro

     写完之后 配置struts-config.xml 和 web.xml 如下:

    <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
    </servlet

    <servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*.do</url-pattern>
    </servlet-mapping>

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE struts-config PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
    "http://struts.apache.org/dtds/struts-config_1_3.dtd">
    <struts-config>
    <form-beans>
    <form-bean
    name="LoginActionForm"
    type="com.LoginActionForm"/>

    </form-beans>
    <action-mappings>
    <action
    name="LoginActionForm" path="/login"
    scope="request"
    type="com.LoginAction"
    validate="true" >
    <forward name="success" path="/loginsuccess.jsp"/>
    <forward name="erro" path="/loginerro.jsp"/>
    </action>
    </action-mappings>
    </struts-config>
    /* 令人蛋痛的 Struts配置 第一行 一定是<? xml ?> 。 还有<!DOCTYPE>,一些拼写错写 以及 ">","/>"的问题要小心 */


     接下来就是源码部分一个一个按照上面写的流程来看

    /*

    这个就是初始化

    */

    ModuleConfig

    实现代码:

    public ModuleConfigImpl(String prefix) {

            super();

            this.prefix = prefix;

            this.actionConfigs = new HashMap();

            this.actionConfigList = new ArrayList();

            this.actionFormBeanClass = "org.apache.struts.action.ActionFormBean";

            this.actionMappingClass = "org.apache.struts.action.ActionMapping";

            this.actionForwardClass = "org.apache.struts.action.ActionForward";

            this.configured = false;

            this.controllerConfig = null;

            this.dataSources = new HashMap();

            this.exceptions = new HashMap();

            this.formBeans = new HashMap();

            this.forwards = new HashMap();

            this.messageResources = new HashMap();

            this.plugIns = new ArrayList();

        }

    /*

    用户发送请求

    */

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

    /*

    解析http的内容  将path 封装成对象 读取struts-config xml  

    * /

    1、 String path = processPath(request, response);

     实现代码:

     path = request.getServletPath();

     path =="/login.do"

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

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

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

                path = path.substring(0, period);

            }

            return (path);

    path="/login"

    2、ActionMapping mapping = processMapping(request, response, path);

    实现代码:

    ActionMapping mapping = (ActionMapping)

         moduleConfig.findActionConfig(path);

    从ActionConfigs的MAP中通过path取得对应的ActionMapping对象

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

    在一个web 项目中,每个资源都必须用URL来引用,资源包括:jsp,html,和制定动作。为了给制定动作一个URL,Struts提供了一个ActionMapping对象

    (Struts中,ActionMapping继承自ActionConfig,大部份的属性定义实际上都已经在ActionConfig中完成,不过ActionMapping仍旧存在)。

    当请求的URL是:http://127.0.0.1:8080/struts_login/login.do,则ActionServlet会将path设定为/login,

    然后会根据 /login, 找到xml里的配置信息并读取 ,找到Actionmapping  对象。ActionMapping对象告知ActionServlet要使用“com.struts.LoginAction”,

    而后ActionServlet会将呼叫LoginActionexecute()方法,并将ActionMapping对象当作参数传递给它。 

    并接下来会根据 name=“loginForm”执行如下

    Ps:(ActionServlet实际上将工作交给Action对象,然而Action对象的运作必须提供一些参数来描述工作的细节,诸如使用哪一个ActionFormforward对象的查找、错误发生时的页面对象等等,Struts将这些信息包装在ActionMapping中,并作为参数传送给Action对象,以使得Action在需要相关的信息时可以从ActionMapping中取得。 

     

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

        

    3、ActionForm form = processActionForm(request, response, mapping);

    实现代码:

     ActionForm instance = RequestUtils.createActionForm()//创建ActionForm

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

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

            } else {

                HttpSession session = request.getSession();

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

            }

            return (instance);

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

           1)public static ActionForm createActionForm()  

           实现代码:

           String attribute = mapping.getAttribute();

            if (attribute == null) {

                return (null);

            }

            String name = mapping.getName();

          

         //从<formbeans>中通过name取得对应的FormBeanConfig对象

            FormBeanConfig config = moduleConfig.findFormBeanConfig(name);

            if (config == null) {

                return (null);

          

          // 从Scope中取得ActionForm

          2)ActionForm instance = lookupActionForm(request, attribute,           

            mapping.getScope());

         实现代码:

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

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

            } else {

                session = request.getSession();

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

            }

            return (instance);}

            if (instance != null && canReuseActionForm(instance, config)) {

                    return (instance);

                }

            return createActionForm(config, servlet);//反射方式生成ActionForm对象

    可以看出创建ActionForm是通过单例模式来实现的。通过name=“LoginForm”,创建表单 "com.LoginActionForm"

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

    /*

    填充表单

    */

    4、 processPopulate(request, response, form, mapping);

     实现代码:

      if (form == null) {

                return;

            }

     form.reset(mapping, request);//ActionForm初始化

     //ActionForm对象自动收集请求参数

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

                                  request);

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

        public static void populate()//自动收集请求参数

        实现代码:

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

       properties.put(stripped, parameterValue);

       BeanUtils.populate(bean, properties);

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

       public static void populate(Object bean, Map properties)

       实现代码:

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

            }

    //对ActionForm信息进行验证

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

                return;

            }

     调用 processPopulate(request, response, form, mapping),将request里面的表单数据自动收集。

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

    //创建action对象

     protected HashMap actions = new HashMap(); //

    5、Action action = processActionCreate(request, response, mapping);

    代码实现:

    protected Action processActionCreate(HttpServletRequest request,

                                             HttpServletResponse response,

                                             ActionMapping mapping)

      {String className = mapping.getType();

     Action instance = null;

            synchronized (actions) {

                instance = (Action) actions.get(className);

                if (instance != null) {

                   return (instance);

                }

         instance = (Action) RequestUtils.applicationInstance(className);

         actions.put(className, instance);

         return (instance);

       }

    action是通过单例加同步创建,高效安全。

    并且在一个xml里面一个action标签对应一个action,一般有多个action标签 

    将这些action 存到hashmap  actions 如上 。

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

    //执行Action

    6、ActionForward forward= 

    processActionPerform(request, response,action, form, mapping);

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

    代码实现:

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

            }

        }

     执行action的   Actionforward execute(request,response,mapping,form) 返回一个  Actionforward

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

    7、processForwardConfig(request, response, forward);

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

    代码实现:

    protected void processForwardConfig(HttpServletRequest request,

                                            HttpServletResponse response,

                                            ForwardConfig forward)

            throws IOException, ServletException {

            if (forward == null) {

                return;

            }

        String forwardPath = forward.getPath();

         uri = forwardPath;

       if (forward.getRedirect()) {

               

                response.sendRedirect(response.encodeRedirectURL(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);

     根据在xml action 标签 里的  forward的标签将跳转 ,整个登入结束。 

    ps:如果没有在xml配置mapping 则会返回一个null。

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

  • 相关阅读:
    Linux程序的执行
    Linux图形操作与命令行
    Linux网络配置
    Zip文件中文乱码问题解决方法(MAC->Windows)
    我只是一直很努力
    Android抓包方法(三)之Win7笔记本Wifi热点+WireShark工具
    Android抓包方法(二)之Tcpdump命令+Wireshark
    Android抓包方法(一)之Fiddler代理
    Android反编译(二)之反编译XML资源文件
    Android反编译(一)之反编译JAVA源码
  • 原文地址:https://www.cnblogs.com/publicmain/p/7338077.html
Copyright © 2011-2022 走看看