首页 > 代码库 > 自定义MVC框架
自定义MVC框架
一、实现自定义MVC的体系结构图
1、Model I模式开发Web应用时,分两种情况:
*纯JSP技术方式开发
*JSP+JavaBean方式开发
2、Model I模式开发的不足:
*JSP页面中嵌入大量的Java代码,可读性差。
*大量代码在JSP中难以复用。
*后期维护及扩展的难度大。
3、为了克服Model I模式的缺陷,引入了Model II的模式开发
*Model II模式体现了基于MVC(Model-View-Controller,模型-视图-控制器)的设计模式,简单的说,Model II模式就是将数据显示、流程控制和业务逻辑处理分离,使之相互独立。
4、MVC设计模式由3个部分组成各部分的作用。
*Model:模型,主要用于数据和业务的处理。
*View:视图,用于数据显示。
*Controller:控制器,用于流程控制。
5、MVC设计模式的特点
*一个模型可以对应多个视图。
*显示与逻辑控制分离。
*分层控制,减低了代码间的耦合。
二、我们如何创建一个自己的MVC框架??
(一)我们要在lib里面准备一个夹包
dom4j-1.6.1.jar 主要作用:解析xml文件
(二)准备配置文档(在src下)
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE myframework[ <!ELEMENT myframework (actions) > <!ELEMENT actions (action*)> <!ELEMENT action (result*)> <!ATTLIST action name CDATA #REQUIRED class CDATA #REQUIRED > <!ATTLIST result name CDATA #IMPLIED redirect (true|false) "false" >]>
解析:
<myframework> <actions> <action name="LoginAction" class="cn.happy.action.LoginAction"> <result name="success">success.jsp</result> <result name="login">index.jsp</result> </action> </actions></myframework>
解析:根据上述约束完成的“*”代表多次
(三)自己准备一个Action接口,用于放入结果集和执行方法
package cn.happy.action;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public interface Action {//定义字符串常量 public static final String SUCCESS="success"; public static final String NONE="none"; public static final String ERROR="error"; public static final String INPUT="input"; public static final String LOGIN="login";//准备一个方法,用于获取数据 public String execute(HttpServletRequest request,HttpServletResponse response)throws Exception; }
(四)定义一个ActionMapping用来存放Action节点
package cn.happy.action;import java.util.HashMap;import java.util.Map;/* * Action配置文件信息,用来放置Action的节点的 * */public class ActionMapping { //访问的Action的名称 private String name; //访问Action的对应的Action的类的全称 private String ClassName; //result定义的结果集 private Map<String,String> resultMaps=new HashMap<String,String>(); //往集合里面添加配置文件中的数据信息 public void addResult(String resultName,String result){ resultMaps.put(resultName, result); } //根据resultName获取对应的result页面 public String getResult(String resultName){ return resultMaps.get(resultName); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getClassName() { return ClassName; } public void setClassName(String className) { ClassName = className; } }
(五)准备一个ActionMappingManager是用来管理ActionMapping的
package cn.happy.action;import java.io.InputStream;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;/* * 用来管理ActionMapping也就是可以保存多个action节点信息 * * */public class ActionMappingManager { //保存多个action节点信息 private Map<String ,ActionMapping> actionMappings=new HashMap<String,ActionMapping>(); public ActionMapping getActionMapping(String name){ return actionMappings.get(name); } //带参构造 public ActionMappingManager(String[] configFileNames){ for(String filaName:configFileNames){ //调用根据文件名读取配置文件的方法 init(filaName); } } //解析xml public void init(String configFileName){ System.out.println("======init"); try { //读取配置文件,肯定用到了输入流 InputStream is=this.getClass().getResourceAsStream("/"+configFileName); //开始读取xml文件 Document doc=new SAXReader().read(is); //获取根节点 Element root=doc.getRootElement(); //获取Action节点 Element actions=(Element) root.elementIterator("actions").next(); //开始遍历Action节点 for(Iterator<Element>action=actions.elementIterator("action");action.hasNext();){ //获取到Action节点,将其属性进行封装 Element actionElement=action.next(); //获取name String name=actionElement.attributeValue("name"); //获取到ClassName String ClassName=actionElement.attributeValue("class"); //一个Action对应着一个ActionMapping,创建ActionMapping进行赋值 ActionMapping actionMapping=new ActionMapping(); actionMapping.setName(name); actionMapping.setClassName(ClassName); //遍历Action的子元素result for(Iterator<Element> result=actionElement.elementIterator("result");result.hasNext();){ Element resultElement=result.next(); //获取result属性值 String resultName=resultElement.attributeValue("name"); String resultValue=resultElement.getText(); //将每个result封装 到ActionMapping中去 actionMapping.addResult(resultName, resultValue); } //将ActionMapping放入ActionMappingManager中去 actionMappings.put(actionMapping.getName(),actionMapping); } } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
(六)利用反射机制找到自己的实列
package cn.happy.action;/* * 利用反射机制,根据类的类型获取到类的实列 * */public class ActionManager {public static Action creatAction(String className){ Class clazz=null; try { //判断当前线程是否有该Action clazz=Thread.currentThread().getContextClassLoader().loadClass(className); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(clazz==null){ try { //根据类的全路径,手动创建一个类的类类型 clazz=Class.forName(className); } catch (ClassNotFoundException e) { e.printStackTrace(); } } Action action=null; try { //根据类的类类型创建出一个类的实例 action=(Action) clazz.newInstance(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return action;}}
(七)写一个业务逻辑
package cn.happy.action;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class LoginAction implements Action { public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception { String name=request.getParameter("name"); String pwd=request.getParameter("pwd"); if("1".equals(name)&&"1".equals(pwd)){ return SUCCESS; }else{ return LOGIN; } }}
(八)写一个Servlet
package cn.happy.Servlet;import java.io.IOException;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import cn.happy.action.Action;import cn.happy.action.ActionManager;import cn.happy.action.ActionMapping;import cn.happy.action.ActionMappingManager;public class MVCServlet extends HttpServlet { /* 出品人:执念 */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } /* 出品人:执念 */ ActionMappingManager actionMappingManager=null; public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { //根据ActionName获取到ActionMapping ActionMapping actionMapping=actionMappingManager.getActionMapping(getActionName(request)); //根据ActionMapping中的ClassName获取到具体的类的实列 Action action=ActionManager.creatAction(actionMapping.getClassName()); //执行业务逻辑,获取到resultName String resultName=action.execute(request,response); //根据resultName获取具体的result视图 String result=actionMapping.getResult(resultName); //重定向到页面 response.sendRedirect(result); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //根据请求的上下文获取到ActionName public String getActionName(HttpServletRequest request){ //获取带URI String uri=request.getRequestURI(); //获取上下文路径 String contextPath=request.getContextPath(); //从上下文截取Actionpath String actionPath=uri.substring(contextPath.length()); //获取到ActionName String actionName=actionPath.substring(1,actionPath.lastIndexOf(‘.‘)).trim(); return actionName; } //在加载servlet的时候就读配置文件信息 @Override public void init(ServletConfig config)throws ServletException{ //读取配置信息 String configStr=config.getInitParameter("config"); String[] fileNames=null; if(configStr==null||configStr.isEmpty()){ fileNames=new String[]{"MyMvc.xml"}; }else{ fileNames=configStr.split(","); } //读取配置文件,将文件中的信息保存到ActionMappingManager中 actionMappingManager=new ActionMappingManager(fileNames); }}
(九)修改web.xml
<servlet-mapping> <servlet-name>MVCServlet</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping>
(十)准备一个login.jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <base href=http://www.mamicode.com/"<%=basePath%>"> <title>My JSP ‘index.jsp‘ starting page</title> </head> <body> <form action="LoginAction.action" method="post"> 用户名:<input type="text" name="name"/><br/> 密码:<input type="password" name="pwd"/><br/> <input type="submit" value=http://www.mamicode.com/"登录"/> </form> </body></html>
(十一)准备一个成功页面代码省略
总结:自定义的MVC模式
定义ActionMapping,是用来放置Action的节点的
定义ActionMappingManager,管理ActionMapping
定义ActionManager利用反射机制,找到具体类的实列
自定义MVC框架