Play源碼深刻之七:Play的MVC實現

總體來講,Play1.x是一個較完善的框架,各類功能都包羅萬象,有點像句老話「麻雀雖小五臟俱全」哈。雖沒有Struts、SpringMVC的大名氣,可是使用起來,至關順手。本文將深刻Play1.x的MVC,也整合前面各方知識。 java

在new一個Play項目以後,都會有models、views、controllers三個文件夾,正好對應MVC,並且每類文件還必須放對地方。spring

這裏要講的是Play框架層面上,對MVC作的工做: json

M:Model(模型),在Model上,Play對每一個Model進行了加強,在PlayPlugin中,有enhaner事件,每一個插件均可以對Model進行加強,觸發的時機在play.Invoker:run()中,調用init方法,檢測play代碼是否有變化,有變化就會發出加強事件,位置在play.classloading.ApplictionClasses:enhance()方法中。響應事件的有CorePlugin和JPAPlugin,JPAPlugin在前文已經說過,是織入JPA支持方法,而CorePlugin的enhaner有多個加強類,全在play.classloading.enhancers包中。 服務器

 QQ20150803-2@2x 

Model採用的ActiveRecord比POJO/DAO/Service高明,以前作SSH項目時,早就煩透了寫一大片DAO/Service,並且裏面尚未代碼……(由於都集中到某個base類中)。而ActiveRecord沒有這等煩惱,讓人用着舒服~。 restful

V:Views(視圖),Play模版引擎是使用Groovy語言,我用過Groovy,感受這貨就是沒法無天版的Java,吸收了各家所長,當模版引擎是小菜一碟。不過Play2已經放棄Groovy。 session

在play.mvc.results中能夠看到各類返回結果,有Html/template/json/xml/text/binary。對於只想用play作移動端restful後臺的項目,果斷好用。 mvc

C:Controller(控制器),Play對比struts2的使用xml映射和springMVC的註解都要直接,使用routes文件,直觀高效。 play會加載route文件,當請求過來時,進行匹配,若是沒有找到就會404。框架

public class Router {
    public static Route route(Http.Request request) {
        ...
        for (Route route : routes) {
            Map<String, String> args = route.matches(request.method, request.path, request.format, request.domain);
            if (args != null) {
                request.routeArgs = args;
                request.action = route.action;
                if (args.containsKey("format")) {
                    request.format = args.get("format");
                }
                if (request.action.indexOf("{") > -1) { // more optimization ?
                    for (String arg : request.routeArgs.keySet()) {
                        request.action = request.action.replace("{" + arg + "}", request.routeArgs.get(arg));
                    }
                }
                if (request.action.equals("404")) {
                    throw new NotFound(route.path);
                }
                return route;
            }
        }
        ...
        throw new NotFound(request.method, request.path);
    }
}

Play使用Netty作服務器,沒有使用j2ee一套,因此得本身實現request/respone/session等類,但Play的實現比j2ee的要靈活好用。dom

每次初始化調用相關準備後,Play就會使用Router中的路由進行請求分發。而返回結果是基於異常機制,這也是爲人所詬病的。這一點在以前的 請求一章提過。 .net

play也有過濾器機制,前文也說過,play經過插件響應出完成過濾,這個機制在play 1.2.3上尚未看見。另外Play的before/after/with註解也有過濾器的做用。

相關文章
相關標籤/搜索