diy面向請求的java框架

這個框架也是爲google app engine準備的。當時感覺直接在gae上sevlet太煩人了,就封裝個簡易的框架。使用的時候只需要配置web.xml中DispacherSevlet和package.properties中的package.path(默認掃描的包)即可
gae例子:http://orzblogs.appspot.com/Home.htm    (記得自己找梯子。。。)

首先聲明:gae本身就是個玩具。這個web框架也是爲了玩玩具而做的玩具。。。性能很有問題,不過gae上也無所謂了。不用多久conetxt就全被清空了。所以全當玩具玩吧,理念可以可以看下。
大學的時候很BS java,學了之後就扔掉了,現在工作了纔開始接觸java。
java在web方面如果不是開源,不是衆多的java框架支持,那麼它確實沒什麼值得稱道的。
倒是jvm被優化的不錯。

java web框架本質上都是sevlet,所有的那麼web框架都是對sevlet進行了封裝,然後對web相關的進行包裝。那麼我們也可以來diy個簡易的web框架,爲的是體驗這個中間的過程,可能框架不實用,甚至不能稱作框架,其實爲的就是減少一點配置,雖然現在springMVC通過註解就可以減少web層的配置,這裏所做的也是同樣的事,性能肯定很差,但是也是一種方法,增加理解而已。

首先任何web框架的入口基本上都是一個XXdispatcher。用來進行請求url的轉發。
OK,那麼我們就來做一個面向web請求的簡易的不能稱爲框架的框架。前端使用velicity進行渲染。
當然一定要把spring給集成進來,要不誰給我們持久化bean呢。

首先通過DispacherSevlet來進行請求的轉發。然後根據請求的名稱加載bean。然後通過反射將bean的相關屬性注入。然後執行bean。然後獲取需要渲染的模板。渲染。返回結果給用戶。

Java代碼 複製代碼
  1. public String doGet(HttpRequest request, HttpResponse response, Map<String, Object> context)   
  2. public String doPost(HttpRequest request, HttpResponse response, Map<String, Object> context)  
public String doGet(HttpRequest request, HttpResponse response, Map<String, Object> context)
public String doPost(HttpRequest request, HttpResponse response, Map<String, Object> context)

用戶請求/Home.htm然後獲取到對應的controller爲Home。然後從框架IOC中獲取Home。如果獲取不到就通過bean加載器來加載Home,然後通過Home的dopost或者doget方法來處理應用。dopost和doget中會放入映射進去一個map<string,object>來存頁面的上下文。當處理完畢後根據Home返回的頁面路徑來進行頁面渲染,並將結果返回給用戶。


細節:
1.維護一個自己的上下文用來存儲所有的controller。當請求來的時候。先看上下文中是否存在這個controller,如果存在就不用去創建了,如果不存在創建之並且緩存到上下文中。
2.維護一個spring的上下文,當創建bean的時候從spring中獲取相應的bean反射到要創建的bean相應的屬性中。
3.前端用velicity進行渲染。實現control和主頁面信息的隔離渲染。


使用步驟:
1.將jar包導入
2.配置web.xml中
Xml代碼 複製代碼
  1. <servlet>  
  2.         <servlet-name>dispatcher</servlet-name>  
  3.         <servlet-class>org.jeasy.core.DispacherServlet</servlet-class>  
  4.     </servlet>  
<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.jeasy.core.DispacherServlet</servlet-class>
	</servlet>

3.在package.properties中的package.path包下增加類(如果訪問Home.htm就增加Home.java
4.Home.java實現Controller接口,然後return 一個String類型,String爲vm模板



核心代碼:
DispacherSevlet
Java代碼 複製代碼
  1. public class DispacherServlet extends HttpServlet {   
  2.     private static final long        serialVersionUID = 1L;   
  3.     private XmlWebApplicationContext applicationContext;   
  4.     private BeanLoaderService        beanLoaderService;   
  5.     private PathResolver             pathResolver;   
  6.     private ViewResolver viewResolver;   
  7.     private FrameWorkFlowManager frameWorkFlowManager;   
  8.   
  9.     /**  
  10.      * 初始化應用信息  
  11.      *   
  12.      * @param config  
  13.      * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)  
  14.      */  
  15.     public void init(ServletConfig servletConfig) throws ServletException {   
  16.         //初始化spring IOC   
  17.         applicationContext = new XmlWebApplicationContext();   
  18.         applicationContext.setServletConfig(servletConfig);   
  19.         applicationContext.refresh();   
  20.   
  21.         //初始化jeasy IOC   
  22.         JEasyApplicationContext jEasyApplicationContext = new JEasyApplicationContext();           
  23.   
  24.         //初始化bean加載器   
  25.         beanLoaderService = new BeanLoaderService(servletConfig.getServletContext(),applicationContext, jEasyApplicationContext);   
  26.   
  27.         //初始化請求解析器   
  28.         pathResolver = new PathResolver();   
  29.   
  30.         //初始化渲染器   
  31.         viewResolver=new VelocityResolver(servletConfig.getServletContext());   
  32.            
  33.         //初始化工作流處理器   
  34.         frameWorkFlowManager=new FrameWorkFlowManager();    
  35.            
  36.         super.init(servletConfig);   
  37.     }   
  38.        
  39.     /**  
  40.      * 通過service來處理請求,不用以前的doPost和doGet  
  41.      * @param request  
  42.      * @param response  
  43.      * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)  
  44.      */  
  45.     public  void service(HttpServletRequest request, HttpServletResponse response){   
  46.         HttpRequest httpRequest = new HttpRequest(request);   
  47.         HttpResponse httpResponse = new HttpResponse(response);   
  48.            
  49.         //初始化工作流處理器   
  50.         frameWorkFlowManager.init(beanLoaderService, viewResolver, httpRequest, httpResponse);   
  51.            
  52.         //獲取請求的地址信息   
  53.         String requestPath = request.getServletPath();   
  54.         String path=pathResolver.getPath(requestPath);   
  55.            
  56.         //裝備、執行、渲染   
  57.         frameWorkFlowManager.work(path);   
  58.     }   
  59. }  
public class DispacherServlet extends HttpServlet {
    private static final long        serialVersionUID = 1L;
    private XmlWebApplicationContext applicationContext;
    private BeanLoaderService        beanLoaderService;
    private PathResolver             pathResolver;
    private ViewResolver viewResolver;
    private FrameWorkFlowManager frameWorkFlowManager;

    /**
     * 初始化應用信息
     * 
     * @param config
     * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
     */
    public void init(ServletConfig servletConfig) throws ServletException {
        //初始化spring IOC
        applicationContext = new XmlWebApplicationContext();
        applicationContext.setServletConfig(servletConfig);
        applicationContext.refresh();

        //初始化jeasy IOC
        JEasyApplicationContext jEasyApplicationContext = new JEasyApplicationContext();        

        //初始化bean加載器
        beanLoaderService = new BeanLoaderService(servletConfig.getServletContext(),applicationContext, jEasyApplicationContext);

        //初始化請求解析器
        pathResolver = new PathResolver();

        //初始化渲染器
        viewResolver=new VelocityResolver(servletConfig.getServletContext());
        
        //初始化工作流處理器
        frameWorkFlowManager=new FrameWorkFlowManager(); 
        
        super.init(servletConfig);
    }
    
    /**
     * 通過service來處理請求,不用以前的doPost和doGet
     * @param request
     * @param response
     * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    public  void service(HttpServletRequest request, HttpServletResponse response){
        HttpRequest httpRequest = new HttpRequest(request);
        HttpResponse httpResponse = new HttpResponse(response);
		
        //初始化工作流處理器
        frameWorkFlowManager.init(beanLoaderService, viewResolver, httpRequest, httpResponse);
        
        //獲取請求的地址信息
        String requestPath = request.getServletPath();
        String path=pathResolver.getPath(requestPath);
        
        //裝備、執行、渲染
        frameWorkFlowManager.work(path);
    }
}

首先在第一次創建的時候會初始化springIOC容器、自己的IOC容器、web層bean加載器、地址轉換器、頁面渲染、工作流

首先獲請求的地址,然後進入工作流

BeanLoadService
Java代碼 複製代碼
  1. /**  
  2.  * bean的裝配器  
  3.  *   
  4.  * @author yuezhen  
  5.  * @version $Id: ControllerLoadService.java,v 0.1 2009-9-24 上午09:35:09 yuezhen Exp $  
  6.  */  
  7. public class BeanLoaderService {   
  8.     private static final Logger     logger = Logger.getLogger(BeanLoaderService.class.getName());   
  9.     private ApplicationContext      applicationContext;   
  10.     private JEasyApplicationContext jEasyContext;   
  11.     private String packagePath;   
  12.   
  13.     /**  
  14.      * 獲取spring的ioc容器和jeasy的ioc容器  
  15.      * @param applicationContext spring的ioc容器  
  16.      */  
  17.     public BeanLoaderService(ServletContext servletContext,ApplicationContext applicationContext,   
  18.                              JEasyApplicationContext jEasyContext) {   
  19.         this.applicationContext = applicationContext;   
  20.         this.jEasyContext = jEasyContext;   
  21.            
  22.         String rootPath = servletContext.getRealPath("/");   
  23.   
  24.         logger.info("[jeasy] rootPath="+rootPath);   
  25.            
  26.         Properties properties = new Properties();   
  27.         try {   
  28.             properties.load(new FileInputStream(rootPath   
  29.                     + "/WEB-INF/package.properties"));   
  30.         } catch (Exception e) {   
  31.             logger.warning("[jeasy] can't load package.properties,rootPath="+rootPath);   
  32.         }   
  33.   
  34.         packagePath = properties.getProperty("package.path","");   
  35.         if(!packagePath.equals("")){   
  36.             packagePath=packagePath+".";   
  37.         }   
  38.     }   
  39.   
  40.     /**  
  41.      * 獲取Controller  
  42.      * 如果在jeasy IOC中存在,直接讀取  
  43.      * 如果在jeasy IOC中不存在,創建Controller,並放入jeasy IOC  
  44.      */  
  45.     public Controller getController(String name) {   
  46.         if (StringUtils.isBlank(name)) {   
  47.             return null;   
  48.         }   
  49.   
  50.         Controller jEasyController = null;   
  51.         jEasyController = jEasyContext.getController(packagePath+name);   
  52.   
  53.         //在jeasy IOC中不存在,創建Controller並存入IOC   
  54.         if (jEasyController == null) {   
  55.             logger.info("init bean:"+packagePath+name);   
  56.             jEasyController = this.createController(packagePath+name);   
  57.             jEasyContext.addController(packagePath+name, jEasyController);   
  58.         }   
  59.   
  60.         return jEasyController;   
  61.     }   
  62.   
  63.     /**  
  64.      * 通過反射創建controller  
  65.      * @param name  
  66.      * @return  
  67.      */  
  68.     public Controller createController(String name) {   
  69.         Controller controller = null;   
  70.         try {   
  71.             //獲取controller   
  72.             controller = (Controller) Class.forName(name).newInstance();   
  73.   
  74.             //包裝controller,將set方法注入   
  75.             buildController(controller);   
  76.         } catch (ClassNotFoundException e) {   
  77.             logger.warning("[jeasy] can't find class named " + name);   
  78.         } catch (InstantiationException e) {   
  79.         } catch (IllegalAccessException e) {   
  80.         }   
  81.         return controller;   
  82.     }   
  83.   
  84.     /**  
  85.      * 將controller裏面所有的set方法全部注入  
  86.      * @param controller  
  87.      */  
  88.     public void buildController(Controller controller) {   
  89.         Class jEasyClass = controller.getClass();   
  90.         Field[] fields = jEasyClass.getDeclaredFields();   
  91.         for (Field field : fields) {   
  92.             String fieldName = field.getName();   
  93.             String method = "set" + fieldName.substring(01).toUpperCase()   
  94.                             + fieldName.substring(1);   
  95.   
  96.             try {   
  97.                 Method setMethod = jEasyClass.getMethod(method, new Class<?>[] { field.getType() });   
  98.                 // 從springIOC中取得bean   
  99.                 Object bean = applicationContext.getBean(field.getName());   
  100.                 if(bean!=null){   
  101.                     setMethod.invoke(controller, bean);   
  102.                 }   
  103.             } catch (SecurityException e) {   
  104.             } catch (NoSuchMethodException e) {   
  105.             } catch (IllegalArgumentException e) {   
  106.             } catch (IllegalAccessException e) {   
  107.             } catch (InvocationTargetException e) {   
  108.             }   
  109.   
  110.         }   
  111.     }   
  112. }  
/**
 * bean的裝配器
 * 
 * @author yuezhen
 * @version $Id: ControllerLoadService.java,v 0.1 2009-9-24 上午09:35:09 yuezhen Exp $
 */
public class BeanLoaderService {
    private static final Logger     logger = Logger.getLogger(BeanLoaderService.class.getName());
    private ApplicationContext      applicationContext;
    private JEasyApplicationContext jEasyContext;
    private String packagePath;

    /**
     * 獲取spring的ioc容器和jeasy的ioc容器
     * @param applicationContext spring的ioc容器
     */
    public BeanLoaderService(ServletContext servletContext,ApplicationContext applicationContext,
                             JEasyApplicationContext jEasyContext) {
        this.applicationContext = applicationContext;
        this.jEasyContext = jEasyContext;
        
        String rootPath = servletContext.getRealPath("/");

        logger.info("[jeasy] rootPath="+rootPath);
        
        Properties properties = new Properties();
		try {
			properties.load(new FileInputStream(rootPath
					+ "/WEB-INF/package.properties"));
		} catch (Exception e) {
			logger.warning("[jeasy] can't load package.properties,rootPath="+rootPath);
		}

		packagePath = properties.getProperty("package.path","");
		if(!packagePath.equals("")){
			packagePath=packagePath+".";
		}
    }

    /**
     * 獲取Controller
     * 如果在jeasy IOC中存在,直接讀取
     * 如果在jeasy IOC中不存在,創建Controller,並放入jeasy IOC
     */
    public Controller getController(String name) {
        if (StringUtils.isBlank(name)) {
            return null;
        }

        Controller jEasyController = null;
        jEasyController = jEasyContext.getController(packagePath+name);

        //在jeasy IOC中不存在,創建Controller並存入IOC
        if (jEasyController == null) {
            logger.info("init bean:"+packagePath+name);
            jEasyController = this.createController(packagePath+name);
            jEasyContext.addController(packagePath+name, jEasyController);
        }

        return jEasyController;
    }

    /**
     * 通過反射創建controller
     * @param name
     * @return
     */
    public Controller createController(String name) {
        Controller controller = null;
        try {
            //獲取controller
            controller = (Controller) Class.forName(name).newInstance();

            //包裝controller,將set方法注入
            buildController(controller);
        } catch (ClassNotFoundException e) {
            logger.warning("[jeasy] can't find class named " + name);
        } catch (InstantiationException e) {
        } catch (IllegalAccessException e) {
        }
        return controller;
    }

    /**
     * 將controller裏面所有的set方法全部注入
     * @param controller
     */
    public void buildController(Controller controller) {
        Class jEasyClass = controller.getClass();
        Field[] fields = jEasyClass.getDeclaredFields();
        for (Field field : fields) {
            String fieldName = field.getName();
            String method = "set" + fieldName.substring(0, 1).toUpperCase()
                            + fieldName.substring(1);

            try {
                Method setMethod = jEasyClass.getMethod(method, new Class<?>[] { field.getType() });
                // 從springIOC中取得bean
                Object bean = applicationContext.getBean(field.getName());
                if(bean!=null){
                    setMethod.invoke(controller, bean);
                }
            } catch (SecurityException e) {
            } catch (NoSuchMethodException e) {
            } catch (IllegalArgumentException e) {
            } catch (IllegalAccessException e) {
            } catch (InvocationTargetException e) {
            }

        }
    }
}

在bean加載器中會根據請求的url來加載bean。比如:請求/Home.htm,那麼地址轉化器會獲取到bean的name爲Home。然後會去加載Home的bean來當作Home的controller。將所有需要set的方法從SpringIOC中讀出進行set,然後將Home以string,object的形式進行緩存。


FrameWorkFlowManager
Java代碼 複製代碼
  1. public class FrameWorkFlowManager {   
  2.     private static final Logger logger = Logger   
  3.             .getLogger(FrameWorkFlowManager.class.getName());   
  4.     private BeanLoaderService beanLoaderService;   
  5.     private ViewResolver viewResolver;   
  6.     private HttpRequest request;   
  7.     private HttpResponse response;   
  8.   
  9.     public void init(BeanLoaderService beanLoaderService,   
  10.             ViewResolver viewResolver, HttpRequest request,   
  11.             HttpResponse response) {   
  12.         this.beanLoaderService = beanLoaderService;   
  13.         this.viewResolver = viewResolver;   
  14.         this.request = request;   
  15.         this.response = response;   
  16.         setResonse();   
  17.     }   
  18.   
  19.     public void work(String path) {   
  20.   
  21.         // 每次進行頁面渲染,每個頁面一個上下文   
  22.         Map<String, Object> context = new HashMap<String, Object>();   
  23.         Control control=new Control(viewResolver, response,context, request,beanLoaderService);   
  24.   
  25.         context.put("control", control);   
  26.            
  27.         render(path,context);   
  28.     }   
  29.   
  30.     public void render(String path,Map<String, Object> context) {   
  31.         Controller controller = null;   
  32.         try {   
  33.             // 獲取控制器對象   
  34.             controller = beanLoaderService.getController(path);   
  35.         } catch (Exception e) {   
  36.         }   
  37.   
  38.         if (controller != null) {   
  39.             String result = null;   
  40.             try {   
  41.                 // 調用Controller處理   
  42.                 if (controller != null) {   
  43.   
  44.                     if (request.getMethod().equals("POST")) {   
  45.                         result = controller.doPost(request, response, context);   
  46.                     } else {   
  47.                         result = controller.doGet(request, response, context);   
  48.                     }   
  49.                 } else {   
  50.                     response.sendError(404);   
  51.                     return;   
  52.                 }   
  53.             } catch (Exception e) {   
  54.             }   
  55.   
  56.             logger.info(result);   
  57.   
  58.             try {   
  59.                 if (result != null) {   
  60.                     if (result.startsWith("redirect:")) {   
  61.                         response.sendRedirect(result.substring("redirect:"  
  62.                                 .length()));   
  63.                     } else {   
  64.                         viewResolver.merge(result, context, response);   
  65.                     }   
  66.                 }   
  67.             } catch (Exception e) {   
  68.             }   
  69.         }   
  70.     }   
  71.        
  72.     private void setResonse(){   
  73.         response.setCharacterEncoding(viewResolver.getCharacterEncoding());   
  74.     }   
  75. }  
public class FrameWorkFlowManager {
	private static final Logger logger = Logger
			.getLogger(FrameWorkFlowManager.class.getName());
	private BeanLoaderService beanLoaderService;
	private ViewResolver viewResolver;
	private HttpRequest request;
	private HttpResponse response;

	public void init(BeanLoaderService beanLoaderService,
			ViewResolver viewResolver, HttpRequest request,
			HttpResponse response) {
		this.beanLoaderService = beanLoaderService;
		this.viewResolver = viewResolver;
		this.request = request;
		this.response = response;
		setResonse();
	}

	public void work(String path) {

		// 每次進行頁面渲染,每個頁面一個上下文
		Map<String, Object> context = new HashMap<String, Object>();
		Control control=new Control(viewResolver, response,context, request,beanLoaderService);

		context.put("control", control);
		
		render(path,context);
	}

	public void render(String path,Map<String, Object> context) {
		Controller controller = null;
		try {
			// 獲取控制器對象
			controller = beanLoaderService.getController(path);
		} catch (Exception e) {
		}

		if (controller != null) {
			String result = null;
			try {
				// 調用Controller處理
				if (controller != null) {

					if (request.getMethod().equals("POST")) {
						result = controller.doPost(request, response, context);
					} else {
						result = controller.doGet(request, response, context);
					}
				} else {
					response.sendError(404);
					return;
				}
			} catch (Exception e) {
			}

			logger.info(result);

			try {
				if (result != null) {
					if (result.startsWith("redirect:")) {
						response.sendRedirect(result.substring("redirect:"
								.length()));
					} else {
						viewResolver.merge(result, context, response);
					}
				}
			} catch (Exception e) {
			}
		}
	}
	
	private void setResonse(){
		response.setCharacterEncoding(viewResolver.getCharacterEncoding());
	}
}


對應的Spring、log4j的jar都要導入一塊使用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章