首先建立MyJFinal的配置類MyAppConfig.java:html
在方法中添加以下代碼:java
@Overrideweb public void configConstant(Constants me) {瀏覽器 me.setDevMode(true);架構 me.setEncoding("utf-8");app me.setViewType(ViewType.JSP);框架 }eclipse
@Overridejsp public void configHandler(Handlers me) {ide me.add(new ContextPathHandler("basePath")); } |
既然MyAppConfig.java是入口,那麼,在Tomcat這個容器中,就須要配置這個入口,使得Tomcat啓動的同時加載這個入口類。
打開web.xml,追加內容:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>MyJFinalApp</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list>
<filter> <filter-name>jfinal</filter-name> <filter-class>com.jfinal.core.JFinalFilter</filter-class> <init-param> <param-name>configClass</param-name> <param-value>cn.myapp.config.MyAppConfig</param-value> </init-param> </filter>
<filter-mapping> <filter-name>jfinal</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app> |
在建立JSP頁面以前先修改一下JSP文件的默認字符集。以下圖所示,打開菜單Windows-->Perferences,在彈出的窗口中修改默認字符集爲utf-8便可:
文件名爲index.jsp,並放入WebContent中:
<body> <form action="${basePath}/sayHello" method="post"> 請輸入您的名字: <input type="text" name="userName" /> <input type="submit" value="肯定"/> </form> </body> |
一樣的步驟,再建立一個hello.jsp,並在<body>標籤中追加以下代碼:
<body> <p>${sayHello}</p><p><a href="${basePath}/"></a></p> </body> |
建立IndexController.java用於響應頁面請求,以下圖:
並添加代碼:
public class IndexController extends Controller {
public void index(){ this.render("/index.jsp"); } public void sayHello(){ String userName = this.getAttr("userName"); String sayHello = "Hello " + userName + ",welcome to JFinal world."; this.setAttr("sayHello", sayHello); this.render("/hello.jsp"); } } |
JSP頁面和Controller都準備完成後,就須要在MyAppConfig.java中將二者關聯起來,JFinal裏稱之爲Route(路由),下面是MyAppConfig類中追加的路由代碼:
@Override public void configRoute(Routes me) { me.add("/", IndexController.class); } |
打開瀏覽器,並輸入URL:http://localhost:8080/MyJFinalApp/,應該可看到以下畫面:
小白們,感動吧,終於將JFinal環境搭建起來了。
在輸入框中輸入「小白」,點擊肯定,出現下面的畫面:
很明顯,頁面中出現了錯誤,紅框中標識的內容是null,而不是期待的「小白」。
再看看控制檯的輸出:
在頁面中輸入的字串正確地傳給了後臺IndexController.sayHello()方法,那麼,爲何沒有顯示出來呢?請小白在IndexController.sayHello()中追加斷點:
而後再次打開URL:http://localhost:8080/MyJFinalApp/,在輸入框中輸入「小白」,點擊肯定。這時,Eclipse進入調試模式。經過調試查看userName取得的值爲null:
仔細分析發生錯誤的這行代碼,或直接查看此方法的源碼,原來,getArrt("userName")方法取到的是HttpServletRequest中的屬性,而不是請求參數。應該改爲從取參數的getPara("userName")方法:
public void sayHello(){ String userName = this.getPara("userName"); 。。。。。。 |
又一次打開UR:http://localhost:8080/MyJFinalApp/,在輸入框中輸入「小白」,點擊肯定,終於出現了使人期待的結果:
實際上,除去Eclipse和Tomcat的準備之外,配置及編碼那塊在熟練的人手裏只須要10分鐘左右,當之無愧的極速WEB開發。固然,前面只是使用到了JFinal的WEB框架,ORM框架在後面的教程中會介紹到。
這一章節,將粗略地講解一下JFinal的WEB部分是如何搭載在Tomcat容器中,啓動並響應用戶操做的過程。
另外,推薦小白們看完此章節後研究下張劍峯同窗寫的《JFinal技術架構淺析》一文。
前面,小白們建立MyAppConfig.java,同時修改web.xml。這就爲啓動JFinal作好了準備,下面咱們就來分析下Tomcat啓動的同時是怎麼初始化MyJFinalApp的。
先來看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>cn.myapp.config.MyAppConfig</param-value> </init-param> </filter>
<filter-mapping> <filter-name>jfinal</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> |
xml中首先聲明瞭<filter>,它是JFinalFilter,同時定義了<init-param>,指向應用程序的配置類MyAppConfig.java。
在<filter-mapping>中,定義了<url-pattern>爲「/*」,也就是說,此Web應用全部的URL都將將由JFinalFilter這個過濾器來處理。
Tomcat啓動過程:
過程當中,對於JFinal開發人員來講,最有用操做就是「調用MyAppConfig各方法」,也就是執行了以下代碼:
@Override public void configConstant(Constants me) { me.setDevMode(true); me.setEncoding("utf-8"); me.setViewType(ViewType.JSP); }
@Override public void configHandler(Handlers me) { me.add(new ContextPathHandler("basePath")); }
@Override public void configRoute(Routes me) { me.add("/", IndexController.class); } |
各方法的做用請參考《JFinal-手冊-1.5.pdf》,此處再也不復述手冊可從官網http://www.jfinal.com/下載。
應用中,建立了兩個JSP頁面,分別是「index.jsp」和「hello.jsp」,在瀏覽器中訪問http://localhost:8080/MyJFinalApp/時明顯打開了index.jsp頁面。經歷過SSH或SpringMVC的小白應該會很奇怪,明明沒有像SpringMVC那樣用註解聲明Controller,也沒有在註解方法對應的URL,而JFinal卻正確地打開了index.jsp。
首先請看MyAppConfig.configRoute()方法中的URL路由代碼:
me.add("/", IndexController.class); |
這句代碼實際上已經配置了URL與Controller之間的對應關係,第一個參數"/"就是指的根。當用戶訪問根URL時,依據約定JFinal會將其路由到IndexController.index()方法。
那麼,在訪問http://localhost:8080/MyJFinalApp/時,JFinal如何知道訪問的是"/"(根)呢?
首先請小白雙擊Tomcat配置項:
在彈出的Tomcat實例屬性窗口中找到Ports選項:
這裏說明Tomcat實例使用的是8080端口,也就是經過http://localhost:8080可訪問此Tomcat。
而後請小白打開部署的Tomcat實例的server.xml:
在server.xml底部,咱們能夠發現MyJFinalApp的配置:
<Context docBase="MyJFinalApp" path="/MyJFinalApp" reloadable="true" source="org.eclipse.jst.jee.server:MyJFinalApp"/> |
請看path參數,它的值爲"/MyJFinalApp"(必定要和前面Context root配置同樣),說明此應用部署到Tomcat的後使用的根URL爲「http://localhost:8080」+ 「/MyJFinalApp」 = 「http://localhost:8080/MyJFinalApp」。
提示:修改reloadable的值爲false,在調試狀態,修改MyJFinalApp的代碼時Tomcat不會頻繁從新加載應用,節省開發調試時間。
經過上面,咱們已經知道,經過訪問http://localhost:8080/MyJFinalApp/,JFinal會將其路由到IndexController.index()方法,爲何是index()方法?其實這是一個約定,具體的約定請參考《JFinal-手冊-1.5.pdf》。
那麼它是如何打開index.jsp文件的呢?咱們來查看index()方法的代碼:
public class IndexController extends Controller { public void index(){ this.render("/index.jsp"); } 。。。。。。 |
只有一句代碼,做用是渲染\WebContent\index.jsp這個文件後返回給瀏覽器。小白們又糊塗了,爲何不return一個字串來指定渲染頁面呀?這裏就是JFinal設計者的聰明之處了,渲染頁面可能不止常見的JSP、FREE_MARKER、VELOCITY等幾種類型,隨着技術的發展,模板頁面類型會層出不窮。JFinal中,只須要擴展Render就可輕鬆支持,贊呀^_^。
打開index.jsp後,用戶在頁面中輸入名字,而後點擊肯定,這裏調用的是以下action代碼:
<form action="${basePath}/sayHello" method="post"> 請輸入您的名字: <input type="text" name="userName" /> <input type="submit" value="肯定"/> </form> |
action的值爲"${basePath}/sayHello",那麼${basePath}是什麼東東呢?有點JSP基礎的人都知道,basePath必須設置到HttpServletRequest中才能在頁面中使用。那麼又是何時設置進去的呢?請注意前面建立MyAppConfig.java中的一段代碼:
@Override public void configHandler(Handlers me) { me.add(new ContextPathHandler("basePath")); } |
在這裏配置了一個ContextPathHandler,構造參數是"basePath",難道它們有聯繫!沒錯,小白們可直接查看此Handler的源碼就能夠發現,一行代碼已經作必須的事情:
public void handle(String target, HttpServletRequest request, HttpServletResponse response, boolean[] isHandled) { request.setAttribute(contextPathName, request.getContextPath()); nextHandler.handle(target, request, response, isHandled); } |
ContextPathHandler就只作了這麼一件事情,就是在每次(注意是每次)請求時將Context Path(此應用中的值爲"/MyJFinalApp")設置到HttpServletRequest的屬性"basePath"中,這樣,頁面就可使用了。
爲了證明這一點,可在瀏覽器中打開index.jsp返回的html源碼:
此頁面中,點擊肯定,就將用戶輸入的」userName」,經過Post方式調用http://localhost:8080/MyJFinalApp/sayHello地址。最終,調用的是IndexController.sayHello()方法。
JFinal是怎麼知道調用的是此方法呢?其實很簡單,在JFinal的路由規則中,首先會去匹配地址」/sayHello」。顯然是找不到的,由於在MyAppConfig.configRoute()方法中根本就沒有配置與」/sayHello」對應的Controller。因此JFinal會截掉最後一個」/」後的內容再次匹配,」/sayHello」截取掉後就成了」/」,也就匹配到了IndexController。根據約定,被截取的內容」sayHello」應該是方法名,因此,也順序定位到了IndexController.sayHello()方法。
小白們,明白了吧,JFianl的路由約定拋棄掉了繁瑣的註解,這就是一種簡潔美。這種設計在JFianl中到處都存在,隨着對JFinal瞭解的加深,你們會慢慢體會到約定大於配置不僅僅是一句口號。
有部分人也提出了質疑:註解能規範編碼,一目瞭然……等等。但若是回過頭來想,註解實際上也就是一種顯示的約定而已,而JFianl將其當成了隱式約定。使用註解功能更強了點嗎?答案是沒有,SSH和SpringMVC的這類註解與JFinal的實際提供的路由在功能上沒有任何區別,沒有脫離Servlet的範疇。
來自:http://my.oschina.net/u/1175852/blog/261235