自定义MVC(上)

简介: 自定义MVC(上)

1.认识MVC

1.1MVC的定义

MVC是一种软件架构模式,它代表了Model-View-Controller(模型-视图-控制器)的缩写。MVC模式将应用程序分为三个主要组件

  1. 模型(Model): 模型代表应用程序的数据和业务逻辑。它负责数据的存储、检索和处理,以及定义应用程序的行为。
  2. 视图(View): 视图负责显示模型的数据给用户。它展示了用户界面的外观和布局,并在需要时将用户的输入传递给控制器。
  3. 控制器(Controller): 控制器处理用户的输入并更新模型和视图。它接收用户的操作和命令,并根据这些输入来调整模型的状态,并更新视图来反映这些状态的变化。

1.2为什么要用MVC

使用MVC架构有以下几个好处:

  1. 分离关注点(Separation of Concerns):MVC将应用程序分解为模型、视图和控制器,使每个组件负责不同的任务。
  2. 可扩展性和可维护性(Scalability and Maintainability):MVC模式将应用程序的不同部分解耦,使得修改或扩展其中一个组件不会对其他组件产生影响。
  3. 代码重用(Code Reusability):MVC模式鼓励将数据处理和业务逻辑放在模型中,这样可以将这些部分抽象出来并在不同的应用场景中重用。
  4. 可测试性(Testability):由于MVC的组件之间的松散耦合,可以更容易地对每个组件进行单元测试。
  5. 支持并行开发(Support for parallel development):MVC模式允许开发团队独立工作在不同的组件上,因为每个组件都有清晰的职责和接口定义。

1.3MVC框架与三层架构的区别

MVC框架和三层架构是软件开发中常用的两种架构模式,它们有一些区别:

①组织方式:

  • MVC框架是一种架构模式,它提供了一种组织和结构化应用程序的方法。它将应用程序分为模型、视图控制器三个组件,每个组件有独立的职责。
  • 三层架构是一种架构模式,它将应用程序分为表示层、业务逻辑层数据访问层三个层级,每个层级有独立的职责。

②关注点:

  • MVC框架的重点在于分离关注点(Separation of Concerns),通过对应用程序的数据、逻辑和展示的分离,实现代码的分层和解耦,使得团队成员能够更好地协作开发和维护应用程序。
  • 三层架构的重点在于将应用程序的不同功能分配到不同的层级上,通过层级的划分实现业务逻辑的解耦和重用,以实现灵活性和可扩展性。

③使用方式:

  • MVC框架是一种开发模式,可以从头开始自行开发,也可以使用现有的MVC框架,如Spring MVC、ASP.NET MVC等。这些框架提供了一套规范和工具,使开发者能够更快速、高效地构建MVC架构的应用程序。
  • 三层架构是一种架构模式,它并没有特定的框架或工具概念。开发者需要自行设计和实现应用程序的不同层级,并定义它们之间的接口和交互方式。

④主要应用场景:

  • MVC框架适用于各种规模的应用程序,并且在Web开发领域得到广泛应用。它可以实现良好的代码组织和可维护性,同时支持前后端分离、RESTful API等现代开发需求。
  • 三层架构适用于大型复杂的应用程序,尤其是企业级应用程序。它通过层级的划分,实现可扩展性和可维护性,同时支持多种技术栈的组合和集成。

2.MVC三层架构代码的演化

下面我们写三个不同版本的代码来演示一下MVC三层架构代码的演化:

2.1版本一

index.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<p>版本1</p>
弊端:每一张表对应的每一个操作,都要写一个servlet类来处理<hr>
<a href="bookAdd.action">增加</a>
<a href="bookDel.action">删除</a>
<a href="bookUpd.action">修改</a>
<a href="bookList.action">查询</a>
<hr><hr>
</body>
</html>

四个Servlet类:

BookListServlet:

package com.Kissship.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;
/**
 * Servlet implementation class BookListServlet
 */
@WebServlet("/bookList.action")
public class BookListServlet 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("BookListServlet.List...");
  }
}

BookDelServlet:

package com.Kissship.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;
/**
 * Servlet implementation class BookDelServlet
 */
@WebServlet("/bookDel.action")
public class BookDelServlet 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("BookDelServlet.del...");
  }
}

BookUpdServlet:

package com.Kissship.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;
/**
 * Servlet implementation class BookUpdServlet
 */
@WebServlet("/bookUpd.action")
public class BookUpdServlet 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("BookUpdServlet.upd...");
  }
}

BookAddServlet:

package com.Kissship.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;
/**
 * Servlet implementation class BookAddServlet
 */
@WebServlet("/bookAdd.action")
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.add...");
  }
}

效果图:

2.2版本二

index.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<p>版本1</p>
弊端:每一张表对应的每一个操作,都要写一个servlet类来处理<hr>
<a href="bookAdd.action">增加</a>
<a href="bookDel.action">删除</a>
<a href="bookUpd.action">修改</a>
<a href="bookList.action">查询</a>
<hr><hr>
<p>版本2</p>
弊端:每一张表对应的每一个操作,只要写一个servlet类来处理,但是每增加一个操作,都需要改变原有代码,换句话说要增加条件分支<hr>
<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>

BookServlet:

package com.Kissship.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;
/**
 * Servlet implementation class BookAddServlet
 */
@WebServlet("/book.action")
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("add".equals(methodName)) {
      add(request,response);
    }else if("del".equals(methodName)){
      del(request,response);
    }else if("upd".equals(methodName)){
      upd(request,response);
    }else if("list".equals(methodName)){
      list(request,response);
    }
  }
  private void list(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("BookListServlet.List...");
  }
  private void upd(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("BookUpdServlet.upd...");
  }
  private void del(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("BookDelServlet.del...");    
  }
  private void add(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("BookAddServlet.add...");    
  }
}

效果图:

2.3版本三

index:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<p>版本1</p>
弊端:每一张表对应的每一个操作,都要写一个servlet类来处理<hr>
<a href="bookAdd.action">增加</a>
<a href="bookDel.action">删除</a>
<a href="bookUpd.action">修改</a>
<a href="bookList.action">查询</a>
<hr><hr>
<p>版本2</p>
弊端:每一张表对应的每一个操作,只要写一个servlet类来处理,但是每增加一个操作,都需要改变原有代码,换句话说要增加条件分支<hr>
<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>
<hr><hr>
<p>版本3</p>
弊端:虽然解决了代码冗余的问题,但是放到项目范围,反射的代码是重复的<hr>
<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>

BookServlet:

package com.Kissship.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;
/**
 * Servlet implementation class BookAddServlet
 */
@WebServlet("/book.action")
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("add".equals(methodName)) {
//      add(request,response);
//    }else if("del".equals(methodName)){
//      del(request,response);
//    }else if("upd".equals(methodName)){
//      upd(request,response);
//    }else if("list".equals(methodName)){
//      list(request,response);
//    }
    try {
      Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
      m.setAccessible(true);
      m.invoke(this, request, response);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  private void list(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("BookListServlet.List...");
  }
  private void upd(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("BookUpdServlet.upd...");
  }
  private void del(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("BookDelServlet.del...");    
  }
  private void add(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("BookAddServlet.add...");    
  }
}

效果图:

3.自定义MVC工作原理

4.MVC框架初步实现

4.1DispatherServlet

该类即对应工作原理图中的ActionServlet(中央控制器)。它需要拦截所有的action请求。

代码如下:

package com.Kissship.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.Kissship.web.BookAction;
/**
 * 对应图中的ActionServlet:中央控制器
 * @author jj
 *
 */
@WebServlet("*.action")
public class DispatherServlet extends HttpServlet{
  public Map<String, Action> actionmap = new HashMap<String, Action>();//通过Map集合去拿到Action类
  @Override
  public void init() throws ServletException {//通过Map集合去拿到Action类之后,写一个初始化的方法init(),把所有的action放进去。(案例只有一个BookAction)
    actionmap.put("/book",new BookAction());
    super.init();
  }
  @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 {
//    book -> BookAction -> add   
    String uri = request.getRequestURI();//获取URL地址
    uri = uri.substring(uri.lastIndexOf("/"),uri.lastIndexOf("."));//截取
    Action action = actionmap.get(uri);//把所有的action放进init()方法之后,就可以通过map拿到uri,在这里返回一个action对象后续要通过它去抓取add等方法去提供服务
    action.execute(request, response);
  }
}

4.2Action类

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

代码如下:

package com.Kissship.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 jj
 *
 */
public class Action {
  protected void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String methodName = request.getParameter("methodName");
    try {
      Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
      m.setAccessible(true);
      m.invoke(this, request, response);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}

4.3BookAction

案例演示需要,Action(子控制器)的子类。

代码如下:

package com.Kissship.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.Kissship.framework.Action;
public class BookAction extends Action{
  public void add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("BookAction.add...");
  }
  public void del(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("BookAction.del...");
  }
  public void upd(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("BookAction.upd...");
  }
  public void list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("BookAction.list...");
  }
}

4.4index.jsp

代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<p>版本1</p>
弊端:每一张表对应的每一个操作,都要写一个servlet类来处理<hr>
<a href="bookAdd.action">增加</a>
<a href="bookDel.action">删除</a>
<a href="bookUpd.action">修改</a>
<a href="bookList.action">查询</a>
<hr><hr>
<p>版本2</p>
弊端:每一张表对应的每一个操作,只要写一个servlet类来处理,但是每增加一个操作,都需要改变原有代码,换句话说要增加条件分支<hr>
<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>
<hr><hr>
<p>版本3</p>
弊端:虽然解决了代码冗余的问题,但是放到项目范围,反射的代码是重复的<hr>
<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>
<hr><hr>
<p>版本4</p>
解决了反射代码重复的问题<hr>
<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>

效果图:

控制台:

BookAction为什么能调add方法?

因为在Action类中有了反射方法,然后BookAction继承了Action类。在BookAction类中都有一个反射的默认动态调用方法。所以BookAction里能直接add和删除修改等方法。

5.MVC框架初步实现个人理解思路

在中央控制器获取URL地址然后截取路径通过/book这个键去找一个对象(BookAction类——处理案例的浏览器请求),然后再BookAction上应该有个父类——即子控制器(真正做事,处理浏览器请求的类)。通过Map集合去拿到Action类之后, 然后写一个初始化的方法init(),把所有的action放进去。把所有的action放进init()方法之后,就可以通过map拿到uri。拿到了之后我们把反射方法copy到Action类中,然后在它的子类BookAction直接调用add和其他方法。最后在中央控制器调用反射代码块execute即可。


最后自定义MVC(上)就到这里,祝大家在敲代码的路上一路通畅!

感谢大家的观看 !

目录
相关文章
|
27天前
|
前端开发 Java 数据库
springBoot:template engine&自定义一个mvc&后端给前端传数据&增删改查 (三)
本文介绍了如何自定义一个 MVC 框架,包括后端向前端传递数据、前后端代理配置、实现增删改查功能以及分页查询。详细展示了代码示例,从配置文件到控制器、服务层和数据访问层的实现,帮助开发者快速理解和应用。
|
6月前
|
前端开发 Java
自定义mvc的增删改查
自定义mvc的增删改查
60 0
|
6月前
|
XML 前端开发 数据格式
自定义MVC引用XML配置文件实现
自定义MVC引用XML配置文件实现
62 0
|
6月前
|
设计模式 前端开发 搜索推荐
自定义mvc框架
自定义mvc框架
65 0
|
11月前
|
设计模式 前端开发
自定义mvc
自定义mvc
50 0
|
11月前
|
XML 前端开发 数据格式
自定义MVC超详细易懂----增删改查
自定义MVC超详细易懂----增删改查
|
11月前
|
存储 前端开发 架构师
自定义MVC实现 很详细(下)---优化版
自定义MVC实现 很详细(下)---优化版
|
11月前
|
存储 设计模式 前端开发
自定义MVC实现
自定义MVC实现
|
11月前
|
安全 Java
自定义mvc----增删改查终极篇
自定义mvc----增删改查终极篇
41 0
|
11月前
|
XML 设计模式 前端开发
自定义MVC---引用XML
自定义MVC---引用XML
50 0