一、什么是MVC?
MVC代表模型-视图-控制器,是一种经典的软件设计模式,常用于构建桌面应用程序、Web应用程序和移动应用程序。它将一个应用程序分为三个主要部分:
1.模型(Model):
2.视图(View):
负责展示和呈现数据给用户,通常是用户界面的组件。它根据模型的数据来渲染界面,提供用户与应用程序交互的界面。
3.控制器(Controller):
充当模型和视图之间的中介,处理用户的输入和响应。它接收用户的动作并更新模型和视图的状态,确保它们保持同步。
二、自定义mvc核心思想
自定义MVC架构的核心思想是将应用程序的不同功能部分分离开来,以实现更好的代码组织、可维护性和可扩展性。虽然MVC的基本架构已经定义了模型、视图和控制器,但是具体实现和组织方式可以根据项目的需求进行自定义。
三、自定义MVC的核心原则
- 核心组件分离: 保持模型、视图和控制器的独立性,每个组件都应该专注于自己的领域。模型负责数据处理和业务逻辑,视图负责展示界面,而控制器负责处理用户输入和协调其他组件。
- 清晰的通信接口: 定义清晰的接口和协议,以确保模型、视图和控制器之间的通信和交互是统一和可预测的。这可以减少耦合性,使组件更容易替换和扩展。
- 事件驱动: 引入事件驱动的思想可以提高MVC架构的灵活性和响应性。组件之间可以通过事件来进行通信,而不是直接调用方法。这样可以减少依赖关系,使系统更能适应变化。
- 分层架构: 根据应用程序的规模和复杂性,可以将MVC架构进一步分层。例如,可以引入服务层或数据访问层来处理特定的功能和访问外部资源,从而实现更好的代码分离和职责划分。
- 可测试性和可扩展性: 考虑如何设计MVC架构以便于测试和扩展。确保模型、视图和控制器的可测试性,以便能够进行单元测试和集成测试。同时,提供灵活的扩展点和插件机制,使新功能的添加和变更更加容易。
四、 三层架构和MVC的区别
1.结构层次不同:
- 三层架构:将应用程序划分为表示层(Presentation Layer)、业务逻辑层(Business Logic Layer)和数据访问层(Data Access Layer)。
- MVC:将应用程序划分为模型(Model)、视图(View)和控制器(Controller)。模型和视图负责应用程序的数据和界面,控制器负责处理用户输入和协调模型和视图之间的交互。
2.重点关注不同:
- 三层架构:着重于将应用程序按照功能职责进行分层,将关注点分离,并提供更好的可维护性和可扩展性。
- MVC:着重于将应用程序按照数据、界面和交互逻辑进行分离,实现用户界面和数据逻辑的解耦,并提供更好的用户体验和可重用性。
3.强调的功能不同
- 三层架构:着重于数据的管理和持久化,业务逻辑的封装和处理,以及用户界面的展示和交互。
- MVC:着重于界面的设计和呈现,用户交互的处理和响应,以及数据模型的管理和更新。
4.可扩展性和复用性不同:
- 三层架构:通过明确的层次划分和职责分离,提供更好的可扩展性和模块化设计,使不同层级的组件可以独立地进行调整和替换。
- MVC:通过分离数据逻辑、界面和交互逻辑,提供更好的复用性和可维护性,使视图和控制器可以被重用于不同的模型和业务逻辑。
五、MVC工作原理
举个栗子:
比如说一个老板他开饭店,刚开始为了节约成本,他一个人做事,从早上起床买菜、洗菜、切菜,切完之后有客人来了、还要招呼客人,客人还要点单点完单之后又要去炒菜,这一系列下来都是他一个人做的,客人吃完之后他还要洗碗,前期当他店小的时候用户量小的情况下他一个人是可以做的到的。
但是当他后期生意越来越好,想扩展规模越来越大的时候,他一个人就做不了这些事情了。
此时只能请人分配各个岗位,老板就做管理,管理员工。(各司其职)
六、MVC结构对应关系
1.模型-视图对应关系:
- 模型(Model):负责封装应用程序的数据和业务逻辑。
- 视图(View):负责展示模型中的数据给用户。
在这个对应关系中,模型代表应用程序的数据和操作方法,它存储和管理数据,并提供与数据相关的操作。视图是用户界面的表示部分,它负责展示模型中的数据给用户,通常是以可视化的形式呈现,如HTML页面、图表、列表等。
2.控制器-视图对应关系:
- 控制器(Controller):负责接收用户的输入和请求,并根据请求的类型和参数选择合适的视图进行展示。
- 视图(View):负责接收控制器传递的数据并将其呈现给用户。
这个对应关系中,控制器充当了视图和模型之间的协调者和中介者。它接收用户的输入或请求,并根据请求对模型进行操作。一旦模型处理完成后,控制器选择适当的视图进行展示,将模型中的数据传递给视图进行渲染。
3.控制器-模型对应关系:
- 控制器(Controller):负责接收用户的输入和请求,并根据请求的类型和参数选择相应的模型进行处理。
- 模型(Model):负责处理数据逻辑和状态管理。
这个对应关系中,控制器负责接收用户的输入,根据输入的请求调用适当的模型来处理数据逻辑和状态管理。控制器根据模型的处理结果来决定下一步的行动,可以进行数据更新、查询、保存等操作。
术语 | 对应关系 |
M | 实体域模型(名词)entity,过程域模型(动词:因为是可变的)dao/biz |
V | jsp |
C | servlet/action |
七.优缺点
优点:
耦合性低
重用性高
生命周期成本低
可维护性高
部署快
缺点:
1.增加系统结构和实现的复杂性
对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。
2.一般高级的界面工具或构造器不支持模式
改造这些工具以适应MVC需要和建立分离的部件的代价是很高的,会造成MVC使用的困难。
细讲原理图:
1.ActionServlet:中央控制层
2.子控制器Action中央控制器就是老板用来做管理的,子控制器就是各个员工,具体做事的那个人就叫子控制器。
注意:子控制器必须获取资格证才能上岗做事,这个资格证相当于Action
它里面有一个execute方法(处理具体逻辑)
八、自定义mvc的简单实现
1.中央控制器
通过servlet来实现一个中央控制器,负责所有请求的接收。(后续中央控制器在再将请求转发给各个子控制器,此处可以先把请求接进来,转发功能后面再加)
package com.ctb.framework; 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 biao */ @WebServlet("*.action") public class ActionDispatchServlet extends HttpServlet { @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) { doPost(req, resp); } @Override public void doPost(HttpServletRequest req, HttpServletResponse resp) { System.out.println("dopost ..... "); } }
2.Action类定义
Action类定义了每个子控制器需要遵循的行为,使得所有的子控制器都有一个同一的抽象类型,所以我们可以在中央控制器中使用Action类类型来引用所有的子控制器。这样就为用户扩展自定义的子控制器提供了条件。
package com.ctb.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 biao * * 2023年6月29日:下午7:08:41 */ public class Action { protected void excute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("................"); } }
3.继承子控制器
package com.ctb.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.ctb.framework.Action; /** * * @author biao * * 2023年6月29日:下午6:41:01 */ public class BookAction extends Action{ System.out.println("欢迎来到....."); }
4.完善中央控制器
为了便于理解,我们可以分步骤的,循序渐进的完善中央控制器:
- 编写简单的请求分发实现功能
- 实现子控制器的功能
- 完善请求参数处理功能
1.请求分发功能
package com.ctb.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.ctb.servlet.BookAction; /** * 请求分发功能 * @author biao * * 2023年6月29日:下午6:45:13 */ @WebServlet("*.action") public class DispathServlet extends HttpServlet{ //用于保存path与action子控制器的映射 public Map<String, Action> actionMap=new HashMap<String, Action>(); @Override public void init() throws ServletException { actionMap.put("/book", new BookAction()); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取uri地址 String uri = req.getRequestURI(); //截取 uri=uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf(".")); //将uri放到map集合中存储 Action action = actionMap.get(uri); //获取父类方法 action.excute(req, resp); } }
2.action子控制器
在上面的示例中,在中央控制器中直接创建action子控制器
package com.ctb.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 biao * * 2023年6月29日:下午7:08:41 */ public class Action { protected void excute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //获取页面传输的参数 String action = req.getParameter("action"); try { //反射动态方法调用 Method method = this.getClass().getDeclaredMethod(action, HttpServletRequest.class,HttpServletResponse.class); method.setAccessible(true); method.invoke(this, req,resp); } catch (Exception e) { e.printStackTrace(); } } }
3.请求参数处理功能
package com.ctb.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.ctb.framework.Action; /** * * @author biao * * 2023年6月29日:下午6:41:01 */ public class BookAction extends Action{ public void detail(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("欢迎来到查看详情💕💕💕"); } public void del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("欢迎来到删除💕💕💕"); } public void upd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("欢迎来到修改💕💕💕"); } public void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("欢迎来到新增💕💕💕"); } public void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("欢迎来到主页面💕💕💕"); } }
接下来,我们建一个jsp页面简单测试一下
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <%-- <p>多个servlet进行增删改查</p> <a href="${pageContext.request.contextPath }/list.do">查询</a> <a href="${pageContext.request.contextPath }/edit.do">修改</a> <a href="${pageContext.request.contextPath }/addbook.do">增加</a> <a href="${pageContext.request.contextPath }/del.do">删除</a> <a href="${pageContext.request.contextPath }/detail.do">查看详情</a> <hr> <p>一个servlet判断参数跳转增删改查方法</p> <a href="book.action?action=list">查询</a> <a href="book.action?action=upd">修改</a> <a href="book.action?action=add">增加</a> <a href="book.action?action=del">删除</a> <a href="book.action?action=detail">查看详情</a> <hr> <p>反射获取参数调用方法</p> <a href="book.do?action=list">查询</a> <a href="book.do?action=upd">修改</a> <a href="book.do?action=add">增加</a> <a href="book.do?action=del">删除</a> <a href="book.do?action=detail">查看详情</a> --%> <hr> <p>初步mvc</p> <a href="book.action?action=list">查询</a> <a href="book.action?action=upd">修改</a> <a href="book.action?action=add">增加</a> <a href="book.action?action=del">删除</a> <a href="book.action?action=detail">查看详情</a> </body> </html>
页面显示:
测试结果:
这篇文章就到这里结束啦(づ ̄ 3 ̄)づ,拜拜。