MyMVC框架说明
* 本框架起源于课堂教学实践,目的在于提高学有余力的学生提高对Java的理解。
*MyMVC Framework目前暂时版本为1.0,可以快速的构建我们自己的MVC Web应用程序。
*其特点是整个应用只有一个核心Servlet,用户只需要实现Action接口就可以了,允许用
*户完全以POJO的方式开发MVC Web应用;同时并不限制用户POJO以及业务逻辑的选择,
*框架对表单使用用户自定义类进行了封装,用户需要强制类型转换为具体类型拆出数据。
*整体上MyMVC Framework实现的比较简洁,功能也比较简单,但对MVC的实现很透彻,
*值得研究与学习,同时本框架可以被读者修改与改进。
*
* 2008年8月2日
* 段尚林
1.核心控制器CenterController:
package com.mymvc.action;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import com.mymvc.sys.ActionMapping;
import com.mymvc.sys.SysConfig;
/**
* <pre>
* MyMVC框架说明
*
* 本框架起源于课堂教学实践,目的在于提高学有余力的学生提高对Java的理解。
*MyMVC Framework目前暂时版本为1.0,可以快速的构建我们自己的MVC Web应用程序。
*其特点是整个应用只有一个核心Servlet,用户只需要实现Action接口就可以了,允许用
*户完全以POJO的方式开发MVC Web应用;同时并不限制用户POJO以及业务逻辑的选择,
*框架对表单使用用户自定义类进行了封装,用户需要强制类型转换为具体类型拆出数据。
*整体上MyMVC Framework实现的比较简洁,功能也比较简单,但对MVC的实现很透彻,
*值得研究与学习,同时本框架可以被读者修改与改进。
*
* 2008年8月2日
* 段尚林
*
* </pre>
*
*
*
* <h1><font color="blue">MyMVC Framework</font></h1>
* <p>
* 本类是MyMVC框架的核心控制器,<br>
* 其职责是寻找mymvc.xml文件的位置,接着初始化SysConfig类并加载系统配置信息
* </p>
*
* @version 1.0
* @author <a href="http://closer1984.blog.edu.cn">段尚林</a>
*
*/
public class CenterController extends HttpServlet {
private static List<ActionMapping> mappings;
private static String configLocation;
private static Action action;
/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
/**
* <p>
* 系统初始化方法
* </p>
*
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
public void initSysConfig(HttpServletRequest request, String configLocation)
throws ServletException, IOException {
mappings = SysConfig.loadSysConfig(configLocation);// 加载配置信息
// 将配置数据设置到ServletContext中,避免重复解析配置文件,从而提高效率
}
public void process(HttpServletRequest request, HttpServletResponse response)
throws Exception{
request.setCharacterEncoding("gbk");
response.setCharacterEncoding("gbk");
if (mappings == null)
{
// 获得配置文件的路径
configLocation = request.getRealPath(configLocation);
//configLocation = request.getRealPath("/WEB-INF/mymvc.xml");
initSysConfig(request, configLocation);
System.out.println("CenterController:\t"+new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date())+"\t"+"系统正在读取配置信息...");
}
String url = request.getRequestURI();
String requestPath = url.substring(url.lastIndexOf("/"));
Iterator it = mappings.iterator();
while (it.hasNext()) {
ActionMapping mapping = (ActionMapping) it.next();
String path = mapping.getPath();
Action actionMapping = mapping.getAction();
Map<String, String> forwards = mapping.getActionForwards();
Iterator fit = forwards.keySet().iterator();
while (fit.hasNext()) {
String forwardName = (String) fit.next();
String forwardPath = forwards.get(forwardName);
if (requestPath.equals(path)) {
action = actionMapping;
Map<String, String> form=mapping.getForm();
Iterator formKeyIt=form.keySet().iterator();
String formName = "";
String formClass = "";
String formScope = "";
while(formKeyIt.hasNext())
{
String key=(String) formKeyIt.next();
if(key.equals("form-name")){
formName=(String) form.get(key);
}
if(key.equals("form-class")){
formClass=(String)form.get(key);
}
if(key.equals("scope")){
formScope=(String) form.get(key);
}
}
//
//1获得请求参数集合,并设置到formBean中1.0
//2获得请求参数集合,并设置到用户自定义的Object中2.0
Enumeration requestNames=request.getParameterNames();
Map requestMap=request.getParameterMap();
Object userBean=null;
if(formClass!=null && !formClass.equals(""))
{
//反射获得用户自定义的JavaBean对象
userBean=Class.forName(formClass).newInstance();
}
Map<String,Object> formMap=new HashMap<String,Object>();//封装表单数据
while(requestNames.hasMoreElements())
{
String key=(String) requestNames.nextElement();
//可能包含字符串数组
request.getParameterMap();
String[] values=(String[]) requestMap.get(key);
System.out.println("读取请求参数的值:\t"+"key:"+key+"\t value:"+values[0]);
if(values.length==1){
formMap.put(key, values[0]);
BeanUtils.setProperty(userBean, key, values[0]);
}else{
formMap.put(key, values);
BeanUtils.setProperty(userBean, key, values);
}
}
//将用户的表单Bean放到用户设置的范围中去
if(formScope.equals("request"))
{
request.setAttribute(formName, userBean);
}else if(formScope.equals("session")){
request.getSession().setAttribute(formName,userBean);
}
//String des = action.execute(request, response,formMap);// 返回页面逻辑名
String des = action.execute(request, response,userBean);// 返回页面逻辑名
//
if (!forwardName.equals(des)) {
continue;
}
request.getRequestDispatcher(forwardPath).forward(request,
response);
}
}
}
}
// public void doGet(HttpServletRequest request, HttpServletResponse response)
// throws ServletException, IOException {
// this.doPost(request, response);
// }
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try{
process(request, response);
}catch(Exception e){
e.printStackTrace();
}
}
/**
* Initialization of the servlet. <br>
*
* @throws ServletException
* if an error occure
*/
public void init(ServletConfig config) throws ServletException {
// Put your code here
configLocation=config.getInitParameter("config");
}
}
2.XML文件解析类SysConfig :
package com.mymvc.sys;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.mymvc.action.Action;
/**
* <h1><font color="blue">MyMVC Framework</font></h1>
* <p>本类的职责是读取系统配置文件mymvc.xml</p>
* @version 1.0
* @author <a href="http://closer1984.blog.edu.cn">段尚林</a>
*
*/
public class SysConfig {
public SysConfig() {
// TODO 自动生成构造函数存根
}
public static List<ActionMapping> loadSysConfig(String configLocation) {
List<ActionMapping> list = new ArrayList<ActionMapping>();
try {
DocumentBuilderFactory DBfactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder DBbuilder = DBfactory.newDocumentBuilder();
Document doc = DBbuilder.parse(configLocation);
NodeList mappingList = doc.getElementsByTagName("action-mapping");
for (int i = 0; i < mappingList.getLength(); i++) {
Node mappingNode = mappingList.item(i);
ActionMapping mapping = new ActionMapping();
NodeList mappingChildren = mappingNode.getChildNodes();// 获得mapping节点的子节点
for (int j = 0; j < mappingChildren.getLength(); j++) {
Node node = mappingChildren.item(j);
if (node.getNodeName().equals("path")) {
String path = node.getTextContent().trim();
mapping.setPath(path);
}
if (node.getNodeName().equals("type")) {
String type = node.getTextContent().trim();
mapping.setAction((Action) Class.forName(type)
.newInstance());
}
if (node.getNodeName().equals("form")) {
NodeList formChildren = node.getChildNodes();// 获得form节点的子节点
Map<String, String> form = new HashMap<String, String>();
String formName = "";
String formClass = "";
String formScope = "";
for (int k = 0; k < formChildren.getLength(); k++) {
Node fnode = formChildren.item(k);
if (fnode.getNodeName().trim().equals("form-name")) {
formName = fnode.getTextContent().trim();
form.put("form-name",formName);
}
if (fnode.getNodeName().trim().equals("form-class")) {
formClass = fnode.getTextContent().trim();
form.put("form-class", formClass);
}
if (fnode.getNodeName().trim().equals("scope")) {
formScope = fnode.getTextContent().trim();
form.put("scope",formScope);
}
}
System.out.println("form-name:"+formName+"\t form-class:"+formClass+"\t formScope:"+formScope);
mapping.setForm(form);
}
if (node.getNodeName().equals("forwards")) {
NodeList forwardList = node.getChildNodes();
Map<String, String> forward = new HashMap<String, String>();
for (int m = 0; m < forwardList.getLength(); m++) {
// 获得forward节点的子元素
NodeList forwardChild = forwardList.item(m)
.getChildNodes();
String forwardName = "";
String forwardPath = "";
for (int n = 0; n < forwardChild.getLength(); n++) {
Node forNode = forwardChild.item(n);
if(forNode.getNodeName().equals("forward-name"))
{
forwardName=forNode.getTextContent().trim();
}
if(forNode.getNodeName().equals("forward-path"))
{
forwardPath=forNode.getTextContent().trim();
}
forward.put(forwardName, forwardPath);
}
}
mapping.setActionForwards(forward);
}
}
list.add(mapping);
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
}
3.操作映射类ActionMapping:
package com.mymvc.sys;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.mymvc.action.Action;
/**
* <h1><font color="blue">MyMVC Framework</font></h1>
* <p>
* 本类是MyMVC框架的操作映射类,<br>
* </p>
* @version 1.0
* @author <a href="http://closer1984.blog.edu.cn">段尚林</a>
*
*/
public class ActionMapping {
private String path;//action的路径
private Action action;//用户自定义操作Action
private Map<String,String> form=new HashMap<String,String>();//表单bean配置信息,如别名、类全名、范围
//页面跳转集合,MAP的键是页面逻辑名,值是具体路径
private Map<String,String> forwards=new HashMap<String,String>();
public ActionMapping() {
// TODO 自动生成构造函数存根
}
public Map<String, String> getActionForwards() {
return forwards;
}
public void setActionForwards(Map<String, String> actionForwards) {
this.forwards = actionForwards;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Action getAction() {
return action;
}
public void setAction(Action action) {
this.action = action;
}
public Map<String, String> getForm() {
return form;
}
public void setForm(Map<String, String> form) {
this.form = form;
}
public Map<String, String> getForwards() {
return forwards;
}
public void setForwards(Map<String, String> forwards) {
this.forwards = forwards;
}
}
4.需要用户实现的接口Action:
package com.mymvc.action;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* <h1><font color="blue">MyMVC Framework</font></h1>
* <p>
* 本接口是MyMVC框架的用户自定义控制器接口<br>
* </p>
*
* @version 1.0
* @author <a href="http://closer1984.blog.edu.cn">段尚林</a>
*
*/
public interface Action
{
/**
*
* @param reqest
* @param response
* @param userBean 表单数据封装后使用反射处理后的 用户自定义对象
* @return 页面跳转的逻辑名
*/
public String execute(HttpServletRequest reqest,HttpServletResponse response,Object userBean);
}