您的位置:首页 > 其它

Jfinal试用报告

2015-05-02 10:40 169 查看
前言

为了解决现有的开发框架配置繁琐,开发效率不高的问题。同时能适应简单业务快速开发的功能,适应多样化需求的变动减少开发人员繁琐、重复的劳动,专注于业务实现。通过讨论认为jFinal比较合适,于是乎试用了一把。本文结合网络咨料和自己的使用心得整理而成,欢迎有兴趣的同学一起探讨学习,推动开源框架向前发展。我的微信公众号见最下面的图。

为了便于sql集中管理,已有的框架也有,但个人不喜欢把sql放到xml里,于是自己写了个sqldb插件,sql放在properties里,有相同想法的同学可以试用一下,源码地址:https://git.oschina.net/wxt/jfinal-dbplugs.git

框架简介

JFinal是一款基于Java语言的开源Web开发框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、Restful风格。在拥有Java语言所有优势的同时再拥有Ruby、Python等动态语言的开发效率。使用它不但能实现多个开发框架的功能,效率方面也有极大的提升。

框架特点

MVC架构,设计精巧,使用简单

遵循COC原则,零配置,无xml

独创Db + Record模式,灵活便利

ActiveRecord支持,使数据库开发极致快速

AOP支持,拦截器配置灵活,功能强大

Plugin体系结构,扩展性强

多视图支持,支持FreeMarker、JSP、Velocity

强大的Validator后端校验功能

功能齐全,拥有struts2的绝大部分功能

体积小仅248K,且无第三方依赖

自动加载修改后的java文件,开发过程中无需重启web server

架构组成

JFinal框架由Handler、Interceptor、Controller、Render、validator和Plugin五大部分组成。每个部分都基于接口实现,支持完整的自定义,扩展性强,使用灵活,设计精巧且使用简单。JFinal的逻辑架构采用经典的MVC架构,其中包括httpServletRequest(客户端请求)、HttpServletResponse(客户端响应)、所有请求的拦截器、请求处理器(对所有请求的公共处理)、动作处理器(它是一个AOP+Command模式变种,由ActionInvocation进行调度,先执行拦截器,最后执行具体方法),这样的逻辑架构使得系统层次分明,便于开发人员理解和使用。

数据持久层以plugin方式提供ActiveRecord插件,ActiveRecord 是 JFinal 最核心的组成部分之一,通过 ActiveRecord 来操作数据库, 将极大地减少代码量,极大地提升开发效率。同时数据持久层可以使用Db + Record 模式,Db 类及其配套的Record 类,提供了在 Model 类之外更为丰富的数据库操作功能。使用Db 与 Record 类时,无需对数据库表进行映射。 Record 相当于一个通用的 Model,适用于快速开发。

总体的架构图如图1。



hander使用场景

配置全局参数

过滤某些不需要进入的URL,例如静态文件

记录耗时

cookie、请求参数的处理

国际化处理

设置请求头消息

interceptor使用场景

权限控制

设置属性

全局异常处理

访问统计

session处理

使用体验

路由默认规则

url 组成访问目标

localhost:8080/controllerKey

调用YourController.index()

localhost:8080/controllerKey/method

调用YourController.method()

localhost:8080/controllerKey/method/v0-v1

调用YourController.method(),所带 url 参数值为:v0-v1

localhost:8080/controllerKey/v0-v1

调用YourController.index(),所带 url 参数值为:v0-v1

页面数据校验

@Before(BlogValidator.class)

public void save() {

Blog me=getModel(Blog.class);

me.set("id", 2);

me.save();

redirect("/blog");

}

校验使用AOP拦截器实现。

页面数据处理

数据获取调用框架的getModel,将resquest中的数据自动映射到Blog类中;也可以在Controller中直接获取数据,getPara(“id”);

持久层配置

单数据源配置

持久层使用ActiveRecord,以下是 Plugin 配置示例代码

C3p0Plugin cp = new C3p0Plugin("jdbc:mysql://localhost/db_name",

"userName", "password");

me.add(cp);

ActiveRecordPlugin arp = new ActiveRecordPlugin(cp);

me.add(arp);

arp.addMapping("user", User.class);

arp.addMapping("article", "article_id", Article.class);

以上代码配置了两个插件:C3p0Plugin 与 ActiveRecordPlugin,前者是 c3p0 数据源插件,ActiveReceord 中定义了 addMapping(String tableName, Class<? extends Model> modelClass>)方法,该方法建立了数据库表名到 Model 的映射关系。

User类定义如下:

public class User extends Model<User> {

public static final User dao = new User();

}

User类中无须定义属性,框架启动时会从数据库中把对应表“user”中的字段通过反射机制实例化到user中,通过user. getStr(String attr)获取从数据库中查询的数据,若数据库字段名有变动加别名解决应用需要同步修改的问题。

多数据源配置

// 配置Druid 数据库连接池插件

DruidPlugin dbPlugin = new DruidPlugin(getProperty("jdbcUrl"), getProperty("user"), getProperty("password") );

me.add(dbPlugin);

// 配置ActiveRecord插件

ActiveRecordPlugin arp = new ActiveRecordPlugin("mysql", dbPlugin);

me.add(arp);

// h2数据库

JdbcConnectionPool cpH2 = JdbcConnectionPool.create(MonitorConfig.dbUrl, MonitorConfig.dbUserName, MonitorConfig.dbPassword);

ActiveRecordPlugin arpH2 = new ActiveRecordPlugin("h2", cpH2);

me.add(arpH2);

arpH2.addMapping("blog", Blog.class); // 映射blog 表到 Blog模型

arp.addMapping("blog", Blog1.class); // 映射blog 表到 Blog模型

数据库操作

实体对应操作的数据库为ActiveRecordPlugin中配置的数据库,可以在初始化时指定不同的数据库,对应配置的代码为:arp.addMapping("user", User.class);操作的数据库对arp配置的数据库。

新增

@Before(BlogValidator.class)

public void save() {

Blog me=getModel(Blog.class);

me.set("id", 2);

me.save();

redirect("/blog");

}

另一种方式

Record user = new Record().set("name", "James").set("age", 25);

Db.save("user", user);

修改

@Before(BlogValidator.class)

public void update() {

getModel(Blog.class).update();

redirect("/blog");

}

删除

public void delete() {

Blog.me.deleteById(getParaToInt());

redirect("/blog");

}

另一种方式

// 删除id值为25的user表中的记录

Db.deleteById("user", 25);

单表查询

public void query() {

setAttr("blog", Blog.me.findById(getParaToInt()));

}

另一种方式

// 查询id值为25的user, 且仅仅取name与age两个字段的

user = Db.findById("user", 25, "name, age");

复杂sql查询

public void relation() {

String sql = "select b.*, u.user_name from blog b inner

join user u on b.user_id=u.id where b.id=?";

Blog blog = Blog.dao.findFirst(sql, 123);

String name = blog.getStr("user_name");

}

说明:返回的blog属性多了name,只要不重复就不会报错,相当于blog对象是的属性是不固定的,根据查询的结果动态增加。

另一种方式查询

// 查询 dsMysql数据源中的 user

List<Record> users = Db.use("mysql").find("select * from user");

// 查询 dsOracle数据源中的 blog

List<Record> blogs = Db.use("oracle").find("select * from blog");

数据库事物

boolean succeed = Db.tx(new IAtom(){

public boolean run() throws SQLException {

int count = Db.update("update account set cash = cash - ? where

id = ?", 100, 123);

int count2 = Db.update("update account set cash = cash + ? where

id = ?", 100, 456);

return count == 1 && count2 == 1;

}});

以上两次数据库更新操作在一个事务中执行,如果执行过程中发生异常或者 invoke()方法

返回 false,则自动回滚事务。

方法2

声名式事务处理

@Before(Tx.class)

public void trans_demo() {





返回页面数据处理

render 系列方法将渲染不同类型的视图并返回给客户端。JFinal 目前支持的视图类型有:

FreeMarker、JSP、Velocity、JSON、File、Text、Html 等等。除了 JFinal 支持的视图型以外,

还可以通过继承 Render 抽象类来无限扩展视图类型。

render(String view)使用例子:

方法调用 描述

render(”test.html”) 渲染名为 test.html 的视图,该视图的 全路径为”/path/test.html”

render(”/other_path/test.html”) 渲染名为 test.html 的视图,该视图的全路径为”/other_path/test.html”,即当参数以”/”开头时将采用绝对路径

其它 render 方法使用例子:

方法调用 描述

renderFreeMarker(”test.html”) 渲染 名为 test.html 的视图 , 且 视图类 型为FreeMarker。

renderJsp(”test.html”) 渲染名为 test.html 的视图,且视图类型为 Jsp。

renderVelocity(“test.html”) 渲染名为 test.html 的视图,且视图类型为 Velocity。

renderJson()将所有通过 Controller.setAttr(String, Object)设置的变量转换成 json 数据并渲染。

renderJson(“users”, userList) 以”users”为根,仅将 userList 中的数据转换成 json数据并渲染。

renderJson(user) 将 user 对象转换成 json 数据并渲染。
http://www.jfinal.com
renderJson(“{\”age\”:18}” ) 直接渲染 json 字符串。

renderJson(new String[]{“user”, “blog”})仅将 setAttr(“user”, user)与 setAttr(“blog”, blog)设置的属性转换成 json 并渲染。使用 setAttr 设置的其它属性并不转换为 json。

renderFile(“test.zip”); 渲染名为 test.zip 的文件,一般用于文件下载

renderText(“Hello JFinal”) 渲染纯文本内容”Hello JFinal”。

renderHtml(“Hello Html”) 渲染 Html 内容”Hello Html”。

renderError (404 , “test.html”) 渲染名为 test.html 的文件,且状态为 404。

renderError (500 , “test.html”) 渲染名为 test.html 的文件,且状态为 500。

renderNull() 不渲染,即不向客户端返回数据。

render(new XmlRender())使用自定义的 XmlRender 来渲染。

结论

通过研究发现JFinal不但可以很好的代替SSH作为Java Web开发的首选框架,而且该框架的思想使java获得第二春,它改变了我们对传统java框架的认识,与Ruby、Python等动态语言的开发效率相媲美;该框架虽然为国人开发,但文档齐全,目前还有视频教学,极大降低了开发人员的学习成本,有利于新手快速入门,比起流行的SSH框架学习成本要低很高。Jfinal为开源框架,源代码非常小,可以快速地通读源码,对源码的充分理解解决了外部框架不可控的问题。

附录

官网
http://www.jfinal.com/
视频文档:
http://jfinalxm.sturgeon.mopaas.com/
jfinal-ext介绍

是对java极速web框架 jfinal 的一个扩充,主要利用jfinal微内核高扩展的特性扩展常用的实用功能和集成各种第三方框架,简化开发者的学习应用成本,引入了guava和joor包,代码更简洁。

常用的插件基本都有

其它插件介绍

cn.dreampie.jfinal-tablebind
https://github.com/Dreampie/jfinal-tablebind jfinal的table自动绑定插件,支持多数据源

cn.dreampie.jfinal-quartz
https://github.com/Dreampie/jfinal-quartz 基于jfinal 的quartz管理器

cn.dreampie.jfinal-sqlinxml
https://github.com/Dreampie/jfinal-sqlinxml 基于jfinal 的类似ibatis的sql语句管理方案

cn.dreampie.jfinal-akka
https://github.com/Dreampie/jfinal-akka java使用akka执行异步任务

cn.dreampie.jfinal-mailer
https://github.com/Dreampie/jfinal-mailer 使用akka发布邮件的jfinal插件

cn.dreampie.jfinal-slf4j
https://github.com/Dreampie/jfinal-slf4j 让jfinal使用slf4j的日志api

cn.dreampie.jfinal-lesscss
https://github.com/Dreampie/jfinal-lesscss java实现的lesscsss实时编译插件,可以由于jfinal

cn.dreampie.jfinal-shiro
https://github.com/Dreampie/jfinal-shiro 支持注解和数据库配置的shiro插件

cn.dreampie.jfinal-shiro-freemarker
https://github.com/Dreampie/jfinal-shiro-freemarker shiro插件实现的freemarker标签库

cn.dreampie.jfinal-web
https://github.com/Dreampie/jfinal-web 相关web插件,简洁model实现

cn.dreampie.jfinal-utils
https://github.com/Dreampie/jfinal-utils 部分jfinal工具

cn.dreampie.jfinal-flyway
https://github.com/Dreampie/jfinal-flyway 数据库脚本升级插件,开发中升级应用时,使用脚本同步升级数据库或者回滚

cn.dreampie.jfinal-captcha

基于jfinal render的超简单验证吗插件

cn.dreampie.jfinal-coffeescript
https://github.com/Dreampie/jfinal-coffeescript java实现的coffeescript实时编译插件

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: