自定义MVC工作原理

简介: 自定义MVC工作原理


一、MVC

MVC(Model View Controller)是一种软件工程中的一种软件架构模式,把软件系统分为三个基本部分:

  • 模型(Model)
  • 视图(View)
  • 控制器(Controller)

详细介绍在这里——>MVC详解

二、MVC的演变

为了更加方便地直观看出MVC的演变,在这里我省略Model层,只写View——JSP和Controller——Servlet

2.1 极易MVC

Controller层——Servlet

这里写4个极易Servlet,crud

package com.xqx.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;
/**
 * 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("add");
  }
}
package com.xqx.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;
/**
 * Servlet implementation class BookAddServlet
 */
@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("del");
  }
}
package com.xqx.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;
/**
 * Servlet implementation class BookAddServlet
 */
@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("upd");
  }
}
package com.xqx.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;
/**
 * Servlet implementation class BookAddServlet
 */
@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("list");
  }
}

view层——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>
<h1>极易MVC</h1>
<a href="bookAdd.action">新增</a>
<a href="bookDel.action">删除</a>
<a href="bookUpd.action">修改</a>
<a href="bookList.action">查看</a>
</body>
</html>

运行后的Jsp,点击哪个链接就跳哪个Servlet

点击修改和查看后,进入了对应的Servlet,打印结果

缺点:Servlet过多、代码冗余

但是这样我们也能非常直观地看出这么写的缺点,每写一个方法就要写一个Servlet,要是我有100个实体,每个实体都要增删改查的话,那么不是要写400个Servler,这样代码量太大了,并且还有很多重复代码。

2.2 简易MVC

用极易MVC Servlet会过多的话,那我们做个通用Servlet不就行了

Controller层——Servlet

通用的Servlet,判断jsp传来的参数即可回显不同内容

package com.xqx.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;
/**
 * 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 {
    // 拿到jsp传来的method
    String method = request.getParameter("method");
    if (method.equals("add")) {
      add(request,response);
    } else if (method.equals("del")) {
      del(request,response);
    } else if (method.equals("upd")) {
      upd(request,response);
    } else if (method.equals("list")) {
      list(request,response);
    }
  }
  private void list(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("list");
  }
  private void upd(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("upd");
  }
  private void del(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("del");
  }
  private void add(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("add");    
  }

view层——JSP

在href路径加方法参数即可

<%@ 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>
<h1>极易MVC</h1>
<a href="bookAdd.action">新增</a>
<a href="bookDel.action">删除</a>
<a href="bookUpd.action">修改</a>
<a href="bookList.action">查看</a>
<h1>简易MVC</h1>
<a href="book.action?method=add">新增</a>
<a href="book.action?method=del">删除</a>
<a href="book.action?method=upd">修改</a>
<a href="book.action?method=list">查看</a>
</body>
</html>

打印结果:

缺点:在Servlet中if语句冗余

虽然只要写一个Servlet了,但是如果有100个需求100个方法呢,难道写100个if语句?代码量不也是很大么,那么怎么解决呢?

2.3普易MVC

在简易MVC中如果方法越多,Servlet中if语句也会越来越多,要是能有一个技术能拿到所有方法就好了,那么你想到这个技术是什么了吗?

没错,就是反射!!!

Controller层——Servlet

package com.xqx.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;
/**
 * 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 {
    // 拿到jsp传来的method
    String method = request.getParameter("method");
    try {
      //拿到HttpServletRequest、HttpServletResponse类型的方法
      Method m = this.getClass().getDeclaredMethod(method, 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("list");
  }
  private void upd(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("upd");
  }
  private void del(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("del");
  }
  private void add(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("add");    
  }
}

view层——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>
<h1>极易MVC</h1>
<a href="bookAdd.action">新增</a>
<a href="bookDel.action">删除</a>
<a href="bookUpd.action">修改</a>
<a href="bookList.action">查看</a>
<hr>
<h1>简易MVC</h1>
<a href="book.action?method=add">新增</a>
<a href="book.action?method=del">删除</a>
<a href="book.action?method=upd">修改</a>
<a href="book.action?method=list">查看</a>
<hr>
<h1>普易MVC</h1>
<a href="book.action?method=add">新增</a>
<a href="book.action?method=del">删除</a>
<a href="book.action?method=upd">修改</a>
<a href="book.action?method=list">查看</a>
</body>
</html>

打印结果:

缺点:反射代码重复

虽然它能通过反射拿到所有的方法,减少了if语句的冗余,但是我们将视角上升到整个项目,一个项目不可能只有一个实体类吧,那Servlet也不是只有一个,但每个类对应的Servlet拿到所有方法的反射代码是一样的呀,这个代码重复,能否有一个真正意义上面对所有类的通用Servlet呢?

没有咱就写一个嘛,对吧,写一个能处理所有前端发送过来请求的Servlet,其实这个Servlet就是MVC中的中央控制器,到了这里其实已经有了MVC架构模式的雏形了。

三、MVC架构模式的初实现

3.1 工作流程图

3.2 实现

  • 创建一个能处理所有前端发送过来请求的Servle,即中央控制器,拿到所有方法的反射代码就在这里,并根据请求的类型调用相应的业务逻辑(去子控制器)
  • 创建一个子控制器,用于处理特定的用户请求或操作,这是真正处理用户请求的Servlet
  • 创建一个定义方法的Servlet,继承子控制器,供子控制器调用方法

Controller层——Servlet

中央控制器
package com.xqx.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;
/** 中央控制器 即工作流程图中的ActionServlet
 * @author W许潜行
 * 2023年6月29日 下午8:10:04
 */
@WebServlet("*.action")
public class DispatherServlet extends HttpServlet {
  Map<String,Action> mapAction=new HashMap<>();
  /**
   * 初始化方法
   */
  public void init() throws ServletException {
    mapAction.put("/book", new BookAction());
    super.init();
  }
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doPost(request, response);
  }
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //得到传过来的路径名
    String uri = request.getRequestURI();// /J2EE_MVC/book.action
    //得到请求的类
    uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));// /book
    //拿到对应的action
    Action action = mapAction.get(uri);
    //调用方法
    action.execute(request, response);
  }
}

当有请求进入时,我们首先获取请求的URI,并从中获取类似"/book"的路径名。然后,我们使用这个路径名作为键在mapAction中查找对应的Action对象。最后,执行该Action的execute方法来处理请求。

这个DispatcherServlet类的目的是根据传入的请求路径来分发请求给不同的Action类处理,通过这种方式实现请求的路由和控制,实现了基本的MVC模式

子控制器
package com.xqx.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 W许潜行 2023年6月29日 下午8:17:41
 */
public class Action {
  public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 拿到jsp传来的method
    String method = request.getParameter("method");
    try {
      Method m = this.getClass().getDeclaredMethod(method, HttpServletRequest.class, HttpServletResponse.class);
      m.setAccessible(true);
      m.invoke(this, request, response);
    } catch (Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}

这个Action类的作用是通过反射机制根据传入的method参数值来调用具体的方法进行请求处理。每个实际的Action类都可以继承这个基类,并重写具体的方法来实现自己的业务逻辑。

具体Action类
package com.xqx.framework;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**定义crud方法
 * @author W许潜行
 * 2023年6月29日 下午8:55:46
 */
public class BookAction extends Action{
  public void list(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("list");
  }
  public void upd(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("upd");
  }
  public void del(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("del");
  }
  public void add(HttpServletRequest request, HttpServletResponse response) {
    System.out.println("add");    
  }
}

view层——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>
<h1>极易MVC</h1>
<a href="bookAdd.action">新增</a>
<a href="bookDel.action">删除</a>
<a href="bookUpd.action">修改</a>
<a href="bookList.action">查看</a>
<hr>
<h1>简易MVC</h1>
<a href="book.action?method=add">新增</a>
<a href="book.action?method=del">删除</a>
<a href="book.action?method=upd">修改</a>
<a href="book.action?method=list">查看</a>
<hr>
<h1>普易MVC</h1>
<a href="book.action?method=add">新增</a>
<a href="book.action?method=del">删除</a>
<a href="book.action?method=upd">修改</a>
<a href="book.action?method=list">查看</a>
</body>
<h1>MVC架构初实现</h1>
<a href="book.action?method=add">新增</a>
<a href="book.action?method=del">删除</a>
<a href="book.action?method=upd">修改</a>
<a href="book.action?method=list">查看</a>
</body>
</html>

打印结果:

初步实现MVC架构就基本完成了,但还有很多优化之处,等之后博客再进行优化与分享。

好啦,今天的分享就到此为止!希望你看完本篇文章有所收获,祝你变得更强!!!

目录
相关文章
|
5月前
|
前端开发
MVVM和MVC的原理以及它们的区别
MVVM和MVC的原理以及它们的区别
|
2月前
|
前端开发 Java 数据管理
Spring MVC 工作原理解析
Spring MVC 工作原理解析
22 0
|
5月前
|
设计模式 前端开发 BI
什么是mvc原理是什么
什么是mvc原理是什么
24 0
|
5月前
|
前端开发 测试技术 数据处理
MVVM和MVC以及MVP的原理以及它们的区别
MVVM和MVC以及MVP的原理以及它们的区别
40 0
|
5月前
|
设计模式 前端开发 Java
Spring Boot之Spring MVC的工作原理 以及使用eclipse开发Spring MVC的Web应用实战(附源码)
Spring Boot之Spring MVC的工作原理 以及使用eclipse开发Spring MVC的Web应用实战(附源码)
46 0
|
5月前
|
XML 前端开发 Java
SpringMVC中<mvc:annotation-driven/>标签原理与实践详解
SpringMVC中<mvc:annotation-driven/>标签原理与实践详解
47 0
|
27天前
|
前端开发 Java
自定义mvc的增删改查
自定义mvc的增删改查
38 0
|
5月前
|
XML 前端开发 数据格式
自定义MVC引用XML配置文件实现
自定义MVC引用XML配置文件实现
41 0
|
5月前
|
设计模式 前端开发 搜索推荐
自定义mvc框架
自定义mvc框架
39 0
|
5月前
|
设计模式 前端开发
自定义mvc
自定义mvc
29 0