![框架模式学习 ———— MVC - stanley - 小老头 框架模式学习 ———— MVC - stanley - 小老头](http://img0.ph.126.net/QBLaHHnCVomZjuUaKy4C6Q==/3139853365307985390.jpg)
- 定义配置文件dtd
<!-- 示例 -->
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT myMvc (actions)>
<!ELEMENT actions (action*)>
<!ELEMENT action (result*)>
<!ATTLIST action
name CDATA #REQUIRED
class CDATA #REQUIRED>
<!ELEMENT result (#PCDATA)>
<!ATTLIST result
name CDATA #IMPLIED
redirect (true|false) "false"> - 定义配置文件
<!-- 创建一个使用刚创建的dtd的配置文件 -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE myMvc PUBLIC "-//UNKOWN/" "mymvc.dtd"><!--此处引用上面的自定义dtd-->
<myMvc>
<actions>
<action name="login" class="cn.stanley.action.LoginAction">
<result name="success">pages/success.jsp</result>
<result name="input">pages/login.jsp</result>
</action>
<action name="regist" class="cn.stanley.action.LoginAction">
<result name="success">pages/success.jsp</result>
<result name="input">pages/login.jsp</result>
</action>
</actions>
</myMvc> - 创建 请求——操作 映射类
/**
* 映射 响应结果与视图之间的关系
*/
public class ResultMapping {
private String name;
private boolean redirect;
private String path;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isRedirect() {
return redirect;
}
public void setRedirect(boolean redirect) {
this.redirect = redirect;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public ResultMapping(){}
public ResultMapping(String name, boolean redirect, String path) {
super();
this.name = name;
this.redirect = redirect;
this.path = path;
}
}/**
* 映射 请求与处理请求方法之间的关联
*/
public class ActionMapping {
private String name;
private String className;
private Map<String,ResultMapping> resultMap=new HashMap<String, ResultMapping>(0);
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public Map<String, ResultMapping> getResultMap() {
return resultMap;
}
public void setResultMap(Map<String, ResultMapping> resultMap) {
this.resultMap = resultMap;
}
public ActionMapping(String name, String className) {
super();
this.name = name;
this.className = className;
}
public ActionMapping(){}
public void addResult(ResultMapping result){
this.resultMap.put(result.getName(), result);
}
} - 创建 配置文件解析类,解析配置文件并生成 请求——操作的映射对象
/**
* 解析配置文件生成相就的映射对象 ,并管理
*/
public class ActionMappingManager {
private Map<String, ActionMapping> actionMappings =new HashMap<String, ActionMapping>();
public ActionMappingManager(String[] configFileNames) {
for (String configFileName : configFileNames) {
try {
init(configFileName);
} catch (DocumentException e) {
e.printStackTrace();
}
}
}
@SuppressWarnings("rawtypes")
public void init(String configFileName)throws DocumentException {
// dom4j 解析器
SAXReader reader = new SAXReader();
// 设置 dtd 解析器 此片因为是自定义dtd,所以写了一个FindDTD类设定dtd
reader.setEntityResolver(new FindDTD());
//读取根节点
Document document = reader.read(DocumentException.class
.getResourceAsStream("/" + configFileName));
//子节点集合
List nodes = document.getRootElement().element("actions")
.elements("action");
//遍楞子节集合
for (Iterator iterator = nodes.iterator();iterator.hasNext();) {
Element node = (Element) iterator.next();
ActionMapping acm = new ActionMapping( node.attributeValue("name"),node.attribute("class").getValue());
// 遍历 result
for (Iterator it2 = node.elements("result").iterator(); it2.hasNext();) {
Element ele = (Element) it2.next();
String name = ele.attributeValue("name");
boolean redirect =Boolean.valueOf(ele.attributeValue("redirect"));
String path = ele.getText();
acm.addResult(new ResultMapping(name, redirect, path));
}
actionMappings.put(acm.getName(), acm);
}
}
/**
* 根据 请求中的 actionName 取 ActionMapping
*
* @param actionName
* @return
* @throws Exception
*/
public ActionMapping getActionMapping(String actionName) {
if (null == actionName || actionName.isEmpty()) {
return null;
}
ActionMapping mapping = actionMappings.get(actionName);
if (mapping == null) {
throw new RuntimeException("不存在此mapping:" +actionName);
}
return mapping;
}
}/**
* 自定义DTE 解析器,因为是自定义DTD,web容器会默认在bin目录下找,
* 而指定相对路径与绝对路径都不能正确获取,所以得自定义
*/
public class FindDTD implements EntityResolver {
@Override
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
//自已的dtd所在的位置
String path = "mymvcframework/" +systemId.substring(systemId.lastIndexOf("/")+1);
InputStream in=this.getClass().getClassLoader()
.getResourceAsStream(path);
InputSource so=new InputSource(in);
return so;
}
} - 定义 action 接口
/**
* Action 接口
* @author Administrator
*
*/
public interface Action {
/**
* 执行 业务与 数据 访问操作
* @param req
* @param res
* @return
* @throws Exception
*/
String execute(HttpServletRequest req, HttpServletResponse res)
throws Exception;
}
- 创建 controller
/**
* 这是整个mvc框加的核心
*/
public class ActionFilter implements Filter {
/**
* actionMappingManager 实例
*/
private ActionMappingManager mappingManage;
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
//请求类型转换
HttpServletRequest hreq = (HttpServletRequest) req;
HttpServletResponse hres = (HttpServletResponse) res;
//获取 动作映射
ActionMapping aMapping=null;
try {
aMapping = getActionMapping(hreq, hres);
} catch (Exception e1) {
throw new RuntimeException(e1);
}
if (null == aMapping) {
throw new RuntimeException("资源不存在");
}
//创建 动作对象 并执行
Action action = ActionFactory.createAction(aMapping.getClassName());
String resultName = null;
try {
resultName = action.execute(hreq, hres);
} catch (Exception e) {
e.printStackTrace();
}
if (resultName == null) {
throw new RuntimeException("结果视图不存在");
}
//取出 结果映射
ResultMapping result = aMapping. getResultMap().get(resultName);
//判断 结果映射 晌应方式
if (result.isRedirect()) { //重定向
hres.sendRedirect(result.getPath());
} else { //转发
req.getRequestDispatcher(result.getPath())
.forward(req, res);
}
}
/**
* 初始化操作 :: 读取web.xml 中的 初始参数配置 ,* 创建 ActionMappingManager 类
*/
@Override
public void init(FilterConfig config) throws ServletException {
//获取配置参数 config
String conStr=config.getInitParameter("config");
//配置的文件名数组
String[] configFileNames=null;
if(conStr==null|| conStr.isEmpty()){
}else{
configFileNames=conStr.split(",");
}
// 创建 actionMappingManager 类
this.mappingManage=new ActionMappingManager(configFileNames);
}
/**
* 获取动作
* @param req
* @param res
* @return
* @throws Exception
*/
private ActionMapping getActionMapping(HttpServletRequest req,
HttpServletResponse res) throws Exception {
//获取 uri
String url = req.getRequestURI();
//获取应用名
String contextPath = req.getContextPath();
//获取 *.action...
String actionPath = url.substring(contextPath.length());
//获取 *.action 中 的 * 部分
String actionName = actionPath
.substring(1, actionPath.lastIndexOf("."));
// 返加 actionMapping
return mappingManage.getActionMapping(actionName);
}
}
/**
* 此处用一个返射工厂来创建Action实例
*/
public class ActionManager {
public static Action createAction(String className){
try {
return (Action) Class.forName(className).newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
} - 将控制器配置到 web.xml中
3、模型的可移植性。因为模型是独立于视图的,所以可以把一个模型独立地移植到新的平台工作。需要做的只是在新平台上对视图和控制器进行新的修改。
1、增加了系统结构和实现的复杂性。对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。
2、视图与控制器间的过于紧密的连接。视图与控制器是相互分离,但确实联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。
3、视图对模型数据的低效率访问。依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。