自定义MVC的优化与实现

本文详细介绍了如何优化MVC框架的中央控制器,实现了动态加载存储子控制器,参数传递封装,以及执行结果转发重定向的优化。通过XML配置文件增强了框架的灵活性,允许配置文件可变,并在web.xml中进行定制。这些改进使得添加新的实体类和调整页面跳转方式变得更加方便。
摘要由CSDN通过智能技术生成

目录

一、中央控制器动态加载存储子控制器

二、参数传递封装优化

三、对执行结果转发重定向优化

​四、框架配置文件可变


一、中央控制器动态加载存储子控制器

在之前所分享的自定义MVC原理中,浏览器通过中央控制器找到对应的子控制器存在着一定的缺陷 例如:假设我们现在有许多实体类,那么我们就需要将他们一个一个的放入map集合中,会出现大量的相似代码,且不便捷

actions.put("/book", new BookAction());
actions.put("/order", new OrderAction());

优化:

我们会使用到之前所学到的Xml建模,actionModel是configModel的子控制器,所以我们定义一个ConfigModel

	private ConfigModel configModel;
	
	
	
	
	//程序启动时只会启动一次
	@Override
	public void init() throws ServletException {
		//actions.put("/book", new BookAction());
		//actions.put("/order", new OrderAction());
		try {
			configModel = ConfigModelFactory.bulid();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}

以前获取子控制器路径的方法

        String url = req.getRequestURI();
		//拿到book
		url = url.substring(url.lastIndexOf("/"), url.lastIndexOf("."));
	    ActionSupport action = actions.get(url);
		action.excute(req, resp);

现在通过ConfigModel获取子控制器路径

String  url = 	request.getRequestURI();
		//要拿到/book,就是最后一个/到最后一个.的位置
		url=url.substring(url.lastIndexOf("/"),url.lastIndexOf("."));
		//相比于上一种从map集合获取子控制器,当前需要获取config.xml中的全路径名,然后反射实例化
		ActionModel actionModel = configModel.pop(url);
		if(actionModel==null) {
			throw new RuntimeException("action配置错误");
		}
		String type = actionModel.getType();//type是配置文件中Action子控制器的全路径名
		
		try {
			Action action = (Action) Class.forName(type).newInstance();
			action.execute(request, response);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

优化思路:先拿到config.xml文件的全路径名,然后再将获取子控制器路径的url放入configModel中,这样我们就拿到了子控制器Actionmodel,接下来我们只要拿到Action的全路径名Type就可以了,我们之后再想添加实体类,就只需要在xml文件中进行配置即可

二、参数传递封装优化

当我们接收前台传过来的值时,我们需要一个一个接收并放入实体类中,如果字段较多的话还会造成大量代码以及可能会发生错误

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));

优化:

1.定义ModelDriven模型驱动接口类

public interface ModelDriven<T> {

	//拿到将要封装的类实例 ModelDriven.getModel==new Book();
	T getModel();
	
}

2.在Bookaction中实现ModelDriven接口,在调用getModel方法

3.在中央控制器中实现ModelDriven接口,给Book参数赋值

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		//http://localhost:8080/mvc/book.action?methodName=list
		String  url = 	request.getRequestURI();
		//要拿到/book,就是最后一个/到最后一个.的位置
		url=url.substring(url.lastIndexOf("/"),url.lastIndexOf("."));
		//相比于上一种从map集合获取子控制器,当前需要获取config.xml中的全路径名,然后反射实例化
		ActionModel actionModel = configModel.pop(url);
		if(actionModel==null) {
			throw new RuntimeException("action配置错误");
		}
		String type = actionModel.getType();//type是配置文件中Action子控制器的全路径名
		
		try {
			Action action = (Action) Class.forName(type).newInstance();
			
			//正式调用方法前,book的属性要被赋值
			if(action instanceof ModelDriven) {
				ModelDriven md =(ModelDriven) action;
				//model指的是Bookaction中的类实例Book
				Object model = md.getModel();
				//要给Model中的属性赋值,要接受前端jsp传来的参数
				//将前端所有参数值封装进实体类
				BeanUtils.populate(model, request.getParameterMap());
				
			
			}
			
			
			action.execute(request, response);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

三、对执行结果转发重定向优化

页面跳转有两种方式:转发和重定向

           重定向:resp.sendRedirect(path);

           转发: req.getRequestDispatcher(path).forward(req, resp);

这些代码往往要写很多次,因此通过配置config文件来解决此类问题;例如这一次我跳转增加页面时是转发,跳转编辑界面是重定向,

 思路:
        1、当点击增加或者编辑时,首先跳转的是中央控制器类(DispatchServlet):获取到url,url将决定要跳到哪一个实体类,
        2、之后进入ActionSupprot(子控制器接口实现类)通过methodname要调用什 么方法,
        3、再然后进入到BookAction中调用methodname方法,找到对应的返回值,
        4、通过返回值在进入到config文件找到path属性,之后在中央控制器中进行判 断,来决定是重定向还是转发。

 

1、中央控制器DispatchServlet

String path = forwardModel.getPath();
			//拿到是否需要转发的配置
			boolean redirect = forwardModel.isRedirect();
			if(redirect) {//是重定向
				//pageContext.request.contextpath
			 response.sendRedirect(request.getServletContext().getContextPath()+path);	
			}
			request.getRequestDispatcher(path).forward(request, response);

2、ActionSupport子控制器接口实现类

package com.zjy.framework;

import java.lang.reflect.Method;

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

public class ActionSupport implements Action{

	@Override
	public String execute(HttpServletRequest request, HttpServletResponse response) {
		//为了区分当前请求的目的 ,增删改查的目的 就从前台将调用的方法传达到后台
		String methodNmae = request.getParameter("methodName");
		//methodName可以是add也可以是del或者其他
		//前台传递什么方法 就调用当前类的对应方法
		try {
			Method m = this.getClass()//BookServlet.class
			.getDeclaredMethod(methodNmae, HttpServletRequest.class,HttpServletResponse.class);
		m.setAccessible(true);
		//调用当前类实例的methodName方法
		 return (String) m.invoke(this, request,response);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
		
		
		
	}

}

3、BookAction

private String add(HttpServletRequest request, HttpServletResponse response) {

		System.out.println("在同一个Servlet中调用add方法");
		return "failed";
	}

	private String list(HttpServletRequest request, HttpServletResponse response) {
		System.out.println("在同一个Servlet中调用list方法");
		return "success";
	}

4、config文件

四、框架配置文件可变

为了使我们的框架更加灵活,我们首先在中央控制器DispatchServlet的初始化Init方法中配置文件地址

try {
			//配置地址
			//getInitParameter的作用是拿到web.xml中的servlet信息配置的参数
			String configLoaction = this.getInitParameter("configLocation");
			if(configLoaction == null || "".equals(configLoaction))
				
			
			configModel = ConfigModelFactory.bulid();
			else
				configModel = ConfigModelFactory.bulid(configLoaction);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		

然后再web.xml中进行配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>MVC</display-name>
  <servlet>
  <servlet-name>mvc</servlet-name>
  <servlet-class>com.zjy.framework.DispatcherServlet</servlet-class>
 <init-param>
 
 <param-name>configLocation</param-name>
 
 <param-value>/zjy.xml</param-value>
 </init-param>
  </servlet>
  <servlet-mapping>
  <servlet-name>mvc</servlet-name>
 <url-pattern>*.action</url-pattern>
  </servlet-mapping>
</web-app>

这样就能够达到一个更改名字还能使用的效果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值