自定义MVC原理

目录

一、自定义MVC简介

二、最初的增删改查

三、反射版的增删改查

四、自定义MVC工作原理图以及后台代码实现解析


一、自定义MVC简介


            1、自定义MVC的概念?

MVC全称名是Model(模型层) View(视图层) controller(控制层),它们分工明确,各司其职,同时也具有高类聚,低耦合的特点。


             2、自定义MVC的作用?

                        节省时间和代码。

比如说:我们在写一个项目时,都是从无到有的,创建的过程要写好多代码,还要花费好多时间。所以我们会写一个MVC来继承它,从而得到通用的效果,以至于有更多的时间与精力去完成自己的项目。


              3、为什么会有自定义MVC?

当我们自己项目要去写这么多servlet以及dao包中的方法时,往往都会出现一个共同的问题,那就是代码思路基本重复,从而就诞生了自定义MVC。

二、最初的增删改查

我们以书本的增删改查为例,先回顾一下最初是怎样部署代码的:

demo1.jsp代码:

 然后建增删改查的servlet:

 我们分别在增删改查的servlet里面写一些内容:

 然后我们运行demo1.jsp界面,得到如下效果:

 接着分别点击增加、删除、修改、查询的按钮,打印结果如下:

 以上就是我们最初的增删改查,那么会存在哪些问题呢?

          ①关于单个实体/表 操作场景越多,需要新建的类也就越多,造成了项目中类的数量过于庞大。

          对于这个问题,我们要优化,

三、反射版的增删改查

新建一个 BookServlet

package com.ycx.web;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/book.action")
public class BookServlet extends HttpServlet{
	@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 methodName = req.getParameter("methodName");
		if("add".equals(methodName)) {
//			如果前台传递到后台的是一个新增的请求,那么后台就新增方法
			add(req,resp);
		}else if("del".equals(methodName)){
			del(req,resp);
		}else if("edit".equals(methodName)){
			edit(req,resp);
		}else if("list".equals(methodName)){
			list(req,resp);
		}
	}

	private void list(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("在同一个servlet中调用 list 方法");
	}

	private void edit(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("在同一个servlet中调用 edit 方法");
	}

	private void del(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("在同一个servlet中调用 del 方法");
	}

	private void add(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("在同一个servlet中调用 add 方法");
	}
}

 然后在demo1.jsp:

<h3>类数量过多问题的优化</h3>
<a href="${pageContext.request.contextPath }/book.action?methodName=add">增加</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=del">删除</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=edit">修改</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=list">查询</a>

控制台运行结果:

那么又遇到另一个问题:

 ②当增加了业务,除了要添加该业务对应的方法(load),同时还要改动原有的代码

优化BookServlet

@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//		为了区分当前请求的目的,增删改查的目的,就从前台将要调用的方法名传递到后台
		String methodName = req.getParameter("methodName");
//		methodName可能是多种方法
		
//		前台传递什么方法就调用当前类的对应方法
		try {
			Method m=this.getClass()// BookServlet.Class
			.getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
			m.setAccessible(true);
//			调用当前类实例的 methodName 方法
			m.invoke(this, req,resp);
		} catch (Exception e) {
			e.printStackTrace();
		}

	private void load(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("在同一个servlet中调用 load 方法");
	}

 在demo1.jsp界面再添加一个回显按钮:

<a href="${pageContext.request.contextPath }/book.action?methodName=load">回显</a>

 控制台运行结果如下:

 好,如果我们再写一个订单类的增删改查:

 一样也可以调用到:

 

 但是又会存在什么问题呢?

注意看:

所以面临第三、四个问题:

        ③ 反射相关代码,在每一个实体类对应的servlet中都存在

        ④每一个servlet中都有doget和dopost方法

所以接下来本节重点来啦!!!

四、自定义MVC工作原理图以及后台代码实现解析

我们接下来按照这个原理图去部署代码:

新建一个com.ycx.framework

DispatcherServlet:

package com.ycx.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 com.ycx.web.BookAction;

/**
 * 中央控制器:
 * 主要职能:接收浏览器请求,找到对应的处理人
 * @author 杨总
 *
 */
@WebServlet("*.action")
public class DispatcherServlet extends HttpServlet{
	private Map<String, Action> actions=new HashMap<String, Action>();
	
//	程序启动时,只会加载一次
	@Override
	public void init() throws ServletException {
		actions.put("/book", new BookAction());
//		actions.put("/order", new BookAction());
	}

	@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 {
		//http:localhost:8080/mvc/book.action?methodName=list
		String uri=req.getRequestURI();
//		拿到/book,就是最后一个“/”到最后一个“.”为止
		uri=uri.substring(uri.lastIndexOf("/"),uri.lastIndexOf("."));
		Action action = actions.get(uri);
		action.execute(req, resp);
	}
}

 注意:其中有一个初始化init方法:

 

 

 就生成了一个init初始化方法:

ActionSupport:

package com.ycx.framework;

import java.lang.reflect.Method;

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

public class ActionSupport implements Action{

	@Override
	public void execute(HttpServletRequest req, HttpServletResponse resp) {
		String methodName = req.getParameter("methodName");
//		methodName可能是多种方法
//		前台传递什么方法就调用当前类的对应方法
		try {
			Method m=this.getClass()// BookServlet.Class
			.getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
			m.setAccessible(true);
//			调用当前类实例的 methodName 方法
			m.invoke(this, req,resp);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Action:

package com.ycx.framework;

import java.io.IOException;

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

/**
 * 子控制器:
 * 对应请求的处理人
 * @author 杨总
 *
 */
public interface Action {
	 void execute(HttpServletRequest req, HttpServletResponse resp);
}

com.ycx.web包内添加一个BookAction类:

BookAction:

package com.ycx.web;

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

import com.ycx.framework.Action;
import com.ycx.framework.ActionSupport;

public class BookAction extends ActionSupport {

		private void load(HttpServletRequest req, HttpServletResponse resp) {
			System.out.println("在同一个servlet中调用 load 方法");
		}

		private void list(HttpServletRequest req, HttpServletResponse resp) {
			System.out.println("在同一个servlet中调用 list 方法");
		}

		private void edit(HttpServletRequest req, HttpServletResponse resp) {
			System.out.println("在同一个servlet中调用 edit 方法");
		}

		private void del(HttpServletRequest req, HttpServletResponse resp) {
			System.out.println("在同一个servlet中调用 del 方法");
		}

		private void add(HttpServletRequest req, HttpServletResponse resp) {
			System.out.println("在同一个servlet中调用 add 方法");
		}

	}

部署完毕之后,我们开始运行

比如点击书籍的删除增加按钮,控制台打印结果如下:

我们的mvc原理就根据原理图以代码的形式呈现出来啦 ~

 今日分享就到这里啦~再会!

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酒醉猫(^・ェ・^)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值