自定义简单算法MVC框架

 什么是MVC框架

   MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,
   它是一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,其好处是将业务逻辑聚集到一个部件里面,在改进和指定个性化页面的同时不需要重新编写业务逻    辑,MVC被独特的发展起来用于映射传统的输入,处理,显示在一个业务逻辑的图形化业务界面中。

  

  核心思想:各司其职

  注1:不能跨层调用
  注2:只能出现由上而下的调用

 

MVC工作原理图:

主控制(ActionServlet)动态调用子控制器(Action)调用完成具体的业务逻辑(火车、控制台、车轨)请求、主控制器、子控制器

 

具体代码如下:

1,导入需要用到的jar包

 

2、mvc.xml建模     将Action的信息配置到xml(反射实例化)

     解决了在框架代码中去改动,以便于完成客户需求,在框架中更改代码是不合理的

mvc.xml文件

<?xml version="1.0" encoding="UTF-8"?>
 
<config>
 
 
 <!-- <action path="/addCal" type="com.yuan.web.AddCalAction">
  <forward name="res" path="/res.jsp" redirect="false" />
 </action>
 
 <action path="/delCal" type="com.yuan.web.DelCalAction">
  <forward name="res" path="/res.jsp" redirect="true"/>
 </action>  -->
 
 
  <action path="/cal" type="com.yuan.web.CalAction">
  <forward name="res" path="/res.jsp" redirect="false"/>
 </action>

</config>

ForwardModel

package com.yuan.framework;

import java.io.Serializable;

/**
 * 用来描述forward标签
 * @author Administrator
 *
 */
public class ForwardModel implements Serializable {

    private static final long serialVersionUID = -8587690587750366756L;

    private String name;
    private String path;
    private String redirect;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getRedirect() {
        return redirect;
    }

    public void setRedirect(String redirect) {
        this.redirect = redirect;
    }

}

ActionModel

package com.yuan.framework;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * 用来描述action标签
 * @author Administrator
 *
 */
public class ActionModel implements Serializable{

    private static final long serialVersionUID = 6145949994701469663L;
    
    private Map<String, ForwardModel> forwardModels = new HashMap<String, ForwardModel>();
    
    private String path;
    
    private String type;
    
    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public void put(ForwardModel forwardModel){
        forwardModels.put(forwardModel.getName(), forwardModel);
    }
    
    public ForwardModel get(String name){
        return forwardModels.get(name);
    }
    
}

ConfigModel

package com.yuan.framework;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * 用来描述config标签
 * @author Administrator
 *
 */
public class ConfigModel implements Serializable{

    private static final long serialVersionUID = -2334963138078250952L;
    
    private Map<String, ActionModel> actionModels = new HashMap<String, ActionModel>();
    
    public void put(ActionModel actionModel){
        actionModels.put(actionModel.getPath(), actionModel);
    }
    
    public ActionModel get(String name){
        return actionModels.get(name);
    }
    
}

ConfigModelFactory

package com.yuan.framework;

import java.io.InputStream;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class ConfigModelFactory {
    private ConfigModelFactory() {

    }

    private static ConfigModel configModel = null;

    public static ConfigModel newInstance() throws Exception {
        return newInstance("mvc.xml");
    }

    /**
     * 工厂模式创建config建模对象
     * 
     * @param path
     * @return
     * @throws Exception
     */
    public static ConfigModel newInstance(String path) throws Exception {
        if (null != configModel) {
            return configModel;
        }

        ConfigModel configModel = new ConfigModel();
        InputStream is = ConfigModelFactory.class.getResourceAsStream(path);
        SAXReader saxReader = new SAXReader();
        Document doc = saxReader.read(is);
        List<Element> actionEleList = doc.selectNodes("/config/action");
        ActionModel actionModel = null;
        ForwardModel forwardModel = null;
        for (Element actionEle : actionEleList) {
             actionModel = new ActionModel();
            actionModel.setPath(actionEle.attributeValue("path"));
            actionModel.setType(actionEle.attributeValue("type"));
            List<Element> forwordEleList = actionEle.selectNodes("forward");
            for (Element forwordEle : forwordEleList) {
                forwardModel = new ForwardModel();
                forwardModel.setName(forwordEle.attributeValue("name"));
                forwardModel.setPath(forwordEle.attributeValue("path"));
                forwardModel.setRedirect(forwordEle.attributeValue("redirect"));
                actionModel.put(forwardModel);
            }

            configModel.put(actionModel);
        }

        return configModel;
    }
    
    public static void main(String[] args) {
        try {
            ConfigModel configModel = ConfigModelFactory.newInstance();
            ActionModel actionModel = configModel.get("/loginAction");
            ForwardModel forwardModel = actionModel.get("failed");
            System.out.println(actionModel.getType());
            System.out.println(forwardModel.getPath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3、创建中央控制器

DispatcherServlet

package com.yuan.framework;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.management.RuntimeErrorException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;

import com.yuan.web.AddCalAction;
import com.yuan.web.DelCalAction;

/**
 * 中央控制器
 *   作用: 接受请求,通过请求寻找处理请求对应的子控制器。
 * @author ***
 *
 */
public class DispatcherServlet extends HttpServlet {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
//    private Map<String , IAction> actionMap = new HashMap<>();
    //在configModel对象中包含了所有的子控制器信息,
    private ConfigModel configModel;
    
    public void init() {
//        actionMap.put("/addCal", new AddCalAction());
//        actionMap.put("/delCal", new DelCalAction());
        try {
            String xmlPath = this.getInitParameter("xmlPath");
            if(xmlPath == null || "".equals(xmlPath)){
                configModel  = ConfigModelFactory.newInstance();
            }
            else {
                configModel  = ConfigModelFactory.newInstance(xmlPath);
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req, resp);
        
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        init();
        String url= req.getRequestURI();
//        /项目名/addCal.action
        url = url.substring(url.lastIndexOf("/"), url.lastIndexOf("."));
//        IAction action = actionMap.get(url);
        ActionModel actionModel = configModel.get(url);
        if(actionModel == null) {
            throw new RuntimeException("你没有配置action标签,找不到对应的子控制器来处理浏览器发送的请求");
            
        }
        
        try {
            
            IAction action = (IAction) Class.forName(actionModel.getType()).newInstance();
            
            //此时的action就是com.yuan.web.CalAction
            if(action instanceof ModelDrivern) {
                ModelDrivern  drivern = (ModelDrivern) action;
                //此时的model的所有属性值是null的
                Object model = drivern.getModel(); 
                
                BeanUtils.populate(model, req.getParameterMap());
            
                //我们可以将req.getParameterMap()的值通过反射的方式将其塞进model实例中 (源码)
//                Map<String, String[]> parameterMap = req.getParameterMap();
//                Set<Entry<String, String[]>> entrySet = parameterMap.entrySet();
//                Class<? extends Object> clz = model.getClass();
//                for (Entry<String, String[]> entry : entrySet) {
//                    Field field = clz.getField(entry.getKey());
//                    field.setAccessible(true);
//                    field.set(model, entry.getValue());
//                }

            }
            
            String code = action.execute(req, resp);
            ForwardModel forwardModel = actionModel.get(code);
            if(forwardModel!=null) {
                String jspPath = forwardModel.getPath();
                if("false".equals(forwardModel.getRedirect())) {
                    //做转发的处理
                    req.getRequestDispatcher(jspPath).forward(req, resp);
                }else {
                    resp.sendRedirect(req.getContextPath()+jspPath);
                }
            }
            
        } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | SecurityException | InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
//        action.execute(req, resp);
    }
    
}

web.xml配置

<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>com.yuan.framework.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>xmlPath</param-name>
      <param-value>/mvc.xml</param-value>
    </init-param>
    
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>*.action</url-pattern>
  </servlet-mapping>

4、一个增强版的子控制器(ActionSupport)实现简单的子控制器(IAction)

IAction(接口)

package com.yuan.framework;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 子控制器
 *   作用:用来直接处理浏览器发送过来的请求。
 * @author **
 *
 */
public interface IAction {
    
 String execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException;
 
 
}

ActionSupport      通过结果码控制页面的跳转,减少了逻辑层中的页面跳转代码重复性

package com.yuan.framework;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 增强版子控制器 
 *  原来的子控制器只可以处理一个请求,
 *  有时候用户请求是多个,但是都是操作同一张表,那么原有的子控制器代码编写繁琐。
 *  增强版的作用就是将一组相关的操作放到一个IAction中(子控制器)。
 * @author **
 *
 */
public class ActionSupport implements IAction {

    @Override
    public final String execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String methodName= req.getParameter("methodName");
        String code = null;
        //this在这里指的是CalAction它的一个类实例
        try {
            Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
            m.setAccessible(true);
            code = (String) m.invoke(this, req,resp);
        } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            e.printStackTrace();
        }
        
        
        return code;   
} }

5、业务逻辑层      将一组相关的操作放到一个Action中(反射调用方法)

CalAction

package com.yuan.web;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.entity.Cal;
import com.yuan.framework.ActionSupport;
import com.yuan.framework.ModelDrivern;

public class CalAction extends ActionSupport implements ModelDrivern<Cal> {

    private Cal cal = new Cal();
    
    public String del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        String num1 = req.getParameter("num1");
//        String num2 = req.getParameter("num2");
//        Cal cal = new Cal(Integer.valueOf(num1),Integer.valueOf(num2));
        req.setAttribute("res", cal.getNum1()- cal.getNum2());
//        req.getRequestDispatcher("res.jsp").forward(req, resp);            
        return "res";
    }
    
    
    public String add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        String num1 = req.getParameter("num1");
//        String num2 = req.getParameter("num2");
//        Cal cal = new Cal(Integer.valueOf(num1),Integer.valueOf(num2));
        req.setAttribute("res", cal.getNum1()+cal.getNum2());
//        req.getRequestDispatcher("res.jsp").forward(req, resp);
        
        return "res";
    }
    
    public String chen(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        String num1 = req.getParameter("num1");
//        String num2 = req.getParameter("num2");
//        Cal cal = new Cal(Integer.valueOf(num1),Integer.valueOf(num2));
        req.setAttribute("res", cal.getNum1()*cal.getNum2());
//        req.getRequestDispatcher("res.jsp").forward(req, resp);
        
        return "res";
    }
    
    
    public String chu(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//        String num1 = req.getParameter("num1");
//        String num2 = req.getParameter("num2");
//        Cal cal = new Cal(Integer.valueOf(num1),Integer.valueOf(num2));
        req.setAttribute("res", cal.getNum1()/cal.getNum2());
//        req.getRequestDispatcher("res.jsp").forward(req, resp);
        
        return "res";
    }


    @Override
    public Cal getModel() {
        
        return cal;
    }
    
    
}

6、创建一个模型接口       利用ModelDriver接口对Java对象进行赋值(反射读写属性),剪掉了逻辑层的获取jsp页面传值的代码重复性

package com.yuan.framework;


/**
 * 模型驱动接口
 *   作用:将jsp页面所有传递过来的参数以及参数值
 *   都自动封装到浏览器所要操作的实体类中,
 * @author **
 *
 */
public interface ModelDrivern<T> {

    T getModel();
    
}

7、Cal 实体类

package com.entity;

public class Cal {

    private int num1;
    private int num2;
    public int getNum1() {
        return num1;
    }
    public void setNum1(int num1) {
        this.num1 = num1;
    }
    public int getNum2() {
        return num2;
    }
    public void setNum2(int num2) {
        this.num2 = num2;
    }
    public Cal(int num1, int num2) {
        super();
        this.num1 = num1;
        this.num2 = num2;
    }
    public Cal() {
        super();
        // TODO Auto-generated constructor stub
    }
 
}

8、jsp页面代码

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
  function doSub(num){
      if(num==1){
          calForm.action = "${pageContext.request.contextPath }/cal.action?methodName=add";
      }else if(num==2){
          calForm.action = "${pageContext.request.contextPath }/cal.action?methodName=del";
      }
      else if(num==3){
          calForm.action = "${pageContext.request.contextPath }/cal.action?methodName=chen";
      }
      else if(num==4){
          calForm.action = "${pageContext.request.contextPath }/cal.action?methodName=chu";
      }
      calForm.submit();
  }
</script>
</head>
<body>
<form name="calForm" action="" method="post">
num1:<input type="text" name="num1"> <br>
num2:<input type="text" name="num2"> <br>
    <button onclick="doSub(1)">+</button>
    <button onclick="doSub(2)">-</button>
    <button onclick="doSub(3)">*</button>
    <button onclick="doSub(4)">/</button>

</form>

</body>
</html>

9、运行结果:

 

 

谢谢观看^-^     !!!

 

posted @ 2019-06-26 16:51  Me*源  阅读(517)  评论(0编辑  收藏  举报