SongXQFrame这个框架是我对OO思想,设计模式以及工作经验的一个总结,小弟刚刚入“道”,经验不多,修为尚浅,请各位高人指点一二。
1、背景 自己比较懒,对Structs,Hibernate等著名的框架虽然机制上有一定的了解,但对于他们复杂的XML配置感到畏惧,于是想做一种编码量少,配置也少的一种简单的框架,能够进行快速开发。
2、基本组成 SongXQFrame包括web层的MVC框架和持久层的ORM框架。
3、SongXQFrame的Web层框架 web框架借鉴了Structs等基于请求的框架技术。核心控制器为一个Servlet,维持了一个请求的生命周期: (1)字符编码设置。 控制器Servlet可以设置encoding参数,对字符编码进行设置,默认为utf-8编码。这样就省去了解决乱码问题的烦恼。 (2)包装请求参数。 将用户的请求参数进行包装成一个RequestData接口的实例,RequestData提供到基本数据类型的转换,如requestData.getInt("name")等方法,并能够自动封装文件上传的Multi-part请求,极大地简化了文件上传的操作,通过requestData.getInputStream("file")方法可以直接获取文件上传流,如果要获取更多上传文件的信息,可以通过getFileItem方法,文件上传是通过apache的fileupload组件实现的。 如果请求参数存在同名情况可以通过相应的get*Array()方法获取一个参数对应值的数组,如String [] values = requestData.getStringArray("key");多文件上传: InputStream [] ins = requestData.getInputStreamArray(); (3)初始化请求上下文。 这个环节是通过名为web-controller.xml的配置文档进行的。配置文档如下: <?xml version="1.0" encoding="utf-8"?> <webapp> <!-- 细粒度配置,配置到每一个请求,每一个请求配置全局只有一个实例 --> <request waid="test"> <!-- 处理器配置 --> <processor class="test.TestProcessor" singleton="true"> <!-- 处理器处理之前的初始化操作,用Setter注入,对于单例没什么作用,反而影响了其他请求 --> <init /> <!-- 处理器前增强,比如权限检测 --> <advisor type="before" class="test.TestBeforeAdvisor" singleton="true"> <init> <set name="pass" value="song,songxq,xuqiong" /> </init> </advisor> <!-- 处理器后增强,比如写日志 --> <!-- advisor type="after" class="" singleton="" / --> </processor> <!-- 渲染器配置,当一切处理正常,由渲染器负责渲染,暂时忽略singleton --> <render class="test.TestRender" singleton="true"> <init> <set name="name" value="songzenghui" /> </init> </render> </request> </webapp>
根据请求的“waid”参数,读取配置文档,最终产生一SongXQWebRequestContext接口的实例,通过这个接口,可以获取一个请求的上下文环境,包括request,response,session,application,processor(处理器),advisor(处理器前后增强),render(渲染器)(处理器和渲染器的作用稍后解释)。 (4)处理器对请求进行处理。 通过读取web-controller.xml,初始化请求上下文后,每一个请求(用waid标志的)都对应了一个Processor接口的实例,即请求处理器,对请求进行逻辑处理。 Processor接口的定义: public interface Processor { /** * 在某个请求环境中处理某数据 * @param data : 需要处理的数据 * @param context :请求的上下文 */ void process(RequestData data ,SongXQWebRequestContext context) throws Exception; } 为了完成一些通用的工作,比如可能要进行权限控制,或者要进行业务日志的记录,因此根据需要可以在处理器处理的前后加上一个Advisor(ProcessorAdvisor 接口的实例)进行拦截处理(不知道是不是AOP)。如果拦截不通过就抛出异常。 ProcessorAdvisor 接口的定义: public interface ProcessorAdvisor { void process(RequestData data ,SongXQWebRequestContext context) throws Exception; } (5)渲染用户输出。 对用户请求处理结束以后,即做出反馈(response)。在SongXQFrame里是通过渲染器(Render)进行输出的。 Render接口的定义: public interface Render { /** * 渲染器在处理器之前可能要做一定的准备工作 */ void prepareBeforeProcessing(HttpServletResponse response, SongXQWebRequestContext context) throws Exception; /** * 在某个请求上下文中进行渲染操作,由于渲染必不可少的需要response,因此显示提供。 * * @param response : 渲染响应 * @param context : 渲染的请求上下文 * @throws RenderException */ void render(HttpServletResponse response, SongXQWebRequestContext context) throws Exception; } 最常见的输出为JSP页面的输出和Ajax里面用到挺多的Text的输出。因此框架内置了DefaultPageRender和DefaultTextRender。还可以自定义许多的Render,比如在新的一个项目里要用到Excel的输出,Word文档的输出,XML的输出,JSON字符串的输出等。
到输出这个阶段一个请求的生命周期基本结束了。 但在这个过程当中随时可能捕获到异常,因此附加了一个异常处理的机制。 (6)异常处理 异常处理的目的主要是为了给用户一个比较友好的系统错误提示方式,这个机制配置在web-exception.xml文档里,非常简单,一个类型的异常指定一个Render输出。 <?xml version="1.0" encoding="utf-8"?> <webappeException> <!-- 所有的异常类都由该异常处理器处理 --> <exception class="java.lang.Exception"> <render class="net.songxq.web.render.DefaultPageRender" singleton="false"> <init> <set name="pageToRend" value="http://www.baidu.com" /> <set name="type" value="browserSide" /> </init> </render> </exception> </webappeException>
4、持久化框架 待续
|
|