自定义MVC框架优化

news2024/12/23 14:02:48

目录

一、前言

二、优化问题

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

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

3.优化参数封装问题

三、进行优化

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

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

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

4.中央控制器 


一、前言

在自定义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框架原理中输出结果差不多,重在代码逻辑

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

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/711424.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis - Redis GEO实现经纬度测算距离,附近搜索范围

Redis GEO 主要用于存储地理位置信息&#xff0c;并对存储的信息进行操作&#xff0c;该功能在 Redis 3.2 版本新增 一、Redis GEO 操作方法 geoadd&#xff1a;添加地理位置的坐标 geopos&#xff1a;获取地理位置的坐标 geodist&#xff1a;计算两个位置之间的距离 geor…

client-go初级篇,从操作kubernetes到编写单元测试

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 尽管长篇系列《client-go实战》的内容足够丰富&#xff0c;然而内容太多每个知识点也有一定深度&#xff0c;对于打算快速学习并开始kubernetes开发…

分层架构简介

MVC是架构模式&#xff08;设计模式中的结构性模式&#xff09;&#xff0c;不是系统架构&#xff0c;更不是我们常说的三层架构 MVC的缺陷如下&#xff1a; 1.导致控制器冗余&#xff08;有大量的业务逻辑&#xff0c;可能开始没有&#xff0c;但是后来越来越多&#xff09;…

QT学习笔记5--槽函数重载解决办法

connect函数 connect(sender, signal, receiver, slot); 槽函数示例 void student:: treat(QString foodname) void student:: treat(int index) 由上可见&#xff0c;有两个名字相同&#xff0c;但形参不同的槽函数。 可以通过函数指针的方式 &#xff0c;用指针指向具体…

linux环境安装mysql8.0.32

linux环境安装mysql8.0.32 一、下载安装包二、安装前准备2.1 卸载旧版本mysql2.2 检查是否安装了 mariadb 数据库2.3 安装依赖包创建 mysql 用户 三、安装3.1 上传并解压安装包&#xff08;上传路径没有要求&#xff0c;一般在/usr/local&#xff09;3.2 初始化数据库3.3 注册数…

Java面试题6月

redis有哪些缓存淘汰策略 https://blog.51cto.com/u_11720620/5198874 生产环境内存溢出&#xff08;OOM&#xff09;问题处理方案 https://note.youdao.com/ynoteshare/index.html?id5cc182642eb02bc64197788c7722baae&typenote&_time1688287588653 jstack找出占用…

C++之GNU C的__attribute__((constructor))和((destructor))静态构造函数实现(一百四十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

Elasticsearch实战(二十三)---ES数据建模与Mysql对比 一对多模型

Elasticsearch实战—ES数据建模与Mysql对比实现 一对多模型 文章目录 Elasticsearch实战---ES数据建模与Mysql对比实现 一对多模型1.一对多 模型1.1 Mysql建模 2.一对多 Index ES 数据模型2.1 类似Mysql, 依旧创建两个Index索引库2.2 采用ES架构 嵌套数组模型2.3采用ES架构 冗余…

【JUC-2】Synchronized关键字相关知识

Synchronized synchronized是Java中的关键字&#xff0c;是一种同步锁。它修饰的对象有以下几种&#xff1a; 修饰一个代码块&#xff0c;被修饰的代码块称为同步语句块&#xff0c;其作用的范围是大括号{}括起来的代码&#xff0c;作用的对象是调用这个代码块的对象&#xf…

【C++2】进程 信号 dbus

文章目录 1.进程&#xff1a;fork()&#xff0c;ps -ef (同-aux) | more2.信号&#xff1a;signal&#xff08;, EXIT&#xff09;&#xff0c;jps2.1 捕捉信号&#xff1a;ctrlc&#xff1a;22.2 捕捉信号&#xff1a;kill -9&#xff1a;92.3 捕捉信号&#xff1a;kill&#…

欧几里得算法

0x00 前言 改补的内容是一点都不会少。本章来看欧几里得算法 0x01 概述 欧几里得算法又称为辗转相除法&#xff0c;指用于计算两个非负整数a和b的最大公约数。 两个整数的最大公约数是能够同时整除他们的最大的正整数。 基本原理&#xff1a;两个整数的最大公约数等于其中…

【动态规划】子数组系列(上)

子数组问题 文章目录 【动态规划】子数组系列&#xff08;上&#xff09;1. 最大子数组和1.1 题目解析1.2 算法原理1.2.1 状态表示1.2.2 状态转移方程1.2.3 初始化1.2.4 填表顺序1.2.5 返回值 1.3 代码实现 2. 环形子数组的最大和2.1 题目解析2.2 算法原理2.2.1 状态表示2.2.2 …

C++2(表达式和关系运算)

目录 1.表达式基础 1.表达式基础 运算符重载&#xff0c;就是自己定义 - * / 之类的运算符怎么运算 C中的左值和右值 C语言左值在左侧&#xff0c;右值在右侧 在cpp中要复杂的多 能取到地址的表达式是左值 不能取到地址的表达式是右值 常量对象为代表的左值不能作为赋值语句的左…

【Linux】网络相关概念概述以及原理简单分析介绍

文章目录 [toc] Linux 网络概述网络发展独立模式网络互联局域网LAN 和 广域网WAN 认识 "协议"协议的分层网络协议栈OSI七层模型TCP/IP五层(四层)模型TCP/IP网络协议栈 与 操作系统 的关系 **重新以计算机的视角看待 网络协议栈 局域网内部通信原理简单介绍不同局域网…

mybatis web使用02

处理 transfer 请求的 servlet package com.wsd.web;import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRe…

GAMES101 笔记 Lecture08 Shading 2(Shading, Pipeline and Texture Mapping)

目录 Specular Term(高光项)Ambient Term(环境光照项)Blinn-Phong Reflection ModelShading Frequencies(着色频率)Shade each triangle(flat shading)在每个三角形上进行着色Shade each vertex (Gouraud shading)(顶点着色)Shade each pixel (Phong shading)Defining Per-Vert…

【C++详解】——哈希

目录 unordered系列关联式容器 unordered_map unordered_map的接口说明 1.unordered_map的构造 2.unordered_map的容量 3.迭代器相关 4.unordered_map的元素访问 5. unordered_map的查询 6.unordered_map的修改操作 unordered_set 性能测试 底层结构——Hash 哈希…

copula简介

二元正态copula最为重要

MySQL - 自连接查询

1. 测试数据 创建 category 表 : CREATE TABLE category(categoryid INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 主题id,pid INT(10) NOT NULL COMMENT 父id,categoryName VARCHAR(50) NOT NULL COMMENT 主题名字,PRIMARY KEY(categoryid) ) ENGINEINNODB AUTO_INCREM…

cmd的学习

目录 常用的cmd命令 使用cmd的例子 常用的cmd命令 指令作用盘符名称:盘符切换dir查看当前路径下的内容tree以树形结构输出当前路径下的内容cd进入单级目录cd ..回退到上一级目录cd 目录1\目录2\...进入多级目录cd \回退到盘符目录cls清屏exit退出窗口 &#xff08;值得注意的…