自定义MVC框架
我们在学习自定义MVC框架的时候常常会听到Model1 ,Model2和MVC。那么什么是Model1 什么是Model2什么又是MVC呢?
什么是Model1?
Model1就是一种纯jsp开发技术,将业务逻辑代码和视图渲染代码杂糅在一起。
什么是Model2?
Model2是在Model1的基础上,将业务逻辑的代码分离开来,单独形成一个Servlet,Model2也是基于MVC开发
什么是MVC框架?
MVC是三个单词的缩写,这三个单词分别为:模型(Model)、视图(View)和控制(Controller)。一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。
其实我们之前也使用过MVC的思想,我们在学习Model2也就是Servlet的时候,用的思想就是基于MVC开发思想
既然我们已经知道了MVC的作用,那么我们就可以开发自己的MVC框架了,就以我们之前学习的Struts2框架为例,定义一个自己的MVC框架
如何开发自己的MVC框架?
开发前的准备 jar包
一个就够了,该jar包的作用就是解析xml文件
第一步:准备配置文档
既然是框架,那肯定少不了的东西就是配置文件
我们配置一个xml文件,如下
<?xml version="1.0" encoding="UTF-8"?>
<!-- 定义我们的DOC约束文件 -->
<!-- 定义根节点 (包含元素)-->
<!-- ELEMENT 表示元素 -->
<!-- ATTLIST 表示属性 -->
<!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="action.LoginAction">
<result name="success">success.jsp</result>
<result name="input">index.jsp</result>
</action>
</actions>
</myframework>
第二步:我们准备自己的Action接口,用于存放结果集和要执行的方法
package 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 sponse)throws Exception;
}
第三步:定义一个ActionMapping用来存放Action节点
package action; import java.util.HashMap;
import java.util.Map; /*
* Action 的配置文件信息
* */
public class ActionMapping {
//访问的Action的名称
private String name;
//访问的Action的对应的Action的类全称
private String ClassName;
//result定义的结果集
private Map<String,String> resultMAp=new HashMap<String, String>(); //往集合里面添加配置文件中的数据信息
public void addResult(String resultName,String result){
resultMAp.put(resultName, result);
} //根据resultName获取对应的result页面
public String getResult(String resultName){
return resultMAp.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 action; import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map; import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; /*
* ActionMapping 的管理类
* */
public class ActionMappingManager {
/**管理ActionMapping 一个ActionMapping表示一个Action
* 但是我们配置文件中可能出现多个Action节点,所以我们需要一个ActionMapping的管理类
* */
private static Map<String,ActionMapping> actionMappings=new HashMap<String,ActionMapping>(); public ActionMappingManager() { }
//带参构造
public ActionMappingManager(String[] configFileNames){
for (String filaName : configFileNames) {
//调用根据文件名读取配置文件的方法
init(filaName);
}
} //根据Action名称获取到某一个具体的Action
public ActionMapping getActionMapping(String actionName){
//根据ActionName获取到Action
ActionMapping actionMapping=actionMappings.get(actionName);
return actionMapping;
} public void init(String configFileName){
try {
//读取配置文件,肯定用到了输入流
InputStream is=this.getClass().getResourceAsStream("/"+configFileName);
//开始读取xml文件
Document doc=new SAXReader().read(is);
//获取根节点
Element root=doc.getRootElement();
//获取Actions节点
Element actions = (Element)root.elementIterator("actions").next();
//开始遍历Actions节点
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 (Exception e) {
e.printStackTrace();
}
} }
第五步:利用反射机制,找到具体类的实例
package action;
/*
* 利用反射机制,根据类的类类型获取到类的实例
* */
public class ActionManager {
public static Action creatAction(String className){
Class clazz=null; try {
//判断当前线程是否有该Action
clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
} catch (ClassNotFoundException e) {
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;
}
}
第六步:写业务逻辑Action
package action; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class LoginAction implements Action { public String execute(HttpServletRequest request, HttpServletResponse sponse)
throws Exception {
//写具体的业务逻辑 return SUCCESS;
} }
第七步:准备Servlet
package 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 action.Action;
import action.ActionManager;
import action.ActionMapping;
import 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) {
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(,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[]{"myframework.xml"};
}else{
fileNames=configStr.split(",");
}
//读取配置文件,将文件中的信息保存到ActionMappingManager中
actionMappingManager=new ActionMappingManager(fileNames);
}
}
第八步:修改web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name></display-name>
<servlet>
<description>This is the description of my J2EE component</description>
<display-name>This is the display name of my J2EE component</display-name>
<servlet-name>MVCServlet</servlet-name>
<servlet-class>servlet.MVCServlet</servlet-class>
</servlet> <servlet-mapping>
<servlet-name>MVCServlet</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
</web-app>
测试页面(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="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head> <body>
<form action="loginAction.action" method="post">
用户名:<input type="text" name="uname"/><br/>
密码:<input type="password" name="pwd"/><br/>
<input type="submit" value="登录"/>
</form>
</body>
</html>
这样我们就完成了一个自定义的MVC框架了
自定义MVC框架的更多相关文章
- Struts2 自定义MVC框架
一.Model1与Model2: Model1:就是一种纯jsp开发技术,将业务逻辑代码和视图渲染代码杂糅在一起. Model2:Model2是在Model1的基础上,将业务逻辑的代码分离开来,单独形 ...
- 第一章 自定义MVC框架
第一章 自定义MVC框架1.1 MVC模式设计 组成:Model:模型,用于数据和业务的处理 View :视图,用于数据的显示 Controller:控制器 ...
- 自定义MVC框架之工具类-模型类
截止目前已经改造了5个类: ubuntu:通过封装验证码类库一步步安装php的gd扩展 自定义MVC框架之工具类-分页类的封装 自定义MVC框架之工具类-文件上传类 自定义MVC框架之工具类-图像处理 ...
- 自定义MVC框架之工具类-图像处理类
截止目前已经改造了4个类: ubuntu:通过封装验证码类库一步步安装php的gd扩展 自定义MVC框架之工具类-分页类的封装 自定义MVC框架之工具类-文件上传类 图像处理类: 1,图片加水印处理( ...
- 自定义MVC框架之工具类-文件上传类
截止目前已经改造了3个类: ubuntu:通过封装验证码类库一步步安装php的gd扩展 自定义MVC框架之工具类-分页类的封装 该文件上传类功能如下: 1,允许定制上传的文件类型,文件mime信息,文 ...
- Java Web自定义MVC框架详解 (转)
转自:http://blog.csdn.net/jackfrued/article/details/42774459 最近给学生讲Java Web,希望他们能够在学完这部分内容后自己实现一个MVC框架 ...
- 使用Intellij Idea自定义MVC框架
---恢复内容开始--- 今天我学习了自定义一个简单的MVC框架,这个我们首先要知道什么是MVC框架! MVC框架: MVC全名是Model View Controller,是模型(model)-视图 ...
- springmvc执行原理及自定义mvc框架
springmvc是spring的一部分,也是一个优秀的mvc框架,其执行原理如下: (1)浏览器提交请求经web容器(比如tomcat)转发到中央调度器dispatcherServlet. (2)中 ...
- struts2自定义MVC框架
自定义MVC:(首先了解Model1和Model2的概念) Model1与Model2: Model1:就是一种纯jsp开发技术,将业务逻辑代码和视图渲染代码杂糅在一起. Model2:Model2是 ...
随机推荐
- 关于EF6的记录Sql语句 与 EntityFramework.Extend 的诟病
1.关于EF6的记录Sql语句,一个老生长谈的问题. 他生成的sql语句实在是烂,大家都这样说 2.EF6 更新删除不方便,没有批量操作.所以,有人出了EF6.Extend 大家用起来也很爽 基于以 ...
- Java NIO1:I/O模型概述
I/O模型 在开始NIO的学习之前,先对I/O的模型有一个理解,这对NIO的学习是绝对有好处的.我画一张图,简单表示一下数据从外部磁盘向运行中进程的内存区域移动的过程: 这张图片明显忽略了很多细节,只 ...
- jws.mono脚本安装详解
就在最近两天,最新版本的jws.mono上线了,这个版本除了提供与之前版本拥有的功能外,还额外提供了一个“自动化”的安装脚本,通过执行该脚本,jws.mono将自动快速的安装到指定的目录,同时,通过改 ...
- Azure PowerShell (12) 通过Azure PowerShell创建SSH登录的Linux VM
<Windows Azure Platform 系列文章目录> 本章将介绍如何使用Azure PowerShell,创建SSH登录的Linux VM 前提要求: 1.安装Azure Pow ...
- removeClass 按钮点击添加class效果
html代码: <div class="game"> <span class="active">全部</span> < ...
- The transaction log for database 'tempdb' is full due to 'ACTIVE_TRANSACTION'
今天早上,Dev跟我说,执行query statement时出现一个error,detail info是: “The transaction log for database 'tempdb' is ...
- 前端学php之常量
× 目录 [1]定义常量 [2]常量检测 [3]系统常量[4]魔术常量 前面的话 常量在javascript中并不存在,在php中却是与变量并列的重要内容.常量类似变量,但常量一旦被定义就无法更改或撤 ...
- ViewStub的使用
ViewStub是一个不可见的.大小为0的控件,运行时ViewStub可以滞后加载.当ViewStub置为可见或者调用inflate()的时候,布局就会加载出来.用加载进来的布局取代ViewStub在 ...
- tomcat:there is no resources that can be added or removed from server
原因: 1.不是web project 解决方式:project-->property--project facet 新建或者修改 2. 版本不兼容 升级tomcat版本
- java 中多线程之间的通讯之生产者和消费者 (多个线程之间的通讯)
在真实开发 中关于多线程的通讯的问题用到下边的例子是比较多的 不同的地方时if 和while 的区别 如果只是两个线程之间的通讯,使用if是没有问题的. 但是在多个线程之间就会有问题 /* * 这个例 ...