自定义MVC框架优化

简介: 自定义MVC框架优化

一、前言

自定义MVC框架原理中讲述了什么是MVC架构,以及它和三层架构的区别,在其简单的代码演示中,还存有一定的缺陷,今天将带大家继续进行优化。

二、优化问题

1.子控制器的初始化配置问题

//用于保存path与action子控制器的映射
  public Map<String, Action> actionMap=new HashMap<String, Action>();
  @Override
  public void init() throws ServletException {
    actionMap.put("/book", new BookAction());
        actionMap.put("/goods", new GoodsAction());
  }

在初始化方法中初始化子配置器的值,当我们每新增一张表,那我们都得在初始化方法中新增一个子配置器的值,我们既然要自定义MVC,最后肯定是要封装成jar包的,封装成jar包后是不能修改的,所以我们要让它变成自动化的。

2.页面跳转优化代码冗余问题

public  void detail(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到查看详情💕💕💕");
        resp.sendRedirect("far.jsp");
  }
  public  void del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到删除💕💕💕"); 
 resp.sendRedirect("far.jsp");  
  }
  public  void upd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到修改💕💕💕");   
 resp.sendRedirect("far.jsp");
  }
  public  void add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到新增💕💕💕");   
 resp.sendRedirect("far.jsp");
  }
  public  void list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到主页面💕💕💕");    
    req.getRequestDispatcher("far.jsp").forward(req, resp);
  }
 .

我们在子控制器中无论是什么操作都是要进行页面回显的,需要进行重定向response.sendRedirect();或者转发request.getRequestDispatcher().forward();操作(ajax方式除外)这些代码是冗余的。

3.优化参数封装问题

Book book=new Book();
  public  String detail(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到查看详情💕💕💕");
    String bid = req.getParameter("bid");
    String bname = req.getParameter("bname");
    String price = req.getParameter("price");
    book.setBid(Integer.valueOf(bid));
    book.setBname(bname);
    book.setPrice(Integer.valueOf(price));
  }

当我们对每张表进行操作时,都要获取参数以及封装对象等,如果一张表有十几个参数,那对我们来说无疑是繁琐的,而且容易出错。

三、进行优化

1.解决子控制器初始化配置

       我们可以利用XML文件来定义和验证MVC配置文件的结构和内容。XML文件可以描述MVC中的模型(Model)、视图(View)和控制器(Controller)之间的关系和行为。拿到配置文件中的信息后,进行反射实例化动态处理。

这个xml文件存放在根目录下,先建立一个Source Folder文件夹将我们的config.xml文件放入即可。

<?xml version="1.0" encoding="UTF-8"?>
<config>
  <action path="/registerAction" type="test.action.RegisterAction">
    <forward name="success" path="/index.jsp" redirect="true" />
    <forward name="failed" path="/register.jsp" redirect="false" />
  </action>
  <action path="/book" type="com.ctb.servlet.BookAction">
    <forward name="list" path="/far.jsp" redirect="false" />
    <forward name="exit" path="/far.jsp" redirect="true" />
  </action>
</config>

action标签中的path:是DispatchServlet类截取到的uri路径。

action标签中的type:是子控制器的全路径名。

forward标签中的name:是重定向还是转发,是否携带数据

forward标签中的path:是跳转的页面。

forward标签中的redirect:判断为true则重定向跳转页面,为false则转发跳转页面

:增删改用重定向,查询用转发

接下来我们将进行xml解析并建模,大家可以翻阅xml解析xml建模这两篇博客

xml建模过程在里面都有,就不进行代码展示了

2.解决页面跳转的代码冗余问题

我们可以利用xml配置文件进行优化,在forward标签中的name属性可以给它设置最终方法所返回的值从而进行判断是重定向还是转发

<forward name="list" path="/far.jsp" redirect="false" />
    <forward name="exit" path="/far.jsp" redirect="true" />

BookAction

package com.ctb.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ctb.entity.Book;
import com.ctb.framework.Action;
import com.ctb.framework.ModelDriver;
/**
 * 
 * @author biao
 *
 * 2023年6月29日:下午6:41:01
 */
public class BookAction extends Action {  
  Book book=new Book();
  public  String detail(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到查看详情💕💕💕");
    return "list";
  }
  public  String del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到删除💕💕💕");
    return "exit";    
  }
  public  String upd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到修改💕💕💕");
    return "exit";    
  }
  public  String add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到新增💕💕💕");
    return "exit";    
  }
  public  String list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到主页面💕💕💕");
    return "list";    
  }
}

3.解决优化参数封装问题

我们定义一个模型驱动接口,让子控制通用

package com.ctb.framework;
/**
 * 定义方法,减少代码冗余
 * 避免了表多和重复代码
 * @author biao
 *
 * 2023年6月30日:下午4:48:27
 */
public interface ModelDriver<T> {
  T getModel();
}

接下来实现接口即可

package com.ctb.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ctb.entity.Book;
import com.ctb.framework.Action;
import com.ctb.framework.ModelDriver;
/**
 * 
 * @author biao
 *
 * 2023年6月29日:下午6:41:01
 */
public class BookAction extends Action implements ModelDriver<Book>{  
  Book book=new Book();
  public  String detail(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到查看详情💕💕💕");
    return "list";
  }
  public  String del(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到删除💕💕💕");
    return "exit";    
  }
  public  String upd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到修改💕💕💕");
    return "exit";    
  }
  public  String add(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到新增💕💕💕");
    return "exit";    
  }
  public  String list(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("欢迎来到主页面💕💕💕");
    return "list";    
  }
  /**
   * 因为实现类必须重写这个方法以及传递泛型,到时候谁用就是谁
   */
  @Override
  public Book getModel() {
    // TODO Auto-generated method stub
    return book;
  }
}

4.中央控制器

       最后,优化我们的中央控制器,在解决上述三个问题的同时,我们的DispathServlet类自然也会改变

package com.ctb.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 org.apache.commons.beanutils.BeanUtils;
import com.ctb.model.ActionModel;
import com.ctb.model.ConfigModel;
import com.ctb.model.ConfigModelFactory;
import com.ctb.model.ForwordModel;
import com.ctb.servlet.BookAction;
/**
 * 请求分发功能
 * @author biao
 *
 * 2023年6月29日:下午6:45:13
 */
@WebServlet("*.action")
public class DispathServlet extends HttpServlet{
  //获取文件配置器中的子控制器
  private ConfigModel configModel;
  @Override
  public void init() throws ServletException {
    try {
      configModel=ConfigModelFactory.build("/config.xml");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  @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 {
    //获取uri地址
    String uri = req.getRequestURI();
    //截取
    uri=uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
    // 根据path也就是路径(uri)找到配置的type(子控制器)
        ActionModel ActionModel = configModel.pop(uri);
        // 防止配置没写完善这里做一个非空判断如果请求路径未配置就抛出一个自定义异常给他
        if (ActionModel == null)
          throw new RuntimeException("Config is not configured yet.");
        // 拿到ActionModel里面的type值(type值就是子控制器的全路径名)
        String type = ActionModel.getType();
        try {
          //根据全路径名获取类类并反射实例化
          Action action = (Action) Class.forName(type).newInstance();
          //查看该类是否实现ModelDriver接口
          if(action instanceof ModelDriver) {
            ModelDriver md=(ModelDriver)action;
            //获取泛型传递的实体对象
            Object model = md.getModel();
            //获取请求参数的所有的属性及参数
            Map<String, String[]> parameterMap = req.getParameterMap();
            //使用工具类将参数值封装到表对应的对象中
            BeanUtils.populate(model, parameterMap);
          }
          //调用子控制器
          String execute =action.excute(req, resp);
          //判断是重定向还是转发-根据返回值找到指定ForwardModel
          ForwordModel pop = ActionModel.pop(execute);
          //如果是ajax不需要配置xml,所以ForwardModel有值的时候才进行跳转判断
          if(pop!=null) {
            //拿到redirect进行相对应的判断
            boolean redirect = pop.isRedirect(); 
            //拿到path进行相对应的页面跳转
            String path = pop.getPath();
            if(redirect) {//true重定向
              //注意这里会丢失项目路径所以要request.getContextPath()
              resp.sendRedirect(req.getContextPath()+path);
            }else {//false转发
              req.getRequestDispatcher(path).forward(req, resp);
            }   
          }     
        } catch (Exception e) {
          e.printStackTrace();
        }
  }
}

结果就不演示了,与自定义MVC框架原理中输出结果差不多,重在代码逻辑

✨原创不易,还希望各位大佬支持一下

👍 点赞,你的认可是我创作的动力!

⭐️ 收藏,你的青睐是我努力的方向!

✏️ 评论,你的意见是我进步的财富!


相关文章
|
3月前
|
前端开发 Java 程序员
从零基础手写Spring MVC框架,准备好进阶程序员了吗?
我们程序员大部分人都是野路子,不懂什么叫代码规范。写了一个月的代码,最后还得其他老司机花3天时间重构,相信大部分老司机都很头疼看新手的代码。
25 1
|
4月前
|
设计模式 前端开发 JavaScript
浅谈MVC、MVP、MVVM框架模式
浅谈MVC、MVP、MVVM框架模式
32 0
|
5月前
|
前端开发 数据库 Python
Python Web 开发: 解释 Django 框架的 MVC 架构是什么?
Python Web 开发: 解释 Django 框架的 MVC 架构是什么?
|
5月前
|
存储 前端开发 Java
Spring基础篇:MVC框架整合
Spring基础篇:MVC框架整合
|
4月前
|
Java 数据库连接 Maven
SSM框架整合:掌握Spring+Spring MVC+MyBatis的完美结合!
SSM框架整合:掌握Spring+Spring MVC+MyBatis的完美结合!
|
27天前
|
前端开发 安全 Java
使用Java Web框架:Spring MVC的全面指南
【4月更文挑战第3天】Spring MVC是Spring框架的一部分,用于构建高效、模块化的Web应用。它基于MVC模式,支持多种视图技术。核心概念包括DispatcherServlet(前端控制器)、HandlerMapping(请求映射)、Controller(处理请求)、ViewResolver(视图解析)和ModelAndView(模型和视图容器)。开发流程涉及配置DispatcherServlet、定义Controller、创建View、处理数据、绑定模型和异常处理。
使用Java Web框架:Spring MVC的全面指南
|
2月前
|
前端开发 JavaScript Java
MVC框架:SpringMVC(三)
MVC框架:SpringMVC
30 0
|
2月前
|
JSON 前端开发 JavaScript
MVC框架:SpringMVC(二)
MVC框架:SpringMVC
37 0
|
2月前
|
前端开发 Java 应用服务中间件
MVC框架:SpringMVC(一)
MVC框架:SpringMVC
60 0
|
3月前
|
前端开发 Java 数据库连接
认识Java中最常用的框架:Spring、Spring MVC、Spring Boot、MyBatis和Netty
Spring框架 Spring是一个轻量级的开源框架,用于构建企业级应用。它提供了广泛的功能,包括依赖注入、面向切面编程、事务管理、消息传递等。Spring的核心思想是控制反转(IoC)和面向切面编程(AOP)。
81 3