自定义MVC架构【上】

news2024/12/23 22:18:30

目录

一、前言

1.什么是MVC架构

2.使用MVC架构的好处

3.MVC架构与三层架构的区别

4.MVC架构的思路

二、自定义MVC

1.最初版本

2.进阶版

3.反射优化版

4.反射增强版


一、前言

1.什么是MVC架构

MVC架构(Model-View-Controller),即模型-视图-控制器架构,是一种常见的软件设计模式,用于组织和分离应用程序的不同组成部分。

  • 模型(Model):表示应用程序中的数据和业务逻辑。模型负责处理数据的读写、验证、计算等操作,以及处理与数据相关的业务逻辑。模型通常不直接与用户界面交互,而是通过控制器来获取和更新数据。

  • 视图(View):表示应用程序中的用户界面。视图负责展示数据给用户,并接收用户的输入。视图通常不包含任何业务逻辑,而是通过控制器来更新和获取数据。一个模型可以有多个视图,视图可以是不同形式的展现,如网页、移动应用界面等。

  • 控制器(Controller):负责处理用户输入、控制应用程序的流程,以及协调模型和视图之间的交互。控制器接收用户的输入并相应地更新模型和视图。它将用户的操作转化为对模型的请求或对视图的更新,以实现数据和界面的交互。

2.使用MVC架构的好处

MVC架构的优势在于它能够实现良好的代码复用性、可扩展性、可维护性和可测试性。通过将应用程序的不同职责分离,使得各个组成部分独立变化,降低了耦合度,同时也使得开发团队能够更好地协作和管理项目。

生活案例:

假如有一家餐馆,只有老板一个人。采购、服务客人、炒菜、上菜、结账,都是老板来做,是不是很费时费力, 如果他招聘人员,来为他做这些事情是不是就大大节省了时间,而且我们一件事情对应一个人,某个环节出了问题都好直接对接。

项目案例:

餐馆就是我们的项目,jsp页面就是老板,什么事情都是他来干,代码量是非常大的而且不利于维护,这时候我们就要进行 “分类管理”将我们的代码变成MVC架构MVC就是模型(model)-视图(view)-控制器(controller)。它们各自处理自己的任务,高内聚低耦合, 提升我们写代码的效率以及后期维护等。

3.MVC架构与三层架构的区别

1. 三层架构是基于业务逻辑来分的,而MVC是基于页面来分的;

2. 三层是种软件架构,通过接口实现编程,MVC模式是一种复合设计模式,一种解决方案;

3. 三层架构模式是体系结构模式,MVC是设计模式;

4. 三层架构模式又可归于部署模式,MVC可归于表示模式。

注意MVC架构和三层架构并不是互斥的,可以根据实际需求进行组合和调整。例如,可以将MVC架构作为表示层的一部分,用于管理用户界面的交互,同时在业务逻辑层和数据访问层中采用三层架构划分职责。

4.MVC架构的思路

 如图所示,视图负责展示模型中的数据给用户,并提供用户界面,用于与用户进行交互,发送请求到Servlet也就是控制器,控制器通过接收用户输入来控制应用程序的行为然后去到后端也就是数据访问层拿到相应数据后根据交互来更新模型和视图。

二、自定义MVC

版本迭代:我将带领大家一步一步演变成我们如今所用的MVC架构让大家更直观的感受到为什么要使用以及怎么演变而来的。

1.最初版本

版本一:一个请求参数(操作)对应一个servlet

package com.xw.servlet;

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;

/**
 * 模拟版本一mvc新增操作
 */
@WebServlet("/BookAdd.do")
public class BookAddServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("我是版本一的mvc__新增操作。。。");
	}

}

不足之处:像以上的servlet要写多遍,一个操作就要写一个servlet,非常的繁琐而且不利于维护。

2.进阶版

版本二:增删改查都是一个Servlet,在Servlet里面进行if操作判断
package com.xw.servlet;

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;

/**
 * 模拟版本二mvc增删改查共用一个Servlet操作
 */
@WebServlet("/BookCRUD.do")
public class BookCRUDServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//接收请求参数
		String parameter = request.getParameter("CrudName");
		//判断前端传递过来的是什么参数
		if(parameter.equals("add")) {
			add(request,response);
		}else if(parameter.equals("upd")) {
			upd(request,response);
		}else if(parameter.equals("del")) {
			del(request,response);
		}else if(parameter.equals("list")) {
			list(request,response);
		}
	}

	private void list(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本二的查询");
		
	}

	private void del(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本二的删除");
		
	}

	private void upd(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本二的修改");
		
	}

	private void add(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本二的新增");
		
	}

}

不足之处:虽然只需要写一个servlet,但是每增加一个操作就要增加一个if条件分支,如果我们的操作需求多了起来代码量也是非常冗余的。

3.反射优化版

版本三:反射机制优化if条件判断

package com.xw.servlet;

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

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

/**
 * 模拟版本三mvc增删改查反射机制优化if条件判断
 */
@WebServlet("/BookClass.do")
public class BookClassCRUDServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//接收请求参数
		String CrudName = request.getParameter("CrudName");
		
		try {
			//获取该servlet的所有方法
			Method m = this.getClass().getDeclaredMethod(CrudName, HttpServletRequest.class, HttpServletResponse.class);
			//打开访问权限
			m.setAccessible(true);
			//调用该类的方法
			m.invoke(this,request,response );
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
	}

	private void list(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本三反射机制优化的查询");
		
	}

	private void del(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本三反射机制优化的删除");
		
	}

	private void upd(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本三反射机制优化的修改");
		
	}

	private void add(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本三反射机制优化的新增");
		
	}

}

不足之处:虽然只需要写一个servlet,也不需要写if条件判断,但是放到项目目中来看,我们不止只有一个book可能还有Goods,Student等 也是需要写多个Servlet,一个Servlet对应一张表。

4.反射增强版

创建DispatchServlet中央控制器接收请求并将请求发送到对应的子控制器并完成init方法中的请求路径与子控制器类的对应配置与doPost方法的请求处理。

package com.xw.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.xw.servlet.BookAction;
import com.xw.servlet.GoodsAction;

/**
 * 中央控制器拦截请求根据请求找到子控制器
 */
@WebServlet("*.do")
public class DispatchServlet extends HttpServlet {
	//保存子控制器
	private Map<String, ActionSupport> actionMap = new HashMap<String, ActionSupport>();
	
	@Override
	public void init() throws ServletException {
		//初始化子控制值
		actionMap.put("/book", new BookAction());
		
	}
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}

	
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//获取到url请求
		 String url = request.getRequestURI();
		//截取指定需要操作的表
		url=url.substring(url.lastIndexOf("/"),url.lastIndexOf("."));
		//根据请求截取到key找到对应的子控制器
		ActionSupport actionSupport = actionMap.get(url);
		//调用子控制器处理业务逻辑
		actionSupport.execute(request, response);
	}

}

创建Action抽象子控制器并定义execute方法,用于处理具体的核心业务逻辑处理。

package com.xw.framework;

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

/**子控制器并定义execute方法,用于处理具体的核心业务逻辑处理
 * @author Java方文山
 *
 */
public interface Action {
		public String execute(HttpServletRequest req, HttpServletResponse resp);
}

创建ActionSupport并继承抽象类Action,重写execute方法,通过反射找到对应的Map集合保存的Servlet子控制器实现业务逻辑层处理。

package com.xw.framework;

import java.lang.reflect.Method;

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


import com.sun.corba.se.spi.orbutil.fsm.FSM;
import com.sun.corba.se.spi.orbutil.fsm.Input;

/**重写execute方法,实现业务逻辑处理
 * @author Java方文山
 *
 */
public  class ActionSupport implements Action {

	public String execute(HttpServletRequest req, HttpServletResponse resp) {
		String invoke = null;
		try {
			//接收请求参数
			String CrudName = req.getParameter("CrudName");
			//获取该servlet的所有方法
			Method m = this.getClass().getDeclaredMethod(CrudName, HttpServletRequest.class, HttpServletResponse.class);
			//打开访问权限
			m.setAccessible(true);
			//调用该类的方法
			invoke = (String) m.invoke(this, req, resp);
			
		} catch (Exception e) {
			e.printStackTrace();
		
	}
		return invoke;

	}

}

创建BookAction继承ActionSuppor,实现业务逻辑处理。

package com.xw.servlet;

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

import com.xw.framework.ActionSupport;


public class BookAction extends ActionSupport {
	private void list(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本四反射机制优化的查询——book");
		
	}

	private void del(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本四反射机制优化的删除——book");
		
	}

	private void upd(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本四反射机制优化的修改——book");
		
	}

	private void add(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本四反射机制优化的新增——book");
		
	}
	
}

到这里我们就完成我们第四代MVC架构啦!!

当我们需要对另一个表进行操作的时候我们只需要在DispatchServlet中央控制器进行子控制器的配置以及最后子控制器的业务逻辑层编写即可。

例如

我还需要对Goods表进行增删改查操作

①配置子控制器

 ②编写子控制器

package com.xw.servlet;

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

import com.xw.framework.ActionSupport;


public class GoodsAction extends ActionSupport {
	private void list(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本四反射机制优化的查询——goods");
		
	}

	private void del(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本四反射机制优化的删除——goods");
		
	}

	private void upd(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本四反射机制优化的修改——goods");
		
	}

	private void add(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("我是版本四反射机制优化的新增——goods");
		
	}
	
}

接下来测试一下看看打印结果

 

是不是相对前三代更为简单了呢?看完过后你对MVC的用途有没有更为理解?

至此我的首篇自定义MVC就分享到这里啦!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/702254.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【MSP432电机驱动设计—下篇】霍尔编码器测车轮运行距离与M/T综合公式法测速概念

开发板型号为MSP432P401r 今日得以继续我的MSP432电赛速通之路&#xff0c;本篇使用MSP432编程学习霍尔编码器M/T公式法测速概念&#xff0c;最终实现用外部中断方式测得小车行走路程&#xff0c;文章学习讲解原理、附上实例实践、附上关键代码、附上…

微信月活破10亿,安全性靠谁来支撑?

&#x1f449;腾小云导读 微信作为月活过10亿的国民级应用&#xff0c;其安全能力备受关注。值得注意的是&#xff0c;没有足够的特征数据&#xff0c;安全策略将是"无根之木&#xff0c;无源之水"。微信安全数据仓库作为安全业务的特征数据存储中心&#xff0c;每天…

【C/C++】解析 类成员属性

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

JVM类加载双亲委派-JVM(二)

上篇文章说了java类的加载&#xff0c;验证、准备、解析、初始化。类的初始化必须是类加载完才执行&#xff0c;所以类的构造方法初始化是在静态方法之后执行。 JVM类加载机制-JVM&#xff08;一&#xff09; 一、类加载和双亲委派机制 前面类加载主要通过类加载器实现&…

JavaWeb小记——登录、注册

目录 登录项目 步骤 1.首先写一个前台页面&#xff0c;一个form表单——login.jsp 2.后台获取前台输入的参数&#xff0c;并作校验 3.写一个JDBC工具类&#xff0c;用来连接数据库&#xff0c;本案例使用Druid连接池 4.写一个登录工具类&#xff0c;在数据库中查询数据&…

【云原生】k8s的pod基础(上)

1.pod的相关知识 1.1 pod的基础概念 pod是kubernetes中最小的资源管理组件&#xff0c;Pod也是最小化运行容器化应用的资源对象。一个Pod代表着集群中运行的一个进程。kubernetes中其他大多数组件都是用绕着Pod来进行支撑和扩展Pod功能的&#xff0c;例如&#xff0c;用于管…

C++面试需求

一.auto 1.介绍&#xff1a; auto 是一个用于类型推导的关键字。它允许变量的类型在编译时根据其初始化值自动推断 例子&#xff1a; &#xff08;1&#xff09;自动类型推导变量 // C program to demonstrate working of auto // and type inference#include <bits/std…

shell正则入门

1.系统通配符 * #所有 . #当前目录 .. #当前目录的上一级目录 - #当前目录的上一次所在的目录 ~ #家目录 # #注释&#xff0c;超级管理员的命令行提示符 $ #引用变量&#xff0c;普通用户的命令行提示符 ? #匹配任意…

Spring Cloud Alibaba体系使用Nacos作为服务注册发现与配置中心

文章目录 Nacos介绍服务注册发现Nacos Discovery引入Nacos DiscoveryProvider和Consumer示例ProviderConsumer Nacos Discovery Starter其他配置选项 服务注册发现Nacos Config引入Nacos Config快速接入配置自动刷新profile粒度控制自定义namespace配置支持自定义Group支持自定…

UE5.2 LyraDemo源码阅读笔记(二)

UE5.2 LyraDemo源码阅读笔记&#xff08;二&#xff09; 创建了关卡中的体验玩家Actor和7个体验玩法入口之后。 接下来操作关卡中的玩家与玩法入口交互&#xff0c;进入玩法入口&#xff0c;选择进入B_LyraFrontEnd_Experience玩法入口&#xff0c;也就是第3个入口。触发以下请…

vue进阶-elementPlus

Element Plus官网 Element Plus 基于 Vue 3&#xff0c;面向设计师和开发者的组件库。减少开发者关注css&#xff0c;重心关注业务逻辑。 1. 入门 1.1 安装 npm install element-plus --save1.2 快速开始 1、main.js 引入并 use element-plus import { createApp } from …

C#,数值计算——灰色码(Gray Codes)的计算方法与源代码

一个 n位灰色码 序列&#xff0c;就是2的n次方 个 整数&#xff1b; 第一个数字为0&#xff1b; 相邻两个数字的二进制只有一位不一样&#xff1b; 第一个数字和最后一个数字的二进制也只有一位不一样。 using System; namespace Legalsoft.Truffer { /// <summary&…

ARM Exynos4412 硬件中断和GIC管理、PWM控制 6.28

day7 1.中断 硬件中断&#xff1a;直接让外部的硬件产生中断&#xff0c;CPU获取中断源并执行异常处理流程 1.需求&#xff1a;&#xff08;中断的原理一样&#xff0c;但外设是按键&#xff09;按键产生中断&#xff0c;并在中断处理中串口发送消息 2.原理图&#xff1a;U…

Mysql 5.6使用配置文件my.ini来设置长时间连接数据库

对于已经安装了mysql和未安装都是同样的步骤。在C:\Program Files (x86)\MySQL\MySQL Server 5.6下生成一个my.ini文件。然后删除或者修改my-default.ini的名字。 一、my.ini配置文件如下 [mysqld] basedirC:\Program Files (x86)\MySQL\MySQL Server 5.6 datadirC:\Program F…

STM32F407 基本定时器使用

介绍STM32F407基本定时器的配置方法&#xff0c;分别介绍轮询方式、中断方式使用定时器完成定时。 【1】定时器介绍 定时器相关的章节在STM32F4xx参考手册第14、15、16、17章节。 【2】基本定时器配置示例 增加一个Timer.c文件&#xff0c;代码如下 #include "timer.h…

【sql】SQL回顾总结,超级全

SELECT&#xff1a;语句用于从数据库中选取数据 从 "Websites" 表中选取 "name" 和 "country" 列 SELECT name,country FROM Websites 从 "Websites" 表中选取所有列 SELECT * FROM Websites; SELECT DISTINCT&#xff1a;用于返…

Nacos(一):简介 如何安装 服务注册与发现 集群 权重 与Eureka区别

一、简介 1、应用场景 当服务调用越来越多&#xff0c;服务的地址需要管理起来&#xff0c;并实现动态调用而不是硬编码在接口中。此时需要一个注册中心来帮助我们管理服务。 流程如下&#xff1a; 商品微服务注册IP和端口到注册中心订单微服务先从注册中心获取到商品微服务…

45 # 实现文件拷贝功能

下面实现边读边写的文件拷贝功能&#xff0c;这样不会淹没系统的可用内存&#xff0c;合理读写 const fs require("fs"); const path require("path");function copy(source, target, callback) {const SIZE 3;const buffer Buffer.alloc(SIZE);let r…

OPENCV 训练分类器一

第一步&#xff0c;安装OPENCV 见最新openCV-Python安装教程(opencv-python版本4.4.0, Python版本: 3.9)_python安装opencv_这个人不是画家的博客-CSDN博客 第二步&#xff0c;下面是修正过后的Python 将文件夹下面所有的图片转换成灰色小图像&#xff0c;用于存正片用的。…

Python几种字符串格式化方法

Python 字符串格式化方法 文章目录 Python 字符串格式化方法1.python中的字符串格式化--百分号 %2. 字符串格式化-数字精度控制 m.n3. 字符串格式化--快速写法 f"{变量}"4. 案例&#xff1a;股价计算小程序 1.python中的字符串格式化–百分号 % %的主要作用将数据转换…