框架模式学习 ———— MVC

mvc模式

结构图:
框架模式学习 ———— MVC - stanley - 小老头
 
示例:
实现一个mvc框架步骤:
  1. 定义配置文件dtd

    <!-- 示例 -->

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

    <!ELEMENT myMvc (actions)>
    <!ELEMENT actions (action*)>
    <!ELEMENT action (result*)>
    <!ATTLIST action
    name CDATA #REQUIRED
    class CDATA #REQUIRED>
    <!ELEMENT result (#PCDATA)>
    <!ATTLIST result
    name CDATA #IMPLIED
    redirect (true|false) "false">


  2. 定义配置文件

    <!-- 创建一个使用刚创建的dtd的配置文件 -->

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE myMvc PUBLIC "-//UNKOWN/" "mymvc.dtd"><!--此处引用上面的自定义dtd-->
    <myMvc>
    <actions>
    <action name="login" class="cn.stanley.action.LoginAction">
    <result name="success">pages/success.jsp</result>
    <result name="input">pages/login.jsp</result>
    </action>
    <action name="regist" class="cn.stanley.action.LoginAction">
    <result name="success">pages/success.jsp</result>
    <result name="input">pages/login.jsp</result>
    </action>
    </actions>
    </myMvc>


  3. 创建 请求——操作 映射类

    /**

    * 映射 响应结果与视图之间的关系

    */
    public class ResultMapping {
    private String name;
    private boolean redirect;
    private String path;
    public String getName() {
    return name;
    }
    public void setName(String name) {
    this.name = name;
    }
    public boolean isRedirect() {
    return redirect;
    }
    public void setRedirect(boolean redirect) {
    this.redirect = redirect;
    }
    public String getPath() {
    return path;
    }
    public void setPath(String path) {
    this.path = path;
    }

    public ResultMapping(){}

    public ResultMapping(String name, boolean redirect, String path) {
    super();
    this.name = name;
    this.redirect = redirect;
    this.path = path;
    }
    }

    /**

    * 映射 请求与处理请求方法之间的关联

    */

    public class ActionMapping {

    private String name;

    private String className;

    private Map<String,ResultMapping> resultMap=

    new HashMap<String, ResultMapping>(0);


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

    public Map<String, ResultMapping> getResultMap() {
    return resultMap;
    }

    public void setResultMap(Map<String, ResultMapping> resultMap) {
    this.resultMap = resultMap;
    }

    public ActionMapping(String name, String className) {
    super();
    this.name = name;
    this.className = className;
    }

    public ActionMapping(){}


    public void addResult(ResultMapping result){
    this.resultMap.put(result.getName(), result);
    }
    }


  4. 创建 配置文件解析类,解析配置文件并生成 请求——操作的映射对象

    /**

    * 解析配置文件生成相就的映射对象 ,并管理

    */

    public class ActionMappingManager {

    private Map<String, ActionMapping> actionMappings = 

    new HashMap<String, ActionMapping>();

    public ActionMappingManager(String[] configFileNames) {
    for (String configFileName : configFileNames) {
    try {
    init(configFileName);
    } catch (DocumentException e) {
    e.printStackTrace();
    }
    }
    }

    @SuppressWarnings("rawtypes")
    public void init(String configFileName) 

    throws DocumentException {
    // dom4j 解析器
    SAXReader reader = new SAXReader();
    // 设置 dtd 解析器 此片因为是自定义dtd,所以写了一个FindDTD类设定dtd
    reader.setEntityResolver(new FindDTD());
    //读取根节点
    Document document = reader.read(DocumentException.class
    .getResourceAsStream("/" + configFileName));
    //子节点集合
    List nodes = document.getRootElement().element("actions")
    .elements("action");
    //遍楞子节集合
    for (Iterator iterator = nodes.iterator();

    iterator.hasNext();) {

    Element node = (Element) iterator.next();
    ActionMapping acm = new ActionMapping(
    node.attributeValue("name"),

    node.attribute("class").getValue());

    // 遍历 result
    for (Iterator it2 = node.elements("result")

    .iterator(); it2.hasNext();) {

    Element ele = (Element) it2.next();

    String name = ele.attributeValue("name");
    boolean redirect = 

    Boolean.valueOf(ele.attributeValue("redirect"));

    String path = ele.getText();
    acm.addResult(new ResultMapping(

    name, redirect, path));
    }
    actionMappings.put(acm.getName(), acm);
    }
    }

    /**
    * 根据 请求中的 actionName 取 ActionMapping
    *
    * @param actionName
    * @return
    * @throws Exception
    */
    public ActionMapping getActionMapping(String actionName) {
    if (null == actionName || actionName.isEmpty()) {
    return null;
    }
    ActionMapping mapping = actionMappings.get(actionName);
    if (mapping == null) {
    throw new RuntimeException("不存在此mapping:" + 

    actionName);
    }
    return mapping;
    }
    }

    /**

    * 自定义DTE 解析器,因为是自定义DTD,web容器会默认在bin目录下找,

    * 而指定相对路径与绝对路径都不能正确获取,所以得自定义

    */

    public class FindDTD implements EntityResolver {

    @Override
    public InputSource resolveEntity(String publicId, String systemId)
    throws SAXException, IOException {

    //自已的dtd所在的位置
    String path = "mymvcframework/" +

    systemId.substring(systemId.lastIndexOf("/")+1);
    InputStream in=this.getClass()

    .getClassLoader()

    .getResourceAsStream(path);
    InputSource so=new InputSource(in);
    return so;
    }

    }


  5. 定义 action 接口


    /**
    * Action 接口
    * @author Administrator
    *
    */
    public interface Action {

    /**
    * 执行 业务与 数据 访问操作
    * @param req
    * @param res
    * @return
    * @throws Exception
    */
    String execute(HttpServletRequest req, HttpServletResponse res)
    throws Exception;

    }



  6. 创建 controller

    /**

    * 这是整个mvc框加的核心

    */

    public class ActionFilter implements Filter {
    /**
    * actionMappingManager 实例
    */
    private ActionMappingManager mappingManage;

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res,
    FilterChain chain) throws IOException, ServletException {
    //请求类型转换
    HttpServletRequest hreq = (HttpServletRequest) req;
    HttpServletResponse hres = (HttpServletResponse) res;
    //获取 动作映射
    ActionMapping aMapping=null;
    try {
    aMapping = getActionMapping(hreq, hres);
    } catch (Exception e1) {
    throw new RuntimeException(e1);
    }
    if (null == aMapping) {
    throw new RuntimeException("资源不存在");
    }
    //创建 动作对象 并执行
    Action action = ActionFactory

    .createAction(aMapping.getClassName());
    String resultName = null;
    try {
    resultName = action.execute(hreq, hres);
    } catch (Exception e) {
    e.printStackTrace();
    }
    if (resultName == null) {
    throw new RuntimeException("结果视图不存在");
    }
    //取出 结果映射
    ResultMapping result = aMapping. getResultMap()

    .get(resultName);
    //判断 结果映射 晌应方式
    if (result.isRedirect()) { //重定向
    hres.sendRedirect(result.getPath());
    } else { //转发
    req.getRequestDispatcher(result.getPath())
    .forward(req, res);
    }

    }

    /**
    * 初始化操作 :: 读取web.xml 中的 初始参数配置 ,

    * 创建 ActionMappingManager 类
    */
    @Override
    public void init(FilterConfig config) throws ServletException {
    //获取配置参数 config
    String conStr=config.getInitParameter("config");
    //配置的文件名数组
    String[] configFileNames=null;
    if(conStr==null|| conStr.isEmpty()){

    }else{
    configFileNames=conStr.split(",");
    }
    // 创建 actionMappingManager 类
    this.mappingManage=new ActionMappingManager(configFileNames);

    }

    /**
    * 获取动作
    * @param req
    * @param res
    * @return
    * @throws Exception
    */
    private ActionMapping getActionMapping(HttpServletRequest req,
    HttpServletResponse res) throws Exception {
    //获取 uri
    String url = req.getRequestURI();
    //获取应用名
    String contextPath = req.getContextPath();
    //获取 *.action...
    String actionPath = url.substring(contextPath.length());
    //获取 *.action 中 的 * 部分
    String actionName = actionPath
    .substring(1, actionPath.lastIndexOf("."));
    // 返加 actionMapping
    return mappingManage.getActionMapping(actionName);
    }

    }


    /**

    * 此处用一个返射工厂来创建Action实例

    */

    public class ActionManager {

    public static Action createAction(String className){
    try {
    return (Action) Class.forName(className)

    .newInstance();
    } catch (InstantiationException e) {
    e.printStackTrace();
    } catch (IllegalAccessException e) {
    e.printStackTrace();
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }

    return null;
    }

    }


  7. 将控制器配置到 web.xml中


MVC的优点:
1、可以为一个模型在运行时同时建立和使用多个视图。变化-传播机制可以确保所有相关的视图及时得到模型数据变化,从而使所有关联的视图和控制器做到行为同步。 
2、视图与控制器的可接插性,允许更换视图和控制器对象,而且可以根据需求动态的打开或关闭、甚至在运行期间进行对象替换。
3、模型的可移植性。因为模型是独立于视图的,所以可以把一个模型独立地移植到新的平台工作。需要做的只是在新平台上对视图和控制器进行新的修改。
 
MVC的不足之处
1、增加了系统结构和实现的复杂性。对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。
2、视图与控制器间的过于紧密的连接。视图与控制器是相互分离,但确实联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。
3、视图对模型数据的低效率访问。依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值