自定义mvc(2)

前言

上一篇文章讲述了自定义mvc框架是什么,以及能够给我们带来的好处,这期小编就来给大家讲解一下如何实现我们的自定义mvc吧

目录

前言

利用xml建模进行反射优化,达到通用效果

优化结果集的跳转问题

Bookaction

action

模型层

forwardmodel

actionmodel

configmodel

工厂建摸方法

中央控制器

封装参数实例化

定义一个接口

子控制器实现接口,返回对应的实例

中央控制器


利用xml建模进行反射优化,达到通用效果

//获取configmodel
	private ConfigModel config;
	//根据xml的工厂建模方式,往config中,添加内容
	@Override
	public void init() throws ServletException {
		test t= new test();
		try {
			ConfigModel configModel = t.build("/config.xml");
			config=configModel;
			//此时模型中已经有了其他模型对象以及信息
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

优化结果集的跳转问题

大家知道,servlet跳转又两种方式,一种是重定向,一种是转发,转发是不会改变地址栏的,所以我们只有查询才用到转发,那么如何判断到底是查询还是增删改呢,改变方法的返回值

Bookaction

package action;

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

import entity.Book;

public class BookAction extends Action implements ModelDriven<Book> {
private Book book;

	
	
	public String add(HttpServletRequest req,HttpServletResponse resp) {
		System.out.println("add"); 
		return "tolist";
	}
	public String del(HttpServletRequest req,HttpServletResponse resp) {
		System.out.println("del"); 
		return "tolist";
	}
	public String upd(HttpServletRequest req,HttpServletResponse resp) {
		System.out.println("upd"); 
		return "tolist";
	}
	public String query(HttpServletRequest req,HttpServletResponse resp) {
		System.out.println("query"); 
		return "query";
	}
	@Override
	public Book getmodel() {
		// TODO Auto-generated method stub
		return book;
	}
}

改变了每个方法的返回值,那么其向上抽取的反射方法,也需要改变一下返回值

action

package action;

import java.lang.reflect.Method;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * 调用方法
 * @author liwen
 *
 */
public class Action  extends HttpServlet{

	public String excute(HttpServletRequest req,HttpServletResponse resp) throws Exception {
		String method = req.getParameter("method");
		//通过反射调用参数
		//一切反射从类类开始
		Class<? extends Action> class1 = this.getClass();
		//通过类类获取方法(参数1,方法名字,参数2:参数类型的类类)
		Method method1 = class1.getDeclaredMethod(method,HttpServletRequest.class,HttpServletResponse.class );
		method1.setAccessible(true);
		//调用方法,通过方法对象进行调用,(参数1,表示调用方法的调用方法的对象,参数2,代表方法参数的类型)
		String invoke = (String) method1.invoke(this, req,resp);
		return invoke;
	}
	
}

最后只需要通过已经通过xml文件建好的模型中拿到对应的子控制器,并且再通过模型,拿到方法的返回值,即可,这里先看xml文件和模型层,不懂的小伙伴们可以去看看小编之前发布的xml篇,否则逻辑会有点混乱

<?xml version="1.0" encoding="UTF-8"?>
<config>
	<action path="/Book" type="action.BookAction">
		<forward name="query" path="/Book.jsp" redirect="false" />
		<forward name="tolist" path="/Book.jsp" redirect="true" />
	</action>

	<action path="/Order" type="action.OrderAction">
		<forward name="query" path="/Order.jsp" redirect="false" />
		<forward name="tolist" path="/Order.jsp" redirect="true" />
	</action>
</config>


模型层

forwardmodel

package model;

public class ForwardModel {

	private String name;
	private String path;
	private boolean redirect;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
	public boolean isRedirect() {
		return redirect;
	}
	public void setRedirect(boolean redirect) {
		this.redirect = redirect;
	}
	
	
	
}

actionmodel

package model;

import java.util.HashMap;
import java.util.Map;

public class ActionModel {

	private String path;
	private String type;
	private Map<String, ForwardModel> map= new HashMap<String, ForwardModel>();
	public String getPath() {
		return path;
	}
	public void setPath(String path) {
		this.path = path;
	}
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	
	public void push(ForwardModel f) {
		map.put(f.getName(), f);
	}
	//根据名字拿到这个集合中forward标签
	public ForwardModel pop(String name) {
		return map.get(name);
	}
	
	
}

configmodel

package model;

import java.util.HashMap;
import java.util.Map;

public class ConfigModel {
	
	private Map<String , ActionModel> map= new HashMap<String, ActionModel>();

	//压栈的行为
	public void push(ActionModel actionmodel) {
		map.put(actionmodel.getPath(), actionmodel); 
	}
	
	//弹栈的行为
	public ActionModel  pop(String path) {
		return map.get(path);
	}
	
	
}

工厂建摸方法

package model;

import java.io.InputStream;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;



public class test {

	//写一个创建模型的方法
	public  ConfigModel build(String path) throws Exception {
		ConfigModel con= new ConfigModel();
		//抓取到xml配置文件
		InputStream in = test.class.getResourceAsStream(path);
		SAXReader s= new SAXReader();
		Document read = s.read(in);
	//拿到配置文件的信息,并且打印
//		System.out.println(read.asXML());
		//接下来拿到所有的config下的所有的action文件
		List<Element> selectNodes = read.selectNodes("config/action");
		
		for (Element selectNode : selectNodes) {
			//拿到每一个action的值并且打印
//			System.out.println("+++++++++++++++++++++++++++++");
//		System.out.println(selectNode.asXML());
		//获取action中的path值和type值
		String actionpath = selectNode.attributeValue("path");
		String actiontype = selectNode.attributeValue("type");
		//将path值以及type值初始化到我们的action模型中去
		ActionModel action= new ActionModel();
		action.setPath(actionpath);
		action.setType(actiontype);
		//拿到了actionmodel的时候,我们再去拿action中的forward
		List<Element> selectNodes2 = selectNode.selectNodes("forward");
		//遍历action	
		for (Element selectNode2 : selectNodes2) {
			//拿到了forward中的属性值
			String forwardname = selectNode2.attributeValue("name");
			String forwardpath = selectNode2.attributeValue("path");
			String forwardredirect = selectNode2.attributeValue("redirect");
			//分别初始化到我们的对象模型中去
			ForwardModel forward= new ForwardModel();
			forward.setName(forwardname);
			forward.setPath(forwardpath);
			forward.setRedirect(!"false".equals(forwardredirect));
			//将初始化好的对象模型放到action模型之中去
			action.push(forward);
			
		}
		
		
		
		//将初始话好的action模型放到config模型中去
		con.push(action);
		
		
		}
		return con; 
	}
	
	
	
	

	
	
}

中央控制器

package farmework;

import java.io.IOException;
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 org.apache.commons.beanutils.BeanUtils;

import action.Action;
import action.ModelDriven;
import model.ActionModel;
import model.ConfigModel;
import model.ForwardModel;
import model.test;


/**
 * Servlet implementation class DispatherServlet
 */
@WebServlet("*.do")
public class DispatherServlet extends HttpServlet {
	//获取configmodel
	private ConfigModel config;
	//根据xml的工厂建模方式,往config中,添加内容
	@Override
	public void init() throws ServletException {
		test t= new test();
		try {
			ConfigModel configModel = t.build("/config.xml");
			config=configModel;
			//此时模型中已经有了其他模型对象以及信息
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	
	
	
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	
	//获取请求路径
	String uri = request.getRequestURI();
	//截取关键的字符
	uri=uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
	//通过configmodel中的pop方法进行弹栈,获取对应的action,也就是获取到子控制器的model
		ActionModel actionModel = config.pop(uri);
		//如果没获取到,给个提示
		if(actionModel==null) {
			throw new RuntimeException("给钱告诉你");
		}
	//获取actionmodel中储存的action全路径名
		String type = actionModel.getType();
		try {
			//获取类类
			 Class<?> classs = Class.forName(type);
			 //反射实例化
			 Action action = (Action) classs.newInstance();
			 //通过action调用其父类的方法(根据返回的参数进行判断,再通过反射进行调用),拿到调用方法后返回的关键字,然后判断是否重定向
			 
			
			 
			String isr = action.excute(request, response);
			//通过返回的值找到forward标签,进行判断
			ForwardModel forward = actionModel.pop(isr);
			
			if(forward==null) {
				//要么给个提示,要么直接跳转错误界面
				System.out.println("没有根据返回值找到方法模型,或者方法模型中,没有这个返回值");
			return;
			}
			
			
			//获取forward中的重定向属性进行判断是否重定向
			if(forward.isRedirect()) {
				//如果是重定向,那就重定向到其指定的地点,forward中的path属性
				response.sendRedirect(request.getContextPath()+forward.getPath());
				//
			}else {
				//如果不是重定向的话,那就转发呗
				request.getRequestDispatcher(forward.getPath()).forward(request, response);
			}
			
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
		
	
	}

}

这里的核心思想其实更多的在于xml建模,如果xml建模懂了,这里会好理解很多

封装参数实例化

在我们处理请求进行操作时,很多时候都会获取参数然后一个一个的set,但是其实这个也是可以进行通用封装的

定义一个接口

package action;
/**
 * 获取实例的接口
 * @author liwen
 *
 * @param <T>
 */
public interface ModelDriven<T> {

	T getmodel();
	
	
}

子控制器实现接口,返回对应的实例

package action;

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

import entity.Book;

public class BookAction extends Action implements ModelDriven<Book> {
private Book book;

	
	
	public String add(HttpServletRequest req,HttpServletResponse resp) {
		System.out.println("add"); 
		return "tolist";
	}
	public String del(HttpServletRequest req,HttpServletResponse resp) {
		System.out.println("del"); 
		return "tolist";
	}
	public String upd(HttpServletRequest req,HttpServletResponse resp) {
		System.out.println("upd"); 
		return "tolist";
	}
	public String query(HttpServletRequest req,HttpServletResponse resp) {
		System.out.println("query"); 
		return "query";
	}
	@Override
	public Book getmodel() {
		// TODO Auto-generated method stub
		return book;
	}
}

中央控制器

package farmework;

import java.io.IOException;
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 org.apache.commons.beanutils.BeanUtils;

import action.Action;
import action.ModelDriven;
import model.ActionModel;
import model.ConfigModel;
import model.ForwardModel;
import model.test;


/**
 * Servlet implementation class DispatherServlet
 */
@WebServlet("*.do")
public class DispatherServlet extends HttpServlet {
	//获取configmodel
	private ConfigModel config;
	//根据xml的工厂建模方式,往config中,添加内容
	@Override
	public void init() throws ServletException {
		test t= new test();
		try {
			ConfigModel configModel = t.build("/config.xml");
			config=configModel;
			//此时模型中已经有了其他模型对象以及信息
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	
	
	
	
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	doPost(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	
	//获取请求路径
	String uri = request.getRequestURI();
	//截取关键的字符
	uri=uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
	//通过configmodel中的pop方法进行弹栈,获取对应的action,也就是获取到子控制器的model
		ActionModel actionModel = config.pop(uri);
		//如果没获取到,给个提示
		if(actionModel==null) {
			throw new RuntimeException("给钱告诉你");
		}
	//获取actionmodel中储存的action全路径名
		String type = actionModel.getType();
		try {
			//获取类类
			 Class<?> classs = Class.forName(type);
			 //反射实例化
			 Action action = (Action) classs.newInstance();
			 //通过action调用其父类的方法(根据返回的参数进行判断,再通过反射进行调用),拿到调用方法后返回的关键字,然后判断是否重定向
			 
			 //如果action继承了获取实例的接口
			 if(action instanceof ModelDriven) {
				 //获取示例,相当于 Book book = new Book()
				 Object getmodel = ((ModelDriven<?>) action).getmodel();
				 //再获取所有的参数
				 Map<String, String[]> map = request.getParameterMap();
				 //将页面传过来的值封装到示例对象中
				 BeanUtils.populate(getmodel, map);
			 }
			 
			 
			String isr = action.excute(request, response);
			//通过返回的值找到forward标签,进行判断
			ForwardModel forward = actionModel.pop(isr);
			
			if(forward==null) {
				//要么给个提示,要么直接跳转错误界面
				System.out.println("没有根据返回值找到方法模型,或者方法模型中,没有这个返回值");
			return;
			}
			
			
			//获取forward中的重定向属性进行判断是否重定向
			if(forward.isRedirect()) {
				//如果是重定向,那就重定向到其指定的地点,forward中的path属性
				response.sendRedirect(request.getContextPath()+forward.getPath());
				//
			}else {
				//如果不是重定向的话,那就转发呗
				request.getRequestDispatcher(forward.getPath()).forward(request, response);
			}
			
			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
		
	
	}

}

每一行代码小编都打上了注释,这里就不一一解释了,最后给大家看一下我的项目结构

这里其实有错误,但是我没有改正,还是提一嘴,我的action类和modeldriven接口应该是放在farmework包中的 ,到时候方便进行打包使用,这样子才是一个通用的jar包,否则是无法进行使用的, 所以这里还是提示一下,小编自己也下次进行改正

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值