• 自定义MVC原理


    目录

    一、MVC简介

    二、最初的增删改查

    三、反射版的增删改查

    四、自定义MVC工作原理图

    五、自定义MVC后台代码实现


    一、MVC简介

       1、什么是MVC?

                MVC的全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种软件设计典范。它是用一种业务逻辑、数据与界面显示分离的方法来组织代码,将众多的业务逻辑聚集到一个部件里面,在需要改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑,达到减少编码的时间。

        2、MVC的好处

            视图层和业务层分离,这样就允许更改视图层代码而不用重新编译模型和控制器代码,同样,一个应用的业务流程或者业务规则的改变只需要改动MVC的模型层即可。因为模型与控制器和视图相分离,所以很容易改变应用程序数据层和业务规则。


    二、最初的增删改查

           jsp界面

    1. <%@ page language="java" contentType="text/html; charset=UTF-8"
    2. pageEncoding="UTF-8"%>
    3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    4. <html>
    5. <head>
    6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    7. <title>Insert title here</title>
    8. </head>
    9. <body>
    10. <h3>目前增删改查的方法</h3>
    11. <a href="${pageContext.request.contextPath }/book/add">增加</a>
    12. <a href="${pageContext.request.contextPath }/book/del">删除</a>
    13. <a href="${pageContext.request.contextPath }/book/edit">修改</a>
    14. <a href="${pageContext.request.contextPath }/book/list">查询</a>
    15. </body>
    16. </html>

    删除的Servlet

    1. package com.zwc.web;
    2. import java.io.IOException;
    3. import javax.servlet.ServletException;
    4. import javax.servlet.annotation.WebServlet;
    5. import javax.servlet.http.HttpServlet;
    6. import javax.servlet.http.HttpServletRequest;
    7. import javax.servlet.http.HttpServletResponse;
    8. @WebServlet("/book/del")
    9. public class DelBookServlet extends HttpServlet{
    10. @Override
    11. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    12. doPost(req, resp);
    13. }
    14. @Override
    15. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    16. System.out.println("处理书籍的删除业务,调用bookbiz");
    17. }
    18. }

     增加Servlet

    1. package com.zwc.web;
    2. import java.io.IOException;
    3. import javax.servlet.ServletException;
    4. import javax.servlet.annotation.WebServlet;
    5. import javax.servlet.http.HttpServlet;
    6. import javax.servlet.http.HttpServletRequest;
    7. import javax.servlet.http.HttpServletResponse;
    8. @WebServlet("/book/list")
    9. public class AddBookServlet extends HttpServlet{
    10. @Override
    11. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    12. doPost(req, resp);
    13. }
    14. @Override
    15. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    16. System.out.println("处理书籍的查询业务,调用bookbiz");
    17. }
    18. }

    修改Servlet

    1. package com.zwc.web;
    2. import java.io.IOException;
    3. import javax.servlet.ServletException;
    4. import javax.servlet.annotation.WebServlet;
    5. import javax.servlet.http.HttpServlet;
    6. import javax.servlet.http.HttpServletRequest;
    7. import javax.servlet.http.HttpServletResponse;
    8. @WebServlet("/book/edit")
    9. public class EditBookServlet extends HttpServlet{
    10. @Override
    11. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    12. doPost(req, resp);
    13. }
    14. @Override
    15. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    16. System.out.println("处理书籍的修改业务,调用bookbiz");
    17. }
    18. }

    查询Servlet 

    1. package com.zwc.web;
    2. import java.io.IOException;
    3. import javax.servlet.ServletException;
    4. import javax.servlet.annotation.WebServlet;
    5. import javax.servlet.http.HttpServlet;
    6. import javax.servlet.http.HttpServletRequest;
    7. import javax.servlet.http.HttpServletResponse;
    8. @WebServlet("/book/add")
    9. public class ListBookServlet extends HttpServlet{
    10. @Override
    11. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    12. doPost(req, resp);
    13. }
    14. @Override
    15. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    16. System.out.println("处理书籍的增加业务,调用bookbiz");
    17. }
    18. }

    界面效果

    点击标签控制台弹出对应的Servlet

     

     

     从最初的增删改查可以看到问题:

          1、 如果关于单个实体/表操作场景越多,需要新建的类也就越多,也就造成了项目中类的数量过于庞大

    三、反射版的增删改查

                   jsp界面:

    1. <%@ page language="java" contentType="text/html; charset=UTF-8"
    2. pageEncoding="UTF-8"%>
    3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    4. <html>
    5. <head>
    6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    7. <title>Insert title here</title>
    8. </head>
    9. <body>
    10. <h3>目前增删改查的方法</h3>
    11. <a href="${pageContext.request.contextPath }/book/add">增加</a>
    12. <a href="${pageContext.request.contextPath }/book/del">删除</a>
    13. <a href="${pageContext.request.contextPath }/book/edit">修改</a>
    14. <a href="${pageContext.request.contextPath }/book/list">查询</a>
    15. <h3>类数量过多问题的优化</h3>
    16. <a href="${pageContext.request.contextPath }/book.action?methodName=add">增加</a>
    17. <a href="${pageContext.request.contextPath }/book.action?methodName=del">删除</a>
    18. <a href="${pageContext.request.contextPath }/book.action?methodName=edit">修改</a>
    19. <a href="${pageContext.request.contextPath }/book.action?methodName=list">查询</a>
    20. <a href="${pageContext.request.contextPath }/book.action?methodName=load">回显</a>
    21. </body>
    22. </html>

    新建一个BookServlet

    1. package com.zwc.web;
    2. import java.io.IOException;
    3. import java.lang.reflect.Method;
    4. import javax.servlet.ServletException;
    5. import javax.servlet.annotation.WebServlet;
    6. import javax.servlet.http.HttpServlet;
    7. import javax.servlet.http.HttpServletRequest;
    8. import javax.servlet.http.HttpServletResponse;
    9. @WebServlet("/book.action")
    10. public class BookServlet extends HttpServlet{
    11. @Override
    12. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    13. doPost(req, resp);
    14. }
    15. @Override
    16. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    17. // 为了区分当前请求的目的,增删改查的目的,就从前台将要调用的方法名传递到后台
    18. String methodName = req.getParameter("methodName");
    19. //
    20. if("add".equals(methodName)) {
    21. // 如果前台传递到后台的是一个新增的请求,那么后台就调用新增方法
    22. add(req,resp);
    23. }
    24. else if("del".equals(methodName)) {
    25. del(req,resp);
    26. }
    27. else if("edit".equals(methodName)) {
    28. edit(req,resp);
    29. }
    30. else if("list".equals(methodName)) {
    31. list(req,resp);
    32. }
    33. }
    34. private void list(HttpServletRequest req, HttpServletResponse resp) {
    35. System.out.println("在同样一个Servlet中调用list方法");
    36. }
    37. private void edit(HttpServletRequest req, HttpServletResponse resp) {
    38. System.out.println("在同样一个Servlet中调用edit方法");
    39. }
    40. private void del(HttpServletRequest req, HttpServletResponse resp) {
    41. System.out.println("在同样一个Servlet中调用del方法");
    42. }
    43. private void add(HttpServletRequest req, HttpServletResponse resp) {
    44. System.out.println("在同样一个Servlet中调用add方法");
    45. }
    46. private void load(HttpServletRequest req, HttpServletResponse resp) {
    47. System.out.println("在同样一个Servlet中调用load方法");
    48. }
    49. }

    运行结果

     

    在上面又有一个问题:

    2、当新增了业务,除了要添加该业务对应的方法(load),同时还要改动原有的方法

    所以我们在这里优化BookServlet:

    1. package com.zwc.web;
    2. import java.io.IOException;
    3. import java.lang.reflect.Method;
    4. import javax.servlet.ServletException;
    5. import javax.servlet.annotation.WebServlet;
    6. import javax.servlet.http.HttpServlet;
    7. import javax.servlet.http.HttpServletRequest;
    8. import javax.servlet.http.HttpServletResponse;
    9. @WebServlet("/book.action")
    10. public class BookServlet extends HttpServlet{
    11. @Override
    12. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    13. doPost(req, resp);
    14. }
    15. @Override
    16. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    17. // 为了区分当前请求的目的,增删改查的目的,就从前台将要调用的方法名传递到后台
    18. String methodName = req.getParameter("methodName");
    19. // methodName可以是add/del/list/edit/.....
    20. // 前台传递上面方法,就调用当前类的对应方法
    21. try {
    22. Method m = this.getClass()//BookSerlvet.class
    23. .getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
    24. m.setAccessible(true);
    25. // 调用当前类实例的methodName 方法
    26. m.invoke(this, req,resp);
    27. } catch (Exception e) {
    28. e.printStackTrace();
    29. }
    30. }
    31. private void list(HttpServletRequest req, HttpServletResponse resp) {
    32. System.out.println("在同样一个Servlet中调用list方法");
    33. }
    34. private void edit(HttpServletRequest req, HttpServletResponse resp) {
    35. System.out.println("在同样一个Servlet中调用edit方法");
    36. }
    37. private void del(HttpServletRequest req, HttpServletResponse resp) {
    38. System.out.println("在同样一个Servlet中调用del方法");
    39. }
    40. private void add(HttpServletRequest req, HttpServletResponse resp) {
    41. System.out.println("在同样一个Servlet中调用add方法");
    42. }
    43. private void load(HttpServletRequest req, HttpServletResponse resp) {
    44. System.out.println("在同样一个Servlet中调用load方法");
    45. }
    46. }

    同样测试运行:

     

     

    若我们在增加一个订单的增删改查,同样写一个orderServlet

     

    我们可以观察到

     3、反射相关代码、在每一个实体类对应的Servlet中都存在
     4、每一个Servlets中都有doget、dopost

    四、自定义MVC工作原理图

     

    五、自定义MVC后台代码实现

    先创建中央控制器:
    主要职能:接受浏览器请求,找到对应的处理人

    1. package com.zwc.framework;
    2. import java.io.IOException;
    3. import java.util.HashMap;
    4. import java.util.Map;
    5. import javax.servlet.ServletException;
    6. import javax.servlet.annotation.WebServlet;
    7. import javax.servlet.http.HttpServlet;
    8. import javax.servlet.http.HttpServletRequest;
    9. import javax.servlet.http.HttpServletResponse;
    10. import com.zwc.web.BookAction;
    11. /**
    12. * 中央控制器:
    13. * 主要职能:接受浏览器请求,找到对应的处理人
    14. * @author Administrator
    15. *
    16. */
    17. @WebServlet("*.action")
    18. public class DispatcherServlet extends HttpServlet{
    19. private Map<String,Action> actions = new HashMap<String,Action>();
    20. // 程序启动时,只会加载一次
    21. @Override
    22. public void init() throws ServletException {
    23. actions.put("/book",new BookAction());
    24. actions.put("/order",new BookAction());
    25. }
    26. @Override
    27. protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    28. doPost(req, resp);
    29. }
    30. @Override
    31. protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    32. //http://localhost:8080/mvc/book.action?methodName=list
    33. String uri = req.getRequestURI();
    34. // 要拿到book,最后一个/到最后一个.为止
    35. uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
    36. Action action = actions.get(uri);
    37. action.execute(req, resp);
    38. }
    39. }

    在创建一个子控制器,对应请求的处理人

    1. package com.zwc.framework;
    2. import javax.servlet.http.HttpServletRequest;
    3. import javax.servlet.http.HttpServletResponse;
    4. /**
    5. * 子控制器:
    6. * 对应请求的处理人
    7. * @author Administrator
    8. *
    9. */
    10. public interface Action {
    11. void execute(HttpServletRequest req, HttpServletResponse resp);
    12. }

    实现子控制器接口 

    1. package com.zwc.framework;
    2. import java.lang.reflect.Method;
    3. import javax.servlet.http.HttpServletRequest;
    4. import javax.servlet.http.HttpServletResponse;
    5. public class ActionSupport implements Action{
    6. @Override
    7. public void execute(HttpServletRequest req, HttpServletResponse resp) {
    8. // 为了区分当前请求的目的,增删改查的目的,就从前台将要调用的方法名传递到后台
    9. String methodName = req.getParameter("methodName");
    10. // methodName可以是add/del/list/edit/.....
    11. // 前台传递上面方法,就调用当前类的对应方法
    12. try {
    13. Method m = this.getClass()//BookSerlvet.class
    14. .getDeclaredMethod(methodName, HttpServletRequest.class,HttpServletResponse.class);
    15. m.setAccessible(true);
    16. // 调用当前类实例的methodName 方法
    17. m.invoke(this, req,resp);
    18. } catch (Exception e) {
    19. e.printStackTrace();
    20. }
    21. }
    22. }

    继承实现子控制器的接口

    1. package com.zwc.web;
    2. import javax.servlet.http.HttpServletRequest;
    3. import javax.servlet.http.HttpServletResponse;
    4. import com.zwc.framework.Action;
    5. import com.zwc.framework.ActionSupport;
    6. public class BookAction extends ActionSupport{
    7. private void list(HttpServletRequest req, HttpServletResponse resp) {
    8. System.out.println("在同样一个Servlet中调用list方法");
    9. }
    10. private void edit(HttpServletRequest req, HttpServletResponse resp) {
    11. System.out.println("在同样一个Servlet中调用edit方法");
    12. }
    13. private void del(HttpServletRequest req, HttpServletResponse resp) {
    14. System.out.println("在同样一个Servlet中调用del方法");
    15. }
    16. private void add(HttpServletRequest req, HttpServletResponse resp) {
    17. System.out.println("在同样一个Servlet中调用add方法");
    18. }
    19. private void load(HttpServletRequest req, HttpServletResponse resp) {
    20. System.out.println("在同样一个Servlet中调用load方法");
    21. }
    22. }

    运行结果:

     

  • 相关阅读:
    【Linux】基本指令-入门级文件操作(二)
    一起用Go做一个小游戏(中)
    WSL2 安装与使用
    7天免登录和加入购物车逻辑
    ES6类的继承
    (dist)vue docker nginx 部署
    C++11——— 包装器
    HTML、css、javascript的区别
    7.0 异常处理
    使用idea(java-decompiler)插件反编译
  • 原文地址:https://blog.csdn.net/qq_65345936/article/details/125456229