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.jfinal</groupId>
<artifactId>jfinal</artifactId>
<version>1.9</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.9</version>
</dependency>
<!-- EHCACHE begin -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.0.13</version>
<scope>runtime</scope>
</dependency>
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.34</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</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>jfinal</filter-name>
<filter-class>com.jfinal.core.JFinalFilter</filter-class>
<init-param>
<param-name>configClass</param-name>
<param-value>com.langmy.music.config.Config</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>jfinal</filter-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<User> users = User.dao.find("select * from user");
// List<User> users = User.dao.find("select * from user where id=?",2);
//分頁查詢
// Page<User> 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
<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" name="defaultCache">
<diskStore path="java.io.tmpdir/music/ehcache/default" />
<!-- DefaultCache setting. -->
<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
<?xml version="1.0" encoding="UTF-8"?>
<!-- configuration file for LogBack (slf4J implementation)
See here for more details: http://gordondickens.com/wordpress/2013/03/27/sawing-through-the-java-loggers/ -->
<configuration scan="true" scanPeriod="60 seconds">
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
<resetJUL>true</resetJUL>
</contextListener>
<!-- To enable JMX Management -->
<jmxConfigurator/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<!-- 日誌輸出編碼 -->
<Encoding>UTF-8</Encoding>
<layout class="ch.qos.logback.classic.PatternLayout">
<!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日誌消息,%n是換行符-->
<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());
}