首页 > 代码库 > 自定义MVC框架

自定义MVC框架

一、实现自定义MVC的体系结构图

技术分享

 

 1、Model I模式开发Web应用时,分两种情况:

  *纯JSP技术方式开发

  *JSP+JavaBean方式开发

2、Model I模式开发的不足:

  *JSP页面中嵌入大量的Java代码,可读性差。

  *大量代码在JSP中难以复用。

  *后期维护及扩展的难度大。

3、为了克服Model I模式的缺陷,引入了Model II的模式开发 

  *Model II模式体现了基于MVC(Model-View-Controller,模型-视图-控制器)的设计模式,简单的说,Model II模式就是将数据显示、流程控制和业务逻辑处理分离,使之相互独立。 

4、MVC设计模式由3个部分组成各部分的作用。

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

  *View:视图,用于数据显示。

  *Controller:控制器,用于流程控制。

5、MVC设计模式的特点

  *一个模型可以对应多个视图。

  *显示与逻辑控制分离。

  *分层控制,减低了代码间的耦合。

二、我们如何创建一个自己的MVC框架??

  (一)我们要在lib里面准备一个夹包

    dom4j-1.6.1.jar    主要作用:解析xml文件

  (二)准备配置文档(在src下)

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE myframework[    <!ELEMENT myframework (actions) >    <!ELEMENT actions (action*)>    <!ELEMENT action (result*)>    <!ATTLIST action name CDATA #REQUIRED                     class CDATA #REQUIRED    >    <!ATTLIST result name CDATA #IMPLIED                    redirect (true|false) "false"    >]>

 

    解析:技术分享 

<myframework>        <actions>            <action name="LoginAction" class="cn.happy.action.LoginAction">                <result name="success">success.jsp</result>                <result name="login">index.jsp</result>            </action>        </actions></myframework>

 

    解析:根据上述约束完成的“*”代表多次

(三)自己准备一个Action接口,用于放入结果集和执行方法

package cn.happy.action;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public interface Action {//定义字符串常量    public static final String SUCCESS="success";    public static final String NONE="none";    public static final String ERROR="error";    public static final String INPUT="input";    public static final String LOGIN="login";//准备一个方法,用于获取数据    public String execute(HttpServletRequest request,HttpServletResponse response)throws Exception;    }

 

(四)定义一个ActionMapping用来存放Action节点

package cn.happy.action;import java.util.HashMap;import java.util.Map;/* * Action配置文件信息,用来放置Action的节点的 * */public class ActionMapping {    //访问的Action的名称    private String name;    //访问Action的对应的Action的类的全称    private String ClassName;    //result定义的结果集    private Map<String,String> resultMaps=new HashMap<String,String>();        //往集合里面添加配置文件中的数据信息    public void addResult(String resultName,String result){        resultMaps.put(resultName, result);    }    //根据resultName获取对应的result页面    public String getResult(String resultName){        return resultMaps.get(resultName);    }        public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getClassName() {        return ClassName;    }    public void setClassName(String className) {        ClassName = className;    }    }

 

(五)准备一个ActionMappingManager是用来管理ActionMapping的

package cn.happy.action;import java.io.InputStream;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;/* * 用来管理ActionMapping也就是可以保存多个action节点信息 *  * */public class ActionMappingManager  {    //保存多个action节点信息    private Map<String ,ActionMapping> actionMappings=new HashMap<String,ActionMapping>();    public ActionMapping getActionMapping(String name){        return actionMappings.get(name);    }        //带参构造    public ActionMappingManager(String[] configFileNames){        for(String filaName:configFileNames){            //调用根据文件名读取配置文件的方法            init(filaName);        }    }    //解析xml    public void init(String configFileName){            System.out.println("======init");        try {            //读取配置文件,肯定用到了输入流            InputStream is=this.getClass().getResourceAsStream("/"+configFileName);            //开始读取xml文件            Document doc=new SAXReader().read(is);            //获取根节点            Element root=doc.getRootElement();            //获取Action节点            Element actions=(Element) root.elementIterator("actions").next();            //开始遍历Action节点            for(Iterator<Element>action=actions.elementIterator("action");action.hasNext();){                //获取到Action节点,将其属性进行封装                Element actionElement=action.next();                //获取name                String name=actionElement.attributeValue("name");                //获取到ClassName                String ClassName=actionElement.attributeValue("class");                //一个Action对应着一个ActionMapping,创建ActionMapping进行赋值                ActionMapping actionMapping=new ActionMapping();                actionMapping.setName(name);                actionMapping.setClassName(ClassName);                //遍历Action的子元素result                for(Iterator<Element> result=actionElement.elementIterator("result");result.hasNext();){                    Element resultElement=result.next();                    //获取result属性值                    String resultName=resultElement.attributeValue("name");                    String resultValue=resultElement.getText();                    //将每个result封装 到ActionMapping中去                    actionMapping.addResult(resultName, resultValue);                }                //将ActionMapping放入ActionMappingManager中去                actionMappings.put(actionMapping.getName(),actionMapping);            }        } catch (DocumentException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }            }    }

 

(六)利用反射机制找到自己的实列

package cn.happy.action;/* * 利用反射机制,根据类的类型获取到类的实列 * */public class ActionManager {public static Action creatAction(String className){    Class clazz=null;        try {        //判断当前线程是否有该Action        clazz=Thread.currentThread().getContextClassLoader().loadClass(className);            } catch (ClassNotFoundException e) {        // TODO Auto-generated catch block        e.printStackTrace();    }    if(clazz==null){                try {            //根据类的全路径,手动创建一个类的类类型            clazz=Class.forName(className);        } catch (ClassNotFoundException e) {            e.printStackTrace();        }    }    Action  action=null;    try {        //根据类的类类型创建出一个类的实例        action=(Action) clazz.newInstance();    } catch (InstantiationException e) {                e.printStackTrace();    } catch (IllegalAccessException e) {        e.printStackTrace();    }    return action;}}

 

(七)写一个业务逻辑

package cn.happy.action;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;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("1".equals(name)&&"1".equals(pwd)){            return SUCCESS;        }else{            return LOGIN;        }            }}

 

(八)写一个Servlet

package cn.happy.Servlet;import java.io.IOException;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import cn.happy.action.Action;import cn.happy.action.ActionManager;import cn.happy.action.ActionMapping;import cn.happy.action.ActionMappingManager;public class MVCServlet extends HttpServlet {    /*            出品人:执念     */    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {            doPost(request, response);    }    /*            出品人:执念     */    ActionMappingManager actionMappingManager=null;    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {                try {            //根据ActionName获取到ActionMapping            ActionMapping actionMapping=actionMappingManager.getActionMapping(getActionName(request));            //根据ActionMapping中的ClassName获取到具体的类的实列            Action action=ActionManager.creatAction(actionMapping.getClassName());            //执行业务逻辑,获取到resultName            String resultName=action.execute(request,response);            //根据resultName获取具体的result视图            String result=actionMapping.getResult(resultName);            //重定向到页面            response.sendRedirect(result);                    } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }            }    //根据请求的上下文获取到ActionName    public String getActionName(HttpServletRequest request){        //获取带URI        String uri=request.getRequestURI();        //获取上下文路径        String contextPath=request.getContextPath();        //从上下文截取Actionpath        String actionPath=uri.substring(contextPath.length());        //获取到ActionName        String actionName=actionPath.substring(1,actionPath.lastIndexOf(.)).trim();        return actionName;    }    //在加载servlet的时候就读配置文件信息    @Override    public void init(ServletConfig config)throws ServletException{        //读取配置信息        String configStr=config.getInitParameter("config");        String[] fileNames=null;        if(configStr==null||configStr.isEmpty()){            fileNames=new String[]{"MyMvc.xml"};        }else{            fileNames=configStr.split(",");        }        //读取配置文件,将文件中的信息保存到ActionMappingManager中        actionMappingManager=new ActionMappingManager(fileNames);    }}

 

(九)修改web.xml

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

 

(十)准备一个login.jsp页面

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href=http://www.mamicode.com/"<%=basePath%>">        <title>My JSP index.jsp starting page</title>  </head>    <body>            <form action="LoginAction.action" method="post">                用户名:<input type="text" name="name"/><br/>                密码:<input type="password" name="pwd"/><br/>                <input type="submit" value=http://www.mamicode.com/"登录"/>            </form>  </body></html>

 

(十一)准备一个成功页面代码省略

总结:自定义的MVC模式

    定义ActionMapping,是用来放置Action的节点的 

    定义ActionMappingManager,管理ActionMapping

    定义ActionManager利用反射机制,找到具体类的实列

 

 

自定义MVC框架