这篇文章是《自己动手设计一个Web框架》文章的续,经过和大家的讨论我总结并归纳一下对《Haweb》这款框架的期待。
首先要感谢各位的热烈讨论,包括线上的还有线下QQ群里的兄弟们。我归纳总结一下大家对于一个框架的期待,不如果有同学觉得还可以有补充的也欢迎随时评论。
总体而言我感觉其实大家对一个框架的要求也蛮多,蛮现实的。现在我简单归纳一下这么几类要求。
- 基本要求,Web框架本身应该具有的一些基本功能。例如:mvc、restful。
- 可以操作数据库,例如数据库操作接口“ORM”、“AR”、“JDBC”等等方式。
- 测试工具,每次开发应用的时候可以快速的测试应用,这一点在Web框架上也有需求。
- 可扩展性,一个良好的框架应该具备一定的可塑性。通过对框架的制定,来完成当初没有考虑到的功能点。
- 代码生成器,我们希望能有一个工具生成一些代码来让我们少做一些重复的事情。
上面我主要列了五大类期望,现在分别讨论一下每一个类别对于《Haweb》的期望都有哪些。为了简单方便,我用列表的方式罗列一下希望提供怎样的特性。
一、基本要求
- 要支持一般的MVC模式,可以通过编写一个类或者方法来处理Web请求。例如:
@MappingTo("/apis/customer") public class Customer extends BaseController { public void execute(@Params PushServiceForm pushServiceForm) { .... } }
- 要支持restful这种风格的API形式,将来可以方便我们开发服务或者其它什么。它看起来应该类似下面这样的:
@MappingTo("/apis/customer/{userID}/{method}") public class Customer extends BaseController { public void execute(@Param("userID") userID , @Param String method) { System.out.println("/apis/customer"); } }
- 希望它支持表单验证,在处理表单的时候如果有一个验证框架帮我们拦一刀会很不错。类似这样:
@MappingTo("/apis/heartbeat") public class Heartbeat extends BaseController { public void execute(@Valid("Access") @Params HeartBeatForm heartBeatForm) { //access验证 } }
-
页面渲染,通过模版引擎或者jsp的形式,可以方便的把数据输出到页面上。例如:
<#if message.type == 0> <div class="list-group paddingBottom"><#list resultList.result as appDO> <#include "/control/app_info.htm"> <#assign pageBaseURL="appManager.htm?1=1"> <#include "/control/pageInfo.htm"> </#list></div> <#else> <div class="panel panel-default"> <div class="panel-body">消息:${message.type} - ${message.message}</div> </div> </#if>
-
上面这个用的是freemarker的语法,当然有的时候我们想换一个模版引擎,这个也要支持。
-
页面装饰器,通常我们会设计一个全网吊顶。每个页面都要加上这个吊顶,但是我又不想在每个页面模版文件中去加这个东西。我希望在一个地方定义一个模版,其它的所有页面就都有这个吊顶了。
-
要能落实前后端分离操作,有些时候后端只需要吐出JSON数据就可以了。相关业务逻辑要交给前端JS去处理。
-
减轻依赖,放弃我们熟知的Spring、Hibernate等。
-
最简化配置,最好的情况是我不需要编写任何配置文件。尤其向Spring那样的开启一个注解化配置还要写配置文件……*&¥%……#@¥……&#
-
要能够进行分布式部署,框架最好能帮助我们解决Session的问题。
-
最后一条,要有一个简单的、唯一扩展方式方便扩展。
二、可以操作数据库
- 至少要有一个可以操作数据的接口,例如:
/**新增用户:默罕默德*/ protected void insertUser_MHMD() throws SQLException, InterruptedException { JdbcTemplate jdbcTemplate = appContext.getInstance(JdbcTemplate.class); String insertUser = "insert into TB_User values(?,'默罕默德','123','mmd@hasor.net',?)"; System.out.println("insert new User ‘默罕默德’..."); jdbcTemplate.update(insertUser, newID(),new Date());//执行插入语句 }
-
说到数据库,框架一定要能支持数据库事务,例如:
@Transactional() public void doTransactional() throws Throwable { System.out.println("begin T2!"); /*安妮.贝隆*/ insertUser_ANBL(); /*吴广*/ insertUser_WG(); System.out.println("commit T2!"); }
-
要能够支持嵌套事务。关于嵌套事务可以参考这篇文章《http://my.oschina.net/u/1166271/blog/199546》
-
有的时候事务不一定要加在方法上,我们想在程序中控制的更多。那么还要能够手动控制事务,例如:
TransactionTemplate temp = appContext.getInstance(TransactionTemplate.class); temp.execute(new TransactionCallbackWithoutResult() { public void doTransactionWithoutResult(TransactionStatus tranStatus) throws Throwable { System.out.println("begin T1!"); /*T1 - 默罕默德*/ insertUser_MHMD(); /*T2 - 安妮.贝隆、吴广*/ doTransactional(); /*T1 - 赵飞燕*/ insertUser_ZFY(); System.out.println("commit T1!"); } });
-
最好能够在配上一个ORM功能,例如:
@Table("Pojo") public class PojoBean implements PojoInfo { @Field(type = DBEnum.PK) private String uuid; @Field() private String name; @Field() private String address; //
-
这样就可以直接将对象保存到数据库或者更新对象了。
三、测试工具
-
普通的单元测试,一般无法满足对web程序的要求。所以测试上框架最好能够提供测试的支持。例如:
@WTest() public void webTest(TestContext context) throws SQLException { ReqMethod req = context.doPost("/logins/login.do"); req.put("userName",1234); req.put("userPassword",1234); int status = req.doCall(); if (status ==200){ context.put("userID",1234); context.put("pageSize",2); req = context.doGet("/userList/index.htm?userID={userID}&pageSize={pageSize}"); status = req.doCall(); ...context... } }
四、扩展性
-
要能支持Token的生成和验证,在安全上提供支持。
-
要能对网站的静态资源做管理,比方说我把静态资源放到一个压缩包里以减少体积加快打包速度。但是又不能影响正常的资源访问。
-
要有国际化的支持,可以方便的根据用户所在区域自动的调出对应的方言。
-
要能支持用户登录和权限判断。
-
要能支持JSON渲染。
-
要能支持一些自定义的函数功能,这些函数功能在渲染页面的时候可以方便的使用。
-
要有一些内置的函数可以方便的在页面渲染中使用,例如判断字符串,时间格式转换等等。
五、代码生成机制
-
要能够提供一种机制可以解放重复模式代码的初始化,例如新建一个实体Bean、生成对应的XML映射文件、生成对应的DAO。
-
其它需要代码生成器的场景。