struts制作过程——让你了解struts原理——达内培训项目哦

struts制作步骤如下(其实看个人喜欢了

首先定义自己想要用户写的配置文件是怎么样子的,在这里仿照了struts的配置文件来写的代码,需要用户自己写的配置文件代码如下:

smart-struts.xml

  <smart-struts>

      <global-forwards>

           <foward name="error"  path="/jsp/error.jsp" redirect="true" >

      </global-forwards>

      <form-beans>

       <form-bean  name="loginForm"  type="arg.smartstruts.form.LoginForm"/>

       </form-beans>

        

        <action-mappings>

            <action path="/loginform"  type="org.smartstruts.action.LoginAction">

                 <forward name="success" path="/go/loginform" redirenct="true"/>

            </action>

        </action-mappings>

   </smart-struts>

                        

     

配置文件需要如下相关类来封装

 

1,ForwardConfig.java类,封装了配置文件action元素下面的forward元素的属性,代码如下:

public class ForwardConfig{

        private String name;

        private String path;

        private boolean redirect = false;//定义转发还是重定向,默认是转发

...get..() set..()....

 

}

 

2 ,ActionConfig.java  //用来封装配置文件中action元素的属性,其中包含了forward子元素,代码如下:

import java.util.HashMap;
import java.util.Map;

public class ActioncConfig{

         private String path;

         private String type;

         private String name;

         private String scope = "session";  //设置scope属性,默认值是session范围(原来这样设置默认值OH)

         private String attribute;   //这个定义了放在session或request范围内的key值

         private Map<String , ForwardConfig> forwards =

                   new HashMap<String , ForwardConfig>  //定义了forward子元素

         public void addForwardConfig(ForwardConfig forwaedCfg){    //表示在action元素中添加forward元素

                   forwards.put(forwardCfg.getName() , fowardCfg);

           }

         public ForwardConfig findForward(String name){

                 if(fowards.containsKey(name){

                      return forwards.get(name);

                     }

                      return null;

          }

         public void setName(String name){   //稍微修改一下setName方法

             this.name = name;

             if(attribute = null){

                 this.attrbute = name ; // 设置attibute的默认属性,不写的话就是这个

               }

          }

      省略get set....

}

 

3,FormBeanConfig.java用来存放formbean元素的属性

public class FormBeanConfig{

           private String name ;

           private String type ;

        省略get set...

}

4,ModuleConfig.java 这个类主要定义根元素smart-struts里面包含的元素,其主要包含global-forward、form-bean和action这三个直接的子元素,

public class ModuleConfig{

             private Map<String , FormBeanConfig> formBeans = new HashMap<String,FormBeanConfig>();

             private Map<String , ActionConfig> actions = new HashMap<String ,ActionConfig>();

             private Map<String , ForwardConfig> globalForwards = new HashMap<String , ForwardConfig>();

             public void addForwardConfig(ForwardConfig forwardCfg){              

                     globalForwards.put(forwardCfg.getName() , forwardCfg) ;  //根据name找到处理类

             }

              public void addFormBeanConfig(FormBeanConfig formBeanCfg){

                       formBeans.put(formBeanCfg.getName , formBeanCfg);    //根据name找到formbean类

              }

              public void addActionConfig(ActionConfig actionCfg){

                        actions.put(actionCfg.getPath, actionCfg) ;//根据path找到对应的Action处理类

               }

              public ForwardConfig findForward(String name){

                         if(globalForwards.containsKey(name);

                             return globalForwards.get(name);

                           }

                          return null;

                }

                public ActionConfig  findActionConfig(String path){

                         if(actions.containsKey(path){

                                return actions.get(path);

                          }

                            return null; 

                 }

                 public FormBeanConfig findFormBeanConfig(String name){

                            if(formBeans.containsKey(name){

                                  return formBeans.get(name);

                               }

                             return null

                  }

}

写完了配置文件相关类之后写它的解析文件,需要编写rule.xml文件还需要commons-degister.jar 、commons-beanutils.jar、commons-collections.jar、commons-lang.jar、commons-logging.jar、jsp-api.jar、servlet-api.jar 、log4j.jar包。由于这里建的是普通的java project工程,所以需要jsp-api.jar、servlet-api.jar  两个包。commons-degister.jar是用来解析smart-struts.xml文件的,这个包功能很强大,许多配置文件都是由它解析的,用这个架包需要写rule.xml文件,这个文件只需要知道大概意思就可以了,不需要去背它。

rule.xml文件:

<?xml version='1.0' encoding='UTF-8' ?>

 

<digester-rules>

  <pattern value="smart-struts">  //smart-struts配置文件的根元素

 

      <pattern value="form-beans/form-bean"/>   form-bean元素用到的类是FormBeanConfig 

          <object-create-rule

                classname="org.smartstruts.config.FormBeanConfig" />   

                <set-next-rule methodname="addFormBeanConfig"/>     <!--想父元素添加子元素信息-->

                <set-properties-rule/>

      </pattern>

      <pattern value="global-forwards/forward">

                  <object-create-rule

                  classname="org.smartstruts.config.ForwardConfig"/>

                  <set-next-rule method="addForwardConfig"/>

                  <set-properties-rule/>

       </pattern>

       <pattern value="action-mappings/action">

                  <object-create-rule

                  classname="org.smartstruts.config.ActionConfig"/>

                  <set-next-rule methodname="addActionConfig"/>

                  <set-properties-rules/>

               <pattern value="forward">            <!-- 其下又包含了forward子元素-->

                    <object-create-rule

                     classname="org.smartstruts.config.ForwardConfig"/>

                     <set-next-rule methodname="addForwardConfig"/>

                     <set-properties-rules/>

                  </pattern>

            </pattern>

          </pattern>

</digester-rules>

 

写完了rule.xml,下面写两个Action类,一个叫Action,一个叫ActionForm,这就是为什么action类和formbean类继承这两个类的原因

1,Action.java,只有一个抽象方法,这里写的跟struts有点不同,返回的是string类型,定义成抽象方法会让每个继承了它的类都必须重写这个方法。

public abstract class Action{

        public abstract String execute(ActionForm form, HttpServletRequest request,

                                        HttpServletResponse response) throws Exception;

}

 

2,ActionForm.java类,里面没有属性和方法,是空的

public class ActionForm{

 

}

 

下面实现国际化,需要自己定义标签,自定义标签的过程是:

             勾画出希望在页面展现的标签格式,如:<t:message  key="" />,然后写一个类来封装标签属性,然后写配置文件,下面是定义类:

1,Message.java文件

 

import java.io.IOException;
import java.util.ResourceBundle;   //用来读取资源文件

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
import javax.servlet.jsp.tagext.SimpleTagSupport;

public class MessageTag extends SimpleTagSupport{

          private String key;     //定义标签属性

          public void doTag()throws JspException,IOException{ //重写方法

                  PageContext pageCtx = (PageContext)this.getJspContext();//这样获得页面所有内置对象

                  ResourceBundle rb = (ResourceBundle)pageCtx.getRequest().getAttribute(

                                   "org.smartstruts.message.resources");  

                  String msg = rb.getString(key);  //获得资源文件的key

                  pageCtx.getOut().write(msg); //相当于在jsp页面通过out.write(msg)输出信息一样

           }

省略get set

}

2,smart-1.1.tld文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib>
 <tlibversion>1.2</tlibversion>
 <jspversion>1.1</jspversion>
 <shortname>smart</shortname>
 <uri>http://smartstruts.org/taglib</uri> <!--随便取一个-->
 
 <tag>
  <name>message</name>  <!--标签名称-->
  <tagclass>org.smartstruts.taglib.MessageTag</tagclass>
  <bodycontent>empty</bodycontent>
  <attribute>
   <name>key</name><!-- 属性名称-->
   <required>true</required>
   <rtexprvalue>true</rtexprvalue>
  </attribute>
 </tag>
</taglib>

 

最后写ActionServlet类,这个类可以叫做前端控制器类,处理了请求响应和国际化等操作

public class ActionServlet extends HttpServlet{

          private Logger logger = Logger.getLogger(ActionServlet.Class);//想要为这个类做日志,得通过.class获取这个类的信息

          private static final long serialVersionUID=1L;

          private static final String prefix = "/go";                // “/go”就相当于struts中的.action后缀一样,这里go是前缀了。

                                                                                      //在web.xml文件中配置成<url-pattern>/go/*</...>

          private Map<String , Action> actions = Collections

                  .synchronizedMap<new HashMap<String , Action>());   //通过Map来缓存action,通过Collections

     

                                                                                                            //将HashMap设置成线程安全的

          private Map<Locale , ResourceBundle> resourceBundles = Collections     //根据语言种类找到resource文件

                  .synchronizedMap(new HashMap<Locale , ResourceBundle> ());

          private ModuleConfig moduleCfg;

          public void init() throws ServletException{ 

                    try{

                              Digester digester = DigesterLoader

                                    .createDigester(ActionServlet.class.getClassLoader()

                                         .getResource("org/smartstruts/config/rule.xml"));

                              moduleCfg = new ModuelConfig();      

                            digester.push(moduleCfg);           //关联ModuleConfig类

                            digester.parse(ActionServlet.class.getClassLoader().getResource("smart-struts.xml"));//加载配置文件

                            logger.debug("初始化配置对象:/n"+moduleCfg);

                         }catch(Exception e){

                                     throw new ServletException(e);

                           }

              }

             public void service(HttpServletRequest request, HttpServletResponse response){

                          try{

                                  processResource(request , response) ; //读取资源文件

                                  String path = processPath(request, response);

                                  ActionConfig actionCfg = moduleCfg.findActionConfig(path);//首先根据path找到action的信息

                                  logger.debug("获取Action配置信息:"+actionCfg);

                                  ActionForm form = processForm(actionCfg, request, respnse);  //根据action的name属性找form

                                  String forwardName = processExecute(actionCfg , form, request,response);

                                  processForward(forwardName, actionCfg ,  request , response);    //响应

                                  }catch(Exception e){

                                        throws new ServletException(e);

                                   }

                                

                     }

             private void processResource(HttpServletRequest request , HttpServletResponse response){

                         Locale locale = request.getLocale(); //获取浏览器请求协议里面的信息,如语言类型

                         ResourceBundle rb = resourceBundles.get(locale);   //先看看缓存里locale语言种类是否有对应的值

                         if(rb == null){

                             rb = ResourceBundle.getBundle("resource" , locale);  //如果没有,就读取名为resource的资源文件,

                                                                                                     //从这可以看出用缓存的好处,如缓存里已经存在了就不需

                                                                                                     // 要再读取资源文件,否则每次都读取会降低性能

                              resourceBundles.put(locale,rb);

                         }

                         request.setAttribute("org.smartstruts.message.resources", rb);//这个key对应了Message类的

                         logger.debug("获取资源文件:"+rb);

                }

             private String processPath(HttpServletRequest request , HttpServletResponse response){

                        String uri = request.getRequestURI();  //获取url路径web.xml中的"/go/ "如: /go/login,想办法得到/login

                        String path = uri.substring(uri.indexOf(prefix) + prefix.length());  //prefix="/go"

                        logger.debug("处理请求:"+path);

                        return path;

              }                       

            private ActionForm processForm(ActionConfig actionCfg,

                         HttpServletRequest request , HttpServletResponse response)

                        throws Exception{

                        String formName = actionCfg.getName();

                        ActionForm form = null;

                        if(formName != null){   //判断action中是否存在name属性

                              String scope = actionCfg.getScope(); //获取scope属性

                               if("request".equals(scope)){         //如果是request就放到request范围中

                                    form = (ActionForm)request.getAttribute(actionCfg.getAttribute());//获取名为action元素

                                                                                                                               //的attribute属性的值所对应的值

                                } else{

                                       form = (ActionForm)request.getSession().getAttribute(

                                              actionCfg.getAttribute());

                                    }

                               if(form == null){         //如果为空,则表示第一次用这个formbean,就创建新的form对象

                                    FormBeanConfig formBeanCfg = moduleCfg.findFormBeanConfig(formName);//根据action元素

                                                                                                                                           //的name属性找到对应的form

                                    if(formBeanCfg != null){    //如果配置了<form-bean>元素则操作如下

                                        String formBeanType = formBeanCfg.getType() ; 

                                        Class formBeanClass = Class.forName(formBeanType); //通过反射建立formBeanType对应的类

                                        form = (ActionForm) formBeanClass.newInstance() ; //所以每个formbean类都继承了ActionForm

                                        if("request".equals(scope)){   //重新判断要存的范围

                                             request.setAttribute(actionCfg.getAttribute() , form);

                                        }else{

                                              request.getSession().setAttribute(actionCfg.getAttribute() , form);

                                        }

                                  }

                           }

                         BeanUtils.populate(form,request.getParameterMap());//将页面表单值赋值给formbean中对应的属性

                         logger.debug("构建ActionForm:" + form);

                         }

                      return form;

            }

            private String processExecute(ActionConfig actionCfg ,ActionForm form,

                         HttpServletRequest request, HttpServletResponse response)
                         throws Exception {

                      Action action = actions.get(actionCfg.getPath()); //看看缓存里是否已经有action了

                      if(action == null){

                          String actionType = actionCfg.getType();

                          Class actionClass = Class.forName(actionType);//根据type值建类

                          action = (Action) actionClass.newInstance();

                          actions.put(actionCfg.getPath,action);

                        }

                         String forwardName = action.execute(form, request,response);//获得Action类中execute方法的返回值

                         logger.debug("调用Action:" +action);

                         return forwardName;

                         }

          private void processForward(String forwardName, ActionConfig actionCfg ,
                          HttpServletRequest request, HttpServletResponse response)

                          throws Exception {

                       ForwardConfig forwardCfg = actionCfg.findForward(forwardName);//找到配置文件中forward属性

                       if (forwardCfg == null){   //找不到就到全局中找

                            forwardCfg = moduleCfg.findForward(forwardName);

                         }

                       if(forwardCfg != null){

                          String fowardPath = forwardCfg.getPath();

                             if(forwardPath != null){

                                if(!forwardCfg.isRedirect())

                                  logger.debug("转发操作:"+ forwardPath);

                                  request.getRequestDispatcher(forwardPath).forward(request,response);

                                  }else{

                                   logger.debug("重定向操作:" + forwardPath);

                                   String ctxPath = request.getContextPath();

                                   response.sendRedirect(ctxPath + forwardPath);

                                   }

                                 }

                            }

               }

}//终于写完这个类

 

 关于反射、绝对路径和相对路径问题在下一篇讲解。。  

最后总结:

第一步读取资源文件实现国际化

   Locale locale = request.getLocale(); //获取浏览器请求协议里面的信息,如语言类型

                         ResourceBundle rb = resourceBundles.get(locale);   //先看看缓存里locale语言种类是否有对应的值

                         if(rb == null){

                             rb = ResourceBundle.getBundle("resource" , locale);  //如果没有,就读取名为resource的资源文件,

                                                                                                                                                                    //用缓存的好处,如缓存里已经存在了就不需要再读取资源文件,否则每次都读取会降低性能

                              resourceBundles.put(locale,rb);

                         }

                         request.setAttribute("org.smartstruts.message.resources", rb);//这个key对应了Message类的

                         logger.debug("获取资源文件:"+rb);

第二:获取请求的绝对路径

String uri = request.getRequestURI();  //获取url路径web.xml中的"/go/ "如: /go/login,想办法得到/login

                        String path = uri.substring(uri.indexOf(prefix) + prefix.length());  //prefix="/go"

第三:根据path找到对应的action元素

第四:先判断action元素中是否有name属性,如果有,则判断scope属性是request还是session值,是request,则通过form = (ActionForm)request.getAttribute(actionCfg.getAttribute());获取曾经存到form中的值,否则在session中获取,如果在requestsession中的到的form值为null,则说明是第一次使用该form,这时候根据actionname属性值去找对应的form-bean元素,如果存在则根据type属性的值通过反射创建form实例,再来判断scope值是request还是session,然后决定将form值放到request还是session中,并以action attribute属性值作为key,然后将页面表单值赋给form

这样完后,就开始做业务逻辑了

第五:其实action相关信息是存在缓存中的,所以到这一步的时候先去缓存找keyaction元素的path的值所对应的action, 如果不存在则根据action元素type属性值通过反射创建Action类,然后将心创建的action放入缓存,根据新创建Action类中execute方法的返回值找到forward元素,如果forward元素不存在则在全局中找,如果得到的forward元素存在,则找到path属性,如果不为空且redirect属性值为fale转发path所指定的路径,如果redirecttrue重定向path所指定的路径。

总结得不好请大家指点!

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值