自定义MVC

一:思维导图

二:自定义MVC




1.什么是MVC?

MVC全名:Model View Controller,其中Model(模型层)、View(视图层)、Controller(控

层)它是一种软件设计典范.

2.框架的演绎过程
1、数据处理Dao(需要多少servlet建多少)

缺点:代码重复太多 ,建的类太多  以图中的(AddBookServlet /  DeleteBookServlet / EditBookServlet / ListBookServlet)

 ​​​​​​​​​​​​​​​​​​​​​

 

 增

package com.lj.web;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/book/add")
public class AddBookServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doPost(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("增");
    }
 
}

package com.lj.web;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/book/delete")
public class DeleteBookServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doPost(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("删");
    }
 
}

package com.lj.web;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/book/edit")
public class EditBookServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doPost(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("改");
    }
 
}


package com.lj.web;
 
import java.io.IOException;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/book/list")
public class ListBookServlet extends HttpServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        doPost(req, resp);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // TODO Auto-generated method stub
        System.out.println("查");
    }
 
}

 
主页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<a href="${pageContext.request.contextPath }/book/add">新增</a>
<a href="${pageContext.request.contextPath }/book/delete">删除</a>
<a href="${pageContext.request.contextPath }/book/edit">修改</a>
<a href="${pageContext.request.contextPath }/book/list">查询</a>
</body>
</html>

结果如下:

2、servlet层

package com.lj.web;
 
import java.io.IOException;
import java.lang.reflect.Method;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
 
public class BookServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		String methodName = req.getParameter("methodName");
		
		if("add".equals(methodName)) {
			add(req,resp);
		}else if("edit".equals(methodName)) {
			edit(req,resp);
		}else if("delete".equals(methodName)) {
			delete(req,resp);
		}else if("list".equals(methodName)) {
			list(req,resp);
		}else if("load".equals(methodName)) {
			load(req,resp);
		}
		
		
	}
 
	private void load(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.load()...");
	}
 
	private void list(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.list()...");
	}
 
	private void delete(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.delete()...");
	}
 
	private void edit(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.edit()...");
	}
 
	private void add(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.add()...");
	}
	
	
	private void ref(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.ref()...");
	}
	
	
	private void other(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.other()...");
	}
	
}

主界面

<a href="${pageContext.request.contextPath }/book.action?methodName=1">新增</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=2">删除</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=3">修改</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=4">查询</a>

结果如下:

 

3、反射优化

servlet层

package com.lj.web;
 
import java.io.IOException;
import java.lang.reflect.Method;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
 
//@WebServlet("/book.action")
public class BookServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		
		String methodName = req.getParameter("methodName");
		try {
			Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
			m.setAccessible(true);
			m.invoke(this, req, resp);
		} catch (Exception e) {
			e.printStackTrace();
		}
 
		
	}
 
	private void load(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.load()...");
	}
 
	private void list(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.list()...");
	}
 
	private void delete(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.delete()...");
	}
 
	private void edit(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.edit()...");
	}
 
	private void add(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.add()...");
	}
	
	
	private void ref(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.ref()...");
	}
	
	
	private void other(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.other()...");
	}
	
}

主页面

<a href="${pageContext.request.contextPath }/book.action?methodName=load">回显</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=ref">关联查询</a>

 结果如下:

三:自定义MVC框架 

1、自定义MVC工作原理图

     *.action           调度           截取*(请求路径名) 处理具体业务逻辑
   JSP ---------> Servlet(中央控制器)--------------------->Action(子控制器)--->Model(Dao、DB)

2、中央控制器与子控制器优化 

中央控制器(DispatchServlet)

package com.lj.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 org.apache.commons.beanutils.PropertyUtils;
 
import com.lj.web.BookAction;
import com.lj.web.GoodsAction;
 
/**
 * 中央控制器
 * @author Administrator
 *	jsp:/book.action/goods.action/order.action...
 */
@WebServlet("*.action")
public class DispatchServlet extends HttpServlet {
//	在当前中央控制器中必然会有所有子控制器的集合
//	缺陷:如果有商品的增删改查-->意味着要改动代码-->代码的设计不够灵活
//	思考:在不改动代码的情况下,中央控制器也能找到对应的子控制器去处理浏览器请求
//	方案:我把加子控制器的逻辑/动作,放到配置文件中完成(Dbutil改连接信息是放在代码中完成/现在是放在Properties文件中完成)
//	放在配置文件中完成的好处在于:代码更加灵活,修改相关信息不用动代码了
//	private Map<String, ActionSupport> actions = new HashMap<>();
//	configModel对象又通过建模的知识,把所有的配置信息给读取过来了
	private ConfigModel configModel = null;
	
	/**
	 * 初始化所有的子控制器到当前的中央控制器中
	 */
	@Override
	public void init() throws ServletException {
//		在集合中就有了一个子控制器
//		actions.put("/book", new BookAction());
//		actions.put("/goods", new GoodsAction());
//		actions.put("/order", new OrderAction());
//		...
		try {
			configModel = ConfigModelFactory.build();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
 
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//		把子控制器与浏览器请求关联起来,"寻找"能够处理请求的子控制器
//		http://localhost:8080/book.action?methodName=add-->BookAction.add();
		/*
		 * 思路
		 * 1.url-->/book
		 * 2.通过/book字符串在actions找到BookAction
		 * 3.调用BookAction的add,想要调用add,实际上只要统一调用execute就可以了
		 */
//		获取到浏览器的请求地址
		String url = req.getRequestURI();
//		url-->/book
		url = url.substring(url.lastIndexOf("/"), url.lastIndexOf("."));
//		通过/book字符串在actions找到BookAction
//		ActionSupport actrion = actions.get(url);
//		在Map中寻找子控制器-->在配置文件中寻找子控制器
		/*
		 * 1.通过/book找到对应的ActionModel对象
		 * 2.通过ActionModel对象拿到类的全路径名com.zking.web.BookAction
		 * 3.反射实例化对象
		 */
		ActionModel actionModel = configModel.pop(url);
//		类的全路径名
		String type = actionModel.getType();
		ActionSupport action = null;
		try {
//			BookAction/GoodsAction/..
			action = (ActionSupport) Class.forName(type).newInstance();
//			完成实体类参数的封装
			if(action instanceof ModelDriver) {
//				当前子控制器实现了模型驱动接口
				ModelDriver m = (ModelDriver) action;
//				Book/Goods/..
				Object bean = m.getModel();
//				所有的请求参数都在这,需要将所有的请求参数封装到Book/Goods/..
				BeanUtils.populate(bean, req.getParameterMap());
//				PropertyUtils.getProperty(bean, name)
			}
//			执行业务逻辑  bookAction.add方法的返回值 “list”
			/*
			 * 1.书籍新增那么跳转书籍展示页面BookList.jsp	转发
			 * 2.书籍编辑跳转编辑界面BookEdit.jsp			重定向
			 */
			String res = action.execute(req, resp);
			ForwardModel forwardModel = actionModel.pop(res);
			String path = forwardModel.getPath();
			boolean isRedirect = forwardModel.isRedirect();
			if(isRedirect) {
				resp.sendRedirect(req.getContextPath()+path);
			}else {
				req.getRequestDispatcher(path).forward(req, resp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

子控制器

package com.lj.framework;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * 子控制器
 *	它来处理浏览器请求
 *	针对于add/ref/other进行向上抽取、抽象	abstract
 */
public interface Action {
	//这一个方法就是add/ref/other进行向上抽取的抽象方法
//	作用:能够处理浏览器的“所有”请求。包括add/ref/other...
//	通过返回值来决定跳转哪一个页面(至于是重定向/转发由中央控制器决定..)
	public String execute(HttpServletRequest req, HttpServletResponse resp);
	
//	private void add(HttpServletRequest req, HttpServletResponse resp) {
//		System.out.println("bookDao.add()...");
//	}
//	private void ref(HttpServletRequest req, HttpServletResponse resp) {
//		System.out.println("bookDao.ref()...");
//	}
//	private void other(HttpServletRequest req, HttpServletResponse resp) {
//		System.out.println("bookDao.other()...");
//	}
}
 

ActionSupport(实现Action接口)

package com.lj.framework;
 
import java.lang.reflect.Method;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * 作用:能够处理浏览器的“所有”请求。包括add/ref/other...
 * 	
 *
 */
public class ActionSupport implements Action {
 
	@Override
	public String execute(HttpServletRequest req, HttpServletResponse resp) {
		String methodName = req.getParameter("methodName");
		String res = null;
		try {
			Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
			m.setAccessible(true);
			res = (String) m.invoke(this, req, resp);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return res;
	}
 
}

BookServlet(继承ActionSupport)

package com.lj.web;
 
import java.io.IOException;
import java.lang.reflect.Method;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
/**
 * 为什么要学习自定义MVC框架?关键词 :自定义MVC		框架
 * 之前的开发模式:
 * 	MVC:模型层(Model) 视图层(view) 控制层(controller)
 * 	mvc怎么出现的:各司其职
 * 	餐馆:点菜、收银、炒菜、传菜、收拾桌子卫生	大了
 * 	编码:实体类、数据处理Dao、servlet、jsp	代码量多了
 * 
 * 自定义MVC(演绎过程)
 * 	分析不足:
 * 		1.数据处理Dao		代码思路基本重复(前几次讲到)
 * 		2.servlet		代码思路基本重复
 * 			2.1.doget/dopost,实际上doGet基本用不上
 * 			2.2.实体类参数接受代码冗余(req.getParammeter(“”),尤其当实体类属性多的情况,封装到实体类中..)
 * 			2.3.关于结果页面的跳转(转发、重定向)
 * 				req.getdispather("/index.jsp").forward(req,resp);
 * 				resp.sendredirect("/index.jsp");
 * 		3.jsp		代码思路基本重复(HTML、JS前几次讲到)
 * 	解决方案
 * 		1.通用分页(讲过的)、单表的增删改(优化)
 * 		2.servlet不需要写冗余的代码-》自定义mvc框架
 * 		3.自定义jsp标签
 * 框架:反射+设计模式(极大的减少了代码量,把重复性的代码交给框架完成,让程序员关注点放在项目业务)
 * 		1.通用分页指点+通用的增删改
 * 		2.各层(MC)数据Dao层、控制层代码缩减
 * 		3.前台代码的缩减优化
 * 	
 * 		
 * @author Administrator
 *
 */
//@WebServlet("/book.action")
public class BookServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		/*
		 * 优点:相较于前一种,代码量是减少的,由原来的4个类变成了1个类
		 * 缺点:
		 * 	每一次新增一个方法,都要改动原有逻辑,使代码过于冗余
		 * 	举例:一般当修改的时候,需要做数据回显	load
		 * 思考:
		 * 	不改动原有逻辑,也能实现需求
		 * 解决方案:
		 * 	调用哪一个方法,实际上是取决于methodName,加if不是必要条件
		 * 	直白一点:动态调用methodName方法,并且是当前类实例的methodName方法
		 * 	
		 * 总结:
		 * 	反射可以修复上面改动代码才能解决需求问题的缺陷;
		 * 	反射这段代码,相当于中央控制器,并不直接处理浏览器请求
		 * 			处理浏览器请求的是子控制器
		 * 	
		 * 中央控制器		子控制器
		 * 
		 * 今天的课程目标
		 * 	将昨天的自定义mvc框架原理形成代码,形成框架
		 * 	ActionServlet-->DispatchServlet(Springmvc)
		 * why(思考):
		 * 	1.BookServlet中要做增删改查,那么必须要在doPost方法中写反射动态调用新增方法
		 * 		GoodsServlet要做增删改查,那么必须要在doPost方法中写反射动态调用新增方法
		 * 		结论:反射动态调用新增方法代码是重复的的,但是这段又是必须的,也就是还需要进一步优化
		 * 		优化昨天所说的中央控制器
		 * 	2.对于BookServlet中要做增删改查而言,依然是每一个Servlet都要写doget/doPost方法
		 * 		但是实际上对处理业务有用的代码,往往是我们新加的,只需关注业务(add/delete/...)
		 * 		优化昨天所说的子控制器
		 * 	3.解决昨天遗留的两个问题
		 * 		实体类参数接受代码冗余(req.getParammeter(“”),尤其当实体类属性多的情况,封装到实体类中..)
		 * 			req.getParammeter(“bid”)/req.getParammeter(“bname”)/req.getParammeter(“price”)...
		 * 		关于结果页面的跳转(转发、重定向)
		 * 			req.getdispather("/index.jsp").forward(req,resp);
		 * 			resp.sendredirect("/index.jsp");
		 */	
		String methodName = req.getParameter("methodName");
		try {
			Method m = this.getClass().getDeclaredMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
			m.setAccessible(true);
			m.invoke(this, req, resp);
		} catch (Exception e) {
			e.printStackTrace();
		}
//		if("add".equals(methodName)) {
//			add(req,resp);
//		}else if("edit".equals(methodName)) {
//			edit(req,resp);
//		}else if("delete".equals(methodName)) {
//			delete(req,resp);
//		}else if("list".equals(methodName)) {
//			list(req,resp);
//		}else if("load".equals(methodName)) {
//			load(req,resp);
//		}
		
		
	}
 
	private void load(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.load()...");
	}
 
	private void list(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.list()...");
	}
 
	private void delete(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.delete()...");
	}
 
	private void edit(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.edit()...");
	}
 
	private void add(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.add()...");
	}
	
	
	private void ref(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.ref()...");
	}
	
	
	private void other(HttpServletRequest req, HttpServletResponse resp) {
		System.out.println("bookDao.other()...");
	}
	
	
}

主页面测试代码

//中央控制器及子控制器优化
<a href="${pageContext.request.contextPath }/book.action?methodName=add">新增</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=list">查询</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=delete">删除</a>

输出结果:

错误:空指针

原因:后面写了页面的跳转但只为add和edit写了所以这会报错 

3、重现参数处理代码冗余的问题 

实体类

package com.lj.entity;
 
public class Book {
	  public String bid;
	  public String bname;
	  public String price;
	  public String athor;
	  public String publish;
	public String getBid() {
		return bid;
	}
	public void setBid(String bid) {
		this.bid = bid;
	}
	public String getBname() {
		return bname;
	}
	public void setBname(String bname) {
		this.bname = bname;
	}
	public String getPrice() {
		return price;
	}
	public void setPrice(String price) {
		this.price = price;
	}
	public String getAthor() {
		return athor;
	}
	public void setAthor(String athor) {
		this.athor = athor;
	}
	public String getPublish() {
		return publish;
	}
	public void setPublish(String publish) {
		this.publish = publish;
	}
	@Override
	public String toString() {
		return "Book [bid=" + bid + ", bname=" + bname + ", price=" + price + ", athor=" + athor + ", publish="
				+ publish + "]";
	}
	
	
	
}
 

中央控制器(DispatchServlet)

package com.lj.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 org.apache.commons.beanutils.PropertyUtils;
 
import com.lj.web.BookAction;
import com.lj.web.GoodsAction;
 
/**
 * 中央控制器
 * @author Administrator
 *	jsp:/book.action/goods.action/order.action...
 */
@WebServlet("*.action")
public class DispatchServlet extends HttpServlet {
//	在当前中央控制器中必然会有所有子控制器的集合
//	缺陷:如果有商品的增删改查-->意味着要改动代码-->代码的设计不够灵活
//	思考:在不改动代码的情况下,中央控制器也能找到对应的子控制器去处理浏览器请求
//	方案:我把加子控制器的逻辑/动作,放到配置文件中完成(Dbutil改连接信息是放在代码中完成/现在是放在Properties文件中完成)
//	放在配置文件中完成的好处在于:代码更加灵活,修改相关信息不用动代码了
//	private Map<String, ActionSupport> actions = new HashMap<>();
//	configModel对象又通过建模的知识,把所有的配置信息给读取过来了
	private ConfigModel configModel = null;
	
	/**
	 * 初始化所有的子控制器到当前的中央控制器中
	 */
	@Override
	public void init() throws ServletException {
//		在集合中就有了一个子控制器
//		actions.put("/book", new BookAction());
//		actions.put("/goods", new GoodsAction());
//		actions.put("/order", new OrderAction());
//		...
		try {
			configModel = ConfigModelFactory.build();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
 
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		doPost(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//		把子控制器与浏览器请求关联起来,"寻找"能够处理请求的子控制器
//		http://localhost:8080/book.action?methodName=add-->BookAction.add();
		/*
		 * 思路
		 * 1.url-->/book
		 * 2.通过/book字符串在actions找到BookAction
		 * 3.调用BookAction的add,想要调用add,实际上只要统一调用execute就可以了
		 */
//		获取到浏览器的请求地址
		String url = req.getRequestURI();
//		url-->/book
		url = url.substring(url.lastIndexOf("/"), url.lastIndexOf("."));
//		通过/book字符串在actions找到BookAction
//		ActionSupport actrion = actions.get(url);
//		在Map中寻找子控制器-->在配置文件中寻找子控制器
		/*
		 * 1.通过/book找到对应的ActionModel对象
		 * 2.通过ActionModel对象拿到类的全路径名com.zking.web.BookAction
		 * 3.反射实例化对象
		 */
		ActionModel actionModel = configModel.pop(url);
//		类的全路径名
		String type = actionModel.getType();
		ActionSupport action = null;
		try {
//			BookAction/GoodsAction/..
			action = (ActionSupport) Class.forName(type).newInstance();
//			完成实体类参数的封装
			if(action instanceof ModelDriver) {
//				当前子控制器实现了模型驱动接口
				ModelDriver m = (ModelDriver) action;
//				Book/Goods/..
				Object bean = m.getModel();
//				所有的请求参数都在这,需要将所有的请求参数封装到Book/Goods/..
				BeanUtils.populate(bean, req.getParameterMap());
//				PropertyUtils.getProperty(bean, name)
			}
//			执行业务逻辑  bookAction.add方法的返回值 “list”
			/*
			 * 1.书籍新增那么跳转书籍展示页面BookList.jsp	转发
			 * 2.书籍编辑跳转编辑界面BookEdit.jsp			重定向
			 */
			String res = action.execute(req, resp);
			ForwardModel forwardModel = actionModel.pop(res);
			String path = forwardModel.getPath();
			boolean isRedirect = forwardModel.isRedirect();
			if(isRedirect) {
				resp.sendRedirect(req.getContextPath()+path);
			}else {
				req.getRequestDispatcher(path).forward(req, resp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

模型驱动接口(ModelDriver)

package com.lj.framework;
 
//import com.lj.entity.Book;
 
/**
 * 模型驱动接口
 * 作用:帮助“中央控制器”完成参数封装的工程
 * 	Book book = new Book();
	book.setBid(req.getParameter("bid"));
	book.setBname(req.getParameter("bname"));
	book.setPrice(req.getParameter("price"));
	book.setAthor(req.getParameter("athor"));
	book.setPublish(req.getParameter("publish"));
	System.out.println(book);
 * @author Administrator
 *
 * @param <T>
 */
public interface ModelDriver<T> {
	/**
	 * GoodsAction-->goods
	 * BookAction-->book
	 * ...
	 * @return
	 */
	T getModel();
}

测试界面代码

重现参数处理代码冗余的问题
<form action="${pageContext.request.contextPath }/book.action?methodName=add" method="post">
    书籍ID:<input type="text" name="bid" value="2">
    书籍名称:<input type="text" name="bname" value="2x">
    书籍价格:<input type="text" name="price" value="2a">
    书籍作者:<input type="text" name="athor" value="2b">
    书籍出版社:<input type="text" name="publish" value="2c">
    <input type="submit">
</form>

测试结果:

4、解决结果码页面跳转代码冗余问题 

上述所有代码

xml

<?xml version="1.0" encoding="UTF-8"?>
<config>
	
	<!-- 
		在这里每加一个配置,就相当于actions.put("/goods", new GoodsAction());
		这样就解决了代码灵活性的问题
	 -->
	<action path="/book" type="com.lj.web.BookAction">
		<forward name="list" path="/bookList.jsp" redirect="false" />
		<forward name="toEdit" path="/bookEdit.jsp" redirect="true" />
	</action>
	
	<action path="/goods" type="com.lj.web.GoodsAction">
		<forward name="failed" path="/login.jsp" redirect="false" />
		<forward name="success" path="/main.jsp" redirect="true" />
	</action>
	
	<action path="/order" type="com.lj.web.OrderAction">
		<forward name="failed" path="/login.jsp" redirect="false" />
		<forward name="success" path="/main.jsp" redirect="true" />
	</action>
</config>

跳转的界面一   (bookEdit)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
书籍编辑界面
</body>
</html>

跳转的界面二       (bookList)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
书籍列表页面
</body>
</html>

测试页面代码

解决结果码页面跳转代码冗余问题
<a href="${pageContext.request.contextPath }/book.action?methodName=add">新增</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=toEdit">去往编辑界面</a>

测试结果;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值