一.什么是自定义MVC框架
自定义MVC(Model-View-Controller)框架的原理是基于MVC设计模式,按照自己的需求和业务逻辑设计和实现一个定制化的应用程序开发框架。
MVC框架的原理可以分为以下几个关键步骤:
- 分析需求:首先,开发人员需要充分理解应用程序的需求和业务逻辑。他们需要分析应用程序的功能、数据流、用户界面等方面,以确定所需的模型、视图和控制器。
- 设计框架结构:根据需求分析,开发人员需要设计自定义MVC框架的结构和组织方式。这包括确定模型、视图和控制器的角色和职责,以及它们之间的交互方式。
- 模型(Model):负责处理应用程序的业务逻辑和数据。它通常包括数据模型、数据访问和业务规则等。
- 视图(View):负责展示应用程序的用户界面。它可以是HTML、CSS和JavaScript等前端技术,用于呈现数据给用户。
- 控制器(Controller):负责处理用户的输入和控制应用程序的行为。它接收用户请求,从模型获取数据,并将数据传递给视图展示给用户。
3.实现核心功能:根据框架设计,开发人员需要实现核心功能的代码。这可能涉及开发模型、视图和控制器的基本功能和接口。开发人员还可以考虑使用一些设计模式,如观察者模式、工厂模式等,来提高框架的灵活性和可扩展性。
4.提供扩展机制:自定义MVC框架通常需要提供扩展机制,以便开发人员可以根据具体的应用需求添加自定义功能。这可以通过提供插件机制、扩展点、路由配置等方式来实现。
5.测试和优化:实现框架后,开发人员需要进行全面的测试以确保功能的正确性和稳定性。他们还可以通过性能测试和代码优化来提升框架的执行效率和响应速度。
6.文档和支持:开发人员应该编写清晰的文档,介绍框架的使用方法和示例。他们还应该提供相应的支持,包括解答开发者的问题、修复bug和提供版本升级等。
总的来说,自定义MVC框架的原理是根据MVC设计模式,按照具体的需求设计和实现一个可定制的应用程序开发框架,以提供更高的灵活性、可扩展性和可维护性。这需要开发人员具备深入的业务理解、设计和编程技能,以及耐心和持续的努力来构建和维护框架。
二.自定义MVC框架与MVC三层架构之间的联系和区别
自定义MVC框架和MVC三层架构都是软件开发中常见的架构模式,它们在一定程度上有联系,但也存在一些区别。
2.1.联系
- 都采用MVC思想:自定义MVC框架和MVC三层架构都基于MVC(Model-View-Controller)思想。它们将应用程序划分为模型、视图和控制器,以实现分离关注点、提高代码的可维护性和可扩展性。
- 模型层:在两者中,模型层负责处理应用程序的业务逻辑和数据操作。它们都关注数据的获取、处理和存储,并根据需求进行相应的操作和计算。
- 视图层:自定义MVC框架和MVC三层架构都将视图层作为用户界面的展示,负责将模型的数据呈现给用户。视图层可以采用不同的技术和工具进行实现,如HTML、CSS、JavaScript等。
- 分离关注点:无论是自定义MVC框架还是MVC三层架构,都强调将不同的功能和职责分离开来,以达到解耦合的目的。模型、视图和控制器各司其职,相互之间的依赖尽可能降低。
2.2.区别
- 都采用MVC思想:自定义MVC框架和MVC三层架构都基于MVC(Model-View-Controller)思想。它们将应用程序划分为模型、视图和控制器,以实现分离关注点、提高代码的可维护性和可扩展性。
- 模型层:在两者中,模型层负责处理应用程序的业务逻辑和数据操作。它们都关注数据的获取、处理和存储,并根据需求进行相应的操作和计算。
- 视图层:自定义MVC框架和MVC三层架构都将视图层作为用户界面的展示,负责将模型的数据呈现给用户。视图层可以采用不同的技术和工具进行实现,如HTML、CSS、JavaScript等。
- 分离关注点:无论是自定义MVC框架还是MVC三层架构,都强调将不同的功能和职责分离开来,以达到解耦合的目的。模型、视图和控制器各司其职,相互之间的依赖尽可能降低。
需要注意的是,MVC三层架构更多地关注整个系统的分层和解耦,而自定义MVC框架更多地关注在一个应用程序内部的架构设计。选择使用哪种架构模式取决于具体的项目需求和开发团队的技术栈。
三.自定义MVC的框架的好处
MVC三层架构(Model-View-Controller)在软件开发中有许多好处,下面是几个主要的优点:
- 分离关注点:MVC三层架构将应用程序分解为模型(Model)、视图(View)和控制器(Controller)三个组件,每个组件专注于不同的职责。这种分离使得代码的维护和扩展更加容易,因为每个组件只需关注自己的功能,降低了代码的耦合度。
- 提高可维护性:由于MVC三层架构中的模型、视图和控制器分离明确,不同组件之间的关系清晰明了。这使得项目的开发团队可以更容易地理解和维护代码,而无需深入了解其他组件的实现细节。
- 增强可扩展性:每个组件在MVC三层架构中都有明确定义的职责和功能,使得应用程序的某个组件可以进行独立的修改、替换或扩展。这降低了对整个系统的影响,提高了系统的可扩展性和灵活性。
- 提升团队协作:MVC三层架构使不同的功能模块分离清晰,开发人员可以并行工作,专注于各自的领域。这促进了团队的协作,提高了开发效率,同时也便于项目管理和维护。
- 可测试性:由于MVC三层架构的模型、视图和控制器之间有着清晰的界限和通信方式,各个组件可以进行独立的单元测试。这极大地简化了测试流程,提高了代码的可测试性和质量。
- 支持多平台:MVC三层架构的视图层是与特定平台无关的,可以比较容易地进行适配和移植。这使得开发人员能够更轻松地在不同的平台(如Web、移动设备等)上实现应用程序。
综上所述,MVC三层架构具有良好的模块化、可维护性、扩展性和测试性,能够提供更好的代码组织和减少耦合度。这使得开发人员能够更高效地开发和维护应用程序,并为未来的需求变化做好准备。
四. 自定义MVC的工作原理
从左至右依次分析:
浏览器:客户 *.action:客户发送请求,→客户发送请求给中央控制器。(客户就是说出自己的请求)
ActionServlet:中央控制器,Action:子控制器 *: →中央控制器根据客户发送的请求给子控制器执行客户的请求。(简单来说:就是根据客户请求执行相对应的任务)
Action→ Model→DB→MOdel→Action:从数据库获取对应的数据给子控制器(正在执行对应的任务)
String:→子控制器响应给客户(给客户一个答复)
五.自定义MVC实例流程
5.1三种方式与其做比较
第一种:
BookAddServlet:
package com.junlinyi.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; /** * * @author: 君临沂 * */ @WebServlet("/bookAdd.action") public class BookAddServlet extends HttpServlet { @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 { System.out.println("恭喜你进入add..."); } }
BookDelServlet:
package com.junlinyi.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; /** * * @author: 君临沂 * */ @WebServlet("/bookDel.action") public class BookDelServlet extends HttpServlet { @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 { System.out.println("恭喜你进入del..."); } }
BookUpdServlet:
package com.junlinyi.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; /** * * @author: 君临沂 * */ @WebServlet("/bookUpd.action") public class BookUpdServlet extends HttpServlet { @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 { System.out.println("恭喜你进入upd..."); } }
BookListServlet:
package com.junlinyi.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; /** * * @author: 君临沂 * */ @WebServlet("/bookList.action") public class BookListServlet extends HttpServlet { @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 { System.out.println("恭喜你进入list..."); } }
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>Insert title here</title> </head> <body> <p>第一种</p> <a href="bookAdd.action">增加</a> <a href="bookDel.action">删除</a> <a href="bookUpd.action">修改</a> <a href="bookList.action">查询</a> </body> </html>
以上代码量就可看出它的弊端了,弊端就是每张表对应的每个操作,都要写一个Servlet来处理。
第二种:
BookServlet:
package com.junlinyi.servlet; 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: 君临沂 * */ //@WebServlet("/book.action") public class BookServlet extends HttpServlet { @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 { // 获取页面传来的方法参数,用于辨别执行对应操作的方法 String methodName = req.getParameter("methodName"); // 根据获取的方法参数做判断执行对应操作 if("add".equals(methodName)) { add(req,resp); }else if("del".equals(methodName)) { del(req,resp); }else if("upd".equals(methodName)) { upd(req,resp); }else if("list".equals(methodName)) { list(req,resp); }else if("good".equals(methodName)) { good(req,resp); } } private void good(HttpServletRequest req, HttpServletResponse resp) { } private void list(HttpServletRequest req, HttpServletResponse resp) { System.out.println("恭喜你进入list..."); } private void upd(HttpServletRequest req, HttpServletResponse resp) { System.out.println("恭喜你进入upd..."); } private void del(HttpServletRequest req, HttpServletResponse resp) { System.out.println("恭喜你进入del..."); } private void add(HttpServletRequest req, HttpServletResponse resp) { System.out.println("恭喜你进入add..."); } }
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>Insert title here</title> </head> <body> <p>第二种</p> <a href="book.action?methodName=add">增加</a> <a href="book.action?methodName=del">删除</a> <a href="book.action?methodName=upd">修改</a> <a href="book.action?methodName=list">查询</a> </body> </html>
以上可以看出比第二种好一点,但是也有弊端 ,它的弊端就是虽然每张表对应的每个操作,只有写一个Servlet来处理,但是每增加一个操作,都需要改变原有代码块,换句话说就是增加条件分支
第三种:
BookServlet:
package com.junlinyi.servlet; 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: 君临沂 * */ //@WebServlet("/book.action") public class BookServlet extends HttpServlet { @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 { // 获取页面传来的方法参数,用于辨别执行对应操作的方法 String methodName = req.getParameter("methodName"); // 反射从获取类类开始 this:代表BookServlet类 try { // 获取当前类的方法对象 Method m = this.getClass().getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class); // 打开访问权限 m.setAccessible(true); // 执行对应方法名对象的方法 m.invoke(this,req,resp); } catch (Exception e) { e.printStackTrace(); } } private void good(HttpServletRequest req, HttpServletResponse resp) { } private void list(HttpServletRequest req, HttpServletResponse resp) { System.out.println("恭喜你进入list..."); } private void upd(HttpServletRequest req, HttpServletResponse resp) { System.out.println("恭喜你进入upd..."); } private void del(HttpServletRequest req, HttpServletResponse resp) { System.out.println("恭喜你进入del..."); } private void add(HttpServletRequest req, HttpServletResponse resp) { System.out.println("恭喜你进入add..."); } }
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>Insert title here</title> </head> <body> <p>第三种</p> <a href="book.action?methodName=add">增加</a> <a href="book.action?methodName=del">删除</a> <a href="book.action?methodName=upd">修改</a> <a href="book.action?methodName=list">查询</a> </body> </html>
5.2.自定义MVC框架
DispathServlet (图中中央控制器)
package com.junlinyi.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.junlinyi.servlet.BookAction; /** * 中央控制器 * @author: 君临沂 * */ @WebServlet("*.action") public class DispathServlet extends HttpServlet{ 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 { String uri = req.getRequestURI(); uri=uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf(".")); Action action = actionMap.get(uri); action.execute(req, resp); } }
BookAction
package com.junlinyi.servlet; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.junlinyi.framework.Action; /** * BookAction类 * @author: 君临沂 * */ public class BookAction extends Action{ public void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("恭喜你进入add...."); } public void del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("恭喜你进入del...."); } public void upd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("恭喜你进入upd...."); } public void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("恭喜你进入list...."); } }
Action(图中子控制器)
package com.junlinyi.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: 君临沂 * */ public class Action { protected void execute(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String methodName = req.getParameter("methodName"); // try { Method m = this.getClass().getDeclaredMethod(methodName,HttpServletRequest.class,HttpServletResponse.class); m.setAccessible(true); m.invoke(this,req,resp); } catch (Exception e) { e.printStackTrace(); } } }
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>Insert title here</title> </head> <body> <a href="book.action?methodName=add">增加</a> <a href="book.action?methodName=del">删除</a> <a href="book.action?methodName=upd">修改</a> <a href="book.action?methodName=list">查询</a> </body> </html>
刚开始增删改查每个操作多要写一个servlet,一步一步的解决前面的弊端,优化出了这个解决方法自定义MVC框架, 解决了反射的代码是重复的问题.