自定义MVC

1.什么是MVC?
MVC全名:Model View Controller,其中Model(模型层)、View(视图层)、Controller(控制层)
它是一种软件设计典范,用于业务逻辑处理、数据、界面显示分离,

常用模式:
model1:jsp+jdbc
model2:mvc

三层架构和MVC的区别?
三层架构是一个经典的分层思想,将开发模式分为三层,每个人专注自己擅长模块即可
MVC是一种设计模式,其目的是让html和业务逻辑分开

2.MVC结构?

V(视图层)--》 JSP

C(控制层)--》 Servlet/Action

M(模型层)--》 Dao、Entity
1)实体域模型(entity层)
2)过程域模型(dao层)

注:1)不能跨层调用;
2)只能由上往下进行调用;View -> Controller -> Model

3.自定义MVC工作原理图

    *.action           调度           截取*(请求路径名) 处理具体业务逻辑

JSP -----------> Servlet(中央控制器)--------------------->Action(子控制器)—>Model(Dao、DB)

通过XML对自定义MVC框架进行3步增强

一、反射增强第一步:
1)config.xml建模

 2)获取Action配置信息  findActionModel

 3)反射机制实例化Action子控制器  createAction

 4)将请求委托给子控制器处理并返回结果码 execute()  -->  processCode

 5)根据返回结果码进行页面跳转  --> forwardModel
  重定向/转发

二、反射增强第二步: 将一组相关的操作放到一个Action中(反射调用方法)

 1)创建DispatcherAction类
 DispatcherAction extends Action
 
 2)根据请求参数获取方法名,利用反射机制调用方法
 参数名:methodName:add/minus/mul/div

 3)创建CalAction类(CalAction提供一组加减乘除的方法)
 CalAction extends DispatcherAction
    提供一组与execute方法的参数、返回值相同的方法,只有方法名不一样

三、反射增强第三步:利用ModelDriver接口对Java对象进行赋值(反射读写属性)

 1)利用反射机制对Java对象进行属性赋值
 简化调用:BeanUtils.populate(calBean, parameterMap);

 2)ModelDriver接口返回的对象不能为空

 注1:Action多例模式?因为Action的属性要用来接收参数

xml建模:

package com.xujie.mvc.forward;

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

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

/**
 * xml建模
 */
public class ConfigModelFactory {
    private static final String defpath="/abc.xml";
    private static ConfigModel configModel;

    public static ConfigModel createConfigModel() throws DocumentException {
        return createConfigModel(defpath);
    }
    public static ConfigModel createConfigModel(String path) throws DocumentException {
        if(null != configModel){
            return configModel;
        }
        configModel = new ConfigModel();
        //获取io流
        InputStream is = ConfigModelFactory.class.getResourceAsStream(path);
        //读取器对象
        SAXReader sr = new SAXReader();
        //得到document对象
        Document document = sr.read(is);
        List<Element> actionElement = document.selectNodes("/config/action");
        ActionModel actionModel = null;
        String actionPath = null;
        String actionType = null;
        ForwardModel forwardModel = null;
        String forwardName = null;
        String forwardPath = null;
        boolean forwardRedirect = false;
        for (Element a:actionElement
             ) {
            actionModel = new ActionModel();
            actionPath = a.attributeValue("path");
            actionType = a.attributeValue("type");
            actionModel.setPath(actionPath);
            actionModel.setType(actionType);
            configModel.put(actionModel);
            //得到forward节点
            List<Element> forward = a.selectNodes("forward");
            //遍历forward节点
            for (Element ward: forward
                 ) {
                forwardModel = new ForwardModel();
                forwardName = ward.attributeValue("name");
                forwardPath = ward.attributeValue("path");
                forwardRedirect = Boolean.parseBoolean(ward.attributeValue("redirect"));
                forwardModel.setPath(forwardPath);
                forwardModel.setName(forwardName);
                forwardModel.setRedirect(forwardRedirect);
                //加到actionmodel里面的键值对里面
                actionModel.put(forwardModel);
            }



        }
        return configModel;

    }

    public static void main(String[] args) throws DocumentException {
        ConfigModel model = ConfigModelFactory.createConfigModel();
        System.out.println(model);
    }

}

子控制器父类:

/**
 * 子控制器父类 也不执行业务代码
 */
public abstract class Action  {
    public abstract String execute(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException;
}

中央控制器:

package com.zking.j2ee12.mvc.framwork;

import com.zking.j2ee12.mvc.entity.CalBean;
import com.zking.j2ee12.mvc.xml.ActionMod;
import com.zking.j2ee12.mvc.xml.ConfigMod;
import com.zking.j2ee12.mvc.xml.ConfigTe;
import com.zking.j2ee12.mvc.xml.ForwardMod;
import org.apache.commons.beanutils.BeanUtils;
import org.dom4j.DocumentException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

/**
 * 中央控制器 不执行业务代码,负责转发请求
 */
public class ActionServlet extends HttpServlet {
    //定义一个集合 放入子控制器
//    Map<String,Action> map = new HashMap<>();
    private ConfigMod configMod;


    @Override
    public void init(ServletConfig config) throws ServletException {
       

        try {

            String path = config.getInitParameter("config");
            if(null == path){
                configMod = ConfigTe.createConfigTe();
            }else{
                configMod = ConfigTe.createConfigTe(path);
            }




        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }


    }

    @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 {
        String servletPath = req.getServletPath();
        int i = servletPath.lastIndexOf(".action");
        String path = servletPath.substring(0, i);

        //通过*部分 从集合找到对应的子控制器
        ActionMod actionModel = this.findActionModel(path, configMod);

        


        try {
            //反射实例化对象
            Action action = this.createAction(actionModel.getType());

            //给实体类赋值
            this.processModelDriver(action,req);

            //执行子控制器中的execute方法
            String code = action.execute(req, resp);



            //通过execute方法的返回值控制跳转
            this.processCode(code,actionModel,req,resp);


        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }


    private ActionMod findActionModel(String path,ConfigMod configMod){
        ActionMod actionMod = configMod.get(path);
       if(null == actionMod){
           throw new RuntimeException("找不到"+path+"对应的action");
       }
        return actionMod;
    }

    /**
     * 反射实例化对象
     * @param type
     * @return
     * @throws ClassNotFoundException
     * @throws InstantiationException
     * @throws IllegalAccessException
     */
    private Action createAction(String type) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        //1.获取类对象
        Class aClass = Class.forName(type);
        //实例化对象
        Action action =(Action) aClass.newInstance();
        return action;
    }

    /**
     * 处理execute方法的返回值 通过返回值实现跳转页面
     */
    private void processCode(String code,ActionMod actionMod, HttpServletRequest req,HttpServletResponse resp) throws IOException, ServletException {
        //1.通过code找到对应的forwardmodel对象
        if(null == code || "".equals(code)){
            return;//如果没有返回值 方法结束
        }
        //1.通过code找到对应的forwardmodel对象
        ForwardMod forwardMod = actionMod.get(code);
        if(null == forwardMod){//判断forwardmodel是否为空
            throw  new RuntimeException("找不到");
        }
        if(forwardMod.isRedirect()){//forwarmodel的属性为true
            resp.sendRedirect(req.getContextPath()+forwardMod.getPath());
        }else{
            req.getRequestDispatcher(forwardMod.getPath()).forward(req,resp);
        }

    }

    /**
     * 配合modeldriver
     */
    private void processModelDriver(Action action,HttpServletRequest req)  {
        //判断action是否实现了modeldriver接口
        if(action instanceof ModelDriver){
            //将action强转成modeldriver类型
            ModelDriver md = (ModelDriver) action;
            Object obj = md.getModel();

            //遍历所有请求参数和obj的属性一致 就赋值
            Map<String, String[]> map = req.getParameterMap();


            try {
                BeanUtils.populate(obj,map);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

        }
    }


}

方法调用:

package com.zking.j2ee12.mvc.action;

import com.zking.j2ee12.mvc.framwork.Action;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;

/**
 * 处理一组相似或者相关的操作方法 反射调用方法
 */
public class DispatcherAction extends Action {


    @Override
    public final String execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1. 获取请求参数中的方法名
        String methodName = this.getMethodName(req);

        //2.放射调用方法
        //2.1获取类对象
        Class clazz = this.getClass();
        //2.2获取方法对象
        Method declaredMethod = clazz.getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);


        //2.3打开访问限制
        declaredMethod.setAccessible(true);
        //调用方法
        String code =(String) declaredMethod.invoke(this, req, resp);


        return code;
    }


    private String getMethodName(HttpServletRequest req){
        String methodName = req.getParameter("methodName");
        if(null == methodName || "".equals(methodName)){
            Map<String, String[]> map = req.getParameterMap();
            Set<String> set = map.keySet();
            for (String key: set
                 ) {
                if(-1 != key.indexOf("method:")){
                    methodName = key.replaceAll("method:", "");


                }
            }


        }
        return methodName;


    }

}

给实体类赋值:

/**
 * 配合actionservlet 给实体类赋值
 * @param <K>
 */
public interface ModelDriver<K> {
    public K getModel();
}

web.xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--配置中央控制器-->
    <servlet>
        <servlet-name>ActionServlet</servlet-name>
        <servlet-class>com.xujie.mvc.forward.ActionServlet</servlet-class>
        <!--配置文件路径-->
        <init-param>
            <param-name>config</param-name>
            <param-value>/abc.xml</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>

        <servlet-name>ActionServlet</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
    <!--配置中文乱码-->
    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>com.xujie.mvc.util.EncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>EncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

<!--欢迎页面-->
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>
package com.zking.j2ee12.mvc.action;

import com.zking.j2ee12.mvc.entity.CalBean;
import com.zking.j2ee12.mvc.framwork.Action;
import com.zking.j2ee12.mvc.framwork.ModelDriver;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 子控制器  负责用户的操作
 */
public class CalAction extends DispatcherAction implements ModelDriver<CalBean> {
    private CalBean calBean = new CalBean();


    public String add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Float rs =  calBean.getNum1()+ calBean.getNum2();
        req.getSession().setAttribute("rs",rs);

        return "rs";
    }

   


    @Override
    public CalBean getModel() {
        return calBean;
    }
}

config.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
	<!--
		config标签:可以包含0~N个action标签
	-->
<config>
	<!--
		action标签:可以饱含0~N个forward标签
		path:/开头的字符串,并且值必须唯一 非空
		type:字符串,非空
	-->
		

	<action path="/calAction" type="com.zking.j2ee12.mvc.action.CalAction">
	<!--
			forward标签:没有子标签; 
			name:字符串,同一action标签下的forward标签name值不能相同 ;
			path:/开头的字符串
			redirect:只能是false|true,允许空,默认值为false
		-->
		<forward name="rs" path="/rs.jsp" redirect="true" />
		<forward name="success" path="/main.jsp" redirect="true" />
	</action>

	<action path="/userAction" type="com.zking.j2ee12.mvc.action.UserAction">
		<forward name="rs" path="/rs.jsp" redirect="true" />
		<forward name="success" path="/main.jsp" redirect="true" />
	</action>
</config>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值