摘要:通過如下命令發布控制臺,運行編寫的默認程序。默認禁用,啟用它需要打開并取消注釋以下行。啟用數據庫啟動應用程序的數據庫,框架提供了內置的數據庫的支持。當用戶發出請求到,一個新的將被創建。方法為給定的獲取,把這個轉換成格式并返回響應。
編者注:我們發現了有趣的系列文章《30天學習30種新技術》,正在翻譯,一天一篇更新,年終禮包。下面是第 30 天的內容。
今天是最后一天,我決定學習一下 Play 框架。原本是想寫關于Scala的,學習了幾個小時之后發現在一天之內是不可能完成Scala的,所以今天會介紹一下Play框架的基本知識,然后學習如何用它開發應用。
什么是 Play 框架?Play是一個開源的現代web框架,用于編寫Java和Scala的可擴展Web應用程序。它通過自動重載變化來提高生產力,由于設計的就是一個無狀態、無阻塞的架構,所以用Play框架來編寫橫向擴展Web應用程序是很容易的。
為什么要用它?我的原因是:
開發人員生產力:我已經寫了8年的Java,但在過去的幾個月里我把更多的時間花在了Python和JavaScript (Node.js) 上。用動態語言工作時最讓我吃驚的,就是用它編寫程序的速度是如此之快。Java EE和Spring框架并不是快速原型和開發的理想選擇,但在用Play框架時,你更改一處刷新一下頁面,更新會立即出現,而且它支持熱重載所有的Java代碼、模板等,可以讓你的迭代快很多。
天性使然:Play框架是建立在Netty之上的,所以它支持非阻塞I/O,這使得并行遠程調用容易了很多,這一點對面向服務的架構中的高性能應用程序是很重要的。
支持Java和Scala:Play框架是一個真正的多語種Web框架,開發者可以在項目中同時使用Java和Scala。
一流的REST JSON支持:它很容易編寫基于REST的應用。對HTTP路由有很好的支持,HTTP路由會將HTTP請求轉化為具體動作;JSON編組/解組API是??目前的核心API,所以沒有必要加一個庫來做到這一點。
應用類型案例今天的介紹中,將開發一個社交書簽應用程序,它允許用戶發布和共享鏈接。你可以在這里查看正在運行的該程序,因為這個和第22天的應用是一樣的,所以請參閱之以便更好地了解這個案例。
開發Play應用請參閱文檔以了解如何安裝Play框架,開始應用程序的開發吧。
$ play new getbookmarks _ _ __ | | __ _ _ _ | "_ | |/ _" | || | | __/|_|\____|\__ / |_| |__/ play 2.2.1 built with Scala 2.10.2 (running Java 1.7.0_25), http://www.playframework.com The new application will be created in /Users/shekhargulati/dev/challenges/30days30technologies/day30/blog/getbookmarks What is the application name? [getbookmarks] > Which template do you want to use for this new application? 1 - Create a simple Scala application 2 - Create a simple Java application > 2 OK, application getbookmarks is created. Have fun!
如上鍵入命令后,該框架會問幾個問題。首先它要求有應用程序的名稱,然后問是否要創建一個Scala或Java應用程序。默認情況下,它會使用文件夾名稱作為應用程序的名稱。
上面的命令將創建一個新的目錄getbookmarks并生成以下文件和目錄:
app 目錄包含如控制器 (controller) 、視圖 (view) 和模型 (model) 的應用程序特定代碼。控制器包中有響應URL路由的Java代碼,視圖目錄包含服務器端模板,模型目錄包含應用程序的域模型。在此應用中,域 (domain) 是一個Story類。
conf 目錄包含應用程序配置和路由定義文件。
project 目錄包含構建腳本,構建系統是基于SBT的。
public 包含了如CSS、JavaScript和img目錄等的公共資源。
test 目錄包含應用測試。
通過如下命令發布play控制臺,運行Play編寫的默認程序。
$ cd getbookmarks $ play [info] Loading project definition from /Users/shekhargulati/dev/challenges/30days30technologies/day30/blog/getbookmarks/project [info] Set current project to getbookmarks (in build file:/Users/shekhargulati/dev/challenges/30days30technologies/day30/blog/getbookmarks/) _ _ __ | | __ _ _ _ | "_ | |/ _" | || | | __/|_|\____|\__ / |_| |__/ play 2.2.1 built with Scala 2.10.2 (running Java 1.7.0_25), http://www.playframework.com > Type "help play" or "license" for more information. > Type "exit" or use Ctrl+D to leave this console. [getbookmarks] $ run [info] Updating {file:/Users/shekhargulati/dev/challenges/30days30technologies/day30/blog/getbookmarks/}getbookmarks... [info] Resolving org.fusesource.jansi#jansi;1.4 ... [info] Done updating. --- (Running the application from SBT, auto-reloading is enabled) --- [info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:9000 (Server started, use Ctrl+D to stop and go back to the console...)
現在可以在 http://localhost:9000 里運行該應用了。
該應用程序只有一個域類 (domain class),叫做story,創建一個新的包模型和Java類。
package models; import play.db.ebean.Model; import javax.persistence.Entity; import javax.persistence.Id; import java.util.Date; @Entity public class Story extends Model{ @Id private String id; private String url; private String fullname; private Date submittedOn = new Date(); private String title; private String text; private String image; public Story() { } public Story(String url, String fullname) { this.url = url; this.fullname = fullname; } public Story(String url, String fullname, String image, String text, String title) { this.url = url; this.fullname = fullname; this.title = title; this.text = text; this.image = image; } // Getter and Setter removed for brevity }
上述代碼定義了一個簡單的JPA實體,并使用 @Entity 和 @Id JPA注解,Play用它自己的一個被稱作Ebean的ORM層,而且每一個實體類必須擴展基本模型類。
Ebean默認禁用,啟用它需要打開application.conf并取消注釋以下行。
ebean.default="models.*"啟用數據庫
啟動應用程序的數據庫,Play框架提供了內置的H2數據庫的支持。要啟用它,打開application.conf文件,并取消如下兩行的注釋。
db.default.driver=org.h2.Driver db.default.url="jdbc:h2:mem:play"
刷新瀏覽器會看到:
點擊Apply this script now將SQL的更改部署上去。
今天講的應用程序和第22天是一樣的,都有AngularJS后臺和REST后端,所以可以使用Play框架重寫REST后臺和AngularJS后端,在conf/routes文件,復制并粘貼如下代碼。
# Routes # This file defines all application routes (Higher priority routes first) # ~~~~ # Home page GET / controllers.Assets.at(path="/public", file="/index.html") GET /api/v1/stories controllers.StoryController.allStories() POST /api/v1/stories controllers.StoryController.submitStory() GET /api/v1/stories/:storyId controllers.StoryController.getStory(storyId) # Map static resources from the /public folder to the /assets URL path GET /assets/*file controllers.Assets.at(path="/public", file)
上述代碼表示:
當用戶發出一個GET請求到應用程序的“/”URL,index.html將被渲染。
當用戶發出一個GET請求到"/ api/v1/stories",將得到JSON格式的所有story。
當用戶發出POST請求到"/ api/v1/stories",一個新的story將被創建。
當用戶GET請求"/ api/v1/stories/123",id為123的story會被渲染。
創建Story控制器在控制器包里創建一個Java類,將如下代碼粘貼進 StoryController.java 文件里。
package controllers; import com.fasterxml.jackson.databind.JsonNode; import models.Story; import play.api.libs.ws.Response; import play.api.libs.ws.WS; import play.db.ebean.Model; import play.libs.Json; import play.mvc.BodyParser; import play.mvc.Controller; import play.mvc.Result; import play.mvc.Results; import scala.concurrent.Await; import scala.concurrent.Future; import scala.concurrent.duration.Duration; import java.util.List; import java.util.concurrent.TimeUnit; public class StoryController { public static Result allStories(){ Liststories = new Model.Finder (String.class, Story.class).all(); return Results.ok(Json.toJson(stories)); } @BodyParser.Of(BodyParser.Json.class) public static Result submitStory(){ JsonNode jsonNode = Controller.request().body().asJson(); String url = jsonNode.findPath("url").asText(); String fullname = jsonNode.findPath("fullname").asText(); JsonNode response = fetchInformation(url); Story story = null; if(response == null){ story = new Story(url,fullname); }else{ String image = response.findPath("image").textValue(); String text = response.findPath("text").textValue(); String title = response.findPath("title").textValue(); story = new Story(url,fullname, image , text , title); } story.save(); return Results.created(); } public static Result getStory(String storyId){ Story story = new Model.Finder (String.class, Story.class).byId(storyId); if(story == null){ return Results.notFound("No story found with storyId " + storyId); } return Results.ok(Json.toJson(story)); } private static JsonNode fetchInformation(String url){ String restServiceUrl = "http://gooseextractor-t20.rhcloud.com/api/v1/extract?url="+url; Future future = WS.url(restServiceUrl).get(); try { Response result = Await.result(future, Duration.apply(30, TimeUnit.SECONDS)); JsonNode jsonNode = Json.parse(result.json().toString()); return jsonNode; } catch (Exception e) { e.printStackTrace(); return null; } } }
上述代碼會操作:
它定義allStories()方法,該方法會找到數據庫中所有的story。它是使用Model.Finder API來做到這一點的,然后把story列表轉換成JSON格式并返回結果,返回HTTP狀態代碼200(即確定)。
submitStory()方法首先會從JSON讀取URL和全名的字段,然后發送GET請求到"http://gooseextractor-t20.rhcloud.com/api/v1/extract?url",這樣就會找出標題、摘要以及已經給定url的主要image。創建一個使用所有信息的story并保存在數據庫中,返回HTTP狀態代碼201(即創建)。
getStory()方法為給定的storyId獲取story,把這個story轉換成JSON格式并返回響應。
可以從我的github倉庫下載AngularJS前端,用其中一個庫更換公共目錄。
現在可以訪問http://localhost:9000/看結果了。
30天系列的文章就此結束,非常感謝大家的持續關注,也希望你們能和SegmentFault一塊成長。
So, see you next year. Oh~ Happy New Year to Y"all !
原文 Day 30: Play Framework--A Java Developer Dream Framework
翻譯整理 SegmentFault
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/64043.html
摘要:注本系列文章所用版本為介紹是個輕量級的框架,致力于讓程序員實現快速高效開發,它具有以下幾個方面的優勢熱加載。在調試模式下,所有修改會及時生效。拋棄配置文件。約定大于配置。 注:本系列文章所用play版本為1.2.6 介紹 Play framework是個輕量級的RESTful框架,致力于讓java程序員實現快速高效開發,它具有以下幾個方面的優勢: 熱加載。在調試模式下,所有修改會及時...
摘要:使用自建的類加載器主要是為了便于處理預編譯后的字節碼以及方便在模式下進行即時的熱更新。 注:本系列文章所用play版本為1.2.6 在上一篇中,我們分析了play的2種啟動方式,這一篇,我們來看看Play類的初始化過程 Play類 無論是Server還是ServletWrapper方式運行,在他們的入口中都會運行Play.init()來對Play類進行初始化。那在解析初始化之前,我們先...
摘要:自定義視頻播放器微信公眾號開發企業級產品全棧開發速成周末班首期班號正式開班,歡迎搶座作者簡介是推出的一個天挑戰。 Day11 - 自定義視頻播放器 (Node+Vue+微信公眾號開發)企業級產品全棧開發速成周末班首期班(10.28號正式開班,歡迎搶座) 作者:?liyuechun 簡介:JavaScript30 是 Wes Bos 推出的一個 30 天挑戰。項目免費提供了 30 個視...
摘要:在舒伯的生涯階段里有個確立階段,歲歲。知識技術安卓程序員需要掌握編程語言應用框架開發工具等這些具體的知識和技術。技術能力與閱歷對安卓程序員來講,知識技術是一方面,是容易習得的,是較淺的層面。 大齡程序員的界定 老早網上有人說,安卓開發干不過30歲,后來又有人說干不過35歲,后來又有人說干不過...
閱讀 873·2021-10-11 10:59
閱讀 2809·2019-08-30 15:43
閱讀 2137·2019-08-30 11:08
閱讀 1657·2019-08-29 15:20
閱讀 1023·2019-08-29 13:53
閱讀 496·2019-08-26 13:24
閱讀 1645·2019-08-26 13:24
閱讀 2829·2019-08-26 12:08