/** ?* 目标:自定义mvc的工作原理 ?* ?? ?1.什么是自定义mvc框架 ?* ?? ??? ?关键:自定义mvc?? ??? ?框架 ?* ?? ?2.它的运行原理 ?* ?? ??? ?2.1代码演绎过程 ?* ?? ??? ?2.2总结代码运行原理 ?*? ?* ?? ?思考: ?* ?? ??? ?什么是mvc ?* ?? ?Model模型、view视图、controller控制层 ?* ?? ?mvc的出现原因:各司其职 ?* ?? ?一个餐馆:点菜、收银、炒菜、上菜、收盘子、洗盘子 ?* ?? ?发展壮大:点菜员、收银员、厨师、传菜员、洗碗阿姨... ?*? ?* 不足: ?* ?? ?Model模型: ?* ?? ??? ?Dao层:(增删改 ?查) ?* ?? ??? ??? ?1.建立数据库连接 ?* ?? ??? ??? ?2.预定义对象Preparestatement ?* ?? ??? ??? ?3.执行查询 ?* ?? ??? ??? ?4.处理结果集 ?* ?? ??? ?通用分页解决了上面问题 ?* ?? ?view视图: ?* ?? ??? ??? ?1.重复的HTML分页条代码 ?* ?? ??? ??? ?2.重复的JS代码 ?* ?? ??? ??? ?自定义page标签 ?* ?controller控制层 ?* ?? ??? ??? ?1.重写了doGet、doPost,并且doGet没有用 ?* ?? ??? ??? ?2.参数的封装代码冗余了 ?* ?? ??? ??? ??? ?req.getParammeter("xxxx"); ?* ?? ??? ??? ?3.对于跳转页面的代码是重复的 ?* ?? ??? ??? ??? ?req.getRequestDispatcher("index.jsp").forward(req,resp); ?* ?? ??? ??? ??? ?resp.sendRedirect("bookList.jsp"); ?* ?? ?解决方案: ?* ?? ??? ?自定义mvc就出现了 ?* ?? ??? ?框架:反射+设计模式,案例:通用分页+自定义page标签+自定义mvc的组合就是框架 ?* ?? ? ?
//@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 {
/*
* 增删改查缺陷
* 当需求发生改变,或者新增需求的时候,需要改动下面代码 load
*
* 解决方案
* 前台传递methodName到后台,实际就是想要调用当前类对象的methodName方法
* this.methodName
*
*/
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 add(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.add()...");
}
private void edit(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.edit()...");
}
private void delete(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.delete()...");
}
private void list(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.list()...");
}
private void ref(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.ref()...");
}
private void load(HttpServletRequest req, HttpServletResponse resp) {
// 修改页面数据回显
System.out.println("bookDao.load()...");
}
}
?需求:删除数据后跳转到书籍展示页面 ?? ??? ? 缺陷:1.出现大量重复代码?? ?2.不好管理(增删改重新跳转到查询界面) ?? ??? ? 解决方案:在一个地方统一管理重定向还是转发,并且是定位跳转到哪一个页面 ?? ??? ? 预测结果 ?? ??? ? ? ?BookAction调用bookDao.delete()... ?? ??? ? ? BookAction调
package com.zking.ydz.web;
import java.io.IOException;
import java.lang.reflect.Field;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zking.entity.Book;
import com.zking.framework.ActionSupport;
import com.zking.framework.ModelDriver;
public class BookAction extends ActionSupport implements ModelDriver<Book>{
private Book book = new Book();
// execute
private String delete(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("BookAction调用bookDao.delete()...");
// try {
// req.getRequestDispatcher("/bookList.jsp").forward(req, resp);
resp.sendRedirect("/bookList.jsp");
// this.list(req, resp);
// } catch (Exception e) {
// e.printStackTrace();
// }
return "toList";
}
private void add(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("BookAction调用bookDao.add()...");
}
private String list(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("BookAction调用bookDao.list()...");
// try {
// req.getRequestDispatcher("/bookList.jsp").forward(req, resp);
// } catch (Exception e) {
// e.printStackTrace();
// }
return "list";
}
private void ref(HttpServletRequest req, HttpServletResponse resp) {
// 解决参数实体类封装的问题
/*
* 缺陷:对于前端传参,实体类属性值封装req.getParammeter("")代码 是重复的
* 需求:做一个book的新增功能
* 思考:将JSP参数塞进实体类的属性中,问题是每个实体类的属性是不一样的,没办法做到代码的完全重复
Book book = new Book();
book.setBid(req.getParameter("bid"));
book.setBname(req.getParameter("bname"));
book.setPrice(req.getParameter("price"));
book.setAuthor(req.getParameter("author"));
book.setPublish(req.getParameter("publish"));
}
@Override
public Book getModel() {
return book;
}
}
用bookDao.list()...
思路: ?? ??? ? * ?? ?不知道是哪一个实体类->泛型T ?? ??? ? * ?? ?不知道这个实体类有哪些属性,但是又要给这些属性赋值->反射动态设置属性值 ?? ??? ? * 解决:泛型+反射 ?? ??? ? * 编码: ?? ??? ? * ?? ?模型驱动接口:ModelDriver
private void ref(HttpServletRequest req, HttpServletResponse resp) {
// 解决参数实体类封装的问题
/*
* 缺陷:对于前端传参,实体类属性值封装req.getParammeter("")代码 是重复的
* 需求:做一个book的新增功能
* 思考:将JSP参数塞进实体类的属性中,问题是每个实体类的属性是不一样的,没办法做到代码的完全重复
* 思路:
* 不知道是哪一个实体类->泛型T
* 不知道这个实体类有哪些属性,但是又要给这些属性赋值->反射动态设置属性值
* 解决:泛型+反射
* 编码:
* 模型驱动接口:ModelDriver
*/
// Book book = new Book();
// book.setBid(req.getParameter("bid"));
// book.setBname(req.getParameter("bname"));
// book.setPrice(req.getParameter("price"));
// book.setAuthor(req.getParameter("author"));
// book.setPublish(req.getParameter("publish"));
System.out.println(book);
System.out.println("BookAction调用bookDao.ref(book)...");
}
以上接下来就是写咱们的增删改查
<%@ 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>
<hr>
增删改查的代码V2.0
<a href="${pageContext.request.contextPath }/book.action?methodName=add">增加</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=delete">删除</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=edit">修改</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=list">查询</a>
<hr>
增删改查的代码V3.0
<a href="${pageContext.request.contextPath }/book.action?methodName=load">回显</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=ref">关联</a>
<hr>
</form>
</body>
</html>
1.处理前台的浏览器请求 ?2.运行JSP传递到后台的方法字符串所代表的方法 ?@author Administrator
package com.zking.framework;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 1.处理前台的浏览器请求
* 2.运行JSP传递到后台的方法字符串所代表的方法
* @author Administrator
*
*/
public interface Action {
public String execute(HttpServletRequest req, HttpServletResponse resp);
// private void delete(HttpServletRequest req, HttpServletResponse resp) {
// System.out.println("bookDao.delete()...");
// }
//
// private void list(HttpServletRequest req, HttpServletResponse resp) {
// System.out.println("bookDao.list()...");
// }
//
// private void ref(HttpServletRequest req, HttpServletResponse resp) {
// System.out.println("bookDao.ref()...");
// }
}
之后
package com.zking.ydz.framework;
import java.util.HashMap;
import java.util.Map;
public class ActionModel {
// <action path="/regAction" type="test.RegAction">
private String path;
private String type;
private Map<String, ForwardModel> fMap = new HashMap<>();
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 forwardModel) {
fMap.put(forwardModel.getName(), forwardModel);
}
public ForwardModel pop(String name) {
return fMap.get(name);
}
在建一个ActionSupport
package com.zking.ydz.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 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;
}
}
之后
目前多数人增删改查的代码
<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>
<hr>
增删改查的代码V2.0
<a href="${pageContext.request.contextPath }/book.action?methodName=add">增加</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=delete">删除</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=edit">修改</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=list">查询</a>
<hr>
增删改查的代码V3.0
<a href="${pageContext.request.contextPath }/book.action?methodName=load">回显</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=ref">关联</a>
<hr>
演示原有初始化子控制器的缺陷
<a href="${pageContext.request.contextPath }/goods.action?methodName=add">增加</a>
<a href="${pageContext.request.contextPath }/goods.action?methodName=delete">删除</a>
<a href="${pageContext.request.contextPath }/goods.action?methodName=edit">修改</a>
<a href="${pageContext.request.contextPath }/goods.action?methodName=list">查询</a>
??目标: ?? ? 根据自定义mvc框架的原理图?? ?完成?? ?框架的研发 ?中央控制器 ?? ? 寻找子控制器
package com.zking.ydz.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.zking.web.BookAction;
import com.zking.web.GoodsAction;
@WebServlet("*.action")
public class DispatchServlet extends HttpServlet {
// 存放子控制器的容器
// private Map<String, ActionSupport> actions = new HashMap<String, ActionSupport>();
private ConfigModel configModel = null;
// 初始化子控制器容器(集合),经过初始化,actions容器内部就有了子控制器
// init,service,destroy
/*
* 需求:
* 在增加一个商品类的增删查改
* 步骤:
* 改动init中代码
* 思考:
* 能不能不改动代码完成这个需求
* 参考DBAccess的数据源配置文件config.properties
* 1.减少代码改动风险性
* 2.减少代码的编译次数(对于已经部署到服务器后)
* 解决方案:
* 改成子控制器可配置
* 解决步骤:
* 1.必须有配置文件config.xml
* 2.配置文件config.xml中要包含处理业务的子控制器
* 3.读取到配置文件config.xml中的对应的处理浏览器请求的子控制器
* 编码
* ...
*/
@Override
public void init() throws ServletException {
try {
configModel = ConfigModelFactory.build();
} catch (Exception e) {
e.printStackTrace();
}
// actions.put("/book", new BookAction());
// actions.put("/goods", new GoodsAction());
// actions.put("/order", new BookAction());
// actions.put("/OrderItem", new BookAction());
}
@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/t266_mvc/book.action?methodName=add
// 目标:BookAction.add()...
/*
* 思路:
* 1.从浏览器URL中获取到“/book”字符串
* 2.在子控制器容器中拿到BookAction
* 3.BookAction.add()
*/
String uri = req.getRequestURI();
uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
// action=BookAction
// ActionSupport action = actions.get(uri);
ActionModel actionModel = configModel.pop(uri);
String type = actionModel.getType();
ActionSupport action;
try {
action = (ActionSupport) Class.forName(type).newInstance();
// ActionSupport action = new BookAction()
if(action instanceof ModelDriver) {
ModelDriver m = (ModelDriver) action;
Object obj = m.getModel();
// 有对象
// 接受所有的前端JSP传递到后台的参数
Map<String, String[]> parameterMap = req.getParameterMap();
// 对 对象 赋值
// PropertyUtils.getProperty(obj, "")
BeanUtils.populate(obj, parameterMap);
}
// execute->delete
String res = action.execute(req, resp);
/*
* 思路
* 1.方法执行完毕必须有一个返回值
* 2.通过返回值决定是否重定向,还是转发
* 3.通过返回值决定跳转哪一个页面
*/
ForwardModel forwardModel = actionModel.pop(res);
if(forwardModel.isRedirect()) {
resp.sendRedirect(req.getContextPath()+forwardModel.getPath());
}else {
req.getRequestDispatcher(forwardModel.getPath()).forward(req, resp);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
接下来就·看看·能不能用·
?
|