前段时间准备做一个小网站,但是又不想用Spring/Struts/WebWork这样的大块头,因此决定自己写一个MVC框架。花了3天左右时间完成,目前运行良好,整个MVC框架仅21KB,感兴趣的朋友可以从http://code.google.com/p/lightweight-mvc/downloads/list下载完整的源代码和jar包。
设计目标:
一个最简单最小巧的MVC框架,花哨的功能一个不要,越简洁越好,并且不使用XML配置文件,而是完全用Java 5注解配置。
功能列表:
组件必须用IoC配置;
处理HTTP请求的Action,类似WebWork每个请求都生成一个新实例,并自动填充属性;
类似Filter的Interceptor机制,但是在IoC容器中配置;
统一的异常处理;
多视图支持。
由于组件需要用IoC容器配置,因此,第一步就是寻找小巧的IoC容器,Google Guice是一个很不错的选择,并且完全用Java 5注解配置组件。这个MVC框架唯一依赖的也就是Guice和Commons Logging两个jar包,如果使用Velocity作为视图则还需要Velocity的jar包。
下一步,开始设计各主要功能类:
负责处理Http请求的Action类必须实现的Action接口:
package com.javaeedev.lightweight.mvc;
public interface Action {
ModelAndView execute() throws Exception;
}
从WebWork抄过来,不过返回值由String改成了ModelAndView(从Spring抄过来的),好处是不必再次根据String查找视图的绝对路径,直接在ModelAndView中包含了。用Spring的MVC其实可以发现,ModelAndView同时包含一个Model(本质是一个Map)和View的路径,减少了Struts和WebWork需要的一个XML映射文件,而维护XML配置文件是一件相当令人头疼的问题,往往改了代码还要改配置,索性写死在代码中得了,视图路径又不会经常改变,没必要为了额外的灵活性给自己搞一堆XML配置文件。
Action返回的ModelAndView:
package com.javaeedev.lightweight.mvc;
public final class ModelAndView {
private String view;
private Map<String, Object> model;
/**
* Construct a View with empty model.
*
* @param view View's logic name.
*/
public ModelAndView(String view) {
this.view = view;
this.model = Collections.emptyMap();
}
/**
* Construct a View with model.
*
* @param view View's logic name.
* @param model Model as a Map.
*/
public ModelAndView(String view, Map<String, Object> model) {
this.view = view;
this.model = model;
}
/**
* Return View.
*
* @return View's logic name.
*/
public String getView() {
return view;
}
/**
* Return model.
*
* @return Model as a Map.
*/
public Map<String, Object> getModel() {
return model;
}
}
这个完全是从Spring MVC抄过来的,Map改成了泛型,View路径可以以"redirect:"开头表示重定向,这个和Spring MVC一致。虽然直接调用HttpServletResponse也可以重定向,但是遇到事务处理起来会很麻烦,还是让MVC框架自己来处理会好一些。
WebWork的Action设计的好处是大大简化了参数的绑定,不过很多时候也需要在Action中访问HttpSession等对象,因此还需要设计一个ActionContext类,通过ThreadLocal让Action对象能轻易地访问到这些对象:
package com.javaeedev.lightweight.mvc;
public final class ActionContext {
private static ThreadLocal<ActionContext> contextThreadLocal = new ThreadLocal<ActionContext>();
/**
* Get current ActionContext.
*
* @return ActionContext.
*/
public static ActionContext getActionContext() {
return contextThreadLocal.get();
}
private HttpServletRequest request;
private HttpServletResponse response;
private HttpSession session;
private ServletContext context;
/**
* Initiate all servlet objects as thread local.
*
* @param request HttpServletRequest object.
* @param response HttpServletResponse object.
* @param session HttpSession object.
* @param context ServletContext object.
*/
static void setActionContext(HttpServletRequest request, HttpServletResponse response, HttpSession session, ServletContext context) {
ActionContext actionContext = new ActionContext();
actionContext.setRequest(request);
actionContext.setResponse(response);
actionContext.setSession(session);
actionContext.setServletContext(context);
contextThreadLocal.set(actionContext);
}
/**
* Remove all servlet objects from thread local.
*/
static void remove() {
contextThreadLocal.remove();
}
/**
* Get HttpServletRequest object.
*
* @return HttpServletRequest object.
*/
public HttpServletRequest getRequest() {
return request;
}
/**
* Set HttpServletRequest object.
*
* @param request HttpServletRequest object.
*/
void setRequest(HttpServletRequest request) {
this.request = request;
}
/**
* Get HttpServletResponse object.
*
* @return HttpServletResponse object.
*/
public HttpServletResponse getResponse() {
return response;
}
/**
* Set HttpServletResponse object.
*
* @param response HttpServletResponse object.
*/
void setResponse(HttpServletResponse response) {
this.response = response;
}
/**
* Get HttpSession object.
*
* @return HttpSession object.
*/
public HttpSession getSession() {
return session;
}
/**
* Set HttpSession object.
*
* @param session HttpSession object.
*/
void setSession(HttpSession session) {
this.session = session;
}
/**
* Get ServletContext object.
*
* @return ServletContext object.
*/
public ServletContext getServletContext() {
return context;
}
/**
* Set ServletContext object.
*
* @param context ServletContext object.
*/
void setServletContext(ServletContext context) {
this.context = context;
}
}
接下来是定义类似Filter功能的Interceptor接口:
package com.javaeedev.lightweight.mvc;
/**
* Intercept action's execution like servlet Filter, but interceptors are
* configured and managed by IoC container. Another difference from Filter
* is that Interceptor is executed around Action's execution, but before
* rendering view.
*
* @author Xuefeng
*/
public interface Interceptor {
/**
* Do intercept and invoke chain.doInterceptor() to process next interceptor.
* NOTE that process will not continue if chain.doInterceptor() method is not
* invoked.
*
* @param action Action instance to handle http request.
* @param chain Interceptor chain.
* @throws Exception If any exception is thrown, process will not continued.
*/
void intercept(Action action, InterceptorChain chain) throws Exception;
}
InterceptorChain对象和FilterChain是一样的,它允许一个拦截器是否将请求继续交给下一拦截器处理,还是中断当前请求的处理:
package com.javaeedev.lightweight.mvc;
/**
* Holds all interceptors as a chain.
*
* @author Xuefeng
*/
public interface InterceptorChain {
/**
* Apply next interceptor around the execution of Action.
*
* @param action Target Action to execute.
* @throws Exception Any exception if error occured.
*/
void doInterceptor(Action action) throws Exception;
}
最后是支持多种View的ViewResolver,这个也抄自Spring MVC:
package com.javaeedev.lightweight.mvc;
import java.io.IOException;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* To resolve and render a view.
*
* @author Xuefeng
*/
public interface ViewResolver {
/**
* Init this ViewResolver.
*
* @param context ServletContext object that holds information of current
* web application.
* @throws ServletException If init failed.
*/
void init(ServletContext context) throws ServletException;
/**
* To resolve view's name and render view if necessary.
*
* @param view View's logic name.
* @param model Model represent as a generic Map.
* @param request HttpServletRequest object.
* @param response HttpServletResponse object.
* @throws ServletException If any ServletException occur.
* @throws IOException If any IOException occur.
*/
void resolveView(String view, Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException;
}
第一个版本支持JSP和Velocity两种View,其实支持其他的View完全是可扩展的,只需要参考现有的两种ViewResolver的实现再写一个实现即可,例如支持FreeMarker的ViewResolver。
到此为止,提供给客户端的API准备完毕。下一步是如何实现这些API。虽然概念和结构都来自WebWork和Spring,但是其具体实现却没有参考他们的源代码,因为读大块头的源码本身就是一件非常费力的事情,还不如自己身体力行,写代码往往比读懂代码更快。
后面我们会讲述如何实现该MVC框架。
分享到:
相关推荐
"超轻量级MVC框架的设计和实现(源码)"是针对这个概念的一个具体实例,它强调了框架的简洁性和无XML配置特性。开发者通常会避免使用XML配置,因为它们可能增加代码的阅读和维护难度。相反,使用Java 5注解可以将配置...
总的来说,"C# MVC+layui.js超轻量级框架(包含数据库)"提供了一个开箱即用的解决方案,适合初学者和有一定经验的开发者快速搭建功能完善的Web应用。通过C# MVC的后端控制和layui.js的前端呈现,结合SQLSugar的...
其中,Biny脱颖而出,它是一款由腾讯开源的高性能、超轻量级PHP框架,专为快速构建现代Web应用程序而设计。Biny以其简洁优雅的代码和易于理解的架构,吸引了许多开发者的眼球。 **框架概述** Biny遵循经典的MVC...
这个框架的核心特性体现在其超轻量级的设计,使得它在资源消耗和性能优化方面表现出色。在这款框架中,你可以发现许多现代Web开发的最佳实践,例如MVC(模型-视图-控制器)架构模式、路由系统、依赖注入等。 1. MVC...
9. **性能优化**:BroPHP的超轻量级设计意味着它有较低的内存占用和较快的执行速度。同时,框架允许开发者通过缓存策略进一步提升性能,例如使用文件缓存或Memcached、Redis等内存缓存。 10. **社区与文档**:作为...
1. **轻量级设计**:BroPHP框架的轻量化设计使得它在项目初期就能快速上手,降低了学习曲线,特别适合小型和中型项目。这种设计理念让开发者能更专注于业务逻辑,而非框架本身的复杂性。 2. **MVC模式**:BroPHP...
BroPHP作为一款超轻量级框架,它的核心特性主要体现在以下几个方面: 1. **路由系统**:BroPHP框架采用直观的路由定义方式,允许开发者通过简单的规则来处理HTTP请求,实现URL与控制器方法的映射,方便地管理应用...
总之,MiniFramework是一款非常适合初学者和小型项目开发的PHP框架,它的轻量化设计和MVC架构使得开发过程更加清晰和高效。对于希望快速搭建Web应用,同时又不想被大型框架的复杂性所困扰的开发者来说,...
Sparkweb 是一个超轻量级的简易高效的 Java WEB 开发框架,其设计思想结合了目前主流的 Spring、Struts2、Playframework、Nodejs-Expressjs、Ruby On Rails 等框架的优秀地方,完美支持 RESTful设计。 二、Sparkweb ...
StartMvc 是一个针对初学者和小型项目设计的超轻量级 PHP 框架。它的主要目标是简化 Web 应用程序的开发过程,同时保持足够的灵活性,使得开发者能够快速构建高效能的应用。在 StartMvc v2.1.2 版本中,我们看到了这...
可以快速搭建出一个项目,作为一个超轻量级的PHP框架,完美支持MVC,完全面向对象。作为一个PHPer,你还需要什么呢? 我们的口号是: 给力的超轻量级PHP框架。 原因: 用了的人都知道! DuoLamPHP框架功能概述: ...
迷你框架MiniFramework是一种常规的Apache2开源协议发布的,支持MVC和RESTful的超轻量级PHP开发框架。MiniFramework能够帮助开发者用最小的学习成本快速构建Web应用程序,在满足开发者最基础的分层开发,数据库和...
#jQM-Lazy-Loading-MVC ###目录 ##Purpose 轻量级 jQuery Mobile MVC-ish 延迟加载库。 使项目创建快速简便。 延迟加载控制器和视图。 模型留给开发人员。 辅助方法提供快速简便的 UI 功能。 ####Notes 这并...
根据提供的资料,“LMVC”被定义为一种“超轻量级MVC框架”。MVC(Model-View-Controller)架构模式是软件工程中一种常用的架构设计模式,尤其适用于Web应用程序的开发。它将应用程序分为三个核心部分:模型(Model...
可以快速搭建出一个项目,作为一个超轻量级的PHP框架,完美支持MVC,完全面向对象。作为一个PHPer,你还需要什么呢? 我们的口号是: 给力的超轻量级PHP框架。 原因: 用了的人都知道! DuoLamPHP框架功能...
JDiy是一个超轻量级的java极速开发框架,内置一个建站平台(不用写代码,生成后台管理界面),有了JDiy,您无需再折腾其它庞大的框架(如SSH) JDiy同时支持javaEE/WEB和javaSE开发环境 JDiy利用本地化Locale,中文显示...
LightningPHP是一个用于PHP的FAST超轻量级MVC(模型,视图,控制器)框架。 与大多数其他可用框架不同,LightningPHP默认情况下几乎不包含任何内容。 这是一个最小的准系统MVC框架,没有绒毛,没有复杂性并且没有...
JunePHP是一个超轻量级的PHP框架,采用MVC架构,基于PHP5.3开发。 关于数据库:数据库操作采用Medoo,支持MySQL, SQLite, MariaDB, PostgreSQL等多种数据库。 关于模板:模板引擎使用原生PHP,高效灵活,支持替换...