目录
思维导图
一.自定义MVC?
二.演绎过程
1、之前的开发模式
2、反射优化
?三.自定义MVC框架
?1、自定义MVC工作原理图
?2、优化中央控制器、优化子控制器
?3、实体类参数接受代码冗余?
?4、关于结果页面的跳转(转发、重定向)?
思维导图
一.自定义MVC?
1.什么是MVC?
MVC全名:Model View Controller,其中Model(模型层)、View(视图层)、Controller(控制层)它是一种软件设计典范.
2、三层架构和MVC的区别?
三层架构是一个经典的分层思想,将开发模式分为三层,每个人专注自己擅长模块即可
MVC是一种设计模式,其目的是让视图和业务逻辑分开
3、MVC结构??
????①、 V(视图层) -->JSP/HTML/freemarker?
? ?②、 C(控制层) -->Servlet/Action/Controller
? ?③、M(模型层) -->entity、dao
?注:(1)不能跨层调用; ? ? ? ?(2)只能由上往下进行调用;View -> Controller -> Model
4、目的
二.演绎过程
1、之前的开发模式
①.绝大多数人采用这种方法做增删改查,需要多少个servlet就建多少
增
package com.ysq.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 AddServlet 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 {
System.out.println("bookDao.add()...");
}
}
删
package com.ysq.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/del")
public class DelServlet 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 {
System.out.println("bookDao.del()...");
}
}
改
package com.ysq.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/upd")
public class UpdServlet 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 {
System.out.println("bookDao.upd()...");
}
}
查
package com.ysq.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 ListServlet 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 {
System.out.println("bookDao.list()...");
}
}
JSP页面:
<%@ 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>
<!-- 绝大多数人开发采用这种方式做增删改查(servlet层) -->
<a href="${pageContext.request.contextPath }/book/add">新增</a>
<a href="${pageContext.request.contextPath }/book/del">删除</a>
<a href="${pageContext.request.contextPath }/book/upd">修改</a>
<a href="${pageContext.request.contextPath }/book/list">查询</a>
</body>
</html>
运行结果如下:
②、少数人采用这种方法做增删改查
select层
package com.ysq.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")
@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("del".equals(methodName)) {
del(req,resp);
}else if("upd".equals(methodName)) {
upd(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.load2()");
}
private void list(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.list2()");
}
private void upd(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.upd2()");
}
private void del(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.del2()");
}
private void add(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.add2()");
}
}
?JSP页面:
jsp页面:
<%@ 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>
<!-- 少数人开发采用这种方式做增删改查(servlet层) -->
<a href="${pageContext.request.contextPath }/book.action?methodName=add">新增2</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=del">删除2</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=upd">修改2</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=list">查询2</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=load">回显2</a>
</body>
</html>
运行结果如下:
2、反射优化
package com.ysq.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{
//动态调用methodName方法,并且是当前类实例的methodName
@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) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void load(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.load2()");
}
private void list(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.list2()");
}
private void upd(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.upd2()");
}
private void del(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.del2()");
}
private void add(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.add2()");
}
private void ather(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.ather2()");
}
}
?三.自定义MVC框架
?1、自定义MVC工作原理图
?2、优化中央控制器、优化子控制器
①.子控制器(Action接口)? ? 处理浏览器请求
package com.ysq.framework;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 子控制器
* 处理浏览器请求
* 针对于add/del进行抽取,抽象 abstract
* @author zjjt
*
*/
public interface Action {
//这一个方法就是add/del进行抽取,抽象方法
//作用:能够处理浏览器的“所有”请求包括add/del
//通过返回值来决定跳转哪一个页面(至于是重定向/转发由中央控制器决定)
public String execute(HttpServletRequest req, HttpServletResponse resp);
}
②.ActionSupport(实现Action接口)
package com.ysq.framework;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 作用:能够处理浏览器的“所有”请求包括add/del
*
* @author zjjt
*
*/
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) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return res;
}
}
③.BookAction(继承ActionSupport)
package com.ysq.web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ysq.entity.Book;
import com.ysq.framework.ActionSupport;
import com.ysq.framework.ModelDriver;
public class BookAction extends ActionSupport implements ModelDriver<Book>{
public Book book=new Book();
@Override
public Book getModel() {
// TODO Auto-generated method stub
return book;
}
//从父类继承了execute方法,就把反射动态调用方法的代码给继承过来了
//BookAction 就相当于以前的BookServlet
//当前子控制器在哪里调用?把子控制与浏览器关联起来
private String upd(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.upd3()");
return "upd";
}
private String add(HttpServletRequest req, HttpServletResponse resp) {
System.out.println(book);
System.out.println("bookDao.add3(book)");
return "del";
}
private void del(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.del3()");
}
}
④.中央控制器(DispatchServlet)
package com.ysq.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 com.ysq.web.BookAction;
import com.ysq.web.GoodsAction;
/**
* 中央控制器
* @author zjjt
* jsp:/book.action
*
*/
@WebServlet("*.action")
public class DispatchServlet extends HttpServlet{
//在当前中央控制器中必然会有所有子控制器的集合
private Map<String, ActionSupport> actions=new HashMap<String, ActionSupport>();
//初始化所有的子控制器到当前的中央控制器中
public void init() throws ServletException {
//在集合就有了一个子控制器
//缺陷:如果有商品的增删改查,就要不断的去累积它,意味着要改动代码 代码不够灵活
try {
actions.put("/book",new BookAction());
actions.put("/goods",new GoodsAction());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 把子控制器与浏览器请求关联起来,“寻找”能够处理请求的子控制器
//http://localhost:8080/book.action?methodName=add
/**思路:
* 1.url-->book
* 2.通过book字符串在actions找到BookAction
* 3.调用BookActions的add 想要掉add 实际上只要统一execute就可以了
*/
//获取到浏览器的请求地址
String url = req.getRequestURI();
url = url.substring(url.lastIndexOf("/"), url.lastIndexOf("."));
ActionSupport action = actions.get(url);
action.execute(req, resp);
}
}
因为④代码的缺陷:如果有商品的增删改查,就要不断的去累积它,意味着要改动代码 代码不够灵活,所以对它进行了优化
?⑤.中央控制器(DispatchServlet) 使用到了建模 和所需的jar包
?代码如下:
package com.ysq.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 com.ysq.web.BookAction;
import com.ysq.web.GoodsAction;
/**
* 中央控制器
* @author zjjt
* jsp:/book.action
*
*/
@WebServlet("*.action")
public class DispatchServlet extends HttpServlet{
//在当前中央控制器中必然会有所有子控制器的集合
//private Map<String, ActionSupport> actions=new HashMap<String, ActionSupport>();
private ConfigModel configModel=null;
//初始化所有的子控制器到当前的中央控制器中
@Override
public void init() throws ServletException {
//在集合就有了一个子控制器
//缺陷:如果有商品的增删改查,就要不断的去累积它,意味着要改动代码 代码不够灵活
//思考:在bu改变代码的情况下,中央控制器也能找到对应的子控制器去处理浏览器的请求
//方案:把加子控制器的逻辑/动作,放到配置文件中完成
//放在配置文件中完成的好处在于:代码更加灵活,修改信息不要动代码了
//configModel对象又通过建模的知识,把所有的配置信息给读取出来了
/* actions.put("/book",new BookAction());
actions.put("/goods",new GoodsAction());*/
try {
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);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 把子控制器与浏览器请求关联起来,“寻找”能够处理请求的子控制器
//http://localhost:8080/book.action?methodName=add
/**思路:
* 1.url-->book
* 2.通过book字符串在actions找到BookAction
* 3.调用BookActions的add 想要掉add 实际上只要统一execute就可以了
*/
//获取到浏览器的请求地址
String url = req.getRequestURI();
url = url.substring(url.lastIndexOf("/"), url.lastIndexOf("."));
//ActionSupport action = actions.get(url);
//action.execute(req, resp);
//原来在map中寻找子控制器 现在在配置文件中找子控制器
/**
* 1.通过/book找到对应的ActionModel对象
* 2.通过ActionModel对象拿到类的全路径名com.zy.web.BookAction
* 3.反射实例化对象
*
*/
ActionModel actionModel = configModel.pop(url);
//拿到全路径名
String type = actionModel.getType();
ActionSupport action=null;
try {
action= (ActionSupport) Class.forName(type).newInstance();
action.execute(req, resp);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
测试:
<%@ 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.action?methodName=add">新增3</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=del">删除3</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=upd">修改3</a>
</body>
</html>
运行结果如下:
?3、实体类参数接受代码冗余?
①、Book(实体类)
package com.ysq.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.ysq.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 org.dom4j.DocumentException;
import com.ysq.servlet.BookAction;
import com.ysq.servlet.GoodsAaction;
/**
* 中央控制器
*jsp:/book.action/goods.action
*/
@WebServlet("*.action")
public class DispatchServlet extends HttpServlet{
private ConfigModel configModel=null;
@Override
public void init() throws ServletException {
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 {
//获取到浏览器的请求地址
String uri = req.getRequestURI();
uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
ActionModel actionModel = configModel.pop(uri);
String type = actionModel.getType();
ActionSupport action;
try {
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);
}
action.execute(req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
③、ModelDriver<T>
package com.ysq.framework;
/**
* 模型驱动接口
* 作用:帮助“中央控制器”完成参数封装工程
* @author zjjt
*
*/
public interface ModelDriver<T> {
T getModel();
}
④、?BookAction (extends ActionSupport implements ModelDriver<Book>)
package com.ysq.web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ysq.entity.Book;
import com.ysq.framework.ActionSupport;
import com.ysq.framework.ModelDriver;
public class BookAction extends ActionSupport implements ModelDriver<Book>{
public Book book=new Book();
@Override
public Book getModel() {
// TODO Auto-generated method stub
return book;
}
//从父类继承了execute方法,就把反射动态调用方法的代码给继承过来了
//BookAction 就相当于以前的BookServlet
//当前子控制器在哪里调用?把子控制与浏览器关联起来
private void upd(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.upd3()");
}
private void del(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.del3()");
}
private void add(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.add3(book)");
}
}
⑤、测试界面
<!--重复参数处理代码冗余的问题 --> <form action="${pageContext.request.contextPath }/book.action?methodName=add" method="post"> ?? ?书籍ID:<input type="text" name="bid" value="1"> ?? ?书籍名称:<input type="text" name="bname" value="2"> ?? ?书籍价格:<input type="text" name="price" value="24"> ?? ?书籍作者:<input type="text" name="athor" value="5"> ?? ?书籍出版社:<input type="text" name="publish" value="9"> ?? ?<input type="submit"> </form>
运行结果如下:
?4、关于结果页面的跳转(转发、重定向)?
①.Action
package com.ysq.framework;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 子控制器
* 处理浏览器请求
* 针对于add/del进行抽取,抽象 abstract
* @author zjjt
*
*/
public interface Action {
//这一个方法就是add/del进行抽取,抽象方法
//作用:能够处理浏览器的“所有”请求包括add/del
//通过返回值来决定跳转哪一个页面(至于是重定向/转发由中央控制器决定)
public String execute(HttpServletRequest req, HttpServletResponse resp);
}
②.ActionSupport
package com.ysq.framework;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 作用:能够处理浏览器的“所有”请求包括add/del
*
* @author zjjt
*
*/
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) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return res;
}
}
③BookAction
package com.ysq.web;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zy.entity.Book;
import com.zy.framework.ActionSupport;
import com.zy.framework.ModelDriver;
public class BookAction extends ActionSupport implements ModelDriver<Book>{
public Book book=new Book();
@Override
public Book getModel() {
// TODO Auto-generated method stub
return book;
}
//从父类继承了execute方法,就把反射动态调用方法的代码给继承过来了
//BookAction 就相当于以前的BookServlet
//当前子控制器在哪里调用?把子控制与浏览器关联起来
private String upd(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.upd3()");
return "upd";
}
private String add(HttpServletRequest req, HttpServletResponse resp) {
System.out.println(book);
System.out.println("bookDao.add3(book)");
return "del";
}
private void del(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("bookDao.del3()");
}
}
④DispatchServlet?
package com.ysq.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 com.ysq.web.BookAction;
import com.ysq.web.GoodsAction;
/**
* 中央控制器
* @author zjjt
* jsp:/book.action
*
*/
@WebServlet("*.action")
public class DispatchServlet extends HttpServlet{
//在当前中央控制器中必然会有所有子控制器的集合
//private Map<String, ActionSupport> actions=new HashMap<String, ActionSupport>();
private ConfigModel configModel=null;
//初始化所有的子控制器到当前的中央控制器中
@Override
public void init() throws ServletException {
//在集合就有了一个子控制器
//缺陷:如果有商品的增删改查,就要不断的去累积它,意味着要改动代码 代码不够灵活
//思考:在bu改变代码的情况下,中央控制器也能找到对应的子控制器去处理浏览器的请求
//方案:把加子控制器的逻辑/动作,放到配置文件中完成
//放在配置文件中完成的好处在于:代码更加灵活,修改信息不要动代码了
//configModel对象又通过建模的知识,把所有的配置信息给读取出来了
/* actions.put("/book",new BookAction());
actions.put("/goods",new GoodsAction());*/
try {
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);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 把子控制器与浏览器请求关联起来,“寻找”能够处理请求的子控制器
//http://localhost:8080/book.action?methodName=add
/**思路:
* 1.url-->book
* 2.通过book字符串在actions找到BookAction
* 3.调用BookActions的add 想要掉add 实际上只要统一execute就可以了
*/
//获取到浏览器的请求地址
String url = req.getRequestURI();
url = url.substring(url.lastIndexOf("/"), url.lastIndexOf("."));
//ActionSupport action = actions.get(url);
//action.execute(req, resp);
//原来在map中寻找子控制器 现在在配置文件中找子控制器
/**
* 1.通过/book找到对应的ActionModel对象
* 2.通过ActionModel对象拿到类的全路径名com.zy.web.BookAction
* 3.反射实例化对象
*
*/
ActionModel actionModel = configModel.pop(url);
//拿到全路径名
String type = actionModel.getType();
ActionSupport action=null;
try {
//如 BookAction
action= (ActionSupport) Class.forName(type).newInstance();
//完成实体类参数的封装
if(action instanceof ModelDriver) {
//当前子控制器实现了模型驱动接口
ModelDriver m=(ModelDriver) action;
//Book
Object bean = m.getModel();
//所有的请求参数都在这,需要将所有的请求参数封装到Book/Goods/
BeanUtils.populate(bean, req.getParameterMap());
}
//执行业务逻辑 bookAction.add方法返回值del
/**
* 1.书籍新增那么跳转为书籍del.jsp 转发
* 2.书籍修改跳book.jsp 重定向
*/
String res = action.execute(req, resp);
//res就是返回值
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) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
⑤config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- config标签:可以包含0~N个action标签 -->
<config>
<!-- action标签:可以饱含0~N个forward标签 path:以/开头的字符串,并且值必须唯一 非空 type:字符串,非空 -->
<!-- 在这里每加一个配置,就相当于写了 actions.put("/goods",new GoodsAction());这样就解决了代码灵活性问题 false代表转发-->
<action path="/book" type="com.ysq.web.BookAction">
<forward name="del" path="/del.jsp" redirect="false" />
<forward name="upd" path="/book.jsp" redirect="true" />
</action>
</config>
⑥测试
<%@ 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>
<!--重复参数处理代码冗余的问题 -->
<form action="${pageContext.request.contextPath }/book.action?methodName=add" method="post">
<!-- -->
<a href="${pageContext.request.contextPath }/book.action?methodName=add">新增4</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=upd">修改4</a>
</form>
</body>
</html>
运行结果如下:
|