JFinal的初了解(二)

上一節介紹了jfinal框架的簡單搭建,這節通過一個小例子了解jfinal的結構和特點


image.png
image.png

1、建數據庫(我用的是oracle數據庫,其他的相對也差不多)

create table CLASSES
(
 classesid      NUMBER not null,
 classesname    VARCHAR2(20),
 classesaddress VARCHAR2(50)
);
-- Create table
create table STUDENT
(
 studentid   NUMBER not null,
 studentname VARCHAR2(10),
 studentage  NUMBER,
 studentsex  VARCHAR2(2),
 classesid   NUMBER
);
alter table STUDENT
 add constraint FK_CLASSESID foreign key (CLASSESID)

新建項目,我用的myeclipse,先把jar包導入

2、實體類
Classes.java

package com.demo.model;

import com.jfinal.plugin.activerecord.Model;

public class Classes extends Model<Classes> {
   public static final Classes dao = new Classes();
}

Student.java

package com.demo.model;

import com.jfinal.plugin.activerecord.Model;

public class Student extends Model<Student> {
   public static final Student dao = new Student();

   public Classes getClasses() {
       return Classes.dao.findById(get("classesid"));
   }

}

什么這是實體類?沒錯?。 ActiveRecord 是 jfinal 最核心的組成部分之一,通過 ActiveRecord 來操作數據庫,將極大地減少代碼量,極大地提升開發效率,配置在后面,我這里用的是Model,Model 是 ActiveRecord 中最重要的組件之一,它充當 MVC 模式中的 Model部分。
以上代碼中的 User 通過繼承 Model,便立即擁有的眾多方便的操作數據庫的方法。在 User 中聲明的 dao 靜態對象是為了方便查詢操作而定義的,該對象并不是必須的。 基于ActiveRecord 的 Model 無需定義屬性, 無需定義 getter、 setter方法,無需 XML 配置,無需 Annotation 配置,極大降低了代碼量。Model常見方法見官方API。

JFinal還有 獨創 Db + Record 模式,Db 類及其配套的 Record 類, 提供了在 Model 類之外更為豐富的數據庫操作功能。使用 Db 與 Record 類時,無需對數據庫表進行映射,Record 相當于一個通用的 Model。Db常見方法見官方API。

3、DemoConfig.java

package com.demo.config;

import com.demo.controller.ClassesController;
import com.demo.controller.StudentController;
import com.demo.model.Classes;
import com.demo.model.Student;
import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.CaseInsensitiveContainerFactory;
import com.jfinal.plugin.activerecord.dialect.OracleDialect;
import com.jfinal.plugin.c3p0.C3p0Plugin;

public class DemoConfig extends JFinalConfig {

   @Override
   public void configConstant(Constants me) {
   }

   @Override
   public void configHandler(Handlers me) {
       // TODO Auto-generated method stub

   }

   @Override
   public void configInterceptor(Interceptors me) {
       // TODO Auto-generated method stub

   }

   @Override
   public void configPlugin(Plugins me) {
       C3p0Plugin cp = new C3p0Plugin("jdbc:oracle:thin:@localhost:1521:orcl",
               "test", "test");
       // 配置Oracle驅動
       cp.setDriverClass("oracle.jdbc.driver.OracleDriver");
       me.add(cp);
       ActiveRecordPlugin arp = new ActiveRecordPlugin(cp);
       me.add(arp);
       // 配置Oracle方言
       arp.setDialect(new OracleDialect());
       // 配置屬性名(字段名)大小寫不敏感容器工廠
       arp.setContainerFactory(new CaseInsensitiveContainerFactory());
       arp.addMapping("student", "studentid", Student.class);
       arp.addMapping("classes", "classesid", Classes.class);
   }

   @Override
   public void configRoute(Routes me) {
       me.add("/", StudentController.class);
       me.add("/student", StudentController.class);
       me.add("/classes", ClassesController.class);
   }

}

我這里是oracle數據庫的配置,oracle有些特別的地方,如表列名會自動轉成大寫,配置個免大小寫的工廠,方便開發等。這里要注意url,驅動,方言,在給個mysql數據庫的配置對比下

public class DemoConfig extends JFinalConfig {
public void configPlugin(Plugins me) {
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);
}
}

4、StudentController.java

package com.demo.controller;

import java.util.List;

import com.demo.interceptor.StudentInterceptor;
import com.demo.model.Student;
import com.demo.validator.StudentValidator;
import com.jfinal.aop.Before;
import com.jfinal.core.Controller;

public class StudentController extends Controller {
   @Before(StudentInterceptor.class)
   public void index() {
       List<Student> list = Student.dao.find("select * from student");
       setAttr("studentList", list);
       render("/index.html");
   }

   public void add() {
       render("/add.html");
   }

   public void delete() {
       // 獲取表單域名為studentID的值
       // Student.dao.deleteById(getPara("studentID"));
       // 獲取url請求中第一個值
       Student.dao.deleteById(getParaToInt());
       forwardAction("/student");
   }

   public void update() {
       Student student = getModel(Student.class);
       student.update();
       forwardAction("/student");
   }

   public void get() {
       Student student = Student.dao.findById(getParaToInt());
       setAttr("student", student);
       render("/index2.html");
   }

   @Before(StudentValidator.class)
   public void save() {
       Student student = getModel(Student.class);
       student.set("studentid", "mysequence.nextval").save();
       forwardAction("/student");
   }

}

獲取studentid那里有多種方法,這個要和前臺傳參寫法一致,Controller 提供了 getPara 系列方法,官網api里很詳細

jfinal用的是原生態sql語句,簡單,方便,setAttr("studentList", list);把結果集放到request范圍里,

jfinal也有直接獲取表單里分裝成對象的方法 getModel(Student.class);就是,和struts2一樣,表單name對應上就可以了,非常方便

添加那里對于oracle用序列維護studentid student.set("studentid", "mysequence.nextval").save(); jfinal有多種返回方式,也可以返回json數據,render 系列方法,官網api里很詳細

5、interceptor和validator(可以不加)

StudentInterceptor.java
package com.demo.interceptor;

import com.jfinal.aop.Interceptor;
import com.jfinal.core.ActionInvocation;

public class StudentInterceptor implements Interceptor {

   public void intercept(ActionInvocation ai) {
       System.out.println("Before action invoking");
       ai.invoke();
       System.out.println("After action invoking");
   }

}

StudentValidator.java

[[圖片上傳中...(image-2d09fd-1514102168223-6)]](javascript:void(0); "復制代碼")

package com.demo.validator;

import com.jfinal.core.Controller;
import com.jfinal.validate.Validator;

public class StudentValidator extends Validator {

   //在校驗失敗時才會調用
   @Override
   protected void handleError(Controller controller) {
       controller.keepPara("student.studentname");//將提交的值再傳回頁面以便保持原先輸入的值
       controller.render("/add.html");
   }

   @Override
   protected void validate(Controller controller) {
       //驗證表單域name,返回信息key,返回信息value
       validateRequiredString("student.studentname", "studentnameMsg",
               "請輸入學生名稱!");
   }

}

6、頁面

我這里用的是FreeMarker模板引擎
index.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
   <head>
       <title>index.html</title>

       <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
       <meta http-equiv="description" content="this is my page">
       <meta http-equiv="content-type" content="text/html; charset=UTF-8">

       <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->

   </head>

   <body>
       <a href="/student/add">添加</a>
       <table border="1">
           <tr>
               <td>
                   姓名
               </td>
               <td>
                   年齡
               </td>
               <td>
                   性別
               </td>
               <td>
                   班級
               </td>
               <td>
                   操作
               </td>
           </tr>
           <#list studentList as student>
           <tr>
               <td>
                   ${student.studentname}
               </td>
               <td>
                   ${student.studentage}
               </td>
               <td>
                   ${student.studentsex}
               </td>
               <td>
                   ${student.getClasses().classesname}
               </td>
               <td>
                   <a href="/student/delete/${student.studentid}">刪除</a>
                   <a href="/student/get/${student.studentid}">修改</a>
               </td>
           </tr>
           </#list>

       </table>
   </body>
</html>

index2.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
   <head>
       <title>index2.html</title>

       <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
       <meta http-equiv="description" content="this is my page">
       <meta http-equiv="content-type" content="text/html; charset=UTF-8">

       <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->

   </head>

   <body>
       <form action="/student/update" method="post">
           <input type="text" name="student.studentid" value="${student.studentid}"/>
           姓名:
           <input type="text" name="student.studentname"  value="${student.studentname}"/>
           <br />
           年齡:
           <input type="text" name="student.studentage" value="${student.studentage}"/>
           <br />
           性別:
           <input type="text" name="student.studentsex" value="${student.studentsex}"/>
           <br />
           班級:
           <input type="text" name="student.classesid" value="${student.classesid}" />
           <br />
           <input type="submit" value="保存" />
       </form>

   </body>
</html>

add.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
   <head>
       <title>add.html</title>

       <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
       <meta http-equiv="description" content="this is my page">
       <meta http-equiv="content-type" content="text/html; charset=UTF-8">

       <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->

   </head>

   <body>
       <form action="/student/save" method="post">
           姓名:
           <input type="text" name="student.studentname" />${studentnameMsg!}${studentnameLMsg!}
           <br />
           年齡:
           <input type="text" name="student.studentage" />
           <br />
           性別:
           <input type="text" name="student.studentsex" />
           <br />
           班級:
           <input type="text" name="student.classesid" />
           <br />
           <input type="submit" value="保存" />
       </form>
   </body>
</html>
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,565評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,115評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 177,577評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,514評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,234評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,621評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,641評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,822評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,380評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,128評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,319評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,879評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,548評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,970評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,229評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,048評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,285評論 2 376

推薦閱讀更多精彩內容