1.思维导图部分
2.1问题(一)
需求:再次增加一个商品类增删查改
步骤:
改动init中代码
思考
能不能不改动代码完成这个需求
参考DBAccess的数据配置文件config.properties
1.减少代码改动的风险
2.减少代码的编译次数(对于已经部署到服务器后)
改成控制器可配置
一.配置文件config.xml
package com.dff.framework;
import java.io.InputStream;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
/**
* @author Administrator
*
*/
public class ConfigModelFactory {
public static ConfigModel build() throws Exception {
return build("config.xml");
}
public static ConfigModel build(String resourcepath) throws Exception {
InputStream in = ConfigModelFactory.class.getResourceAsStream(resourcepath);
SAXReader saxReader = new SAXReader();
Document doc = saxReader.read(in);
ConfigModel configModel = new ConfigModel();
List<Element> actionEles = doc.selectNodes("/config/action");
for (Element actionEle : actionEles) {
ActionModel actionModel = new ActionModel();
actionModel.setPath(actionEle.attributeValue("path"));
actionModel.setType(actionEle.attributeValue("type"));
List<Element> forwardEles = actionEle.selectNodes("forward");
for (Element forwardEle : forwardEles) {
ForwardModel forwardModel = new ForwardModel();
forwardModel.setName(forwardEle.attributeValue("name"));
forwardModel.setPath(forwardEle.attributeValue("path"));
forwardModel.setRedirect(!"false".equals(forwardEle.attributeValue("redirect")));
actionModel.push(forwardModel );
}
configModel.push(actionModel);
}
return configModel;
}
}
2.DispatchServlet(中央控制器中初始化地方法)
@Override
public void init() throws ServletException {
try {
configModel = ConfigModelFactory.build();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
使用mvc解决子控制器初始化问题运行结果
总结:1.必须有配置文件config.xml
2.配置文件config.xml中要包含处理业务的子控制器
3.读取到配置文件config.xml中对应的处理浏览器请求的子控制器
2.2问题二:(实体类参数封装问题)
2.2.1 在使用mvc封装参数之前对于
前端传参,实体类属性封装req.getparammeter("")代码 是重复的(有多少个参数就要封装多少次)
MVC封装参数代码
package com.dff.framework;
public interface ModelDriver<T> {
/**
* 是中央控制器来做实体类封装的
* @return
*/
T getModel();
}
.DispatchServlet(中央控制器中初始化地方法)
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//完成寻找子控制器
//浏览器:http://localhost:8080/javaEE_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("."));
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;
Object obj = m.getModel();
//接受所有的前端JSP传递到后台的参数
Map<String, String[]> parameterMap = req.getParameterMap();
//对 对象 赋值
//PropertyUtils.getProperty(obj, "")
BeanUtils.populate(obj, parameterMap);
}
解决封装属性方法后在原有属性上加了remark属性后运行结果前后对比
2.3问题三:(结果集代码重复问题)
缺陷:1.出现大量重复代码 2.不好管理(增删改重新跳转到查询界面)
处理前每跳转一次页面就要写一个跳转方法
解决方法 :在一个地方统一管理重定向还是转发,并且是定位跳转到哪一个页面
思路
1.方法执行完毕必须有一个返回值
2.通过返回值决定是否重定向,还是转发
package com.dff.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.dff.Servlet.BookAction;
import com.dff.Servlet.GoodsAction;
/**
* 目标:
* 根据自定义mvc框架的原理图 完成 框架地研发
* @author zjjt
* 中央控制器
* 寻找子控制器
*/
@WebServlet("*.action")
public class DispatchServlet extends HttpServlet{
//专门存放子控制器的容器
// private Map<String, ActionSupport> actions=new HashMap<String, ActionSupport>();
private ConfigModel configModel=null;
//初始化子控制器(集合),经过初始化,actions容器里面就有的子控制器
/**
* 需求:在增加一个商品类增删查改
* 步骤:
* 改动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) {
// 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/javaEE_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("."));
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;
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());
// System.out.println(req.getContextPath());
}else {
req.getRequestDispatcher(forwardModel.getPath()).forward(req, resp);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.通过返回值决定跳转哪一个页面
package com.dff.Servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.dff.entity.Book;
import com.dff.framework.ActionSupport;
import com.dff.framework.ModelDriver;
public class BookAction extends ActionSupport implements ModelDriver<Book>{
private Book book = new Book();
private String delete(HttpServletRequest req,HttpServletResponse resp) {
System.out.println("BookAction调用delete()");
/*
* 需求:删除数据后跳转到书籍展示页面
* 缺陷:1.出现大量重复代码 2.不好管理(增删改重新跳转到查询界面)
* 解决方案:在一个地方统一管理重定向还是转发,并且是定位跳转到哪一个页面
* 预测结果
* BookAction调用bookDao.delete()...
* BookAction调用bookDao.list()...
*
*/
return "toList";
}
@Override
public Book getModel() {
// TODO Auto-generated method stub
return book;
}
}