自定义MVC框架(中)进阶版---详细讲解

目录

一,自定义mvc的流程

二,XML建模进行反射优化

2.1常见的优化方法

2.2 xml建模反射优化案例:

三,优化方法结果集调用跳转

 3.1大概步骤:

四,优化参数的封装


一,自定义mvc的流程

  1. 用户发送请求到指定的 URL。
  2. 应用程序的路由器(Router)根据 URL 分发请求给对应的控制器。
  3. 控制器解析用户的输入,调用相应的模型和视图,并获取处理结果。
  4. 视图负责生成用户界面,并将处理结果展示给用户。
  5. 用户与视图进行交互,发送新的请求。
  6. 控制器再次处理新的请求,并返回结果给用户。

二,XML建模进行反射优化

2.1常见的优化方法

  1. 定义路由配置:将路由规则和URL与控制器的映射关系配置在XML文件中。这样可以避免在代码中硬编码路由规则,提高了代码的可维护性和灵活性。

  2. 定义视图配置:将视图相关的配置信息,如视图路径、模板引擎的配置等,放在XML文件中。这样可以使视图的配置更加集中和可配置化,方便扩展和管理。

  3. 定义模型配置:将模型的相关配置信息,如数据库连接、数据表映射等配置在XML文件中。这样可以使模型的配置更加灵活和易于管理,同时也降低了与数据库相关的代码依赖。

  4. 自定义注入配置:将依赖注入(DI)容器的配置信息放在XML文件中。通过配置XML文件中的依赖注入关系,可以实现灵活的控制器、模型和视图的注入,减少耦合度,提高代码的可测试性和可维护性。

  5. 定义拦截器配置:将拦截器的配置信息,如拦截的URL规则、拦截器的顺序等,放在XML文件中。这样可以方便地定义和管理拦截器链,实现各种应用场景下的权限控制、日志记录等功能。

2.2 xml建模反射优化案例:

首先定义一个xml配置文件

注意:该xml配置文件需要放到到跟目录中(如下图)包--New--Shurce Folder

本案例需要操作的XML文件:

本XML各属性名含义:

  action:

          path=""前端操作类名称

          type=""该类的路径名

  forward:

        name:方法返回名

        path:跳转的路径

         redirect:该结果集是否进行重定向

<?xml version="1.0" encoding="UTF-8"?>

<config>
	
	<action path="/Order" type="com.LiuBing.framework.OrderAction">
		<forward name="failed" path="/reg.jsp" redirect="false" />
		<forward name="success" path="/login.jsp" redirect="true" />
	</action>
	<action path="/Book" type="com.LiuBing.framework.BookAction">
		<forward name="list" path="/res.jsp" redirect="false" />
		<forward name="tolist" path="/res.jsp" redirect="true" />
	</action>
</config>

中央控制器代码:

    前言:获取建模xml文件总容器ConFigModel,获取子容器actionmodel进行判断,判断xml配置文件中是否有前端所操作的类及对象,如果没有将会报出自定义异常action not config

如:

package com.LiuBing.framework;
/**
 * 中央控制器
 */
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
/**
 * 中央控制器
 */
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.LiuBing.framework.model.ActionModel;
import com.LiuBing.framework.model.ConFigModel;
import com.LiuBing.framework.model.ConfigModelFactory;
import com.LiuBing.framework.model.ForwardModel;

@WebServlet("*.action")
public class DispatherServlet extends HttpServlet {
	// 定义一个map集合
	// public Map<String, Action> actionmap= new HashMap<String, Action>();
	private ConFigModel conFigModel;

	@Override
	public void init(ServletConfig config) throws ServletException {
		// actionmap.put("/Book",new BookAction());
		// actionmap.put("/Order",new OrderAction());
		try {
			// conFigModel包含所有子控制器
			conFigModel = ConfigModelFactory.build();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}

	@SuppressWarnings("rawtypes")
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		String uri = req.getRequestURI();// 地址方法

		// 获取到相关的地址信息并过滤
		uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
		// 将地址保存到action
		// Action action = actionmap.get(uri);

		// 获取配置文件中action
		ActionModel actionmodel = conFigModel.pop(uri);
		// 判断action是否为空
		if (actionmodel == null)
			// 为空提示语句
			throw new RuntimeException("action not config");
		// 不为空就获取到type路径(想进行哪个的业务操作路径)
		String type = actionmodel.getType();
		Action action;
		try {
			// 获取反射需要操作的类类
			action = (Action) Class.forName(type).newInstance();
			
			//判断子容器BookAction有无实现ModelDriver 模型驱动接口接口
		   if(action instanceof ModelDriver) {//默认实现了该接口
			   ModelDriver md = (ModelDriver) action;
			   Object bean = md.getModel();
		     BeanUtils.populate(bean, req.getParameterMap());
		   }
			
			// Action的res返回值
			String res = action.execut(req, resp);
			
			//根据Action的返回值  该方法是重定向还是转发 
			ForwardModel forwardmodel = actionmodel.pop(res);
			
			//判断如果forwardmodel模型中有数据
			if(forwardmodel!=null) {
				//前端操作数据是转发还是重定向 true false 
				boolean redirect = forwardmodel.isRedirect();
				//转发的页面
				String path = forwardmodel.getPath();
				//转发
				if(redirect) {
					resp.sendRedirect(path);
				}else {
					//重定向
					req.getRequestDispatcher(path).forward(req, resp);
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

三,优化方法结果集调用跳转

 3.1大概步骤:

         在子类对象相对应的操作返回类型例如BookAction返回类型定义为String类型,并在中央控制器中接受子类的方法返回值,中央控制器中判断redirect重定向,最后进行xml文件的相对应的配置

子控制器代码:

package com.LiuBing.framework;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.LiuBing.entity.Book;

public class BookAction extends Action implements ModelDriver<Book> {
	Book book = new Book();

	public String add(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("进入的是增加BookaddServlet....");
		request.setAttribute("content", "崽崽");
		response.sendRedirect("res.jsp");
		return "tolist";
	}

	public String del(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("进入的是删除BookadelServlet....");
		request.setAttribute("content", "崽崽");
		response.sendRedirect("res.jsp");
		return "tolist";
	}

	public String upd(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("进入的是修改BookupdServlet....");
		request.setAttribute("content", "崽崽");
		response.sendRedirect("res.jsp");
		return "tolist";
	}

	public String list(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("进入的是查询BooklistServlet....");
		request.setAttribute("content", "崽崽");
		return "list";
	}

	@Override
	public Book getModel() {

		return book;
	}
}

中央控制器代码:

// Action的res返回值
			String res = action.execut(req, resp);
			
			//根据Action的返回值  该方法是重定向还是转发 
			ForwardModel forwardmodel = actionmodel.pop(res);
			
			//判断如果forwardmodel模型中有数据
			if(forwardmodel!=null) {
				//前端操作数据是转发还是重定向 true false 
				boolean redirect = forwardmodel.isRedirect();
				//转发的页面
				String path = forwardmodel.getPath();
				//转发
				if(redirect) {
					resp.sendRedirect(path);
				}else {
					//重定向
					req.getRequestDispatcher(path).forward(req, resp);
				}
			}
配置文件代码按本案例配置文件操作即可

最后运行结果:

 进行增删改操作只会显示跳转成功,而查询所有会显示相对应的内容,这是因为增删改是重定向而查询是转发

四,优化参数的封装

4.1 前言:

     在我们进行接受前端带过来的参数,往往会带很多参数在子控制器中进行遍历及封装加到实体中,这样会很麻烦的大大降低了代码效率,那有什么办法在进行这一步进行一个改善呢?有!模型驱动接口---连接模型和其他系统或应用程序的接口。它允许使用模型的输出来驱动和控制其他系统的行为。

定义一个模型驱动接口

在中央控制器中,进行判断子控制器是否继承了模型驱动接口, BeanUtils.populate方法以键值对形式存储该被反射的类

模型驱动接口:

package com.LiuBing.framework;
/**
 * 模型驱动接口
 * @param <T>
 */
public interface ModelDriver<T> {
	T getModel();
}

中央控制器判断代码:

Action action;
		try {
			// 获取反射需要操作的类类
			action = (Action) Class.forName(type).newInstance();
			
			//判断子容器BookAction有无实现ModelDriver 模型驱动接口接口
		   if(action instanceof ModelDriver) {//默认实现了该接口
			   ModelDriver md = (ModelDriver) action;
			   Object bean = md.getModel();//哪个继承了模型驱动接口
		     BeanUtils.populate(bean, req.getParameterMap());//映射到该方法中  键值对形式
		   }

泛型指定子控制器实体类。最后在子控制器中实现模型驱动接口实现其中的方法即可

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

.Doll

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值