先从Controller入手,用户登录,经过路由转发,到达Controller类,在Action中进行对应的处理。
1.登录:
地址:http://localhost:8080/Jdemo/index.jsp
跳转:http://localhost:8080/Jdemo/users/loginUsers
Action类的代码:
@Before(ControllerInterceptor.class)
public class UsersController extends Controller {
private IUsersService us = new UsersServiceImpl();
/**
* 用户登录Action
*/
@Before({ LoginValidator.class, ActionInterceptor.class })
public void loginUsers() {
String uName = getPara("USERS.UNAME");
String uPswd = getPara("USERS.UPSWD");
Users u = us.getUsers(uName, uPswd);
System.out.println(u);
if (null != u) {
setSessionAttr("CURRENT_USER", u);
renderJsp("/users/home.jsp");
} else {
setAttr("loginUsersMsg", "用户名或密码错误!");
renderJsp("/index.jsp");
}
}
}
使用Annotation无侵入式的在类上别添加了Controller级别的拦截器,在Action上添加了Action级别的拦截器和登录校验。
在配置类中添加Global级别的拦截器
@Override
public void configInterceptor(Interceptors me) {
me.add(new GlobalInterceptor());
}
下面是登录动作完成后,控制台显示信息,可以反映一次请求应答过程。
分析说明:
第一步:全局拦截器;
第二步:进入Controller级别拦截器;
第三步:为loginUsers方法设置了校验类,进入校验方法(校验通过进入第四步)
第四步:进入Action级别拦截器;
第五步:通过Action将请求信息传信息给Service和Model进行数据处理,并返回到视图;
第六步:各级别拦截器以栈的顺序退出。
2.查看所有用户:
地址:http://localhost:8080/Jdemo/users/showUsersList
转到:http://localhost:8080/Jdemo/users/home.jsp页面
Action类代码:
/**
* 获取所有用户的信息的Action
*/
public void showUsersList() {
@SuppressWarnings("unchecked")
List<Users> listUsers = us.getUsersAll();
setAttr("LIST_USERS", listUsers);
renderJsp("/users/home.jsp");
}
执行流程结束,控制台信息:
从控制台显示信息可以看到没有了Action级别的拦截器,同是可以看到showUsersList()方法上也没有添加注解信息(Action级别的拦截器)。
3.上传文件:
Jsmart/JFinal提供了非常方便的可上传10M的大小的文件。
上传文件的方法很简单,直接调用Controller的方法,getFile(...);
参见例子:
/**
* 上传用户资料的Action
*/
public void uploadImage() {
String uId = getPara("uId");
String realPath = getPara("realPath");
String uploadPath = ServiceUtils.newSaveDir(realPath);
//*******************************************
//***********获取表单中的File立即上传********
//*******************************************
UploadFile ufile = getFile("uImage", uploadPath);
if (null != ufile) {
ServiceUtils.renameFile(ufile, uId);
setSessionAttr("UPLOAD_MSG", "上传成功!");
} else {
setSessionAttr("UPLOAD_MSG", "上传失败!");
}
redirect("/users/showUsersList");
}
JFinal的作者给出的修改上传文件名的方式和我做的不谋而合,这也是提供一种为上传文件添加时间戳的方式。
上面代码中的ServiceUtils.renameFile(UploadFile uploadFile, <Type> newName)给予具体实现。
public static void renameFile(UploadFile uf, String newName) {
File uf.getFile();
String srcName = src.getName();
String dstName = src.getParent() + File.separator + newName
+ srcName.substring(srcName.indexOf('.'));
File dst = new File(dstName);
/**
* 重命名的文件存在则删除!
*/
if (dst.exists()) {
dst.delete();
}
src.renameTo(dst);
}
关于文件下载,JFinal/Jsmart框架提供了一个很好用的方法renderFile(File f);该法直接为页面产生一个指定的下载文件,非常简单方便。
JFinal/Jsmart框架很灵活,很注重解决实际问题,撇开了很多很少用到的功能,并提供了插件机制为扩展提供的基础。
框架工作流程如上面两个例子1,2,文件下载,上传如例子3。
关于数据访问很有ibatis的味道,通过配置sql,Model和数据库表映射来完成。
表映射
package com.broncho.jsmart.model.users; import com.jsmart.ext.plugin.tablebind.TableBind; import com.jsmart.plugin.activerecord.Model; /** * Users表的数据模型 * * @author Broncho * @time 2013年7月17日 09:17:18 */ @TableBind(tableName = "USERS", pkName = "UID") public class Users extends Model<Users> { /** * */ private static final long serialVersionUID = 5631774099405889205L; /** * Users数据模型的共享对象 */ public static final Users dao = new Users(); }
数据库访问
配置SQL文件
<?xml version="1.0" encoding="UTF-8"?> <sqlGroup name="USERS"> <sql id="queryCurrentUsers"> SELECT * FROM USERS WHERE UNAME=? AND UPSWD=? </sql> </sqlGroup>
查询实例:
@Override public Users getUsers(String uName, String uPswd) { List<Users> ulist = null; ulist=Users.dao.find("USERS.queryCurrentUsers", new Object[]{uName,uPswd}); Users u = null; if (null != ulist && ulist.size() != 0) { u = ulist.get(0); } return u; }
SQL配置文件使用了Group-Id的方式来管理SQL语句,这样就可以用GroupName.Id的方式使用配置好的SQL语句。
JFinal正真的做到了所描述的那些特性,而每一种特性都可一从已有的框架中看到,学习起来容易,比如:Action和Struts2的Action同理,Model层的数据库访问和ibatis框架同理,还有体现了约定优于配置,做到了可扩展,可插拔的,轻量级,无依赖的优势。JFinal更像是化繁为简,为己所有的一款框架,更像是开发者为了逃离繁琐,减轻学习负担而开发的框架。