zoukankan      html  css  js  c++  java
  • Struts2 自定义MVC框架

    一、Model1与Model2:

    Model1:就是一种纯jsp开发技术,将业务逻辑代码和视图渲染代码杂糅在一起。

    Model2:Model2是在Model1的基础上,将业务逻辑的代码分离开来,单独形成一个Servlet,Model2也是基于MVC开发

    二、MVC设计模式:

    由3个部分组成,各部分作用如下:

    Model:模型,主要用于数据和业务的处理

    View:视图,用于数据的显示

    Controller:控制器,用于进行流程控制

    MVC设计模式的特点:

    ①一个模型可以对应多个视图

    ②显示与逻辑控制的分离

    ③分层控制,减轻了代码间的耦合


    自定义MVC框架只需dom4j.jar包即可!

     三、准备XML文档Framework.xml

    注意点:

    <!-- ELEMENT 表示元素 -->
    <!-- ATTLIST 表示属性 -->
    <!-- CDATA 表示字符串类型 -->
    <!-- REQUIRED 表示此属性必须的写 -->
    <!-- *代表多个 -->
    <!-- IMPLIED 表示此属性可写 -->

    复制代码
    <!DOCTYPE Framework[
    <!ELEMENT Framework (actions)>
    <!ELEMENT actions (action*)>
    <!ELEMENT action (result*)>
    
    <!ATTLIST action name CDATA #REQUIRED
                     class CDATA #REQUIRED
    >
    
    
    <!ATTLIST RESULT name CDATA #IMPLIED
                     redirect (true|false) "false"
    >
    
    ]>
    
    <Framework>
    <actions>
    <action name="loginAction" class="cn.happy.action.LoginAction">
    <result name="success">success.jsp</result>
    <result name="login">index.jsp</result>
    </action>
    </actions>
    </Framework>
    复制代码


    四、定义自己的Action接口,用于存放结果集和要执行的方法

    复制代码
    public interface Action {
        //定义两个静态字符串常量(逻辑视图名)
        public static final String SUCCESS="success";
        public static final String LOGIN="login";
        //定义一个抽象方法execute
        public String execute(HttpServletRequest request,HttpServletResponse response)throws Exception;
    
    }
    复制代码

    五、定义ActionMapping类用于存放Action节点,即一个ActionMapping类可以视为配置文件中的一个action节点

    复制代码
    public class ActionMapping {
        //根据action节点中的属性 以及action节点中的<result></result>节点定义三个私有属性
        
        private String name;//action的名称
        private String classname;//action对应程序中的类
        private Map<String,String> results=new HashMap<String,String>();
        
        //向results集合中添加数据的方法
        public void addResult(String name,String value){
            results.put(name, value);
        }
    
        //根据名称获取的方法
        public String getResults(String name){
            return results.get(name);
        }
        
        public Map<String, String> getResults() {
            return results;
        }
        public void setResults(Map<String, String> results) {
            this.results = results;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getClassname() {
            return classname;
        }
        public void setClassname(String classname) {
            this.classname = classname;
        }
        
    复制代码

    六、定义ActionMappingManager类用于管理ActionMapping,并通过dom4j解析Framework.xml配置文件。从而获取根节点,以及actions节点,并通过for循环遍历actions节点下的action节点拿到name和class的属性值,由于一个action节点下有多个result节点 及遍历action下所有的result节点,分别存入到actionMapping中的双列集合中,最后得到所有action节点的集合

    复制代码
    public class ActionMappingManager {
        //actionMapping类的集合
        private Map<String,ActionMapping> maps=new HashMap<String,ActionMapping>();
    
        public ActionMapping getActionMapping(String name){
            return maps.get(name);
        }
        
        //解析src下所有配置文件
        public ActionMappingManager(String[]files){
            for (String filename : files) {
                init(filename);
            }
        }
        
        //创建初始化方法,使用dom4j解析配置文件
        public void init(String path){
            try {
                 //getResourceAsStream取得该资源输入流的引用保证程序可以从正确的位置抽取数据
                InputStream is=this.getClass().getResourceAsStream("/"+path);
                //解析XML
                Document doc=new SAXReader().read(is);
                //获取根节点
                Element root = doc.getRootElement();
                //获取actions节点
                 Element actions =(Element)root.elementIterator("actions").next();
                 //使用for循环来
                 //遍历actions节点下的所有action节点
                 for (Iterator<Element> action=actions.elementIterator("action");action.hasNext();) {
                    //获取到action节点
                     Element actionnext = action.next();
                    //分别获取到action节点中的name属性和class属性
                     String name=actionnext.attributeValue("name");
                     String classname=actionnext.attributeValue("class");
                     //将以上两个属性保存到ActionMapping类中
                     ActionMapping mapp=new ActionMapping();
                     mapp.setClassname(classname);
                     mapp.setName(name);
                     //由于一个action节点下有多个result节点 遍历action下所有的result节点
                     for (Iterator<Element> result=actionnext.elementIterator("result");result.hasNext();){
                         //获取到result节点
                         Element resultnext = result.next();
                         //提取result节点的name属性值和result节点中的值
                         String resultname= resultnext.attributeValue("name");
                        String resultvalue= resultnext.getText();
                         //将其分别存入到actionMapping中的双列集合中去,方便调用actionMapping类(actionMapping类中就有数据了!)
                        mapp.addResult(resultname, resultvalue);
                     }
                    //得到所有action节点的集合
                     maps.put(mapp.getName(), mapp);
                 }
            
            } catch (Exception e) {
                
            }
        }
    复制代码

    七、使用反射机制根据字符串类型的类名获取到具体的类--ActionManager

    复制代码
    public class ActionManager {
    
        public static Action getActionClass(String classname){
            Class clazz=null;
            Action action=null;
            //获取当前线程的加载类
            try {
                clazz=Thread.currentThread().getContextClassLoader().loadClass(classname);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            
            if(clazz==null){
                try {
                    //如果该线程中没有,那么使用class.forname方法获取
                    clazz=Class.forName(classname);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
            
            if(action==null){
                //将获取到的类型转换为action,调用无参构造函数,某种程度上相当于new,不过new需要指定类型
                try {
                    action =(Action)clazz.newInstance();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            return action;
        }
    复制代码

    八、定义Servlet类,详情见注释!注意点在web.xml中添加 <load-on-startup>节点,让程序一开始就初始化servlet

    复制代码
    public class MyServlet extends HttpServlet {
    
        
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
               doPost(request,response);
            
        }
    
        ActionMappingManager man=null;
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
              //获取到ActionMapping对象
            ActionMapping actionMapping=man.getActionMapping(getname(request));
            //获取action接口利用反射机制
            Action action = ActionManager.getActionClass(actionMapping.getClassname());
            try {
                String message=action.execute(request, response);
                String results=actionMapping.getResults(message);
                response.sendRedirect(results);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
            //获取请求路径名
            public String getname(HttpServletRequest request)
            {
                //项目+请求地址
                String requestURI =request.getRequestURI();
                //项目名称
                String contextPath=request.getContextPath();
                //具体的请求
                String path=requestURI.substring(contextPath.length());
                String filename=path.substring(1,path.lastIndexOf(".")).trim();
                return filename;
            
            }
        
        //重写servlet的init方法,让程序一开始就初始化servlet
        //由于一个项目src根目录下有可能有多个配置文件,不止一个,所以逐个解析
            
        @Override
        public void init(ServletConfig config) throws ServletException {
            
            //初始化参数信息
            String filename = config.getInitParameter("config");
            String [] filenames=null;
            
            if(filename==null){
                //如果没有别的参数信息,就将已经配好的放入数组中
                filenames=new String[]{"Framework.xml"};
            }
            else{
                //拆分配置文件名称字符串
                filenames=filename.split(",");
            }
            //使用init方法初始化
            man=new ActionMappingManager(filenames);
        }
    复制代码

    九、业务逻辑Action并实现Action接口,并重写自定义的execute方法

    复制代码
    public class LoginAction implements Action{
    
        public String execute(HttpServletRequest request,
                HttpServletResponse response) throws Exception {
            String name=request.getParameter("name");
            String pwd=request.getParameter("pwd");
            if(name.equals("1")&&pwd.equals("1")){
                return SUCCESS;
            }
            else{
                return LOGIN;
            }
        }
    复制代码

    十、编写登录界面

    复制代码
      <body>
         <form action="loginAction.action" method="post">
        姓名:<input type="text" name="name"/><br/>
        密码:<input type="text" name="pwd"/><br/>
        <input type="submit" value="登录">
        </form>
      </body>
    复制代码

     实现效果:

  • 相关阅读:
    VS2010调试技巧
    asp.net中Web.Config配置文件详解
    vi进入编辑模式,按向左,向右,向上,向下,出现A,B,C,D字符解决方法
    su root后还是不能使用usermod,useradd等命令,错误描述:bash:usermod:command not found(转自http://myjieli.blog.51cto.com/135162/286462)
    启动VMware出现报错:The VMware Authorization Service is not running
    C++调用被C编译器编译过的函数要加extern "C"(转自http://zhidao.baidu.com/question/193713666.html)
    json,junit运行java.lang.NoClassDefFoundError: org/apache/commons/collections/map/ListOrderedMap
    java生成xml文件
    java连接数据库
    eclipse_javaee运行时总是未响应
  • 原文地址:https://www.cnblogs.com/jingpeipei/p/5989259.html
Copyright © 2011-2022 走看看