YangMVC-一個(gè)易學(xué)易用高效便捷的MVC和ORM框架

YangMVC

開(kāi)發(fā)目的

@copyright 楊同峰 保留所有權(quán)利

本文可以轉(zhuǎn)載,但請(qǐng)保留版權(quán)信息雳灾。

SSH框架配置復(fù)雜涨岁、難用拐袜。個(gè)人認(rèn)為這不是一個(gè)框架應(yīng)該有的樣子∩倚剑框架應(yīng)該使用簡(jiǎn)單阻肿、配置簡(jiǎn)單、代碼簡(jiǎn)潔沮尿。于是參照Django的一些特性丛塌,編寫(xiě)了這個(gè)MVC+ORM框架。

特性

  1. 大量的默認(rèn)約定畜疾,避免了大量的配置
  2. 配置方便赴邻、使用便捷、易于上手
  3. 支持延遲加載技術(shù)的List
  4. 和JSTL無(wú)縫兼容

配置

  1. 新建一個(gè)Web Project(MyEclipse為例)

  2. 將以下jar放到WebRoot/Web-INF下面
    yangmvc-1.6-all-in-one.jar
    下載地址
    http://git.oschina.net/yangtf/YangMVC/attach_files

  3. 在web.xml中(web-app標(biāo)簽內(nèi))加入

  <filter>
    <filter-name>yangmvc</filter-name>
    <filter-class>org.docshare.mvc.MVCFilter</filter-class>
    <init-param>
      <param-name>controller</param-name>
      <param-value>org.demo</param-value>
    </init-param>
    <init-param>
      <param-name>template</param-name>
      <param-value>/view</param-value>
    </init-param>
  </filter>
  
  <filter-mapping>
    <filter-name>yangmvc</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <context-param>
    <param-name>dbhost</param-name>
    <param-value>localhost</param-value>
  </context-param>
  <context-param>
    <param-name>dbusr</param-name>
    <param-value>root</param-value>
  </context-param>
  <context-param>
    <param-name>dbpwd</param-name>
    <param-value>123456</param-value>
  </context-param>
  <context-param>
    <param-name>dbname</param-name>
    <param-value>mvc_demo</param-value>
  </context-param>
  <context-param>
    <param-name>dbport</param-name>
    <param-value>3306</param-value>
  </context-param>  

所有需要配置的都在這里了啡捶。這里做個(gè)簡(jiǎn)要說(shuō)明
MVCFilter是我們MVC框架的入口姥敛。(不管是啥MVC框架都免不了這個(gè))
它有controller和template兩個(gè)參數(shù)银择。
controller 是你控制器存放位置的包名变抽。 比如這里是org.demo 你建立的控制器都必須寫(xiě)在這個(gè)包中
template是你存放模板(視圖)的地方曙求。這個(gè)路徑是相對(duì)于WebRoot即網(wǎng)站根目錄的卖词。
比如這里的配置(/view)是WebRoot下的view目錄。

dbhost dbname dbusr dbpwd 是數(shù)據(jù)庫(kù)的 地址墨榄、數(shù)據(jù)庫(kù)名玄糟、用戶(hù)名和密碼。目前這個(gè)MVC框架只支持MySQL袄秩,后續(xù)會(huì)添加其他數(shù)據(jù)庫(kù)的支持阵翎。

注意,模板目錄(template參數(shù)所配置的值)以/開(kāi)頭之剧,如/view郭卫。

YangMVC的第零個(gè)例子-HelloWorld程序

public class IndexController extends Controller {
    public void index(){
        output("Hello YangMVC");
    }
}

他的作用就是顯示一句話(huà)。如圖

第零個(gè)例子的顯示

IndexController來(lái)處理應(yīng)用的根目錄下的請(qǐng)求背稼。 index方法來(lái)處理這個(gè)目錄下的默認(rèn)請(qǐng)求贰军。

YangMVC第一個(gè)Demo

在org.demo包下建立此類(lèi):

public class BookController extends Controller {
    public void index(){
        DBTool tool = Model.tool("book");
        LasyList list = tool.all().limit(0, 30);
        put("books", list);
        render();
    }
}

在WebRoot/view/book/下建立一個(gè)index.jsp
其中核心的代碼為

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
(此處省略一堆無(wú)關(guān)的HTML代碼)
<table class="table table-bordered">
    <c:forEach var="b" items="${books }">
    <tr>
        <td>${b.id }</td>
        <td>${b.name }</td>
        <td>${b.author }</td>
        <td>${b.chaodai }</td>
        <td>${b.tm_year }</td>
        <td>
            <a href='book/edit?id=${b.id}'>編輯</a>
            <a href='book/del?id=${b.id}'>刪除</a>
        
        </td>
    </tr>
    </c:forEach>
</table>

一個(gè)顯示列表的網(wǎng)頁(yè)就此搞定。訪問(wèn)應(yīng)用目錄下的book/目錄即可顯示出結(jié)果


這里寫(xiě)圖片描述

你作出的結(jié)果可能沒(méi)那么好看蟹肘,這完全取決于css谓形。
在YangMVCDemo / WebRoot / view / book / mvc.css 中有一個(gè)漂亮的表格定義。
你可以通過(guò)類(lèi)似下面的語(yǔ)句來(lái)加入到網(wǎng)頁(yè)中

<link href="view/book/mvc.css" rel="stylesheet">

注意路徑要對(duì)疆前。

說(shuō)明:

這個(gè)BookController是一個(gè)控制器寒跳,它的每一個(gè)公共方法都對(duì)應(yīng)一個(gè)網(wǎng)頁(yè)(如果不想對(duì)應(yīng),你需要將其設(shè)為私有的)

Model和DBTool是整個(gè)ORM框架的核心竹椒。Model表示模型童太,它用來(lái)與數(shù)據(jù)庫(kù)表相對(duì)應(yīng)。在創(chuàng)建一個(gè)Model時(shí)胸完,會(huì)指定對(duì)應(yīng)的表名书释。

這里和Hibernate不同,Hibernate需要預(yù)先生成所有數(shù)據(jù)庫(kù)表的對(duì)應(yīng)類(lèi)赊窥, 而這個(gè)Model可以與任何表格關(guān)聯(lián)爆惧,而不需要預(yù)先生成任何一個(gè)類(lèi)。 這正是YangMVC中的ORM的優(yōu)勢(shì)所在锨能。

DBTool tool = Model.tool("book");

程序中使用Model的靜態(tài)方法tool獲取一個(gè)DBTool對(duì)象扯再,tool傳入的參數(shù)book是數(shù)據(jù)庫(kù)的表名。
這樣DBTool就和book表建立了關(guān)聯(lián)址遇。

LasyList list = tool.all().limit(0, 30);

伙計(jì)們快看熄阻,這是個(gè)LasyList,一個(gè)支持懶惰加載機(jī)制的列表倔约。它是List類(lèi)的子類(lèi)秃殉,這也就是它為什么能在JSTL中使用foreach變量的原因。

首先我們調(diào)用了tool的all()方法,天哪钾军,難道要加載book表的所有數(shù)據(jù)鳄袍,兄弟不用害怕,在這個(gè)時(shí)候吏恭,它并沒(méi)有進(jìn)行任何數(shù)據(jù)的讀寫(xiě)拗小,指示記錄了現(xiàn)在要訪問(wèn)book表的所有數(shù)據(jù)這一信息。 all()方法會(huì)返回一個(gè)LasyList對(duì)象砸泛。這么設(shè)計(jì)的原因是我們后面可以跟一連串的過(guò)濾方法。方便我們編程蛆封。我們可以寫(xiě)出這樣的東西:

list = tool.all().gt("id", 12).lt("id", 33).eq("name","haha").like("author","王");

這個(gè)例子相當(dāng)于執(zhí)行了如下SQL語(yǔ)句:

 select * from book where id>12 and id<33 and name='haha' and author like '%王%'

在上面的例子中唇礁, all()返回的LasyList又調(diào)用了它的limit方法,這一步仍然沒(méi)有真正訪問(wèn)數(shù)據(jù)庫(kù)惨篱。
那么訪問(wèn)數(shù)據(jù)庫(kù)從哪里開(kāi)始呢盏筐? 從你獲取這個(gè)列表的一項(xiàng)時(shí)。

一個(gè)List砸讳,可以使用枚舉的方法來(lái)訪問(wèn)

for(Model m : list){
    
}

也可以使用get方法來(lái)訪問(wèn)琢融。如

Model m = list.get(12)

在你訪問(wèn)具體它的一個(gè)元素(Model)時(shí),數(shù)據(jù)庫(kù)查詢(xún)才會(huì)啟動(dòng)簿寂。而且也不是將所有數(shù)據(jù)放到內(nèi)存中漾抬。比如你通過(guò)上面for的方法枚舉時(shí),其實(shí)它是通過(guò)ResultSet的next游標(biāo)在移動(dòng)常遂,所以它很高效纳令!也避免了無(wú)用的數(shù)據(jù)庫(kù)操作。

put("book",list)

該方法將查詢(xún)得到的book塞入request中克胳,在jsp網(wǎng)頁(yè)中就可以使用JSTL來(lái)使用它平绩。因?yàn)樗且粋€(gè)List,所以用forEach去訪問(wèn)他漠另。

Model 的一個(gè)對(duì)象對(duì)應(yīng)于數(shù)據(jù)庫(kù)表的一行(一條記錄)捏雌,Model是一個(gè)Map的子類(lèi)!0蚀辍性湿!,所以在JSTL中满败,你可以使用
${ b.name } 的方式來(lái)訪問(wèn)名為b的Model 的name項(xiàng)窘奏。 它相當(dāng)于

   Model m = ....
   m.get("name")

是不是很方便?葫录?着裹? 真的是非常方便的。。

第二個(gè)Demo

添加書(shū)籍頁(yè)面

    public void add(){
        DBTool tool = Model.tool("book");
        //處理提交數(shù)據(jù)
        if(isPost()){ //isPost
            Model m = tool.create(); //創(chuàng)建新的
            Log.d(m);
            paramToModel(m);
            tool.save(m);
            put("msg","添加成功");
        }

        //顯示數(shù)據(jù)
        renderForm(tool.create());
    }

對(duì)應(yīng)的/view/book/add.jsp (這是默認(rèn)對(duì)應(yīng)的模板地址)的核心內(nèi)容

  <div style="margin-left:100px">
  <h1>添加書(shū)籍 ${msg }</h1>
  ${book_form }
  </div>
這里寫(xiě)圖片描述

上面的例子控制器其實(shí)是對(duì)應(yīng)兩個(gè)頁(yè)面骇扇。 在收到Get請(qǐng)求的時(shí)候顯示表單摔竿,在用戶(hù)提交數(shù)據(jù)時(shí),做插入操作少孝,并顯示表單继低。(我們當(dāng)然可以把這兩個(gè)頁(yè)面寫(xiě)到兩個(gè)不同的方法中)
我們還是使用Model.tool獲取一個(gè)DBTool。

先來(lái)看顯示表單稍走,就一句話(huà)

        renderForm(tool.create());

tool的create方法會(huì)返回一個(gè)Model對(duì)象袁翁,這個(gè)對(duì)象和book表相關(guān)聯(lián)(因?yàn)閠ool和book表關(guān)聯(lián))。
并將這個(gè)Model傳遞給renderForm方法婿脸。這個(gè)方法會(huì)根據(jù)book表格的元數(shù)據(jù)自動(dòng)創(chuàng)建一個(gè)表格粱胜。
哇偶!

那么這個(gè)Form插入到網(wǎng)頁(yè)的什么位置呢狐树? 將 ${book_form } 放入網(wǎng)頁(yè)中 即可焙压。

如果來(lái)的是POST請(qǐng)求(使用isPost()方法來(lái)判斷)
使用tool的create方法創(chuàng)建一個(gè)新的Model, 盡快還有其他創(chuàng)建Model對(duì)象的方式,但如果你希望插入抑钟,請(qǐng)盡量使用這種方式涯曲。
paramToModel(m) ,這個(gè)方法會(huì)自動(dòng)查找表單中,名字與數(shù)據(jù)庫(kù)字段名匹配的項(xiàng)在塔,并自動(dòng)賦值給Model的相應(yīng)項(xiàng)幻件。是不是很方便。蛔溃。傲武。

想起了Struts那悲催的功能定義。 淚奔城榛。揪利。。狠持。

隨后直接調(diào)用tool的save方法將其保存到數(shù)據(jù)庫(kù)中疟位!OK了!萬(wàn)事大吉喘垂!

細(xì)心的小朋友會(huì)問(wèn): 數(shù)據(jù)庫(kù)中的字段名都是英文的如name甜刻,為什么在網(wǎng)頁(yè)上顯示的是中文?正勒?得院?
看看我的數(shù)據(jù)庫(kù)表格定義

CREATE TABLE `book` (
  `id` int(11) NOT NULL auto_increment COMMENT '編號(hào)',
  `file_name` varchar(50) default NULL,
  `name` varchar(50) default NULL COMMENT '名稱(chēng)',
  `author` varchar(50) default NULL COMMENT '作者',
  `chaodai` varchar(50) default NULL COMMENT '朝代',
  `tm_year` varchar(50) default NULL COMMENT '年代',
  `about` longtext COMMENT '簡(jiǎn)介',
  `type` varchar(50) default NULL COMMENT '類(lèi)型',
  `catalog_id` int(11) default NULL COMMENT '分類(lèi)',
  PRIMARY KEY  (`id`),
  KEY `catalog` USING BTREE (`catalog_id`)
) ENGINE=InnoDB AUTO_INCREMENT=912 DEFAULT CHARSET=utf8;

真相大白與天下,我是通過(guò)給字段加注釋實(shí)現(xiàn)的這一點(diǎn)章贞。只要你將數(shù)據(jù)庫(kù)表格加上注釋?zhuān)蜁?huì)自動(dòng)獲取注釋并顯示祥绞,對(duì)于沒(méi)有注釋的字段,則會(huì)顯示字段名。如那個(gè)扎眼的file_name

好了蜕径,這幾行代碼就搞定了輸入表單和表單的處理两踏。

第三個(gè)demo-編輯(自動(dòng)創(chuàng)建的修改表單)

細(xì)心的朋友發(fā)現(xiàn),我們是按照CRUD的邏輯來(lái)將的兜喻。下面是編輯網(wǎng)頁(yè)梦染。

    public void edit() throws NullParamException{

        DBTool tool = Model.tool("book");
        //處理提交數(shù)據(jù)
        if(isPost()){ //isPost
            Model m = tool.get(paramInt("id"));
            Log.d(m);
            paramToModel(m);
            tool.save(m);
            put("msg","修改成功");
        }

        //顯示數(shù)據(jù)
        Integer id = paramInt("id");
        checkNull("id", id);
        renderForm(tool.get(id));

    }

HTML頁(yè)面放在/view/book/edit.jsp中,核心代碼只是將add.jsp中的添加二字改為了"編輯“二字朴皆。

  <div style="margin-left:100px">
  <h1>編輯書(shū)籍 ${msg }</h1>
  ${book_form }
  </div>

這個(gè)代碼長(zhǎng)了一點(diǎn)帕识, 有17行。對(duì)于用YangMVC的遂铡,已經(jīng)算夠長(zhǎng)的了肮疗。它仍然是兩個(gè)網(wǎng)頁(yè)!S潜恪族吻!
你可以吧顯示表單的代碼和處理表單的分到兩個(gè)方法中寫(xiě)帽借。

先看顯示數(shù)據(jù)珠增。 首先使用paramInt方法獲取URL參數(shù)id,我們就是要編輯id指定的書(shū)籍砍艾。
調(diào)用checkNull來(lái)檢查一下蒂教。 在我的開(kāi)發(fā)生涯中,遇到各種參數(shù)檢查脆荷,所以這個(gè)功能是必須有的凝垛,如果checkNull不過(guò),就會(huì)拋出一個(gè)異常蜓谋。 這樣做的目的是不要讓這種參數(shù)檢查干擾我們正常的邏輯梦皮。這不就是異常之所以存在的意義么?

如果缺少這個(gè)參數(shù)桃焕,頁(yè)面會(huì)提示說(shuō)缺少這個(gè)參數(shù)剑肯。
下面使用tool.get(id)方法來(lái)獲取一個(gè)Model(一條記錄)。這個(gè)方法是根據(jù)表格的主鍵進(jìn)行查詢(xún)观堂,返回的不是列表而是一個(gè)具體的Model對(duì)象让网。在這里我建議主鍵應(yīng)當(dāng)是整數(shù)、且是數(shù)據(jù)庫(kù)自增的师痕。
renderForm傳入一個(gè)model溃睹,這個(gè)model中有數(shù)據(jù),就會(huì)被顯示出來(lái)胰坟。

就這樣因篇。編輯功能寫(xiě)好了。

有的朋友問(wèn),如果不想用默認(rèn)的表單怎么辦惜犀? 那你自己寫(xiě)一個(gè)表單在你的模板里就是了铛碑。只不過(guò),你可以先用這個(gè)方法吧表單生成出來(lái)虽界,然后按你的意圖修改就成了汽烦。這也節(jié)省大量時(shí)間啊。做過(guò)Form的請(qǐng)舉手莉御。

第四個(gè)DEMO-刪除

    public void del(){
        Integer id = paramInt("id");
        Model.tool("book").del(id);
        jump("index");
        
        
    }

瞧瞧就這點(diǎn)代碼了撇吞, 獲取參數(shù)id,并調(diào)用tool的del方法刪除礁叔。最后一句我們第一次見(jiàn)牍颈,就是跳轉(zhuǎn)。跳轉(zhuǎn)到同目錄下的index這個(gè)默認(rèn)頁(yè)(顯示的是書(shū)籍列表)

控制器創(chuàng)建

控制器是一個(gè)Java類(lèi)琅关,類(lèi)有若干方法煮岁。在YangMVC的設(shè)計(jì)中,控制器的每一個(gè)公共的方法都映射對(duì)應(yīng)一個(gè)網(wǎng)頁(yè)涣易。這樣一個(gè)Java類(lèi)可以寫(xiě)很多的網(wǎng)頁(yè)画机。 方便管理。(當(dāng)然新症,你也可以在一個(gè)控制器中只寫(xiě)一個(gè)方法來(lái)支持網(wǎng)頁(yè)步氏,這沒(méi)問(wèn)題(⊙﹏⊙)b)

所有的控制器都要繼承 org.docshare.mvc.Controller 這個(gè)類(lèi)。充當(dāng)控制器方法的方法應(yīng)當(dāng)是沒(méi)有參數(shù)沒(méi)有返回值的徒爹。如上面demo所示荚醒。

public class IndexController extends Controller {
    public void index(){
        output("Hello YangMVC");
    }
}

這些控制器都要寫(xiě)在配置所制定的package中,或者子package中隆嗅。如在上面的配置中

    <init-param>
      <param-name>controller</param-name>
      <param-value>org.demo</param-value>
    </init-param>

這個(gè)包為org.demo所有的控制器都要卸載這個(gè)包內(nèi)界阁。(你可以寫(xiě)到外面,但它不會(huì)管用O(∩_∩)O~)

路徑映射

所謂路徑映射就是要將 一個(gè)控制器(一個(gè)Java類(lèi))和一個(gè)網(wǎng)址建立關(guān)聯(lián)胖喳。 用戶(hù)訪問(wèn)某網(wǎng)址時(shí)泡躯,框架自動(dòng)調(diào)用控制器的某個(gè)函數(shù)。

因?yàn)楸究蚣茉O(shè)計(jì)思想希望配置盡可能少禀晓,所以這里的路徑映射是通過(guò)命名關(guān)系的精续。

假設(shè)應(yīng)用的根目錄為
http://localhost:8080/YangMVC/

如在org.demo下(這個(gè)目錄可以在web.xml中配置,可見(jiàn)上一節(jié))有一個(gè)BookController粹懒。
那么這個(gè)類(lèi)的路徑是 http://localhost:8080/YangMVC/book/
用戶(hù)訪問(wèn)這個(gè)路徑時(shí)重付,框架會(huì)調(diào)用BookController 的index方法。如果沒(méi)有這個(gè)方法則會(huì)報(bào)錯(cuò)凫乖。

index方法用以處理某個(gè)路徑下的默認(rèn)網(wǎng)頁(yè)(網(wǎng)站以斜杠結(jié)尾的都會(huì)調(diào)用某個(gè)類(lèi)的index方法來(lái)處理)确垫。

book這個(gè)地址弓颈,將第一個(gè)字母大寫(xiě),后面追加Controller删掀。于是
book (路徑名)-> Book -> BookController(類(lèi)名)
這就是路徑和類(lèi)名的默認(rèn)關(guān)聯(lián)翔冀。

在這個(gè)網(wǎng)站后加入方法名可以訪問(wèn)BookController的 任何一個(gè)公共方法。
http://localhost:8080/YangMVC/book/edit 與BookController的edit方法關(guān)聯(lián)披泪。

需要注意的是纤子,如果你寫(xiě)的是 http://localhost:8080/YangMVC/book/edit/ (比上一個(gè)網(wǎng)站多了一個(gè)斜杠), 則它對(duì)應(yīng)的是 book.EditController下的index方法 而不是BookController下的edit方法款票。

控制器方法

獲取request中的參數(shù)

String s = param("name");
Integer id = paramInt("id");

輸出方法

output方法

    output("Hello YangMVC");

這個(gè)方法輸出一個(gè)文本到網(wǎng)頁(yè)上(輸出流中)控硼,并關(guān)閉輸出流。因?yàn)樗鼤?huì)關(guān)閉流艾少,所以你不要調(diào)用它兩次卡乾。你如果需要輸出多次,以將內(nèi)容放到StringBuffer中缚够,然后統(tǒng)一輸出幔妨。

render方法

    public void paramDemo(){
        put("a", "sss");
        render("/testrd.jsp");
        
    }

這里的testrd.jsp是模板目錄(/view)目錄下的。 /view/testrd.jsp
這里的參數(shù)應(yīng)該是相對(duì)于模板目錄的相對(duì)路徑谍椅。

render方法使用參數(shù)制定的網(wǎng)頁(yè)(一個(gè)包含JSTL的jsp文件)误堡,將其輸出√焊ǎ可以通過(guò)put來(lái)制定參數(shù)埂伦。下面會(huì)詳細(xì)講煞额。

render()方法

這個(gè)render方法是沒(méi)有參數(shù)的思恐,它會(huì)使用默認(rèn)模板,如果這個(gè)模板不存在膊毁,就會(huì)提示錯(cuò)誤胀莹。
    public void renderDemo(){
        request.setAttribute("a", "sss");
        render();
        
    }

在配置 controller 為org.demo , template為/view 這種情況下。
org.demo.IndexController的renderDemo方法會(huì)對(duì)應(yīng)/view/renderDemo.jsp
之所以模板存在于模板根目錄下婚温,是因?yàn)檫@個(gè)IndexController是處理應(yīng)用根目錄的描焰。他們有對(duì)應(yīng)關(guān)系。

如果是org.demo.BookController,它對(duì)應(yīng) app根目錄下的 /book/ 目錄栅螟。
它的add方法對(duì)應(yīng)路徑 /book/add
如果應(yīng)用名為hello,那么完成路徑應(yīng)該是 /hello/book/add

outputJSON 方法

該方法將參數(shù)轉(zhuǎn)化為JSON荆秦,并向網(wǎng)頁(yè)輸出。

    public void jsonDemo(){
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("id", 12);
        map.put("name", "Yang MVC");
        map.put("addtm",new Date());
        
        outputJSON(map);
    }
這個(gè)代碼稍長(zhǎng)力图,其實(shí)上面的所有都是生成一個(gè)Map步绸,最后一句輸出。outputJSON可以輸出List吃媒,Map和任何Java對(duì)象瓤介。內(nèi)部轉(zhuǎn)換是使用fastjson實(shí)現(xiàn)的吕喘。

自動(dòng)生成并輸出一個(gè)表單

public void renderForm(Model m,String template,String postTo)

該函數(shù)會(huì)根據(jù)模型對(duì)應(yīng)的表結(jié)構(gòu),自動(dòng)生成一個(gè)表單刑桑,并將其內(nèi)容放入 表格名_form 中氯质,如book表會(huì)輸出到 book_form 中。
在網(wǎng)頁(yè)中祠斧,直接寫(xiě) ${book_form}就可以將表單放下去闻察。

template制定對(duì)應(yīng)的模板文件,可以省略琢锋,省略后按照默認(rèn)規(guī)則查找模板文件蜓陌。
postTo設(shè)定 表單提交的網(wǎng)頁(yè),可以省略吩蔑,默認(rèn)是"",即當(dāng)前網(wǎng)頁(yè)(Controller)钮热。

獲取參數(shù)的方法

  1. param(String p) 獲取參數(shù)p的值,以String類(lèi)型返回
  2. paramInt(String p) 獲取參數(shù)p的值烛芬,以Int類(lèi)型返回隧期,如果不是整數(shù),則會(huì)出現(xiàn)異常
  3. public Model paramToModel(Model m)
    根據(jù)名稱(chēng)匹配的原則赘娄,將與模型中參數(shù)名相同的參數(shù)的值放入模型中仆潮。并返回該模型。
    是收集表單數(shù)據(jù)到模型中的神器遣臼,手機(jī)后就可以直接進(jìn)行數(shù)據(jù)庫(kù)操作了性置。
  4. paramWithDefault 獲取參數(shù),但同時(shí)帶上默認(rèn)值揍堰,如果沒(méi)這個(gè)參數(shù)則返回默認(rèn)值鹏浅。

檢查方法

public void checkNull(String name,Object obj)
檢查obj是否為null,如果是拋出NullParamException異常屏歹。

ORM框架

Model與DBTool

Model 對(duì)象對(duì)應(yīng)數(shù)據(jù)庫(kù)的表格隐砸,它會(huì)與一個(gè)表格進(jìn)行綁定。DBTool相當(dāng)于是它的DAO類(lèi)蝙眶。
YangMVC的ORM組件可以單獨(dú)使用季希。使用前需要先配置數(shù)據(jù)庫(kù):

    Config.dbhost = "localhost";
    Config.dbname = "dc2";
    Config.dbpwd = "123456";
    Config.dbusr ="root";
    Config.dbport="3306";

也可以和MVC框架一起使用。配置時(shí)在web.xml中配置

創(chuàng)建一個(gè)DBTool對(duì)象

        DBTool tool = Model.tool("book");

其中book是數(shù)據(jù)庫(kù)表的名字幽纷。

創(chuàng)建一個(gè)空的Model

        DBTool tool = Model.tool("book");
        Model m = tool.create(); //創(chuàng)建新的

根據(jù)主鍵讀取一個(gè)Model

            Model m = tool.get(12);

查詢(xún)表中所有的行

        LasyList list = tool.all();
all返回一個(gè)LasyList對(duì)象式塌。這個(gè)對(duì)象在此事并沒(méi)有真正進(jìn)行數(shù)據(jù)庫(kù)查詢(xún),只有在頁(yè)面真正讀取時(shí)才會(huì)讀取數(shù)據(jù)庫(kù)友浸。這是它叫做Lasy的原因峰尝。此處借鑒了Django的實(shí)現(xiàn)機(jī)制。

查詢(xún)的limit語(yǔ)句

    LasyList list = tool.all().limit(30);
    list = tool.all().limit(10,30);
    

查詢(xún)的等式約束

    tool.all().eq("name","本草綱目")

查詢(xún)的不等式約束

    tool.all().gt("id",12) //id < 12
    tool.all().lt("id",33) //id <33
    tool.all().gte("id",12) //id>=12
    tool.all().lte("id",33) //id<=33
    tool.all().ne("id",33) //不相等
    

模糊查詢(xún)

    tool.all().like("name","本草")
查找所有名字中包含本草的書(shū)尾菇。返回一個(gè)LasyList

排序

    tool.all().orderby("id",true);
按照id的增序排列境析。 如果是false囚枪,則是降序。

級(jí)聯(lián)查詢(xún)

因?yàn)檫@些上面的過(guò)濾器函數(shù)全部都會(huì)返回一個(gè)LasyList對(duì)象劳淆, 所以可以采用級(jí)聯(lián)的方式進(jìn)行復(fù)雜查詢(xún)链沼。如:

list = tool.all().gt("id", 12).lt("id", 33).eq("name","haha").like("author","王");

這個(gè)例子相當(dāng)于執(zhí)行了如下SQL語(yǔ)句:

 select * from book where id>12 and id<33 and name='haha' and author like '%王%'

根據(jù)原始sql獲取(version >=1.5.4)

    LasyList list = LasyList.fromRawSql("select name from book");

使用原始的sql獲取的List中的模型將和數(shù)據(jù)庫(kù)表沒(méi)有關(guān)聯(lián)沛鸵。

Model的相關(guān)功能

model 是一個(gè)繼承自Map<String,Object> 的類(lèi)括勺,所以對(duì)于
Model m;
你可以在網(wǎng)頁(yè)中使用${m.name}的方式來(lái)訪問(wèn)它的name鍵對(duì)應(yīng)的值。相當(dāng)于m.get("name")
這種寫(xiě)法在JSTL中非常有用曲掰。讓Model繼承Map的初衷就在于此:方便在JSTL中使用疾捍。

大家也許注意到了LasyList是一個(gè)繼承自List<Model> 的類(lèi).
這就使得不管是LasyList還是Model在JSTL中訪問(wèn)都極為的便利。

訪問(wèn)所有的鍵值(即DAO對(duì)象的所有屬性)

    model.keySet();

訪問(wèn)某一個(gè)屬性的值

    model.get(key)

設(shè)置某一個(gè)屬性的值

    model.put(key,value)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末栏妖,一起剝皮案震驚了整個(gè)濱河市乱豆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吊趾,老刑警劉巖宛裕,帶你破解...
    沈念sama閱讀 223,002評(píng)論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異论泛,居然都是意外死亡揩尸,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門(mén)屁奏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)岩榆,“玉大人,你說(shuō)我怎么就攤上這事坟瓢∮卤撸” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,787評(píng)論 0 365
  • 文/不壞的土叔 我叫張陵载绿,是天一觀的道長(zhǎng)粥诫。 經(jīng)常有香客問(wèn)我油航,道長(zhǎng)崭庸,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,237評(píng)論 1 300
  • 正文 為了忘掉前任谊囚,我火速辦了婚禮怕享,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘镰踏。我一直安慰自己函筋,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,237評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布奠伪。 她就那樣靜靜地躺著跌帐,像睡著了一般首懈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谨敛,一...
    開(kāi)封第一講書(shū)人閱讀 52,821評(píng)論 1 314
  • 那天究履,我揣著相機(jī)與錄音,去河邊找鬼脸狸。 笑死最仑,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的炊甲。 我是一名探鬼主播泥彤,決...
    沈念sama閱讀 41,236評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起篡九,我...
    開(kāi)封第一講書(shū)人閱讀 40,196評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤口锭,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后搁凸,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,716評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,794評(píng)論 3 343
  • 正文 我和宋清朗相戀三年炕贵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片野崇。...
    茶點(diǎn)故事閱讀 40,928評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡称开,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出乓梨,到底是詐尸還是另有隱情鳖轰,我是刑警寧澤,帶...
    沈念sama閱讀 36,583評(píng)論 5 351
  • 正文 年R本政府宣布扶镀,位于F島的核電站蕴侣,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏臭觉。R本人自食惡果不足惜昆雀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,264評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蝠筑。 院中可真熱鬧狞膘,春花似錦、人聲如沸什乙。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,755評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)臣镣。三九已至辅愿,卻和暖如春智亮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背点待。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,869評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工鸽素, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人亦鳞。 一個(gè)月前我還...
    沈念sama閱讀 49,378評(píng)論 3 379
  • 正文 我出身青樓馍忽,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親燕差。 傳聞我的和親對(duì)象是個(gè)殘疾皇子遭笋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,937評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容