目录
一、前言
1.什么是MVC架构
2.使用MVC架构的好处
3.MVC架构与三层架构的区别
4.MVC架构的思路
二、自定义MVC
1.最初版本
2.进阶版
3.反射优化版
4.反射增强版
MVC架构(Model-View-Controller),即模型-视图-控制器架构,是一种常见的软件设计模式,用于组织和分离应用程序的不同组成部分。
模型(Model):表示应用程序中的数据和业务逻辑。模型负责处理数据的读写、验证、计算等操作,以及处理与数据相关的业务逻辑。模型通常不直接与用户界面交互,而是通过控制器来获取和更新数据。
视图(View):表示应用程序中的用户界面。视图负责展示数据给用户,并接收用户的输入。视图通常不包含任何业务逻辑,而是通过控制器来更新和获取数据。一个模型可以有多个视图,视图可以是不同形式的展现,如网页、移动应用界面等。
控制器(Controller):负责处理用户输入、控制应用程序的流程,以及协调模型和视图之间的交互。控制器接收用户的输入并相应地更新模型和视图。它将用户的操作转化为对模型的请求或对视图的更新,以实现数据和界面的交互。
MVC架构的优势在于它能够实现良好的代码复用性、可扩展性、可维护性和可测试性。通过将应用程序的不同职责分离,使得各个组成部分独立变化,降低了耦合度,同时也使得开发团队能够更好地协作和管理项目。
生活案例:
假如有一家餐馆,只有老板一个人。采购、服务客人、炒菜、上菜、结账,都是老板来做,是不是很费时费力, 如果他招聘人员,来为他做这些事情是不是就大大节省了时间,而且我们一件事情对应一个人,某个环节出了问题都好直接对接。
项目案例:
餐馆就是我们的项目,jsp页面就是老板,什么事情都是他来干,代码量是非常大的而且不利于维护,这时候我们就要进行 “分类管理”将我们的代码变成MVC架构MVC就是模型(model)-视图(view)-控制器(controller)。它们各自处理自己的任务,高内聚低耦合, 提升我们写代码的效率以及后期维护等。
1. 三层架构是基于业务逻辑来分的,而MVC是基于页面来分的;
2. 三层是种软件架构,通过接口实现编程,MVC模式是一种复合设计模式,一种解决方案;
3. 三层架构模式是体系结构模式,MVC是设计模式;
4. 三层架构模式又可归于部署模式,MVC可归于表示模式。
注意:MVC架构和三层架构并不是互斥的,可以根据实际需求进行组合和调整。例如,可以将MVC架构作为表示层的一部分,用于管理用户界面的交互,同时在业务逻辑层和数据访问层中采用三层架构划分职责。
如图所示,视图负责展示模型中的数据给用户,并提供用户界面,用于与用户进行交互,发送请求到Servlet也就是控制器,控制器通过接收用户输入来控制应用程序的行为然后去到后端也就是数据访问层拿到相应数据后根据交互来更新模型和视图。
版本迭代:我将带领大家一步一步演变成我们如今所用的MVC架构让大家更直观的感受到为什么要使用以及怎么演变而来的。
版本一:一个请求参数(操作)对应一个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,非常的繁琐而且不利于维护。
版本二:增删改查都是一个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条件分支,如果我们的操作需求多了起来代码量也是非常冗余的。
版本三:反射机制优化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对应一张表。
创建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
actionMap = new HashMap (); @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就分享到这里啦!!!