自定义mvc框架

自定义mvc框架工作原理

什么是mvc

MVC全名:Model View Controller,其中Model(模型层)、View(视图层)、Controller(控制层)

三层架构和MVC的区别
三层架构是一个经典的分层思想,将开发模式分为三层,每个人专注自己擅长模块即可

MVC是一种设计模式,其目的是让视图和业务逻辑分开
 

一.优化中央控制器,子控制器

xml建模

 jar包

 中央控制器
 

package com.lsy.framework;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.dom4j.DocumentException;
import com.lsy.servlet.BookAction;
import com.lsy.servlet.GoodsAaction;
 
@WebServlet("*.action")
public class DispatchServlet extends HttpServlet{
	//在当前中央控制器中必然会有所有子控制器集合
	//缺陷:如果有商品的增删改查-->意味着要改动代码-->代码的设计不够灵活
	//思考:在不改动代码的情况下,中央控制器也能找到对应的子控制器去处理浏览器请求
	//方案:我把加子控制器的逻辑/动作,放到配置文件中完成(Dbutil改连接信息是放在代码中完成/现在是放在Properties文件中完成)
	//放在配置文件中完成的好处在于代码更加灵活,修改相关信息不用动代码
	//ConfigModel对象又通过建模的知识,把所有的配置信息给读取过来了
	//private Map<String, ActionSupport> actions=new HashMap<>();
    //现在在xml中改
	private ConfigModel configModel=null;
	
	
	@Override
	public void init() throws ServletException {
		//在集合中就有了一个子控制器
		//actions.put("/book", new BookAction());
		//缺陷显示
		//actions.put("/goods",new GoodsAaction());
		try {
			configModel=ConfigModelFactory.build();
		} catch (Exception e) {
			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 {
		//把子控制器与浏览器请求关联起来,“寻找”能够处理请求的子控制器
		/**
		 * 思路
		 * 1、uri-->book
		 * 2、通过/book字符串在actions找到BookAction
		 * 3、调用BookAction的add,想要调用add,实际上只要统一调用execute就可以了
		 */
		//获取到浏览器的请求地址
		String uri = req.getRequestURI();
        //通过截取获取到请求地址
		uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
		
		//通过/book字符串在actions找到BookAction
		
		//原来在Map中寻找子控制器-->在配置文件中寻找子控制器
		
		
		ActionModel actionModel = configModel.pop(uri);
		String type = actionModel.getType();
		ActionSupport action;
		try {
			action = (ActionSupport) Class.forName(type).newInstance();
			action.execute(req, resp);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
 
 
//不需要在代码中动,在xml中动
<?xml version="1.0" encoding="UTF-8"?>
<config>
	<!-- 
	在这里每加一个配置,就相当于actions.put("/goods",new GoodsAaction());
	这样就解决了代码灵活性的问题
	 -->
	 <action path="/book" type="com.lsy.servlet.BookAction">
		<forward name="list" path="/bookList.jsp" redirect="false" />
		<forward name="toEdit" path="/bookEdit.jsp" redirect="true" />
	</action>
	 
	<action path="/goods" type="com.lsy.servlet.GoodsAction">
		<forward name="failed" path="/login.jsp" redirect="false" />
		<forward name="success" path="/main.jsp" redirect="true" />
	</action>
	
	<action path="/order" type="com.lsy.servlet.OrderAction">
		<forward name="failed" path="/login.jsp" redirect="false" />
		<forward name="success" path="/main.jsp" redirect="true" />
	</action>
</config>

子控制器

package com.lsy.framework;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 子控制器用于处理浏览器请求
 */
public interface Action {
	//这个方法就是add/ref进行向上抽取的方法
	//作用:能够处理浏览器的“所有”请求,包括add/ref
	public void execute(HttpServletRequest req,HttpServletResponse resp);
	
//	private void add(HttpServletRequest req, HttpServletResponse resp) {
//		System.out.println("--增加--");
//		
//	}
//	
//	private void ref(HttpServletRequest req, HttpServletResponse resp) {
//		System.out.println("--ref--");
//		
//	}
 
}

ActionSupport

用于实现上面的action接口

作用:能够处理浏览器的“所有”请求,意思就是可以获取到当前的方法

package com.lsy.framework;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 作用:能够处理浏览器的“所有”请求,包括add/ref
 *
 */
public class ActionSupport implements Action{
 
	@Override
	public void execute(HttpServletRequest req, HttpServletResponse resp) {
		String methodName = req.getParameter("methodName");
		try {
			Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
			m.setAccessible(true);
			m.invoke(this,req, resp);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}	
}

BookAction继承ActionSupport

通过继承将方法反射调用过来,减少代码重复,方便

 
  1.  
    package com.lsy.servlet;
     
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import com.lsy.framework.ActionSupport;
    public class BookAction extends ActionSupport{
    	//从父类继承了execute方法,就把反射动态调用方法的代码继承过来了
    	//当前子控制器在哪里调用?把子控制器与浏览器请求关联起来
    //以下只需要关注业务	
    private void add(HttpServletRequest req, HttpServletResponse resp) {
    	System.out.println("--增加--");
    }
     
     
    private void list(HttpServletRequest req, HttpServletResponse resp) {
    	System.out.println("--查询--");
    	
    }
     
    private void ref(HttpServletRequest req, HttpServletResponse resp) {
    	System.out.println("--ref--");
    	
    }
    	
    private void goods(HttpServletRequest req, HttpServletResponse resp) {
    	System.out.println("--购物--");
    	
    }
    }

    实体类代码冗余  Book实体类

    模型驱动接口   ModelDriver<T>  T是实体类,驱动接口可以进行参数封装

    package com.lsy.framework;
    import org.apache.commons.beanutils.BeanUtils;
    import com.lsy.entity.Book;
    /**
     * 模型驱动接口作用,帮助中央控制器完成参数封装工程
     * BeanUtils.populate(bean, req.getParameterMap());相当于下面代码
     *  Book book=new Book();
    	book.setBid(req.getParameter("bid"));
    	book.setBname(req.getParameter("bname"));
    	book.setPrice(req.getParameter("price"));
    	book.setAthor(req.getParameter("athor"));
    	book.setPublish(req.getParameter("publish"));
     * @param <T>
     */
    public interface ModelDriver<T> {
    	/**
    	 * GoodsAction-->goods
    	 * BookAction-->book
    	 * @return
    	 */
    	T getModel();	
     
    }

    BookAction (extends ActionSupport implements ModelDriver<Book>)

    继承ActionSupport实现模型驱动  T传入要封装的实体类

    package com.lsy.servlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import com.lsy.entity.Book;
    import com.lsy.framework.ActionSupport;
    import com.lsy.framework.ModelDriver;
    public class BookAction extends ActionSupport implements ModelDriver<Book>{
    	//从父类继承了execute方法,就把反射动态调用方法的代码继承过来了
    	//当前子控制器在哪里调用?把子控制器与浏览器请求关联起来
    	Book book=new Book();
    //以下只需要关注业务	
    private void add(HttpServletRequest req, HttpServletResponse resp) {
    //	book.setBid(req.getParameter("bid"));
    //	book.setBname(req.getParameter("bname"));
    //	book.setPrice(req.getParameter("price"));
    //	book.setAthor(req.getParameter("athor"));
    //	book.setPublish(req.getParameter("publish"));
    	System.out.println(book);
    	System.out.println("--增加--");
    	}
    @Override
    public Book getModel() {
    	// TODO Auto-generated method stub
    	return book;
    }	
    }

    结果页面统一跳转

    中央控制器

    package com.lsy.framework;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.apache.commons.beanutils.BeanUtils;
    import org.apache.commons.beanutils.PropertyUtils;
    import org.dom4j.DocumentException;
    import com.lsy.servlet.BookAction;
    import com.lsy.servlet.GoodsAaction;
     
    @WebServlet("*.action")
    public class DispatchServlet extends HttpServlet{
    	//在当前中央控制器中必然会有所有子控制器集合
    	//缺陷:如果有商品的增删改查-->意味着要改动代码-->代码的设计不够灵活
    	//思考:在不改动代码的情况下,中央控制器也能找到对应的子控制器去处理浏览器请求
    	//方案:我把加子控制器的逻辑/动作,放到配置文件中完成(Dbutil改连接信息是放在代码中完成/现在是放在Properties文件中完成)
    	//放在配置文件中完成的好处在于代码更加灵活,修改相关信息不用动代码
    	//ConfigModel对象又通过建模的知识,把所有的配置信息给读取过来了
    	//private Map<String, ActionSupport> actions=new HashMap<>();
        //现在在xml中改
    	private ConfigModel configModel=null;
    	
    	
    	@Override
    	public void init() throws ServletException {
    		//在集合中就有了一个子控制器
    		//actions.put("/book", new BookAction());
    		//缺陷显示
    		//actions.put("/goods",new GoodsAaction());
    		try {
    			configModel=ConfigModelFactory.build();
    		} catch (Exception e) {
    			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 {
    		//把子控制器与浏览器请求关联起来,“寻找”能够处理请求的子控制器
    		/**
    		 * 思路
    		 * 1、uri-->book
    		 * 2、通过/book字符串在actions找到BookAction
    		 * 3、调用BookAction的add,想要调用add,实际上只要统一调用execute就可以了
    		 */
    		//获取到浏览器的请求地址
    		String uri = req.getRequestURI();
            //通过截取获取到请求地址
    		uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
    		
    		//通过/book字符串在actions找到BookAction
    		
    		//原来在Map中寻找子控制器-->在配置文件中寻找子控制器
    		
    		
    		ActionModel actionModel = configModel.pop(uri);
    		String type = actionModel.getType();
    		ActionSupport action;
    		try {
    			action = (ActionSupport) Class.forName(type).newInstance();
    			action.execute(req, resp);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    }
     
     
    //不需要在代码中动,在xml中动
    <?xml version="1.0" encoding="UTF-8"?>
    <config>
    	<!-- 
    	在这里每加一个配置,就相当于actions.put("/goods",new GoodsAaction());
    	这样就解决了代码灵活性的问题
    	 -->
    	 <action path="/book" type="com.lsy.servlet.BookAction">
    		<forward name="list" path="/bookList.jsp" redirect="false" />
    		<forward name="toEdit" path="/bookEdit.jsp" redirect="true" />
    	</action>
    	 
    	<action path="/goods" type="com.lsy.servlet.GoodsAction">
    		<forward name="failed" path="/login.jsp" redirect="false" />
    		<forward name="success" path="/main.jsp" redirect="true" />
    	</action>
    	
    	<action path="/order" type="com.lsy.servlet.OrderAction">
    		<forward name="failed" path="/login.jsp" redirect="false" />
    		<forward name="success" path="/main.jsp" redirect="true" />
    	</action>
    </config>

    子控制器

    package com.lsy.framework;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    /**
     * 子控制器用于处理浏览器请求
     */
    public interface Action {
    	//这个方法就是add/ref进行向上抽取的方法
    	//作用:能够处理浏览器的“所有”请求,包括add/ref
    	public void execute(HttpServletRequest req,HttpServletResponse resp);
    	
    //	private void add(HttpServletRequest req, HttpServletResponse resp) {
    //		System.out.println("--增加--");
    //		
    //	}
    //	
    //	private void ref(HttpServletRequest req, HttpServletResponse resp) {
    //		System.out.println("--ref--");
    //		
    //	}
     
    }

    ActionSupport

     
  2.  
    package com.lsy.framework;
    import java.lang.reflect.Method;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    /**
     * 作用:能够处理浏览器的“所有”请求,包括add/ref
     *
     */
    public class ActionSupport implements Action{
     
    	@Override
    	public void execute(HttpServletRequest req, HttpServletResponse resp) {
    		String methodName = req.getParameter("methodName");
    		try {
    			Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
    			m.setAccessible(true);
    			m.invoke(this,req, resp);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}	
    }

    BookAction

    package com.lsy.servlet;
     
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import com.lsy.framework.ActionSupport;
    public class BookAction extends ActionSupport{
    	//从父类继承了execute方法,就把反射动态调用方法的代码继承过来了
    	//当前子控制器在哪里调用?把子控制器与浏览器请求关联起来
    //以下只需要关注业务	
    private void add(HttpServletRequest req, HttpServletResponse resp) {
    	System.out.println("--增加--");
    }
     
     
    private void list(HttpServletRequest req, HttpServletResponse resp) {
    	System.out.println("--查询--");
    	
    }
     
    private void ref(HttpServletRequest req, HttpServletResponse resp) {
    	System.out.println("--ref--");
    	
    }
    	
    private void goods(HttpServletRequest req, HttpServletResponse resp) {
    	System.out.println("--购物--");
    	
    }
    }

    xml配置

    <?xml version="1.0" encoding="UTF-8"?>
    <config>
     
    	 <action path="/book" type="com.lsy.servlet.BookAction">
    		<forward name="list" path="/bookList.jsp" redirect="false" />
    		<forward name="toEdit" path="/bookEdit.jsp" redirect="true" />
    	</action>
    	<action path="/goods" type="com.lsy.servlet.GoodsAction">
    		<forward name="failed" path="/login.jsp" redirect="false" />
    		<forward name="success" path="/main.jsp" redirect="true" />
    	</action>
    </config>

    总之,了解思路就行了,知道运行的思路,前端发送请求,后台进行处理与跳转,进行返回,还有一些减少重复代码的方法,可能比较绕,慢慢理解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值