Struts1的基础知识

Posted 阿叮339

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Struts1的基础知识相关的知识,希望对你有一定的参考价值。

struts1.0的配置

 

在web.xml文件中的配置

 

<servlet>

<!--配置ActionServlet类,一启动就创建该类对象-->

<servlet-name>action</servlet-name>

<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

 

<!--配置struts-config.xml文件的位置,默认从WEN-INF/下找文件名为struts-config.xml文件 如果是按照默认路径和默认文件名存放的配置文件,就可以不用配置,但是建议配置-->

      <init-param>

           <param-name>config</param-name>

           <param-value>/WEB-INF/struts-config.xml<param-value>

      </init-param>

     

      <!-- 错误日志配置,一旦出错会自动生成错误日志 -->

      <init-param>

           <param-name>debug</param-name>

           <param-value>2<param-value>

      </init-param>

     

      <!-- 对xml文件的解析日志 -->

      <init-param>

           <param-name>detail</param-name>

           <param-value>2<param-value>

      </init-param>

     

      <!--配置为:tomcat一启动就创建ActionServlet类的对象 这个一定要记得配置-->

      <load-on-startup>1</load-on-startup>

</servlet>

 

<servlet-mapping>

      <!--处理所有的.do请求-->

      <servlet-name>action</servlet-name>

      <url-pattern>*.do</url-pattern>

</servlet-mapping>

 

 

在struts-config.xml文件中的配置

<action-mappings>

      <!--

        action标签 每个请求对应一个action配置,

       path:请求路径 与发送请求的表单的action=””对应,只是多了个斜杠

       name:对应的表单bean name,与 form-bean标签中的name属性相同

       scope:存储的域  默认为session 建议存储在request域中

       type:指明Action子类的全路径名 (包名+类名)

      -->

      <action path="" name="" scope="" type="">

      <!--

           forward标签是指定跳转信息

           name:跳转的名字,通过名字找到path

           path:指定要跳转到的jsp页面

redirect:指定跳转方式,默认为false 为true的时候表示客户端跳转,为false的时候表示服务端跳转

      -->

      <forward name="" path="" redirect=""></forward>

      </action>

 

</action-mappings>

      <!--

           form-bean标签对应form对象 继承ActionForm的子类

           name:指定收集表单数据的对象名

           type:指定ActionForm子类的全路径名(包名+类名)

      -->

<form-beans>

      <form-bean name="" type=""></form-bean>

</form-beans>

 

 

 

自己对于struts1.0执行流程的理解:

 

tomcat服务器一启动,就创建ActionServlet对象 ModuleConfig对象 ModuleConfig对象中封装了三个Map集合

1、  : Map  actionConfigs = new HashMap();//用来存储ActionMapping对象的集合, action标签中的path属性的属性值作为该集合的key,ActionMapping对象作为集合的value

 

      actionConfigs.put(path,new ActionMapping());//往集合中添加数据

      ActionMapping mapping=actionConfigs.get(path);//通过path取出ActionMapping对象 path作为actionConfigs集合的key,ActionMapping对象作为actionConfigs集合的value

      mapping.getName();//通过ActionMapping对象得到<action>标签中的name属性对应的属性值 (与form-bean标签的name值相同,formBeans正好使用这个值取得FormBeanConfig对象)

      mapping.getScope();//通过ActionMapping对象得到<action>标签中的scope属性对应的属性值 (确定ActionForm对象的存储域,一般是session 或 request)

      mapping.getType();//通过ActionMapping对象得到<action>标签中的type属性对应的属性值 --(类的全路径名,通过这个值来创建Action对象)

      mapping.getValidate();//通过ActionMapping对象得到<action>标签中的validate属性对应的属性值, (确定是否对收集的表单数据做验证,默认为true ,设值为false的时候不验证)

 

2、 Map formBeans = new HashMap();//用来存储FormBeanConfig对象的集合,form-bean标签中的name属性作为该集合的key,FormBeanConfig对象作为集合的value

 

      formBeans.put(name,new FormBeanConfig());//往集合中添加数据

      FormBeanConfig form=formBeans.get(name);//通过《action》标签中的name属性值取出FormBeanConfig对象,name是map集合formBeans中的key,FormBeanConfig对象为formBeans集合的value

      form.getType();//通过FormBeanConfig对象得到<form-bean>标签中的type属性对应的属性值 (类的全路径名,用来创建ActionFrom对象)

 

 

3、 : Map forwards = new HashMap();//用来存储ActionForward对象的集合,forward标签中的name属性作为该集合的key,ActionForward对象作为该集合的value。

 

     forwards.put(name,new ActionForward());//往集合中添加数据

     ActionForward forward = forwards.get(name);//通过name属性得到ActionForward对象,name为forwards集合中的key,ActionFoward对象为forwards集合中的value

      forwards.getRedirect();//通过ActionForward对象得到<froward>标签中的redirect属性对应的属性值, (确定跳转方式,默认为false 服务端跳转,设值为true的时候为客户端跳转)

      forwards.getPath();//通过ActionForward对象得到<forward>标签中的path属性对应的属性值(得到跳转路径,确定跳转的目的jsp页面)

 

 

 

 

执行流程

ActionServlet对象一创建,就将struts-config.xml文件读到内存中,ModuleConfig对象存在整个配置文件中的信息

用户发*.do请求时,tomcat会自动把请求交给ActionServlet对象处理(也可以说是交给struts处理),

ActionServlet会调用根据发送请求的方式调用本身的doGet()或者doPost()方法。

     

      //ActionServlet类中的doGet()方法

      public void doGet(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException{

           process(request,response);//调用ActionServlet类中的process方法处理请求

      }

     

      //ActionServelt类中的doPost()方法

      public void doPost(HttpServletRequest request,HttpServletResponse response)throws IOException,ServletException{

           process(request,response);//调用ActionServlet类中的process方法处理请求

      }

     

//ActionServlet类中的process方法(在这个process方法中完成对请求的处理全部流程,从请求字符串的截取(processPath)—>ActionMapping对象的创建(processMapping)—>ActionForm对象的创建(processActionForm)—>表单数据的收集(processPopulate)—>Action对象的创建(processActionCreate)—>Action对象的execute的方法的执行(processActionPerform)—>完成跳转(processForwardConfig

 

protected void process(HttpServletRequest request,HttpServlet

Response response)throws IOException, ServletException {

 

 ModuleConfig config = getModuleConfig(request);//config为ModuleConfig对象

    RequestProcessor processor = getProcessorForModule(config);//通过ModuleConfig对象创建RequestProcessor对象

          

     processor.process(request, response);//调用RequestProcessor类的process()方法

 

    }

   

    //RequestProcessor类中的process()方法

    public void process(HttpServletRequest request,  HttpServletResponse response)throws IOException, ServletException {

 

String path=processPath(request,response); //调用RequestProcessor类的processPath ()方法

 

//RequestProcessor类中的processPath()方法,返回path

protected String processPath(HttpServletRequest request,HttpServletResponse response)  throws IOException {

 

String url=request.getContextPath();//获取除项目名以外的项目全路径名

(例如:请求路径  http://localhost:8080/struts1.0/login.do? username="dfx"&  password="123"  url="  /login.do?username="dfx" &password="123" 这里就算是post请求,表单中的参数名和参数值都会发送过来,只是被封装在协议体中,不显示而已 ")

               

      int index=url.lastIndexOf(".");//找到从请求字符串从最后一个位置开始反向搜索,第一次出现(.)的位置  ,这里index=6;

      int start=ur.lastIndexOf("/");//找到请求字符串中从最后一个位置开始反向搜索,第一次出现(/)的位置,这里start=0;

      //截取请求 作为path

      String path=url.substring(start,index);//这里的  path= “/login” ;

    } 

//调用RequestProcessor类中的processMapping()方法得到ActionMapping对象

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

      

       //RequestProcessor类中processMapping()

  protected ActionMapping processMapping(HttpServletRequest request, HttpServletResponse response, String path)throws IOException {

          

        //调用ModuleConfig接口中的findActionConfig()方法取得ActionMapping对象

      ActionMapping mapping = (ActionMapping)moduleConfig.findActionConfig(path);

    }

    //ModuleConfig实现类中的findActionConfig()方法 (该方法中的actionConfigs是Map集合,该map集合的key为path,value为ActionMapping对象)

     public ActionConfig findActionConfig(String path) {

        ActionConfig config = (ActionConfig) actionConfigs.get(path);//通过key (path)取出map集合中的value值(ActionMapping对象)

        return config;//返回ActionConfig对象(ActionMapping是ActionConfig的子类)

    }

    //取出ActionMapping对象后,调用RequestProcessor类中的processActionForm()方法得到ActionForm对象

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

    

     //RequestProcessor类中的processActionForm()方法

     protected ActionForm processActionForm(HttpServletRequest request,HttpServletResponse response,  ActionMapping mapping) {

 

//调用RequestUtils类中的静态方法 createActionForm()创建ActionForm对象

        ActionForm instance = RequestUtils.createActionForm(request, mapping, moduleConfig, servlet);

            return instance;//返回ActionForm对象

        }

    

     //RequestUtils类中的静态方法 createActionForm()

      public static ActionForm createActionForm(HttpServletRequest request,ActionMapping mapping, ModuleConfig moduleConfig, ActionServlet servlet) {

 

        String name = mapping.getName();//通过ActionMapping对象得到<action>标签中name属性对应的属性值(这个name属性和《form-bean》标签中的name属性是一样的)

       

//通过name属性值,调用ModuleConfig接口中的moduleConfig.findFormBeanConfig()方法得到FormBeanConfig对象

        FormBeanConfig config = moduleConfig.findFormBeanConfig(name);

       

        《

        //ModuleConfig接口实现类中的方法findFormBeanConfig()

        public FormBeanConfig findFormBeanConfig(String name) {

//formbeans为map集合,该集合中的key为<form-bean>标签中的name属性值,value为FormBeanConfig对象

        return ((FormBeanConfig) formBeans.get(name));//所以这里可以通过formBeans.get(name)取得value FormBeanConfig对象

       }

        》

  //调用RequestUtils类中的lookupActionForm()方法,得到ActionForm对象

ActionForm instance = lookupActionForm(request, attribute, mapping.getScope());

       

    《

    // RequestUtils类中的lookupActionForm()方法

     private static ActionForm lookupActionForm(HttpServletRequest request, String attribute, String scope)

{

//ActionForm类型变量用来接收ActionForm对象

          ActionForm instance = null;

        HttpSession session = null;

        if ("request".equals(scope)) {//判断ActionForm对象是否被指定存储在request域中

/*判断是request域的时候,就从request域中取出ActionForm对象

注:这里的getAttribute()方法是指从request中取出属性值,

 attribute作为默认属性名,如果attribute属性不存在就从name属性中取值 name属性中存放的是ActionForm对象存储在内置对象中的属性名,内置对象的属性值为 ActionForm对象

例如: request.setAttribute("loginForm",new LoginForm()); //这里 name="loginform" ,getAttribute(name),取出来的便是ActionForm对象

*/

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

        } else {

            session = request.getSession();//如果ActionForm对象是否被指定存储在session域中,

            instance = (ActionForm) session.getAttribute(attribute);//这里的解释和request域雷同

        }

        return (instance);

    }

    》

//调用RequestUtils类中的createActionForm()方法创建ActionForm对象

        return createActionForm(config, servlet);

       

        《

        //RequestUtils类中的createActionForm()方法

        public static ActionForm createActionForm(FormBeanConfig config, ActionServlet servlet){

      

        ActionForm instance = null;

        try {

            //通过FormBeanConfig对象,调用FormBeanConfig类的createActionForm()方法创建ActionForm对象

            instance = config.createActionForm(servlet);

           

            《

        //FormBeanConfig类的createActionForm()方法

        public ActionForm createActionForm(ActionServlet servlet) throws IllegalAccessException, InstantiationException {

 

        Object obj = null;

      //调用FormBeanConfig类中的formBeanClass()方法创建 Object类型的对象

        obj = formBeanClass().newInstance();

        

        《

        //FormBeanConfig类中的formBeanClass()方法

      protected Class formBeanClass() {

ClassLoader classLoader =  Thread.currentThread().getContextClassLoader();//加载该对象

         try {

            return (classLoader.loadClass(getType()));//<form-bean>标签中的type属性(类全路径名)对应的类对象,暂时定义为Object类型

       } catch (Exception e) {

            return (null);

    }

 }

        》

 

        ActionForm form = null;

        if (obj instanceof ActionForm) {

            form = (ActionForm)obj;//将FormBeanConfig类中的formBeanClass()方法得到的type指定的类对象造型为ActionForm类型

        }

        form.setServlet(servlet);

        return form; //返回ActionForm对象

    } 

            》

        } catch(Throwable t) {

            log.error(servlet.getInternal().getMessage("formBean", config.getType()), t);

        }

        return (instance);

    }

        》

    }

   

         //调用RequestProcessor类中的processPopulate()方法,将表单中的数据封装到表单bean中 (ActionForm对象中)

        processPopulate(request, response, form, mapping);

       

       // RequestProcessor类中的processPopulate()方法

protected void processPopulate(HttpServletRequest request, HttpServletResponse response, ActionForm form, ActionMapping mapping)  throws ServletException {

 

    if (form == null) {

            return;

 }

        form.setServlet(this.servlet);

        form.reset(mapping, request);//在收集表单中的数据到表单bean中之前,调用reset()方法,初始化数据

       

        //调用RequestUtils类中的populate()方法,收集表单数据

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

       

        《

        //RequestUtils类中的populate()方法

         public static void populate(Object bean,String prefix,String suffix, HttpServletRequest request) throws ServletException {

 

        HashMap properties = new HashMap();//创建map集合,表单中的参数名和参数值分别作为key和value存储在该集合中

        Enumeration names = null;//创建Enumeration集合,迭代出request内置对象(域)中的所有参数名和参数值

       

         names = request.getParameterNames();//迭代出封装在request内置对象中的所有参数名

 

        while (names.hasMoreElements()) {

            String name = (String) names.nextElement();//迭代取得request内置对象中参数名  (假若是个登录表单:第一个取出 username ,第二次取出password)

            String stripped = name;//将参数名保存在临时变量中,作为map集合的key

           

            Object parameterValue = null;

            //得到request内置对象的参数名对应的参数值(假若是个登录表单:参数名为 username对应的参数值为“admin” ,参数名password对应的参数值为“123”)

            parameterValue = request.getParameterValues(name);

           

             properties.put(stripped, parameterValue);//将参数名和参数值分别作为key和value存储到map集合中

        }

 

        try {

            //调用BeanUtils中的populate()方法

            BeanUtils.populate(bean, properties);

           

                  《

//BeanUtils中的populate()方法

             public static void populate(Object bean, Map properties)throws IllegalAccessException, InvocationTargetException {

 

                   if ((bean == null) || (properties == null)) {

                      return;

                   }

//先将map集合转换成Set集合,然后调用iterator()方法进行迭代输出(map集合中存放的是request内置对象中的参数名和参数值)

                   Iterator names = properties.keySet().iterator();

                  while (names.hasNext()) {

String name = (String) names.next();//得到request内置对象中的参数名 username

                      Object value = properties.get(name);//参数名name作为key,map.get(name)得到value值,request内置对象中的参数值 "admin"

/*bean:为ActionForm对象,name为参数名 (username),value为参数值(admin)//这句代码的意思就是将request内置对象中的参数名和参数值设置到ActionForm对象(bean)中。

*/

           setProperty(bean, name, value);      

注:表单bean ActionForm对象 bean会从表单中找到和它属性名相同的参数名进行收集,并且只收集属性名相同的表单参数,和属性名不同参数名的不会被收集。找到对应的属性名的参数,调用set方法,设值(这里会找到与name对应的表单bean的属性进行设值。比如:当name为username时,bean.setUsername(value); 当name为password时,bean.setPasswrod(value); value的值和name值一 一对应

                   }

          }

           

                  》

        } catch(Exception e) {

            throw new ServletException("BeanUtils.populate", e);

        } finally { }

    }

      》

        //在RequestProcessor类中的process()方法中调用processActionCreate()方法创建Action对象(使用map单例+同步方法创建保证安全性

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

        《

        //RequestProcessor类中的processActionCreate()方法

        protected Action processActionCreate(HttpServletRequest request,HttpServletResponse response, ActionMapping mapping)  throws IOException {

 

        String className = mapping.getType();//得到type属性值,也就是继承Action类的类全路径名(cn.action.LoginAction)

        Action instance = null;

        synchronized (actions) {         

//actions是一个map集合 ,HashMap actions=new HashMap();//该map集合的key为type属性值(cn.action.LoginAction),value为type类名对应的类对象

            instance = (Action) actions.get(className);//先从map中type对应的类对象,取到了就直接返回(保证单例)

            if (instance != null) {

                return (instance);

            }

            try {

            //从map集合中没有取到Action对象时,就通过反射创建该对象

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

            } catch (Exception e) {

            }

           

            instance.setServlet(this.servlet);

            actions.put(className, instance);//将继承Action类的类名和类对象分别作为key和value存入map集合中

        }

        return (instance);

    }

        》

//在RequestProcessor类中的process()方法中调用processActionPerform()方法创建ActionFoward对象

        ActionForward forward = processActionPerform(request, response, action, form, mapping);

       

        《

        //RequestProcessor类中的processActionPerform()方法

        protected ActionForward processActionPerform(HttpServletRequest request, HttpServletResponse response, Action action, ActionForm form,

                ActionMapping mapping) throws IOException, ServletException {

 

        try {

            return (action.execute(mapping, form, request, response));//执行Action对象的execute()方法,返回值为ActionForward对象

        } catch (Exception e) {

            return (processException(request, response,  e, form, mapping));

        }

    }

    》

          

//在RequestProcessor类中的process()方法中调用processForwardConfig()转向信息方法

        processForwardConfig(request, response, forward);

       

        《

   //RequestProcessor类中的processForwardConfig()方法,完成跳转

    protected void processForwardConfig(HttpServletRequest request, HttpServletResponse response,ForwardConfig forward)

        throws IOException, ServletException {

 

        if (forward == null) {//先判断转向对象是否为null,为null的时候表示不是要struts提供的转向方法,使用自己写的跳转信息

            return;

        }

        String forwardPath = forward.getPath();//通过ForwardConfig对象获得<forward>标签中的path  转向路径 例如 “/success.jsp”

        String uri = null;

       

        if (forward.getRedirect()) {//判断跳转方式,为true的时候表示客户端跳转

            response.sendRedirect(response.encodeRedirectURL(uri));

        } else {

        //这里调用RequestProcessor类中的doForward()方法完成服务端跳转

            doForward(uri, request, response);//为false的时候表示服务端跳转(默认为false 服务端跳转)

           《

            //RequestProcessor类中的doForward()方法

 protected void doForward( String uri, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

           

       RequestDispatcher rd = getServletContext().getRequestDispatcher(uri);

       rd.forward(request, response);

   》   

        }

 

    }

}

 

以上是关于Struts1的基础知识的主要内容,如果未能解决你的问题,请参考以下文章

在面试过程中SpringMVC常常被问到的有哪些知识点?

Struts2 基础

struts2和strtus1的主要区别

Struts2与Struts1的区别

Struts2基础篇

java中的struts是啥?