自定义MVC

本文涉及的产品
性能测试 PTS,5000VUM额度
注册配置 MSE Nacos/ZooKeeper,118元/月
可观测可视化 Grafana 版,10个用户账号 1个月
简介: 自定义MVC是指根据特定项目的需求和规模,自行设计和实现的MVC架构。传统的MVC架构提供了一种通用的模式来组织应用程序,但在特殊情况下,可能需要根据项目的特定需求,做一些定制化的调整或扩展。自定义MVC使开发团队能够根据项目的需要,灵活地定义模型视图和控制器的职责以及它们之间的通信机制。可以根据具体业务需求来调整模型和控制器的逻辑设计符合项目需求的视图层。这样能够更好地满足项目的特殊要求,提高开发效率和代码质量。在自定义MVC中,开发人员可以自由选择和设计使用的技术和工具。


一、MVC概念描述

1、什么是MVC?

MVC是一种设计模式,用于开发软件应用程序。它将应用程序分为三个核心部分:模型(Model)、视图(View)和控制器(Controller)

    • 模型(Model)是应用程序的数据和业务逻辑层。它负责处理数据的读取、存储、更新和删除,以及定义业务规则和逻辑。
    • 视图(View)是用户界面的呈现层,负责展示数据给用户,并接收用户的输入。视图通常是用户可以看到和与之交互的界面元素,如图形界面、网页或移动应用程序的界面。
    • 控制器(Controller)是模型和视图之间的中介,负责处理用户的输入、控制数据的流动以及调度视图的更新。它接收来自用户界面的输入,然后通过更新模型或通知视图来响应这些输入。

    MVC的目标是将应用程序的逻辑和用户界面分离,使得代码更容易维护修改测试。通过将应用程序的不同部分分隔开来,可以提高代码的可读性可扩展性可重用性

    2、什么是自定义MVC?

    自定义MVC是指根据特定项目的需求和规模,自行设计和实现的MVC架构。传统的MVC架构提供了一种通用的模式来组织应用程序,但在特殊情况下,可能需要根据项目的特定需求,做一些定制化的调整或扩展。

    自定义MVC使开发团队能够根据项目的需要,灵活地定义模型视图控制器的职责以及它们之间的通信机制。可以根据具体业务需求来调整模型控制器的逻辑设计符合项目需求的视图层。这样能够更好地满足项目的特殊要求,提高开发效率和代码质量。

    在自定义MVC中,开发人员可以自由选择设计使用技术和工具,并根据项目的需要来决定是否引入其他架构模式或设计模式。这样可以根据具体的场景,综合考虑各种因素,选择最适合项目需求的架构方案。

    自定义MVC是根据项目需求和规模设计的定制化MVC架构,能够更好地满足特定项目的要求,并提高开发效率和代码质量

    3、自定义MVC有什么用(主要用途)?

      1. 灵活性和定制化:自定义MVC允许开发团队根据项目的具体需求来调整和扩展MVC的各个组成部分,以更好地满足特定项目的要求。可以根据具体场景自由选择和设计使用的技术和工具,以及决定是否引入其他架构模式或设计模式。
      2. 代码组织和可维护性:通过自定义MVC,开发人员可以将应用程序的不同层(模型、视图和控制器)进行清晰分离,并明确各自的职责。这样有助于更好地组织和管理项目代码,提高代码的可维护性和可读性。
      3. 可测试性:自定义MVC架构通常支持对不同部分进行单元测试或集成测试,从而提高代码的质量和可靠性。通过将业务逻辑从视图和控制器中剥离出来,可以更轻松地进行单元测试,并模拟不同场景来验证应用程序的功能。
      4. 适应性和扩展性:自定义MVC可以根据项目的增长和变化进行扩展和调整。如果对特定功能或模块需要进行更改或增加,可以根据需要修改模型、视图和控制器,而不会对整个应用程序产生过大的影响。这种灵活性和可扩展性有助于保持应用程序的可持续发展。
      5. 提高开发效率:通过自定义MVC,开发人员可以更好地组织和管理项目代码,优化开发流程,提高开发效率。不同开发人员可以更容易地理解和协同工作,将每个层的职责清晰分离,提高团队的协作效率。

      自定义MVC提供了灵活性可定制化代码组织可维护性可测试性适应性扩展性以及提高开发效率等多个方面的优势,使开发团队能够更好地满足项目的需求并提高开发质量。

      二、MVC三层架构

      第一种版本

      第一种方式是有弊端的:

             比如:你的每一个操作都需要编一个servlet类来处理

      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>index</title>
      </head>
      <body>
        <h1>第一种</h1>
        <a href="BookAddServlet">增加</a>
        <a href="BookDelServlet">删除</a>
        <a href="BookUpdateServlet">修改</a>
        <a href="BookListServlet">查询</a>
        <h1>第二种</h1>
        <a href="">增加</a>
        <a href="">删除</a>
        <a href="">修改</a>
        <a href="">查询</a>
        <h1>第三种</h1>
        <a href="">增加</a>
        <a href="">删除</a>
        <a href="">修改</a>
        <a href="">查询</a>
      </body>
      </html>

      image.gif

      servlet

      我们可以利用重定向跳转到首页,这样可以更好的给我们一个体验

           

      response.sendRedirect("index.jsp");
      image.gif
      package com.tgq.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;
      /**
       * 
       * @author tgq
       *
       */
      @WebServlet("/BookAddServlet")
      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");
              //利用重定向跳转到首页
          response.sendRedirect("index.jsp");
        }
      }

      image.gif

      以此我们编写四个一样的servlet

      image.gif编辑

      结果

      我们依次点击增加===》删除===》修改===》查询

      image.gif编辑

      打印结果

      image.gif编辑

      第二种版本

      弊端:虽然每一个对应每一个操作,只要写一个servlet来处理,但是每增加一个操作,都需要改变原有的代码块

      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>index</title>
      </head>
      <body>
        <h1>第一种</h1>
        <a href="BookAddServlet">增加</a>
        <a href="BookDelServlet">删除</a>
        <a href="BookUpdateServlet">修改</a>
        <a href="BookListServlet">查询</a>
        <h1>第二种</h1>
        <a href="BookServlet?methodName=add">增加</a>
        <a href="BookServlet?methodName=del">删除</a>
        <a href="BookServlet?methodName=update">修改</a>
        <a href="BookServlet?methodName=list">查询</a>
        <h1>第三种</h1>
        <a href="">增加</a>
        <a href="">删除</a>
        <a href="">修改</a>
        <a href="">查询</a>
      </body>
      </html>

      image.gif

      servlet

      package com.tgq.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;
      /**
       * 
       * @author tgq
       *
       */
      @WebServlet("/BookServlet")
      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 (methodName.equals("add")) {
            add(request, response);
          } else if (methodName.equals("del")) {
            del(request, response);
          } else if (methodName.equals("update")) {
            update(request, response);
          } else if (methodName.equals("list")) {
            list(request, response);
          }
          response.sendRedirect("index.jsp");
        }
        private void list(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("list");
        }
        private void update(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("update");
        }
        private void del(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("del");
        }
        private void add(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("add");
        }
      }

      image.gif

      结果

      我们依次点击增加===》删除===》修改===》查询

      image.gif编辑

      输出结果:

      image.gif编辑

      第三种版本

      弊端:

      虽然解决了if条件分支代码冗余的问题,但是放在项目范围内,反射的代码时重复的

      根据以上两种,我们进行一个优化修改

      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>index</title>
      </head>
      <body>
        <h1>第一种</h1>
        <a href="BookAddServlet">增加</a>
        <a href="BookDelServlet">删除</a>
        <a href="BookUpdateServlet">修改</a>
        <a href="BookListServlet">查询</a>
        <h1>第二种</h1>
        <a href="BookServlet?methodName=add">增加</a>
        <a href="BookServlet?methodName=del">删除</a>
        <a href="BookServlet?methodName=update">修改</a>
        <a href="BookServlet?methodName=list">查询</a>
        <h1>第三种</h1>
        <a href="BookServlet?methodName=add">增加</a>
        <a href="BookServlet?methodName=del">删除</a>
        <a href="BookServlet?methodName=update">修改</a>
        <a href="BookServlet?methodName=list">查询</a>
      </body>
      </html>

      image.gif

      servlet

      package com.tgq.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;
      /**
       * 
       * @author tgq
       *
       */
      @WebServlet("/BookServlet")
      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");
          try {
            // 利用反射调用方法
            Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,
                HttpServletResponse.class);
            // 打开访问权限
            method.setAccessible(true);
            // 操作以下的代码不发生任何变化
            method.invoke(this, request, response);
          } catch (Exception e) {
            e.printStackTrace();
          }
          response.sendRedirect("index.jsp");
        }
        private void list(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("list");
        }
        private void update(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("update");
        }
        private void del(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("del");
        }
        private void add(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("add");
        }
      }

      image.gif

      结果

      我们依次点击增加===》删除===》修改===》查询

      image.gif编辑

      输出结果:

      image.gif编辑

      三、自定义MVC框架的雏形

      工作原理图

      image.gif编辑

      类的创建

      我们需要新建一个包framework,在这个包下面我们新建两个类ClassDispatherServlet、Action)。

      在我们原本的包下面新建一个类ClassBookAction

      DispatherServlet:对应图中ActionServlet:中央处理器。

      (需要继承HttpServlet:需要拦截所有的.action请求)

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

      BookAction:需要继承Action

      我们需要拿到我们请求的servlet的url,我们再把他截取下来。

      需要一个容器来保存

      public Map<String, Action> actionMaps = new HashMap<String, Action>();
      image.gif

      利用init()方法初始化加载,添加进map集合保存

      package com.tgq.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.tgq.web.BookAction;
      /**
       * 对应图中ActionServlet:中央处理器
       * 
       * @author tgq
       *
       */
      @WebServlet("/*.action")
      public class DispatherServlet extends HttpServlet {
        public Map<String, Action> actionMaps = new HashMap<String, Action>();
        @Override
        public void init() throws ServletException {
          actionMaps.put("/BookServlet", 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 uri = request.getRequestURI();
          // 拿到路径进行一个截取,拿到最后一个“/”到最后一个“.”之间的字符串
          uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
          Action action = actionMaps.get(uri);
        }
      }

      image.gif

      我们的反射代码需要写在Action

      package com.tgq.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 tgq
       *
       */
      public class Action {
        public void execute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          String methodName = request.getParameter("methodName");
          try {
            // 利用反射调用方法
            Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,
                HttpServletResponse.class);
            // 打开访问权限
            method.setAccessible(true);
            // 操作以下的代码不发生任何变化
            method.invoke(this, request, response);
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }

      image.gif

      我们把需要调用的方法写在BookAction

      package com.tgq.web;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import com.tgq.framework.Action;
      public class BookAction extends Action {
        public void add(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("add");
        }
        public void list(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("list");
        }
        public void update(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("update");
        }
        public void del(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("del");
        }
      }

      image.gif

      最后我们在到我们的DispatherServlet,调用方法action.execute(request, response);

      这就是我们的第四个版本:解决代码重复的问题

      实践:第四种版本

      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>index</title>
      </head>
      <body>
        <h1>第一种</h1>
        <a href="BookAddServlet">增加</a>
        <a href="BookDelServlet">删除</a>
        <a href="BookUpdateServlet">修改</a>
        <a href="BookListServlet">查询</a>
        <h1>第二种</h1>
        <a href="BookServlet.action?methodName=add">增加</a>
        <a href="BookServlet.action?methodName=del">删除</a>
        <a href="BookServlet.action?methodName=update">修改</a>
        <a href="BookServlet.action?methodName=list">查询</a>
        <h1>第三种</h1>
        <a href="BookServlet.action?methodName=add">增加</a>
        <a href="BookServlet.action?methodName=del">删除</a>
        <a href="BookServlet.action?methodName=update">修改</a>
        <a href="BookServlet.action?methodName=list">查询</a>
        <h1>第四种</h1>
        <a href="BookServlet.action?methodName=add">增加</a>
        <a href="BookServlet.action?methodName=del">删除</a>
        <a href="BookServlet.action?methodName=update">修改</a>
        <a href="BookServlet.action?methodName=list">查询</a>
      </body>
      </html>

      image.gif

      debug测试

      我们在image.gif编辑

      进行一个断点测试


      我们依次点击增加===》删除===》修改===》查询

      image.gif编辑

      我们可以看到的断点的地方已经出现我们想要的结果了,走完之后就会调用

      action.execute(request, response);
      image.gif

      image.gif编辑

      我们到action里面的这里打个断点,可以看到我们想要的结果了。最后跳进我们BookAction里面的方法

      image.gif编辑

      结果

      image.gif编辑

      帮助

       

      如果想想我一样可以像这样建包、类等

      image.gif编辑

      四、利用XML建模反射优化(第五种)

      查询必须转发,增删改只用重定向

      弊端:中央控制器中的action容器加载不可以灵活配置

      示例

      我们再次添加一个Order的事件,首先我们在web包里面新建一个OrderAction

      package com.tgq.web;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;
      import com.tgq.framework.Action;
      public class OrderAction extends Action {
        public void add(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("OrderAction.add...");
        }
        public void list(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("OrderAction.list...");
        }
        public void update(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("OrderAction.update...");
        }
        public void del(HttpServletRequest request, HttpServletResponse response) {
          System.out.println("OrderAction.del...");
        }
      }

      image.gif

      我们在framework包里面的DispatherServlet里面init()方法里面新写一个

       

      actionMaps.put("/Order", new OrderAction());
      image.gif
      package com.tgq.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.tgq.web.BookAction;
      import com.tgq.web.OrderAction;
      /**
       * 对应图中ActionServlet:中央处理器
       * 
       * @author tgq
       *
       */
      @WebServlet("*.action")
      public class DispatherServlet extends HttpServlet {
        public Map<String, Action> actionMaps = new HashMap<String, Action>();
        @Override
        public void init() throws ServletException {
          actionMaps.put("/Book", new BookAction());
          actionMaps.put("/Order", new OrderAction());
        }
        @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 {
          // 拿到url路径
          String uri = request.getRequestURI();
          // 拿到路径进行一个截取,拿到最后一个“/”到最后一个“.”之间的字符串
          uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
          Action action = actionMaps.get(uri);
          action.execute(request, response);
        }
      }

      image.gif

      我们在jsp页面也编写一下事件

      <h1>第五种</h1>
        <h3>Book</h3>
        <a href="BookServlet.action?methodName=add">增加</a>
        <a href="BookServlet.action?methodName=del">删除</a>
        <a href="BookServlet.action?methodName=update">修改</a>
        <a href="BookServlet.action?methodName=list">查询</a>
        <h3>Order</h3>
        <a href="OrderServlet.action?methodName=add">增加</a>
        <a href="OrderServlet.action?methodName=del">删除</a>
        <a href="OrderServlet.action?methodName=update">修改</a>
        <a href="OrderServlet.action?methodName=list">查询</a>

      image.gif

      我们点击Order的删除

      image.gif编辑

      优化

      我们的framework是要导成jar包的,如果不可能在

      @Override
        public void init() throws ServletException {
          actionMaps.put("/Book", new BookAction());
          actionMaps.put("/Order", new OrderAction());
        }
      image.gif

      方法里面经常改,所以我们要用到xml

      我们再在同一路径下新建Source Folder 文件夹取名conf在这个文件夹下面放入我们的xml文件

      image.gif编辑

      <?xml version="1.0" encoding="UTF-8"?>
      <config>
        <action path="/order" type="com.zking.web.OrderAction">
        </action>
        <action path="/book" type="com.zking.web.BookAction">
          <forward name="list" path="/res.jsp" redirect="false" />
          <forward name="toList" path="/res.jsp" redirect="true" />
        </action>
      </config>

      image.gif

      我们以前的子控制器是写在map集合里的,现在的子控制器实在mvc.xml里面,就是放在configModel里面

      我们在DispatherServlet进行一个修改

      package com.tgq.framework;
      import java.io.IOException;
      import java.util.HashMap;
      import java.util.Map;
      import javax.management.RuntimeErrorException;
      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.tgq.framework.model.ActionModel;
      import com.tgq.framework.model.ConfigModel;
      import com.tgq.framework.model.ConfigModelFactory;
      import com.tgq.web.BookAction;
      import com.tgq.web.OrderAction;
      /**
       * 对应图中ActionServlet:中央处理器
       * 
       * @author tgq
       *
       */
      @WebServlet("/*.action")
      public class DispatherServlet extends HttpServlet {
        // public Map<String, Action> actionMaps = new HashMap<String, Action>();
        // 原来所有的子控制器是写在map集合里面,现在是写在mvc.xml文件里,也就是configModel里面
        private ConfigModel configModel;
        @Override
        public void init() throws ServletException {
          try {
            // 包含了所有的子控制器
            configModel = ConfigModelFactory.bulid();
          } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
          // actionMaps.put("/Book", new BookAction());
          // actionMaps.put("/Order", new OrderAction());
        }
        @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 {
          // 拿到url路径
          String uri = request.getRequestURI();
          // 拿到路径进行一个截取,拿到最后一个“/”到最后一个“.”之间的字符串
          uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
          // Action action = actionMaps.get(uri);
          // 通过uri=/book,在configModel对象中找
          ActionModel actionModel = configModel.pop(uri);
          // actionModel如果==null给个提示
          if (actionModel == null)
            throw new RuntimeException("action not config");
          // 拿到我们的路径
          String type = actionModel.getType();
          // 反射
          try {
            Action action;
            action = (Action) Class.forName(type).newInstance();// =BookAction bookAction=new BookAction();
            action.execute(request, response);
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }

      image.gif

      输出结果

      image.gif编辑

      五、优化方法调用结果集跳转问题

      我们在BookAction里面的del()方法里面添加一个Attribute和重定向

      request.setAttribute("content", "哈喽");
      response.sendRedirect("res.jsp");
      image.gif

      我们新建一个res.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>res</title>
      </head>
      <body>
      跳转成功:参数${content }
      </body>
      </html>
      image.gif

      我们点击jsp界面的删除

      输出结果:

      image.gif编辑

      我们省掉

      response.sendRedirect("res.jsp");
      request.getRequestDispatcher("res.jsp").forward(request, response);
      image.gif

      Actionexecute()方法的返回值改成StringBookAction里面方法的返回值也改成String

      ,注释掉

      //response.sendRedirect("res.jsp");
      //request.getRequestDispatcher("res.jsp").forward(request, response);
      image.gif

      Action中的execute()方法优化

      package com.tgq.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 tgq
       *
       */
      public class Action {
        public String execute(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
          String methodName = request.getParameter("methodName");
          String res = "";
          try {
            // 利用反射调用方法
            Method method = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class,
                HttpServletResponse.class);
            // 打开访问权限
            method.setAccessible(true);
            // 操作以下的代码不发生任何变化
            res = (String) method.invoke(this, request, response);
          } catch (Exception e) {
            e.printStackTrace();
          }
          return res;
        }
      }
      image.gif

       

      我们在DispatherServlet里面进行一个大的优化

      package com.tgq.framework;
      import java.io.IOException;
      import java.util.HashMap;
      import java.util.Map;
      import javax.management.RuntimeErrorException;
      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.tgq.framework.model.ActionModel;
      import com.tgq.framework.model.ConfigModel;
      import com.tgq.framework.model.ConfigModelFactory;
      import com.tgq.framework.model.ForwardModel;
      import com.tgq.web.BookAction;
      import com.tgq.web.OrderAction;
      /**
       * 对应图中ActionServlet:中央处理器
       * 
       * @author tgq
       *
       */
      @WebServlet("/*.action")
      public class DispatherServlet extends HttpServlet {
        // public Map<String, Action> actionMaps = new HashMap<String, Action>();
        // 原来所有的子控制器是写在map集合里面,现在是写在mvc.xml文件里,也就是configModel里面
        private ConfigModel configModel;
        @Override
        public void init() throws ServletException {
          try {
            // 包含了所有的子控制器
            configModel = ConfigModelFactory.bulid();
          } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
          // actionMaps.put("/Book", new BookAction());
          // actionMaps.put("/Order", new OrderAction());
        }
        @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 {
          // 拿到url路径
          String uri = request.getRequestURI();
          // 拿到路径进行一个截取,拿到最后一个“/”到最后一个“.”之间的字符串
          uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
          // Action action = actionMaps.get(uri);
          // 通过uri=/book,在configModel对象中找
          ActionModel actionModel = configModel.pop(uri);
          // actionModel如果==null给个提示
          if (actionModel == null)
            throw new RuntimeException("action not config");
          // 拿到我们的路径
          String type = actionModel.getType();
          // 反射
          try {
            // 具体业务代码执行后的返回值 add、update、del、list返回值===toList/list
            Action action = (Action) Class.forName(type).newInstance();// =BookAction bookAction=new BookAction();
            String execute = action.execute(request, response);
            // 要通过返回值拿到该方法结果是重定向还是转发,还是跳转哪个页面
            ForwardModel forwardModel = actionModel.pop(execute);
            if (forwardModel != null) {
              boolean redirect = forwardModel.isRedirect();
              // 拿到路径path
              String path = forwardModel.getPath();
              // 判断增删改重定向
              if (redirect) {
                // 加上request.getContextPath(),不然找不到项目路径
                response.sendRedirect(request.getContextPath() + "/" + path);
              } else {
                request.getRequestDispatcher(request.getContextPath() + "/" + path).forward(request, response);
              }
            }
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }
      image.gif

      六、优化参数封装

      弊端 :jsp传递到后台,封装到实体类的代码过多

      实操

      <h1>第六种</h1>
        <h3>Book</h3>
        <a href="BookServlet.action?methodName=add&bid=1&bname=nb&price=9.9">增加</a>

      image.gif

      我们常常传递数据的时候是用

      public String add(HttpServletRequest request, HttpServletResponse response) throws Exception {
          String bid = request.getParameter("bid");
          String bname = request.getParameter("bname");
          String price = request.getParameter("price");
          Book book = new Book();
          book.setBid(Integer.parseInt(bid));
          book.setBname(bname);
          book.setPrice(Float.parseFloat(price));
          System.out.println("BookAction.add...");
          request.setAttribute("content", "哈喽");
          // response.sendRedirect("res.jsp");
          return "toList";
        }
      image.gif

      这种方法传递的,最后添加到数据库里面去。写在我们进行一个优化。

      我们利用

      Map<String, String[]> parameterMap = request.getParameterMap();
      image.gif

      进行一个保存。

      优化

        1. 要有表对应的类属性对象 Book book
        2. 获取到所有的参数 及参数 req.getParameterMap();
        3. 将参数值封装到表对应的对象中
        4. 要做到所有子控制器通用

        编写一个模型驱动接口

        package com.tgq.framework;
        /**
         * 模型驱动接口 Book book = new Book();
         * 
         * @author L
         *
         * @param <T>
         */
        public interface ModelDriver<T> {
          T getModel();
        }

        image.gif

        实现ModelDriver接口肯定会重写getModel()方法,我们返回book

        image.gif编辑

        DispatherServlet:中央处理器优化

        package com.tgq.framework;
        import java.io.IOException;
        import java.util.HashMap;
        import java.util.Map;
        import java.util.Map.Entry;
        import java.util.Set;
        import javax.management.RuntimeErrorException;
        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 org.apache.commons.beanutils.BeanUtils;
        import com.tgq.framework.model.ActionModel;
        import com.tgq.framework.model.ConfigModel;
        import com.tgq.framework.model.ConfigModelFactory;
        import com.tgq.framework.model.ForwardModel;
        import com.tgq.web.BookAction;
        import com.tgq.web.OrderAction;
        /**
         * 对应图中ActionServlet:中央处理器
         * 
         * @author tgq
         *
         */
        @WebServlet("/*.action")
        public class DispatherServlet extends HttpServlet {
          // public Map<String, Action> actionMaps = new HashMap<String, Action>();
          // 原来所有的子控制器是写在map集合里面,现在是写在mvc.xml文件里,也就是configModel里面
          private ConfigModel configModel;
          @Override
          public void init() throws ServletException {
            try {
              // 包含了所有的子控制器
              configModel = ConfigModelFactory.bulid();
            } catch (Exception e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
            }
            // actionMaps.put("/Book", new BookAction());
            // actionMaps.put("/Order", new OrderAction());
          }
          @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 {
            // 拿到url路径
            String uri = request.getRequestURI();
            // 拿到路径进行一个截取,拿到最后一个“/”到最后一个“.”之间的字符串
            uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
            // Action action = actionMaps.get(uri);
            // 通过uri=/book,在configModel对象中找
            ActionModel actionModel = configModel.pop(uri);
            // actionModel如果==null给个提示
            if (actionModel == null)
              throw new RuntimeException("action not config");
            // 拿到我们的路径
            String type = actionModel.getType();
            // 反射
            try {
              // 具体业务代码执行后的返回值 add、update、del、list返回值===toList/list
              Action action = (Action) Class.forName(type).newInstance();// =BookAction bookAction=new BookAction();
              // 判断BookAction有没有ModelDriver接口
              if (action instanceof ModelDriver) {
                // 转型
                ModelDriver md = (ModelDriver) action;
                Object bean = md.getClass();
                Map<String, String[]> map = request.getParameterMap();
                BeanUtils.populate(bean, map);
              }
              String execute = action.execute(request, response);
              // 要通过返回值拿到该方法结果是重定向还是转发,还是跳转哪个页面
              ForwardModel forwardModel = actionModel.pop(execute);
              if (forwardModel != null) {
                boolean redirect = forwardModel.isRedirect();
                // 拿到路径path
                String path = forwardModel.getPath();
                // 判断增删改重定向
                if (redirect) {
                  // 加上request.getContextPath(),不然找不到项目路径
                  response.sendRedirect(request.getContextPath() + "/" + path);
                } else {
                  request.getRequestDispatcher(request.getContextPath() + "/" + path).forward(request, response);
                }
              }
            } catch (Exception e) {
              e.printStackTrace();
            }
          }
        }

        image.gif

        在这个里面

        BeanUtils.populate(bean, map);
        image.gif

        已经替代了

        Set<Entry<String, String[]>> entrySet = map.entrySet();
                   for (Entry<String, String[]> entry : entrySet) {
                     entry.getKey();
                    }
        image.gif

        我么进行一个断点测试,可以发现book里面是有值的

        image.gif编辑

        【注意】以后编写XXXAction 的时候我们只要实现implements ModelDriver<T>省去一大部分的东西

        帮助

        image.gif编辑

        希望对你们有用!谢谢!!!

        相关文章
        |
        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