?一:什么是自定义MVC
1.什么是MVC?
MVC全名:Model View Controller,其中Model(模型层)、View(视图层)、Controller(控
层)它是一种软件设计典范,用于业务逻辑处理、数据、界面显示分离
2、三层架构和MVC的区别?
mvc:
M即Model(模型层),主要负责处理业务逻辑及数据库的交互
V即View(视图层),主要扶着显示数据和提交数据
C即Controller(控制层),主要是永作辅助捕获请求并口至请求转发
三层:
Ui界面层
BLL业务逻辑层
DAL数据访问层
三层是基于业务逻辑来分的,区分层次的目的即为了“高内聚,低耦合”的思想,而mvc是基于页面分页来分的。
3、MVC结构?
? ①、 V(视图层) -->JSP/HTML/freemarker
? ?②、 C(控制层) -->Servlet/Action/Controller
? ?③、M(模型层) -->entity、dao
注:(1)不能跨层调用; ? ? ? ?(2)只能由上往下进行调用;View -> Controller -> Model
为什么要学习MVC:
?二: 演绎过程
方法①?绝大多数人采用这种方法做增删改查,需要多少个servlet就建多少
package com.zxy.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 {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("bookDao.add()....");
}
}
//删除
package com.zxy.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 {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("bookDao.delete()....");
}
}
jsp界面
<h4>大多数人采用这种方式做增删改查(servlet层)方法①</h4>
<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>
方法②、少数人采用这种方法做增删改查(select层)
package com.zxy.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 代码思路基本重复
* servlet 代码思路基本重复
* 2.1doget/dopost,实际上doget基本用不上
* 2.2实体类参数接受代码冗余(req.getparammeter(""),尤其当实体类属性多的情况,封装到实体类中)
* 2.3关于结果页面的跳转(转发,重定向)
*
* 3.jsp 代码思路基本重复
* 解决方案
* 1.通用分页,单表的增删改查
* 2.servlet不需要写冗余的代码-》自定义mvc框架
* 3.自定义jsp标签
*
* 框架:反射+设计模式(极大的减少了代码量)把重复性代码交给框架完成。
* 1.通用分页指点+通用的的增删改
* 2.各层(mc)数据dao层,控制层代码缩减
* 3.前台代码的缩减优化
* @author zjjt
*
* 8.28课程目标
* 将昨天的自定义mvc框架形成代码,形成框架
* 思考:
* bookservlet中要做增删改查,那么必须要在dopost方法中写反射动态调用新增方法
* Goodsservlet中要做增删改查,那么必须要在dopost方法中写反射动态调用新增方法
*结论:
*优化昨天所说的中央控制器
*1.反射动态调用新增方法代码是重复的,但是这段又是必须的,还需要进行进一步优化
* 优化昨天的自控制器
*2.对于bookservlet中要做增删改查而言,依然是每一个Servlet都要写doget、dopost方法
*但是实际上对处理业务有用的代码,往往是我们新加的,只需要关注所需业务(add、delete...)
*3.解决昨天遗留问题
*实体类参数接受代码冗余(req.getParamenter(""),尤其当实体类属性多的情况,封装到实体类上)
*关于结果页面错误(转发,重定向)
*/
@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,加if不是不是必要条件
* 直接一点就是动态调用methodName方法,并且是当前类实例的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);
}
}
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()...");
}
}
jsp界面
<!-- 少数人写法反射优化 方法②-->
<h4> 少数人写法反射优化 方法②</h4>
<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>
?运行:
?2.反射优化
反射优化的优点在于:
? ? ? ? ? ?① 反射可以修复上面改动代码才能解决需求问题的缺陷 ? ? ? ? ? ?②反射这段代码相当于中央控制器,并不直接控制浏览器请求 ? ? ? ? ? ? ?处理浏览器请求的是子控制器
package com.zxy.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 {
/**
* 优点:相交于前一种,代码量时间少的,由原来4个类变成了1个类
* 缺点:
* 每一次新增一个方法,都要改动原有逻辑,使代码过于冗余
* 举例:一般当修改的时候,需要做数据回显load
* 思考:
* 不改动原有逻辑,也能实现需求
* 解决方案:
* 调用哪个方法,实际上是取决于methodName,加if不是必要条件
* 直白一点:动态调用methodName方法,并且是当前类实例的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();
}
}
private void load(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("--回显--");
}
private void ref(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("--ref--");
}
}
jsp界面
反射优化
<a href="${pageContext.request.contextPath }/book.action?methodName=load">回显</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=ref">关联查询</a>
运行结果如下:
?三、自定义MVC框架
?图中修改名称: ActionServlet-->DispatchServlet(Springmvc)
2、优化中央控制器、优化子控制器
①、使用到xml建模?
所需jar包
?③、中央控制器(DispatchServlet?)
package com.zxy.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.zxy.servlet.BookAction;
import com.zxy.servlet.GoodsAaction;
/**
* 中央控制器
*jsp:/book.action/goods.action
*
*/
@WebServlet("*.action")
public class DispatchServlet extends HttpServlet{
//在当前中央控制器中必然会有所有子控制器集合
//缺陷:如果有商品的增删改查-->意味着要改动代码-->代码的设计不够灵活
//思考:在不改动代码的情况下,中央控制器也能找到对应的子控制器去处理浏览器请求
//方案:我把加子控制器的逻辑/动作,放到配置文件中完成(Dbutil改连接信息是放在代码中完成/现在是放在Properties文件中完成)
//放在配置文件中完成的好处在于代码更加灵活,修改相关信息不用动代码
//ConfigModel对象又通过建模的知识,把所有的配置信息给读取过来了
//private Map<String, ActionSupport> actions=new HashMap<>();
//现在在xml中改
private ConfigModel configModel=null;
/**
* 初始化所有的子控制器到当前的中央控制器中
*/
@Override
public void init() throws ServletException {
//在集合中就有了一个子控制器
//actions.put("/book", new BookAction());
//缺陷显示
//actions.put("/goods",new GoodsAaction());
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 {
//把子控制器与浏览器请求关联起来,“寻找”能够处理请求的子控制器
/**
* 思路
* 1、uri-->book
* 2、通过/book字符串在actions找到BookAction
* 3、调用BookAction的add,想要调用add,实际上只要统一调用execute就可以了
*/
//获取到浏览器的请求地址
String uri = req.getRequestURI();
uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
//通过/book字符串在actions找到BookAction
//ActionSupport action = actions.get(uri);
//原来在Map中寻找子控制器-->在配置文件中寻找子控制器
/**
* 1、通过/book找到对应的ActionModel对象
* 2、通过ActionModel对象拿到类的全路径名com.zxy.servlet.BookAction
* 3、反射实例化对象
*/
ActionModel actionModel = configModel.pop(uri);
String type = actionModel.getType();
ActionSupport action;
try {
action = (ActionSupport) Class.forName(type).newInstance();
action.execute(req, resp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//不需要在代码中动,在xml中动
<?xml version="1.0" encoding="UTF-8"?>
<config>
<!--
在这里每加一个配置,就相当于actions.put("/goods",new GoodsAaction());
这样就解决了代码灵活性的问题
-->
<action path="/book" type="com.zxy.servlet.BookAction">
<forward name="list" path="/bookList.jsp" redirect="false" />
<forward name="toEdit" path="/bookEdit.jsp" redirect="true" />
</action>
<action path="/goods" type="com.zxy.servlet.GoodsAction">
<forward name="failed" path="/login.jsp" redirect="false" />
<forward name="success" path="/main.jsp" redirect="true" />
</action>
<action path="/order" type="com.zxy.servlet.OrderAction">
<forward name="failed" path="/login.jsp" redirect="false" />
<forward name="success" path="/main.jsp" redirect="true" />
</action>
</config>
?④、子控制器(Action接口)
package com.zxy.framework;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 子控制器
*他来处理浏览器请求
*针对于add/ref进行向上抽取、抽象 abstract
*/
public interface Action {
//这个方法就是add/ref进行向上抽取的方法
//作用:能够处理浏览器的“所有”请求,包括add/ref
public void execute(HttpServletRequest req,HttpServletResponse resp);
// private void add(HttpServletRequest req, HttpServletResponse resp) {
// System.out.println("--增加--");
//
// }
//
// private void ref(HttpServletRequest req, HttpServletResponse resp) {
// System.out.println("--ref--");
//
// }
}
?⑤、ActionSupport(实现Action接口)
package com.zxy.framework;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 作用:能够处理浏览器的“所有”请求,包括add/ref
*
*/
public class ActionSupport implements Action{
@Override
public void execute(HttpServletRequest req, HttpServletResponse resp) {
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();
}
}
}
⑥、BookAction (继承ActionSupport)
package com.zxy.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.mwy.framework.ActionSupport;
public class BookAction extends ActionSupport{
//从父类继承了execute方法,就把反射动态调用方法的代码继承过来了
//BookAction-->BookServlet
//BookAction/GoodsAction/OrderAction...
//当前子控制器在哪里调用?把子控制器与浏览器请求关联起来
//以下只需要关注业务
private void add(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("--增加--");
}
private void list(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("--查询--");
}
private void ref(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("--ref--");
}
private void goods(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("--购物--");
}
}
?⑦、测试界面
中央控制器及子控制器优化
<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=ref">关联查询</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=goods">购物</a>
③、④、⑤、⑥、⑦所形成的界面及结果
?
?
3、实体类参数接受代码冗余?
?①、Book(实体类)
package com.zxy.entity;
public class Book {
private String bid;
private String bname;
private String price;
private String athor;
private 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.zxy.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.zxy.servlet.BookAction;
import com.zxy.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.zxy.framework;
import org.apache.commons.beanutils.BeanUtils;
import com.zxy.entity.Book;
/**
* 模型驱动接口作用,帮助中央控制器完成参数封装工程
* BeanUtils.populate(bean, req.getParameterMap());相当于下面代码
* 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"));
* @param <T>
*/
public interface ModelDriver<T> {
/**
* GoodsAction-->goods
* BookAction-->book
* @return
*/
T getModel();
}
④、?BookAction (extends ActionSupport implements ModelDriver<Book>)
package com.zxy.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zxy.entity.Book;
import com.zxy.framework.ActionSupport;
import com.zxy.framework.ModelDriver;
public class BookAction extends ActionSupport implements ModelDriver<Book>{
//从父类继承了execute方法,就把反射动态调用方法的代码继承过来了
//BookAction-->BookServlet
//BookAction/GoodsAction/OrderAction...
//当前子控制器在哪里调用?把子控制器与浏览器请求关联起来
Book book=new Book();
//以下只需要关注业务
private void add(HttpServletRequest req, HttpServletResponse resp) {
// 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);
System.out.println("--增加--");
}
@Override
public Book getModel() {
// TODO Auto-generated method stub
return 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="xs">
书籍价格<input type="text" name="price" value="45">
书籍作者<input type="text" name="athor" value="xx">
书籍出版社<input type="text" name="publish" value="sss">
<input type="submit">
</form>
①、②、③、④、⑤所形成的界面及结果
?
?4、关于结果页面的跳转(转发、重定向)?
1、2、3、4中所有的
①、中央控制器
package com.zxy.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.zxy.servlet.BookAction;
import com.zxy.servlet.GoodsAaction;
/**
* 中央控制器
*jsp:/book.action/goods.action
*
*/
@WebServlet("*.action")
public class DispatchServlet extends HttpServlet{
//在当前中央控制器中必然会有所有子控制器集合
//缺陷:如果有商品的增删改查-->意味着要改动代码-->代码的设计不够灵活
//思考:在不改动代码的情况下,中央控制器也能找到对应的子控制器去处理浏览器请求
//方案:我把加子控制器的逻辑/动作,放到配置文件中完成(Dbutil改连接信息是放在代码中完成/现在是放在Properties文件中完成)
//放在配置文件中完成的好处在于代码更加灵活,修改相关信息不用动代码
//ConfigModel对象又通过建模的知识,把所有的配置信息给读取过来了
//private Map<String, ActionSupport> actions=new HashMap<>();
private ConfigModel configModel=null;
/**
* 初始化所有的子控制器到当前的中央控制器中
*/
@Override
public void init() throws ServletException {
//在集合中就有了一个子控制器
//actions.put("/book", new BookAction());
//缺陷显示
//actions.put("/goods",new GoodsAaction());
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 {
//把子控制器与浏览器请求关联起来,“寻找”能够处理请求的子控制器
/**
* 思路
* 1、uri-->book
* 2、通过/book字符串在actions找到BookAction
* 3、调用BookAction的add,想要调用add,实际上只要统一调用execute就可以了
*/
//获取到浏览器的请求地址
String uri = req.getRequestURI();
uri = uri.substring(uri.lastIndexOf("/"), uri.lastIndexOf("."));
//通过/book字符串在actions找到BookAction
//ActionSupport action = actions.get(uri);
//原来在Map中寻找子控制器-->在配置文件中寻找子控制器
/**
* 1、通过/book找到对应的ActionModel对象
* 2、通过ActionModel对象拿到类的全路径名com.mwy.servlet.BookAction
* 3、反射实例化对象
*/
ActionModel actionModel = configModel.pop(uri);
String type = actionModel.getType();
ActionSupport action;
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 fm = actionModel.pop(res);
String path = fm.getPath();
boolean isRedirect = fm.isRedirect();
if(isRedirect) {
resp.sendRedirect(req.getContextPath()+path);
}else {
req.getRequestDispatcher(path).forward(req, resp);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
?
②、子控制器
package com.zxy.framework;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 子控制器
*他来处理浏览器请求
*针对于add/ref进行向上抽取、抽象 abstract
*/
public interface Action {
//这个方法就是add/ref进行向上抽取的方法
//作用:能够处理浏览器的“所有”请求,包括add/ref
//通过返回值来决定跳转哪一个页面(至于是重定向/转发由中央控制器来决定)
public String execute(HttpServletRequest req,HttpServletResponse resp);
}
?③、ActionSupport?
package com.zxy.framework;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 作用:能够处理浏览器的“所有”请求,包括add/ref
*/
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;
}
}
?④、BookAction?
package com.zxy.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.mwy.entity.Book;
import com.mwy.framework.ActionSupport;
import com.mwy.framework.ModelDriver;
public class BookAction extends ActionSupport implements ModelDriver<Book>{
//以下只需要关注业务
private String add(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("--增加--");
return "list";
}
private String toEdit(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("--toEdit--");
return "toEdit";
}
@Override
public Book getModel() {
// TODO Auto-generated method stub
return book;
}
}
?⑤、xml?
<?xml version="1.0" encoding="UTF-8"?>
<config>
<!--
在这里每加一个配置,就相当于actions.put("/goods",new GoodsAaction());
这样就解决了代码灵活性的问题
-->
<action path="/book" type="com.zxy.servlet.BookAction">
<forward name="list" path="/bookList.jsp" redirect="false" />
<forward name="toEdit" path="/bookEdit.jsp" redirect="true" />
</action>
<action path="/goods" type="com.zxy.servlet.GoodsAction">
<forward name="failed" path="/login.jsp" redirect="false" />
<forward name="success" path="/main.jsp" redirect="true" />
</action>
</config>
jsp跳转界面
测试
解决结果码页面跳转代码冗余问题
<a href="${pageContext.request.contextPath }/book.action?methodName=add">新增</a>
<a href="${pageContext.request.contextPath }/book.action?methodName=toEdit">去往编辑界面</a>
?
|