论坛首页 Java企业应用论坛

框架初试,一个粗略mvc框架。模仿webwork

浏览 8774 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-05-10  

我写的这个框架大致模仿webwork的原理。我只用过webwork一个框架,当然模仿它了^^

主要是为了学习,苦思冥想写出来了。把它帖出来,大家多给我一些意见。

在我的框架里面出现大量的sophie是我的名字,呵呵,女性写的代码命名也比较女性化吧*^_^*

 

Sophie的web框架
主要思路
Init配置文件-》dispatcher调度-》invocation执行action=》result处理结果,显示页面
 
主要功能部分
1.       调度器,在启动服务的时候调用init方法,初始化action的配置文件。保存servlet的内容到SophieContext 中dispatcher
2.       和resultConfiguration模型,把配置文件中的action信息,封装到一个configration类中。多个action信息组成一个map。每个action的result信息,封装到resultConfiguration中,多个result组成一个map.configuration
3.       类。逻辑的东西可以写在action中。Action类从servlet中分离出来。专注与逻辑本身。提供给框架的使用者。action
4.       保存context的类。里面有个静态的map。SophieContext
5.       执行actionSophieInvocation
6.       处理action执行的结果,根据resultConfiguration里的配置,转向显示页面。sophieResult
7.       标签,可以在页面上用标签调用actionActionTag action
代码详细说明

1)SophieDispatcher是一个servlet,init()方法中初始化一些配置文件。

service()方法中执行action

 

SophieDispatcher 代码
  1. package com.sophie.dispatcher;   
  2.   
  3. import java.io.IOException;   
  4. import java.util.HashMap;   
  5. import java.util.Iterator;   
  6. import java.util.Map;   
  7. import java.util.Set;   
  8.   
  9. import javax.servlet.ServletConfig;   
  10. import javax.servlet.ServletContext;   
  11. import javax.servlet.ServletException;   
  12. import javax.servlet.http.HttpServlet;   
  13. import javax.servlet.http.HttpServletRequest;   
  14. import javax.servlet.http.HttpServletResponse;   
  15.   
  16. import com.sophie.context.ConfigUtil;   
  17. import com.sophie.context.Configuration;   
  18. import com.sophie.context.SophieContext;   
  19. import com.sophie.parameter.Parameter;   
  20.   
  21. public class SophieDispatcher extends HttpServlet {   
  22.     @Override  
  23.     protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {   
  24.         /*  
  25.          * 因为进入该servlet的不是来至对该servelt本身的请求,(eg:test.action)所以这里用getServletConfig()得不到ServletConfig,从而无法得到ServletContext  
  26.          *保存servlet中的信息到自己定义的SophieContext对象中,备用  
  27.          */  
  28.         Map parametersMap=request.getParameterMap();   
  29.         setParamtersMap(request, parametersMap);   
  30.         SophieContext.setRequest(request);   
  31.         SophieContext.setResponse(response);   
  32.            
  33.         //根据url得到actionName   
  34.         String actionName=getActionName(request);   
  35.            
  36.         //执行action   
  37.         SophieInvocation invocation=new SophieInvocation(actionName);   
  38.         String resultString=invocation.execute();   
  39.         ResultDispatcher resultDispatcher=new ResultDispatcher(invocation.getResultConfigMap(),resultString);   
  40.         resultDispatcher.Dispatcher();   
  41.     }   
  42.        
  43.     @Override  
  44.     /*  
  45.      * init sophieContext  
  46.      */  
  47.     public void init(ServletConfig config) throws ServletException {   
  48.         ServletContext context=config.getServletContext();   
  49.         /*  
  50.          * 更改于2007-5-10  
  51.          * 1.把备置文件读出以后保存在对象里面,而不再是数组里面  
  52.          * 2.把配置文件的map保存在sophieContext里面而不是servletContext里面  
  53.          *  init the action and result map   
  54.          * Map map=new HashMap();  
  55.          * map=PropertiesUtil.convertPropertyFileToMap(PropertiesUtil.ACTION_PROPERTIES);  
  56.          * context.setAttribute(SophieStatic.ACTION_RESULT_MAP, configMap);  
  57.          */  
  58.   
  59.         Map configMap=new HashMap();   
  60.         configMap=ConfigUtil.initConfigurationMap();   
  61.            
  62.         SophieContext.setServletContext(context);   
  63.         SophieContext.setConfigurationMap(configMap);   
  64.         System.out.println("===init====");   
  65.     }   
  66.        
  67.     //把parameter放到一个map中并存入SophieContext的map中备用   
  68.     private void setParamtersMap(HttpServletRequest request,Map parametersMap){   
  69.         Parameter parm=new Parameter();   
  70.         Set entrySet=parametersMap.entrySet();   
  71.         Map map=new HashMap();   
  72.         for (Iterator iter = entrySet.iterator(); iter.hasNext();) {   
  73.             Map.Entry entry=(Map.Entry)iter.next();   
  74.             parm.setName((String)entry.getKey());   
  75.             parm.setValue((String[])entry.getValue());   
  76.             map.put((String)entry.getKey(), parm);   
  77.         }   
  78.         SophieContext.setRequestParametersMap(map);   
  79.     }   
  80.        
  81.     //分析uri得到action的name   
  82.     private String getActionName(HttpServletRequest request){   
  83.         String uri=request.getRequestURI();   
  84.         String actionName=uri.substring(uri.lastIndexOf("/")+1, uri.indexOf(".action"));   
  85.         return actionName;   
  86.     }   
  87.        
  88.        
  89.   
  90. }   

 

2)SophieContext 保存servlet中的信息,如servletContext,requet,response

java 代码
  1. package com.sophie.context;   
  2.   
  3. import java.util.HashMap;   
  4. import java.util.Map;   
  5.   
  6. import javax.servlet.ServletContext;   
  7. import javax.servlet.http.HttpServletRequest;   
  8. import javax.servlet.http.HttpServletResponse;   
  9.   
  10. import com.sophie.parameter.Parameter;   
  11.   
  12. public class SophieContext {   
  13.        
  14.   
  15.     //save actioncontext to a map   
  16.     private  static Map context=new HashMap();   
  17.        
  18.     //private static SophieContext sophieContext;   
  19.        
  20.     private SophieContext(){   
  21.            
  22.     }   
  23.        
  24.     /*  
  25.      * 在后面的使用中,好像没有体现单例的作用,因为context已经是static了,不管是不是单例,context都是唯一的,  
  26.      * 所以把所有的方法都改成静态的  
  27.      */  
  28.     /*public static SophieContext getInstance(){  
  29.         if(null==sophieContext){  
  30.             sophieContext=new SophieContext();  
  31.         }  
  32.         return sophieContext;  
  33.     }*/  
  34.   
  35.     public static Map getContext() {   
  36.         return context;   
  37.     }   
  38.   
  39.     //  get httpServletResponse   
  40.     public static HttpServletRequest getRequest(){   
  41.         return (HttpServletRequest)getContext().get(SophieStatic.HTTP_REQUEST);   
  42.     }   
  43.        
  44.     public static void setRequest(HttpServletRequest request){   
  45.         getContext().put(SophieStatic.HTTP_REQUEST, request);   
  46.     }   
  47.        
  48.     //get httpServletResponse   
  49.     public static HttpServletResponse getResponse(){   
  50.         return (HttpServletResponse)getContext().get(SophieStatic.HTTP_RESPONSE);   
  51.     }   
  52.        
  53.     public static void setResponse(HttpServletResponse response){   
  54.         getContext().put(SophieStatic.HTTP_RESPONSE, response);   
  55.     }   
  56.        
  57.     /*  
  58.      * save ServletContext  
  59.      */  
  60.     public static void setServletContext(ServletContext servletContext){   
  61.         getContext().put(SophieStatic.SERVLET_CONTEXT, servletContext);   
  62.     }   
  63.        
  64.     //get servletContext   
  65.     public static ServletContext getServletContext(){   
  66.         return (ServletContext)getContext().get(SophieStatic.SERVLET_CONTEXT);   
  67.     }   
  68.        
  69.     /*  
  70.      * save action config map  
  71.      */  
  72.     public static void setConfigurationMap(Map configMap){   
  73.         getContext().put(SophieStatic.SOPHIE_ACTION_CONFIG_MAP, configMap);   
  74.     }   
  75.        
  76.     @SuppressWarnings("unchecked")   
  77.     public static Map getConfigurationMap(){   
  78.         return (Map)getContext().get(SophieStatic.SOPHIE_ACTION_CONFIG_MAP);   
  79.     }   
  80.        
  81.     /*  
  82.      * get the parameters from httpservletRequest   
  83.      */  
  84.     public static void setRequestParametersMap(Map parametersMap){   
  85.         getContext().put(SophieStatic.PARAMETERS_MAP, parametersMap);   
  86.     }   
  87.        
  88.     @SuppressWarnings("unchecked")   
  89.     /*  
  90.      * get the parameters    
  91.      */  
  92.     public static Map getRequestParametersMap(){   
  93.         return (Map)getContext().get(SophieStatic.PARAMETERS_MAP);   
  94.     }   
  95.        
  96. }  

 

3)Configuration, ResultConfiguration两个类是两个model,封装备置文件中action的属性信息

java 代码
  1. /*  
  2.  * author sophie dong 2007-5-10  
  3.  * action config object  
  4.  */  
  5. package com.sophie.context;   
  6.   
  7. import java.util.Map;   
  8.   
  9. public class Configuration {   
  10.   
  11.     private String actionName;   
  12.   
  13.     private String className;   
  14.   
  15.     private String methodName;   
  16.   
  17.     private Map resultMap;   
  18.   
  19. //get set……   
  20.   
  21. }   

 

4)配置文件action.properties

java 代码
  1. test|com.sophie.action.TestAction||success--/hello.jsp   
  2. testInclude|com.sophie.action.TestAction|testParameter|success--/includePage.html  

 

5)action的执行 这里用反射

java 代码
  1. /*  
  2.  * author:sophie dong  
  3.  * 把不同的result分发到相应的result类去处理  
  4.  */  
  5. package com.sophie.dispatcher;   
  6.   
  7. import java.io.IOException;   
  8. import java.util.Map;   
  9.   
  10. import javax.servlet.ServletException;   
  11. import javax.servlet.http.HttpServletRequest;   
  12. import javax.servlet.http.HttpServletResponse;   
  13.   
  14. import com.sophie.context.ResultConfiguration;   
  15. import com.sophie.context.SophieContext;   
  16. import com.sophie.result.SophieResult;   
  17.   
  18. public class ResultDispatcher {   
  19.     private Map resultMap;   
  20.     private String resultString;   
  21.        
  22.     //resultType=dispatcher的时候 判断用include还是forward   
  23.     private String include;   
  24.        
  25.     public ResultDispatcher(Map resultMap,String resultString) {   
  26.         this.resultMap=resultMap;   
  27.         this.resultString=resultString;   
  28.     }   
  29.   
  30. //  处理result   
  31.     public void Dispatcher(){   
  32.            
  33.         HttpServletRequest request=SophieContext.getRequest();   
  34.         HttpServletResponse response=SophieContext.getResponse();   
  35.         ResultConfiguration resultConfig=resultMap.get(resultString);   
  36.         //result type==dispatcher   
  37.         if(null==resultConfig.getResultType() || "".equals(resultConfig.getResultType() )){   
  38.             SophieResult dispatcher=new SophieResult();   
  39.             dispatcher.setLocation(resultConfig.getPageUrl());   
  40.             dispatcher.setInclude(include);   
  41.             try {   
  42.                 dispatcher.service(request, response);   
  43.             } catch (ServletException e) {   
  44.                 e.printStackTrace();   
  45.             } catch (IOException e) {   
  46.                 e.printStackTrace();   
  47.             }   
  48.         }   
  49.            
  50.     }   
  51.   
  52.     public void setInclude(String include) {   
  53.         this.include = include;   
  54.     }   
  55.   
  56. }   

 

7) result类 处理输出

java 代码
  1. /*  
  2.  * author sophie dong  
  3.  * resultType for HttpServletRequest de forward or include  
  4.  */  
  5. package com.sophie.result;   
  6.   
  7. import java.io.IOException;   
  8. import javax.servlet.RequestDispatcher;   
  9. import javax.servlet.ServletException;   
  10. import javax.servlet.http.HttpServlet;   
  11. import javax.servlet.http.HttpServletRequest;   
  12. import javax.servlet.http.HttpServletResponse;   
  13.   
  14. public class SophieResult extends HttpServlet{   
  15.        
  16.     private String location;   
  17.     private String include;   
  18.   
  19.     public void setLocation(String location) {   
  20.         this.location = location;   
  21.     }   
  22.        
  23.     @Override  
  24.     protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {   
  25.         if(null!=location){   
  26.             RequestDispatcher dispatcher=request.getRequestDispatcher(location);   
  27.             if(null!=include && "include".equals(include))   
  28.                 dispatcher.include(request, response);   
  29.             else  
  30.                 dispatcher.forward(request, response);   
  31.         }   
  32.            
  33.     }   
  34.   
  35.     public void setInclude(String include) {   
  36.         this.include = include;   
  37.     }   
  38. }   
   发表时间:2007-05-10  
LZ还挺有钻研精神的,值得学习。我用过好几个MVC的框架,可就没有自己DIY一个。
0 请登录后投票
   发表时间:2007-05-10  
好长啊。支持下...一会细看
0 请登录后投票
   发表时间:2007-05-10  
能先给个类图,或者关系图也行,先从大概上给个轮廓,看代码毕竟有点累
0 请登录后投票
   发表时间:2007-05-11  

赞一个先!

 

不断的模仿、练习必能提高个人的设计水平。

 

为演示Guice框架的使用,我也设计了一个简单的MVC,不过和楼主的相比就逊色很多,有时间我们可以交流一下设计思想,共同提高。

AromaRI

0 请登录后投票
   发表时间:2007-05-11  
zyl 写道
能先给个类图,或者关系图也行,先从大概上给个轮廓,看代码毕竟有点累

我不会画类图
给一个文字描述

Sophie的web框架
主要思路
Init配置文件-》dispatcher调度-》invocation执行action=》result处理结果,显示页面

主要功能部分
1. dispatcher 调度器,在启动服务的时候调用init方法,初始化action的配置文件。保存servlet的内容到SophieContext 中
2. configuration和resultConfiguration模型,把配置文件中的action信息,封装到一个configration类中。多个action信息组成一个map。每个action的result信息,封装到resultConfiguration中,多个result组成一个map.
3. action 类。逻辑的东西可以写在action中。Action类从servlet中分离出来。专注与逻辑本身。提供给框架的使用者。
4. SophieContext 保存context的类。里面有个静态的map。
5. SophieInvocation 执行action
6. sophieResult 处理action执行的结果,根据resultConfiguration里的配置,转向显示页面。
7. ActionTag action标签,可以在页面上用标签调用action
0 请登录后投票
   发表时间:2007-05-11  
爱专研技术的MM还真不多. ^_^

你的那个只是个front controller的一部分,
Context和Invocation那部分你可参考xwork部分,如ThreadLocal
而且ww的一大核心是它的interception.

不过代码写得还不错.
0 请登录后投票
   发表时间:2007-05-11  
你发的EMIAL收到,可能是我这边的网络有些问题,老是发送不成功,所以在这回复你,:)

我刚才抽了点时间仔细的看了你的源码,真的值得学习呀,:)
自己封装那些东西当然不错了,放在一个全局的静态变量中,避免了每次调用都要开辟内存空间。是否可以在调用的时候,判断一下MAP是否生成了,如果生成了就不用去调用那些获取属性文件中的类。
0 请登录后投票
   发表时间:2007-05-11  
hgq0011 写道

是否可以在调用的时候,判断一下MAP是否生成了,如果生成了就不用去调用那些获取属性文件中的类。

调用那些获取属性文件中的类是在服务启动的时候调用的,
因为是写在servlet的init方法里面,所以只会被调用到一次的:)

我现在觉得SophieDispatcher类里面 service方法中存入静态map里的一些对象,在并发的环境下是会冲突。我现在在考虑怎么改进这块
0 请登录后投票
   发表时间:2007-05-11  
map改用hashtable或用collections.synchroized方法设置下,实在不行用同步锁住。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics