JFinal 是基于 Java 语言的极速 WEB + ORM 框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、Restful。
官方文档:http://www.jfinal.com/download?file=jfinal-1.8-manual.pdf
官网:http://www.jfinal.com/man
1.创建工程、准备Jar包
创建一个Maven项目,然后Pom中导入JFinal等Jar包。
Pom.xml
<dependencies>
<dependency>
<groupId>com.jfinalgroupId>
<artifactId>jfinalartifactId>
<version>1.9version>
dependency>
<dependency>
<groupId>javax.servletgroupId>
<artifactId>javax.servlet-apiartifactId>
<version>3.0.1version>
<scope>providedscope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>freemarkergroupId>
<artifactId>freemarkerartifactId>
<version>2.3.9version>
dependency>
<dependency>
<groupId>net.sf.ehcachegroupId>
<artifactId>ehcacheartifactId>
<version>2.8.1version>
dependency>
<dependency>
<groupId>c3p0groupId>
<artifactId>c3p0artifactId>
<version>0.9.1.2version>
dependency>
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>1.7.5version>
<scope>compilescope>
dependency>
<dependency>
<groupId>ch.qos.logbackgroupId>
<artifactId>logback-classicartifactId>
<version>1.0.13version>
<scope>runtimescope>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.34version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>3.8.1version>
<scope>testscope>
dependency>
dependencies>
2.创建JFinal核心配置类
JFinal属于配置极少,基本属于无XML零配置的框架,它的所有配置都在一个继承JFinalConfig的核心配置类中。
Config.java
public class Config extends JFinalConfig {
@Override
public void configConstant(Constants me) {
}//配置 JFinal 常量值
@Override
public void configHandler(Handlers me) {
}
@Override
public void configInterceptor(Interceptors me) {
}
@Override
public void configPlugin(Plugins me) {
}
@Override
public void configRoute(Routes me) {
}//来配置 JFinal 访问路由
}
3.修改Web.xml
将如下内容添加至 web.xml
<filter>
<filter-name>jfinalfilter-name>
<filter-class>com.jfinal.core.JFinalFilterfilter-class>
<init-param>
<param-name>configClassparam-name>
<param-value>com.langmy.music.config.Configparam-value>
init-param>
filter>
<filter-mapping>
<filter-name>jfinalfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
4.创建Controller访问第一个页面
(1) 创建IndexController
public class IndexController extends Controller{
public void index(){
renderFreeMarker("/index.html");//FreeMarker是模板引擎,访问普通的Html页面也可以。
}
}
Controller需要继承JFinal的Controller类。
(2) 加入路由
在Config中加入IndexController的路由
public void config(Routes me) {
me.add("/", IndexController.class);
}
路由规则如下:
controllerKey指的是是config中配置的”/”,然后在默认情况下会访问Controller会访问index()方法。
在保证Webapp下有index.html的情况下,打开浏览器打入http://localhost:8080/[项目名称]/ 就能进入index.html页面.
(3) ActionKey
JFinal 在以上路由规则之外还提供了 ActionKey 注解,可以打破原有规则。
在IndexController加入两个方法,然后IndexController变成如下:
public class IndexController extends Controller{
public void index(){
renderFreeMarker("/index.html");
}
public void showText(){
renderText("Show Text");
}
@ActionKey("actionKey")
public void testActionKey(){
renderText("Test ActionKey");
}
}
打开浏览器分别访问http://localhost:8080/[项目名称]/showText和http://localhost:8080/[项目名称]/actionKey可以看到页面如下:
5.路由拆分
JFinal 路由还可以进行拆分配置,这对大规模团队开发特别有用,以下是代码示例:
public class FrontRoutes extends Routes {
public void config() {
add("/", IndexController.class);
}
}
public class AdminRoutes extends Routes{
@Override
public void config() {
// TODO 写后台的路由
}
}
public class Config extends JFinalConfig {
.....
@Override
public void configRoute(Routes me) {
me.add(new FrontRoutes());
me.add(new AdminRoutes());
}
}
如上三段代码, FrontRoutes 类中配置了系统前端路由, AdminRoutes 配置了系统后端路由,
Config.configRoute(…)方法将拆分后的这两个路由合并起来。使用这种拆分配置不仅
可以让 Config文件更简洁,而且有利于大规模团队开发,避免多人同时修改Config版本冲突。
6.数据库操作
(1) 新建数据库
新建mysql数据库testJFinal,新建一个表user(id,user_acc,name)。
(2) 新建Model类
public class User extends Model<User>{
public static final User dao = new User();
}
(3) 加入数据库操作插件与User与表user映射:
public class Config extends JFinalConfig {
@Override
public void configPlugin(Plugins me) {
//C3p0数据源插件
C3p0Plugin cp = new C3p0Plugin("jdbc:mysql://localhost/testJFinal",
"root", "19930815");
me.add(cp);
// ActiveRecord插件
ActiveRecordPlugin arp = new ActiveRecordPlugin(cp);
me.add(arp);
arp.addMapping("user", User.class);
}
}
ActiveRecord 是 JFinal 最核心的组成部分之一,通过 ActiveRecord 来操作数据库,将极大地减少代码量,极大地提升开发效率。ActiveRecord 是作为 JFinal 的 Plugin 而存在的,所以使用时需要在 JFinalConfig 中配置ActiveRecordPlugin。
(4) 数据库操作
在IndexController中加入方法testDB。
public class IndexController extends Controller{
....
public void testDB() {
List users = User.dao.find("select * from user");
// List users = User.dao.find("select * from user where id=?",2);
//分页查询
// Page users = User.dao.paginate(1, 10, "select *","from user where id=?",2);
for(User user :users.getList()) System.out.println(user.toString()+user.getStr("user_acc"));
}
//新增一条User数据
/*User user = new User();
user.set("user_acc", "accNew");
user.set("name", "nameNew");
boolean flag = user.save();
System.out.println(flag);*/
setAttr("user", users);
renderFreeMarker("/test.html");
}
}
以下是官方文档中对于数据库操作的一些示例:
// 创建name属性为James,age属性为25的User对象并添加到数据库
new User().set("name", "James").set("age", 25).save();
// 删除id值为25的User
User.dao.deleteById(25);
// 查询id值为25的User将其name属性改为James并更新到数据库
User.dao.findById(25).set("name", "James").update();
// 查询id值为25的user, 且仅仅取name与age两个字段的值
User user = User.dao.findById(25, "name, age");
// 获取user的name属性
String userName = user.getStr("name");
// 获取user的age属性
Integer userAge = user.getInt("age");
// 查询所有年龄大于18岁的user
List<User> users = User.dao.find("select * from user where age>18");
// 分页查询年龄大于18的user,当前页号为1,每页10个user
Page<User> userPage = User.dao.paginate(1, 10, "select *", "from user
where age > ?", 18);
7.ehcache缓存加入
(1) 加入EhCachePlugin
EhCachePlugin 是 JFinal 集成的缓存插件,通过使用 EhCachePlugin 可以提高系统的并发访问速度。
在Config的configPlugin中加入:
me.add(new EhCachePlugin());
(2) 配置文件ehcache.xml
<ehcache updateCheck="false" name="defaultCache">
<diskStore path="java.io.tmpdir/music/ehcache/default" />
<defaultCache maxEntriesLocalHeap="100" eternal="false" timeToIdleSeconds="300" timeToLiveSeconds="600"
overflowToDisk="true" maxEntriesLocalDisk="100000" maxElementsInMemory="500" />
<cache name="userList" maxElementsInMemory="150" eternal="false" timeToLiveSeconds="3600"
timeToIdleSeconds="360" overflowToDisk="true"/>
ehcache>
ehcache中各种属性的配置请参考下一篇Blog 《ehcache 简单配置》。
(2) 缓存注解加入
CacheInterceptor 可以将 action 所需数据全部缓存起来, 下次请求到来时如果 cache 存在则
直接使用数据并 render,而不会去调用 action。此用法可使 action 完全不受 cache 相关代码所
污染,即插即用,以下是示例代码:
EvictInterceptor 可以根据 CacheName 注解自动清除缓存。
在相应需要加入缓存的方法上加入:
@Before(CacheInterceptor.class)
@CacheName("userList")
需要清除缓存的方法上加入:
@Before(EvictInterceptor.class)
@CacheName("userList")
我在testDB中注释了save方法,只剩下find方法,加入缓存注解。
在浏览器第一次访问这个方法的时候会调用方法加入缓存,第二次就不会再进方法。
8.LogBack日志加入
(1) 加入配置文件logback.xml
<configuration scan="true" scanPeriod="60 seconds">
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>trueresetJUL>
contextListener>
<jmxConfigurator/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<Encoding>UTF-8Encoding>
<layout class="ch.qos.logback.classic.PatternLayout">
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
pattern>
layout>
appender>
<root level="DEBUG">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
root>
configuration>
(2) 使用日志
//在类中加入:
public static Logger LOG = LoggerFactory.getLogger(IndexController.class);
//在方法中加入
if(LOG.isDebugEnabled()){
LOG.debug(users.toString());
}
源代码下载地址:https://github.com/crazyBugLzy/JFinalLearn