自定义MVC

news2024/11/17 23:54:34

目录

一、MVC概念描述

1、什么是MVC?

2、什么是自定义MVC?

3、自定义MVC有什么用(主要用途)?

二、MVC三层架构

第一种版本

JSP页面

servlet

 结果

第二种版本

 JSP代码

servlet

结果

第三种版本

jsp页面

servlet

结果

三、自定义MVC框架的雏形

工作原理图

类的创建

实践:第四种版本

jsp代码

debug测试

结果

帮助


一、MVC概念描述

1、什么是MVC?

MVC是一种设计模式,用于开发软件应用程序。它将应用程序分为三个核心部分:模型(Model)、视图(View)和控制器(Controller)

  • 模型(Model)是应用程序的数据和业务逻辑层。它负责处理数据的读取、存储、更新和删除,以及定义业务规则和逻辑。
  • 视图(View)是用户界面的呈现层,负责展示数据给用户,并接收用户的输入。视图通常是用户可以看到和与之交互的界面元素,如图形界面、网页或移动应用程序的界面。
  • 控制器(Controller)是模型和视图之间的中介,负责处理用户的输入、控制数据的流动以及调度视图的更新。它接收来自用户界面的输入,然后通过更新模型或通知视图来响应这些输入。

MVC的目标是将应用程序的逻辑和用户界面分离,使得代码更容易维护修改测试。通过将应用程序的不同部分分隔开来,可以提高代码的可读性可扩展性可重用性

2、什么是自定义MVC?

自定义MVC是指根据特定项目的需求和规模,自行设计和实现的MVC架构。传统的MVC架构提供了一种通用的模式来组织应用程序,但在特殊情况下,可能需要根据项目的特定需求,做一些定制化的调整或扩展。

自定义MVC使开发团队能够根据项目的需要,灵活地定义模型视图控制器的职责以及它们之间的通信机制。可以根据具体业务需求来调整模型控制器的逻辑设计符合项目需求的视图层。这样能够更好地满足项目的特殊要求,提高开发效率和代码质量。

在自定义MVC中,开发人员可以自由选择设计使用技术和工具,并根据项目的需要来决定是否引入其他架构模式或设计模式。这样可以根据具体的场景,综合考虑各种因素,选择最适合项目需求的架构方案。

自定义MVC是根据项目需求和规模设计的定制化MVC架构,能够更好地满足特定项目的要求,并提高开发效率和代码质量

3、自定义MVC有什么用(主要用途)?

  1. 灵活性和定制化:自定义MVC允许开发团队根据项目的具体需求来调整和扩展MVC的各个组成部分,以更好地满足特定项目的要求。可以根据具体场景自由选择和设计使用的技术和工具,以及决定是否引入其他架构模式或设计模式。
  2. 代码组织和可维护性:通过自定义MVC,开发人员可以将应用程序的不同层(模型、视图和控制器)进行清晰分离,并明确各自的职责。这样有助于更好地组织和管理项目代码,提高代码的可维护性和可读性。
  3. 可测试性:自定义MVC架构通常支持对不同部分进行单元测试或集成测试,从而提高代码的质量和可靠性。通过将业务逻辑从视图和控制器中剥离出来,可以更轻松地进行单元测试,并模拟不同场景来验证应用程序的功能。
  4. 适应性和扩展性:自定义MVC可以根据项目的增长和变化进行扩展和调整。如果对特定功能或模块需要进行更改或增加,可以根据需要修改模型、视图和控制器,而不会对整个应用程序产生过大的影响。这种灵活性和可扩展性有助于保持应用程序的可持续发展。
  5. 提高开发效率:通过自定义MVC,开发人员可以更好地组织和管理项目代码,优化开发流程,提高开发效率。不同开发人员可以更容易地理解和协同工作,将每个层的职责清晰分离,提高团队的协作效率。

自定义MVC提供了灵活性可定制化代码组织可维护性可测试性适应性扩展性以及提高开发效率等多个方面的优势,使开发团队能够更好地满足项目的需求并提高开发质量。

二、MVC三层架构

第一种版本

第一种方式是有弊端的:

        比如:你的每一个操作都需要编一个servlet类来处理

JSP页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>index</title>
</head>
<body>

	<h1>第一种</h1>
	<a href="BookAddServlet">增加</a>
	<a href="BookDelServlet">删除</a>
	<a href="BookUpdateServlet">修改</a>
	<a href="BookListServlet">查询</a>

	<h1>第二种</h1>
	<a href="">增加</a>
	<a href="">删除</a>
	<a href="">修改</a>
	<a href="">查询</a>

	<h1>第三种</h1>
	<a href="">增加</a>
	<a href="">删除</a>
	<a href="">修改</a>
	<a href="">查询</a>


</body>
</html>

servlet

我们可以利用重定向跳转到首页,这样可以更好的给我们一个体验
      

 response.sendRedirect("index.jsp");
package com.tgq.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;

/**
 * 
 * @author tgq
 *
 */
@WebServlet("/BookAddServlet")
public class BookAddServlet extends HttpServlet {

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

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		System.out.println("BookAddServlet");
        //利用重定向跳转到首页
		response.sendRedirect("index.jsp");
	}

}

以此我们编写四个一样的servlet

 结果

我们依次点击增加===》删除===》修改===》查询

打印结果

第二种版本

弊端:虽然每一个对应每一个操作,只要写一个servlet来处理,但是每增加一个操作,都需要改变原有的代码块

 JSP代码

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>index</title>
</head>
<body>

	<h1>第一种</h1>
	<a href="BookAddServlet">增加</a>
	<a href="BookDelServlet">删除</a>
	<a href="BookUpdateServlet">修改</a>
	<a href="BookListServlet">查询</a>


	<h1>第二种</h1>
	<a href="BookServlet?methodName=add">增加</a>
	<a href="BookServlet?methodName=del">删除</a>
	<a href="BookServlet?methodName=update">修改</a>
	<a href="BookServlet?methodName=list">查询</a>


	<h1>第三种</h1>
	<a href="">增加</a>
	<a href="">删除</a>
	<a href="">修改</a>
	<a href="">查询</a>


</body>
</html>

servlet

package com.tgq.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;

/**
 * 
 * @author tgq
 *
 */
@WebServlet("/BookServlet")
public class BookServlet extends HttpServlet {

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

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String methodName = request.getParameter("methodName");

		if (methodName.equals("add")) {
			add(request, response);
		} else if (methodName.equals("del")) {
			del(request, response);
		} else if (methodName.equals("update")) {
			update(request, response);
		} else if (methodName.equals("list")) {
			list(request, response);
		}
		response.sendRedirect("index.jsp");
	}

	private void list(HttpServletRequest request, HttpServletResponse response) {

		System.out.println("list");

	}

	private void update(HttpServletRequest request, HttpServletResponse response) {

		System.out.println("update");

	}

	private void del(HttpServletRequest request, HttpServletResponse response) {

		System.out.println("del");

	}

	private void add(HttpServletRequest request, HttpServletResponse response) {

		System.out.println("add");

	}

}

结果

我们依次点击增加===》删除===》修改===》查询

输出结果:

第三种版本

弊端:

虽然解决了if条件分支代码冗余的问题,但是放在项目范围内,反射的代码时重复的

根据以上两种,我们进行一个优化修改

jsp页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>index</title>
</head>
<body>

	<h1>第一种</h1>
	<a href="BookAddServlet">增加</a>
	<a href="BookDelServlet">删除</a>
	<a href="BookUpdateServlet">修改</a>
	<a href="BookListServlet">查询</a>


	<h1>第二种</h1>
	<a href="BookServlet?methodName=add">增加</a>
	<a href="BookServlet?methodName=del">删除</a>
	<a href="BookServlet?methodName=update">修改</a>
	<a href="BookServlet?methodName=list">查询</a>


	<h1>第三种</h1>
	<a href="BookServlet?methodName=add">增加</a>
	<a href="BookServlet?methodName=del">删除</a>
	<a href="BookServlet?methodName=update">修改</a>
	<a href="BookServlet?methodName=list">查询</a>


</body>
</html>

servlet

package com.tgq.web;

import java.io.IOException;
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;

/**
 * 
 * @author tgq
 *
 */
@WebServlet("/BookServlet")
public class BookServlet extends HttpServlet {

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

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String methodName = request.getParameter("methodName");

		try {
			// 利用反射调用方法
			Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,
					HttpServletResponse.class);
			// 打开访问权限
			method.setAccessible(true);
			// 操作以下的代码不发生任何变化
			method.invoke(this, request, response);

		} catch (Exception e) {
			e.printStackTrace();
		}

		response.sendRedirect("index.jsp");
	}

	private void list(HttpServletRequest request, HttpServletResponse response) {

		System.out.println("list");

	}

	private void update(HttpServletRequest request, HttpServletResponse response) {

		System.out.println("update");

	}

	private void del(HttpServletRequest request, HttpServletResponse response) {

		System.out.println("del");

	}

	private void add(HttpServletRequest request, HttpServletResponse response) {

		System.out.println("add");

	}

}

结果

我们依次点击增加===》删除===》修改===》查询

 输出结果:

三、自定义MVC框架的雏形

工作原理图

类的创建

我们需要新建一个包framework,在这个包下面我们新建两个类ClassDispatherServlet、Action)。

在我们原本的包下面新建一个类ClassBookAction

DispatherServlet:对应图中ActionServlet:中央处理器。

(需要继承HttpServlet:需要拦截所有的.action请求)

Action:子控制器,真正做事处理浏览器发送的请求类。

BookAction:需要继承Action

我们需要拿到我们请求的servlet的url,我们再把他截取下来。
需要一个容器来保存

public Map<String, Action> actionMaps = new HashMap<String, Action>();

利用init()方法初始化加载,添加进map集合保存

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

/**
 * 对应图中ActionServlet:中央处理器
 * 
 * @author tgq
 *
 */
@WebServlet("/*.action")
public class DispatherServlet extends HttpServlet {
	public Map<String, Action> actionMaps = new HashMap<String, Action>();

	@Override
	public void init() throws ServletException {
		actionMaps.put("/BookServlet", 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 uri = request.getRequestURI();
		// 拿到路径进行一个截取,拿到最后一个“/”到最后一个“.”之间的字符串
		uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));

		Action action = actionMaps.get(uri);

	}

}

我们的反射代码需要写在Action

package com.tgq.framework;

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

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

/**
 * 子控制器,真正做事处理浏览器发送的请求类
 * 
 * @author tgq
 *
 */
public class Action {
	public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String methodName = request.getParameter("methodName");
		try {
			// 利用反射调用方法
			Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,
					HttpServletResponse.class);
			// 打开访问权限
			method.setAccessible(true);
			// 操作以下的代码不发生任何变化
			method.invoke(this, request, response);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}
}

我们把需要调用的方法写在BookAction

package com.tgq.web;

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

import com.tgq.framework.Action;

public class BookAction extends Action {
	public void add(HttpServletRequest request, HttpServletResponse response) {

		System.out.println("add");

	}

	public void list(HttpServletRequest request, HttpServletResponse response) {

		System.out.println("list");

	}

	public void update(HttpServletRequest request, HttpServletResponse response) {

		System.out.println("update");

	}

	public void del(HttpServletRequest request, HttpServletResponse response) {

		System.out.println("del");

	}
}

最后我们在到我们的DispatherServlet,调用方法action.execute(request, response);
这就是我们的第四个版本:解决代码重复的问题

实践:第四种版本

jsp代码
 

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>index</title>
</head>
<body>

	<h1>第一种</h1>
	<a href="BookAddServlet">增加</a>
	<a href="BookDelServlet">删除</a>
	<a href="BookUpdateServlet">修改</a>
	<a href="BookListServlet">查询</a>

	<h1>第二种</h1>
	<a href="BookServlet.action?methodName=add">增加</a>
	<a href="BookServlet.action?methodName=del">删除</a>
	<a href="BookServlet.action?methodName=update">修改</a>
	<a href="BookServlet.action?methodName=list">查询</a>

	<h1>第三种</h1>
	<a href="BookServlet.action?methodName=add">增加</a>
	<a href="BookServlet.action?methodName=del">删除</a>
	<a href="BookServlet.action?methodName=update">修改</a>
	<a href="BookServlet.action?methodName=list">查询</a>

	<h1>第四种</h1>
	<a href="BookServlet.action?methodName=add">增加</a>
	<a href="BookServlet.action?methodName=del">删除</a>
	<a href="BookServlet.action?methodName=update">修改</a>
	<a href="BookServlet.action?methodName=list">查询</a>

</body>
</html>

debug测试

我们在

 进行一个断点测试

我们依次点击增加===》删除===》修改===》查询

我们可以看到的断点的地方已经出现我们想要的结果了,走完之后就会调用

action.execute(request, response);

 

 

我们到action里面的这里打个断点,可以看到我们想要的结果了。最后跳进我们BookAction里面的方法

 

结果

 

帮助
 

如果想想我一样可以像这样建包、类等

 

希望对你们有用!谢谢!!!

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

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

相关文章

unity Embedded Browser(ZFBrowser)使用相关问题

在使用ZFBrowser的时候 碰到获取不到声音权限的问题 在插件的BrowserNative.cs脚本中&#xff0c;找到commandLineSwitches变量&#xff0c; 只需要开启以下两个配置项&#xff1a; "--enable-media-stream"&#xff1a;允许收集用户的摄像头视频流与mic的音频流。…

【Rust】入门教程-7章

Package、Crate、Module 7.1 代码组织 7.2 路径 根级可以相互访问 super 关键字 pub struct 7.4 use关键字

【Spark大作业】财政收入影响因素分析及预测模型

文章目录 前言一、数据的基本描述性分析1.1 导包与读取数据1.2 数据的基本情况1.3 变量的分布情况1.4 相关性分析 二、数据的预处理2.1 Lasso变量选择模型 三、建立财政收入预测模型3.1 灰色模型3.2 神经网络预测模型 环境搭建Spark pandsAPI接口&#xff08;了解&#xff09;分…

windows本地上传文件到服务器(scp)

命令 1.ssh 用户名ip&#xff1a;远程登录服务器。 ssh root1.15.233.1932.scp 本地文件路径 用户名ip:上传路径 &#xff1a;本地文件与服务器进行传递。 scp C:\a.txt root1.15.233.193:/var/www/html3.本地文件夹上传到服务器 scp -r C:\user root1.15.233.193:/home4…

三防工业平板在哪些行业中得到广泛应用?

随着科技的不断进步&#xff0c;工业平板正逐渐成为各行业中不可或缺的工具。其中&#xff0c;三防工业平板由于其卓越的耐用性和丰富的功能&#xff0c;在许多行业中得到了广泛的应用。本文将重点介绍三防工业平板在以下几个行业中的应用。 三防工业平板在物流行业中发挥着关键…

shell脚本ssh远程执行命令给变量赋值的问题

需求及目标 从A机器通过SSH方式到B机器&#xff0c;并执行相关的命令。命令中包含变量及变量的赋值。 代码如下&#xff0c;意思是&#xff0c;ssh到10.111.111.27这台机器&#xff0c;cd到 / 根目录下&#xff0c;并执行ls命令&#xff0c;如果ls出来的结果不为空&#xff0…

【鲁棒优化】微电网鲁棒优化定价方案研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

【算法】区间DP (从记忆化搜索到递推DP)⭐

文章目录 前期知识516. 最长回文子序列思路1——转换问题&#xff1a;求 s 和反转后 s 的 LCS&#xff08;最长公共子序列&#xff09;思路2——区间DP&#xff1a;从两侧向内缩小问题规模补充&#xff1a;记忆化搜索代码 1039. 多边形三角剖分的最低得分从记忆化搜索开始翻译成…

改造3dmax的快捷键自定义3dmax快捷键

快捷键需要整体规划&#xff0c;不然太乱了&#xff0c;不要担心你的自定义快捷键破坏了系统原有的快捷键&#xff0c;或者和原有的某些快捷键冲突&#xff0c;如果那些被系统定义的快捷键所对应的功能指令你都不知道他们是干什么用的&#xff0c;你要他们有什么用。还不如来得…

Rust 基础入门 ——数值类型

数值类型 概述 数值类型 这里重点在于一些特殊的书写方式的格式&#xff0c;和几种特殊类型。除此以外&#xff0c;还包括一些常见的类型处理方式&#xff08;这之中包括了一些问题处理和Rust 特有内容&#xff09;。 细分之下为&#xff1a; 整数类型 重点问题&#xff1a…

基于PyQt5的图形化界面开发——天气应用

目录 0. 前言1. 注册心知天气2. 代码实现3. 其他PyQt5文章 0. 前言 本节使用PyQt5开发天气应用程序实现以下功能&#xff1a; 通过调用天气API获取实时天气数据&#xff0c;并在应用程序中显示当前城市的温度、天气状况、风速等信息。 操作系统&#xff1a;Windows10 专业版…

关于 3.0 和 2.0 的数据文件差异以及性能优化思路

如果需要对数据库性能优化&#xff0c;了解数据文件的存储方式和工作原理是必要的。 对于时序数据库&#xff08;Time Series Database&#xff09; TDengine 来说&#xff0c;在 2.x 版本中时序数据的保留策略是由keep和days这两个参数把控的。&#xff08;详情可见&#xff…

云原生——Kubenetes基础

❄️作者介绍&#xff1a;奇妙的大歪❄️ &#x1f380;个人名言&#xff1a;但行前路&#xff0c;不负韶华&#xff01;&#x1f380; &#x1f43d;个人简介&#xff1a;云计算网络运维专业人员&#x1f43d; 目录 一.什么是Kubernetes&#xff1f; 二.为什么你需要 Kubern…

markdown数学公式总结

行内与独行 行内公式&#xff1a;将公式插入到本行内&#xff0c;符号&#xff1a; 公式内容 公式内容 公式内容&#xff0c;如&#xff1a; x y z xyz xyz 独行公式&#xff1a;将公式插入到新的一行内&#xff0c;并且居中&#xff0c;符号&#xff1a; 公式内容 公式内容 公…

RISC-V IDE MRS使用笔记(十):嵌入式编程开发技巧汇总

RISC-V IDE MRS使用笔记(十)&#xff1a;嵌入式编程开发技巧汇总 MRS常见嵌入式开发技巧: Q1&#xff1a;如何修改程序编译生成库&#xff1f; A1&#xff1a;在工具栏中点击活动工程的编译配置按钮&#xff0c;在Build Artifact的Tab页面指定目标类型&#xff0c;选中为Stat…

uniapp仿浙北惠生活微信小程序

最近给公司写了一个内部微信小程序&#xff0c;功能比较简单&#xff0c;之前是用微信小程序原声写的&#xff0c;一遍看文档一边写&#xff0c;js&#xff0c;wxml&#xff0c;wxcc&#xff0c;json分在不同文件的写法很不习惯&#xff0c;于是花了两天用uniapp重写了一遍&…

思维导图对我生活以及工作的帮助(用户投稿)

作为一名白领&#xff0c;我每天都面临着各种各样的工作和生活压力。 为了更好地应对这些挑战&#xff0c;我开始尝试使用思维导图来帮助自己更好地组织和管理各种信息和任务。其中一款非常优秀的软件就是ProcessOn思维导图&#xff0c;它为我的工作和生活带来了很多便利和帮助…

Spring Boot|启动图案修改ASCII字符画

效果图 实现 在项目目录的resources文件夹中新建一个banner.txt&#xff0c;将内容放入即可&#xff1a; // _ooOoo_ // // o8888888o // // …

华为ENSP配置无线AC-网关模式

1、配置交换机以及AC的接口为trunk 交换机 vlan b 10 20 # interface GigabitEthernet0/0/1port link-type trunkport trunk allow-pass vlan 10 20 # # interface GigabitEthernet0/0/2port link-type trunkport trunk pvid vlan 10port trunk allow-pass vlan 10 20 # …

Linux系统安装QQ最新版 2023-06-30

腾讯在2023-05-30更新了linux版的qq&#xff0c;这次界面终于不再复古&#xff0c;好看多了。 安装步骤&#xff1a; 1.进入官网&#xff0c;寻找合适的安装包下载 https://im.qq.com/linuxqq/index.shtml 选择跟自己计算机匹配的版本&#xff0c;一般都是X86&#xff0c;如…