摘要:現(xiàn)在可以通過點(diǎn)擊指標(biāo)檢查的指標(biāo),該數(shù)據(jù)是可用的格式。健康檢查被添加。現(xiàn)在啟動(dòng),可以看到第步創(chuàng)建現(xiàn)在寫類,它負(fù)責(zé)創(chuàng)建博客條目。為了測(cè)試,做一個(gè)請(qǐng)求第步更新現(xiàn)在,更新方法來從獲取所有的博客文件。
編者注:我們發(fā)現(xiàn)了比較有趣的系列文章《30天學(xué)習(xí)30種新技術(shù)》,準(zhǔn)備翻譯,一天一篇更新,年終禮包。下面是第十三天的內(nèi)容。
我已經(jīng)是一個(gè)使用了8年Java的軟件開發(fā)人員了,我寫過的大多數(shù)應(yīng)用程序是用的Spring框架或Java EE。最近,我花了一些時(shí)間學(xué)習(xí)用Python進(jìn)行web開發(fā),其中印象非常深刻的是 Flask 框架——一個(gè)微型架構(gòu),這使得它很容易寫REST后端。所以今天我決定找一個(gè)Java的Python Flask框架替代品,做一些研究后,我發(fā)現(xiàn) Dropwizard 框架可以幫助達(dá)到Flask框架同樣的生產(chǎn)力。在這篇博客中,我們將學(xué)習(xí)如何使用Dropwizard構(gòu)建一個(gè)基于REST的Java MongoDB應(yīng)用程序。
Dropwizard 是一個(gè)開源的Java框架,用于開發(fā)OPS友好、高性能的基于REST的后端。它是由Yammer開發(fā)的,來驅(qū)動(dòng)基于JVM的后端。
Dropwizard提供同類最佳的Java庫到一個(gè)嵌入式應(yīng)用程序包。它由以下部分組成:
嵌入式Jetty:每一個(gè)應(yīng)用程序被打包成一個(gè)jar(而不是war)文件,并開始自己的嵌入式Jetty容器。沒有任何war文件和外部servlet容器。
JAX-RS:Jersey(JAX-RS的參考實(shí)現(xiàn))是用來寫基于REST的Web服務(wù)的。
JSON:REST服務(wù)用的是JSON,Jackson庫用來做所有的JSON處理。
日志:使用Logback和SLF4J完成。
Hibernate驗(yàn)證:Dropwizard使用Hibernate驗(yàn)證API進(jìn)行聲明性驗(yàn)證。
指標(biāo):Dropwizard支持監(jiān)控使用標(biāo)準(zhǔn)庫,它在監(jiān)控代碼方面有無與倫比的洞察力。
除了上面提到的這幾個(gè),Dropwizard還使用了一些其他的庫,你可以在這里找到完整的列表。
我決定學(xué)Dropwizard的原因有以下幾點(diǎn):
快速的項(xiàng)目引導(dǎo):如果你已經(jīng)在使用Spring和Java EE,你就會(huì)明白開發(fā)人員在引導(dǎo)項(xiàng)目時(shí)的痛苦。使用Dropwizard,你只需要在你的 pom.xml 文件中添加一個(gè)依賴就完成了。
應(yīng)用指標(biāo):Dropwizard自帶應(yīng)用程序指標(biāo)的支持。它提供了類似請(qǐng)求/響應(yīng)時(shí)間這種非常有用的信息,只要把@ 定時(shí)注解來獲取方法的執(zhí)行時(shí)間。
生產(chǎn)力:每個(gè)Dropwizard應(yīng)用程序有一個(gè)啟動(dòng)Jetty容器的主程序。這意味著,完全可以把應(yīng)用程序作為一個(gè)主程序在IDE中運(yùn)行和調(diào)試。所以就沒有重新編譯或部署war文件。
今天的演示應(yīng)用程序的代碼在GitHub上有:day13-dropwizard-mongodb-demo-app。
必備條件基礎(chǔ)的Java知識(shí)是必須的;
下載并安裝 MongoDB數(shù)據(jù)庫;
安裝最新版本的Java Development Kit (JDK),OpenJDK 7 或是 Oracle JDK 7 都可以,這篇文章中使用JDK 7;
去Eclipse官網(wǎng)下載最新版本的Eclipse包,就目前而言eclipse最新版的代號(hào)是Kepler;
Eclipse的安裝很容易,只需要解壓下載下來的包即可。如果是在Linux或者M(jìn)ac機(jī)器上,開個(gè)命令行窗口,輸入如下命令:
$ tar -xzvf eclipse-jee-kepler-R-*.tar.gz
Windows下,你解壓到哪里,那里就會(huì)有一個(gè)eclipse文件夾,這樣就可以直接操作了,當(dāng)然你也可以創(chuàng)建執(zhí)行文件的快捷方式到桌面。
打開Eclipse IDE,然后到項(xiàng)目工作區(qū)(project workspace)。要?jiǎng)?chuàng)建一個(gè)新的項(xiàng)目,轉(zhuǎn)到 文件>新建> Maven項(xiàng)目 (File > New > Maven Project) ,然后選擇 Maven 原型 - 快速啟動(dòng) (maven-archetype-quickstart),然后進(jìn)入Ground Id 和 Artifact Id,最后點(diǎn)擊“完成”。
現(xiàn)在更新pom.xml文件以包括dropwizard核心maven依賴。同時(shí)也將更新Maven項(xiàng)目使用Java 1.7版本,更新pom.xml文件后,更新Maven項(xiàng)目(右鍵單擊>Maven>更新項(xiàng)目)。
第3步:創(chuàng)建配置類4.0.0 com.shekhar blog 0.0.1-SNAPSHOT jar blog http://maven.apache.org UTF-8 com.yammer.dropwizard dropwizard-core 0.6.2 org.apache.maven.plugins maven-compiler-plugin 3.1 1.7
每個(gè)Dropwizard應(yīng)用程序都有一個(gè)配置類,它指定特定的環(huán)境參數(shù)。文章后面會(huì)將如主機(jī)、端口和數(shù)據(jù)庫名之類的MongoDB的配置參數(shù)添加給它。這個(gè)類擴(kuò)展了 com.yammer.dropwizard.config.Configuration類。
import com.yammer.dropwizard.config.Configuration; public class BlogConfiguration extends Configuration{ }第4步:創(chuàng)建服務(wù)類
該Dropwizard項(xiàng)目由一個(gè)服務(wù)類自舉。這個(gè)類將各種提供基本功能的捆綁和命令集合在一塊,它還啟動(dòng)嵌入式Jetty服務(wù)器并延伸com.yammer.dropwizard.Service。
import com.yammer.dropwizard.Service; import com.yammer.dropwizard.config.Bootstrap; import com.yammer.dropwizard.config.Environment; public class BlogService extends Service{ public static void main(String[] args) throws Exception { new BlogService().run(new String[] { "server" }); } @Override public void initialize(Bootstrap bootstrap) { bootstrap.setName("blog"); } @Override public void run(BlogConfiguration configuration, Environment environment) throws Exception { } }
上面的這些服務(wù)類可以:
有一個(gè)作為服務(wù)入口點(diǎn)的main方法。在main方法里面,創(chuàng)建BlogService的實(shí)例,并調(diào)用run方法。我們將服務(wù)器命令作為參數(shù)傳遞,服務(wù)器命令將啟動(dòng)嵌入式Jetty服務(wù)器。
初始化方法在服務(wù)運(yùn)行方法之前被調(diào)用。
接下來,服務(wù)運(yùn)行時(shí)將調(diào)用它的run方法,文章后面會(huì)將JAX-RS源加到這個(gè)方法里。
第5步:寫IndexResource寫一個(gè)當(dāng)GET請(qǐng)求指向“/” URL時(shí)會(huì)被調(diào)用的源,創(chuàng)建一個(gè)新的JAX-RS源(此資源將列出所有的博客),如下:
import java.util.Arrays; import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import com.yammer.metrics.annotation.Timed; @Path("/") public class IndexResource { @GET @Produces(value = MediaType.APPLICATION_JSON) @Timed public Listindex() { return Arrays.asList(new Blog("Day 12: OpenCV--Face Detection for Java Developers", "https://www.openshift.com/blogs/day-12-opencv-face-detection-for-java-developers")); } }
上面這段代碼是一個(gè)標(biāo)準(zhǔn)的JAX-RS資源類。它添加@ Path注釋和定義index()方法,這個(gè)index()會(huì)返回一個(gè)博客集合,這些博客將被轉(zhuǎn)換為JSON文檔。
上面提到IndexResource是用博客表示的。下面這段則表明該博客使用Hibernate驗(yàn)證器注解,以確保內(nèi)容是有效的。例如,使用@URL注釋,以確保只有合法的URL存儲(chǔ)在MongoDB數(shù)據(jù)庫。
import java.util.Date; import java.util.UUID; import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.URL; public class Blog { private String id = UUID.randomUUID().toString(); @NotBlank private String title; @URL @NotBlank private String url; private final Date publishedOn = new Date(); public Blog() { } public Blog(String title, String url) { super(); this.title = title; this.url = url; } public String getId() { return id; } public String getTitle() { return title; } public String getUrl() { return url; } public Date getPublishedOn() { return publishedOn; } }
接下來,在服務(wù)類的run方法注冊(cè)IndexResource。用下面的方式更新BlogService run方法。
@Override public void run(BlogConfiguration configuration, Environment environment) throws Exception { environment.addResource(new IndexResource()); }
現(xiàn)在,可以將BlogService類??作為一個(gè)主程序來運(yùn)行(右鍵點(diǎn)擊>運(yùn)行方式> Java應(yīng)用程序),這將啟動(dòng)嵌入式Jetty容器,我們可以看到程序在 http://localhost:8080/ 里運(yùn)行。
$ curl http://localhost:8080 [{"id":"9bb43d53-5436-4dac-abaa-ac530c833df1","title":"Day 12: OpenCV--Face Detection for Java Developers","url":"https://www.openshift.com/blogs/day-12-opencv-face-detection-for-java-developers","publishedOn":1384090975372}]
現(xiàn)在可以通過點(diǎn)擊“指標(biāo)(Metrics)”檢查IndexResource的指標(biāo),該數(shù)據(jù)是可用的JSON格式。
"com.shekhar.blog.IndexResource" : { "index" : { "type" : "timer", "duration" : { "unit" : "milliseconds", "min" : 17.764, "max" : 17.764, "mean" : 17.764, "std_dev" : 0.0, "median" : 17.764, "p75" : 17.764, "p95" : 17.764, "p98" : 17.764, "p99" : 17.764, "p999" : 17.764 }, "rate" : { "unit" : "seconds", "count" : 1, "mean" : 7.246537731991882E-4, "m1" : 2.290184897291144E-12, "m5" : 3.551918562683463E-5, "m15" : 2.445031498756583E-4 } } },第6步:配置MongoDB
在pom.xml 里加入 mongo-jackson-mapper 的依賴。
net.vz.mongodb.jackson mongo-jackson-mapper 1.4.2
用MongoDB數(shù)據(jù)庫的詳細(xì)信息(如主機(jī)、端口和數(shù)據(jù)庫名等)更新BlogConfiguration類。
import javax.validation.constraints.Max; import javax.validation.constraints.Min; import org.codehaus.jackson.annotate.JsonProperty; import org.hibernate.validator.constraints.NotEmpty; import com.yammer.dropwizard.config.Configuration; public class BlogConfiguration extends Configuration { @JsonProperty @NotEmpty public String mongohost = "localhost"; @JsonProperty @Min(1) @Max(65535) public int mongoport = 27017; @JsonProperty @NotEmpty public String mongodb = "mydb"; }
接下來,創(chuàng)建一個(gè)名為MongoManaged的新類,它將允許你在應(yīng)用程序啟動(dòng)和停止時(shí)管理程序資源。這樣就實(shí)現(xiàn)了com.yammer.dropwizard.lifecycle.Managed。
import com.mongodb.Mongo; import com.yammer.dropwizard.lifecycle.Managed; public class MongoManaged implements Managed { private Mongo mongo; public MongoManaged(Mongo mongo) { this.mongo = mongo; } @Override public void start() throws Exception { } @Override public void stop() throws Exception { mongo.close(); } }
在上面的代碼中,關(guān)閉了stop方法中的MongoDB連接。
下一步,寫一個(gè)MongoHealthCheck來檢查MongoDB的連接與否。
import com.mongodb.Mongo; import com.yammer.metrics.core.HealthCheck; public class MongoHealthCheck extends HealthCheck { private Mongo mongo; protected MongoHealthCheck(Mongo mongo) { super("MongoDBHealthCheck"); this.mongo = mongo; } @Override protected Result check() throws Exception { mongo.getDatabaseNames(); return Result.healthy(); } }
現(xiàn)在,更新BlogService類??,將MongoDB的配置包含進(jìn)來。
package com.shekhar.blog; import com.mongodb.Mongo; import com.yammer.dropwizard.Service; import com.yammer.dropwizard.config.Bootstrap; import com.yammer.dropwizard.config.Environment; public class BlogService extends Service{ public static void main(String[] args) throws Exception { new BlogService().run(new String[] { "server" }); } @Override public void initialize(Bootstrap bootstrap) { bootstrap.setName("blog"); } @Override public void run(BlogConfiguration configuration, Environment environment) throws Exception { Mongo mongo = new Mongo(configuration.mongohost, configuration.mongoport); MongoManaged mongoManaged = new MongoManaged(mongo); environment.manage(mongoManaged); environment.addHealthCheck(new MongoHealthCheck(mongo)); environment.addResource(new IndexResource()); } }
上面這段代碼:
使用BlogConfiguration對(duì)象創(chuàng)建了一個(gè)新的Mongo實(shí)例。
一個(gè)新的MongoManaged實(shí)例被創(chuàng)建并添加到環(huán)境中。
健康檢查被添加。
運(yùn)行該應(yīng)用程序作為主程序。你可以到本地的 http://localhost:8081/healthcheck 健康檢查頁面去檢驗(yàn)MongoDB是否在運(yùn)行,如果MongoDB沒有運(yùn)行,會(huì)看到一個(gè)異常堆棧跟蹤。
! MongoDBHealthCheck: ERROR ! can"t call something : Shekhars-MacBook-Pro.local/192.168.1.101:27017/admin com.mongodb.MongoException$Network: can"t call something : Shekhars-MacBook-Pro.local/192.168.1.101:27017/admin at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:227) at com.mongodb.DBApiLayer$MyCollection.__find(DBApiLayer.java:305) at com.mongodb.DB.command(DB.java:160) at com.mongodb.DB.command(DB.java:183) at com.mongodb.Mongo.getDatabaseNames(Mongo.java:327) at com.shekhar.blog.MongoHealthCheck.check(MongoHealthCheck.java:17) at com.yammer.metrics.core.HealthCheck.execute(HealthCheck.java:195) at Caused by: java.io.IOException: couldn"t connect to [Shekhars-MacBook-Pro.local/192.168.1.101:27017] bc:java.net.ConnectException: Connection refused at com.mongodb.DBPort._open(DBPort.java:228) at com.mongodb.DBPort.go(DBPort.java:112) at com.mongodb.DBPort.call(DBPort.java:79) at com.mongodb.DBTCPConnector.call(DBTCPConnector.java:218) ... 33 more * deadlocks: OK
現(xiàn)在啟動(dòng)MongoDB,可以看到:
* MongoDBHealthCheck: OK * deadlocks: OK第7步:創(chuàng)建BlogResource
現(xiàn)在寫B(tài)logResource類,它負(fù)責(zé)創(chuàng)建博客條目。
import java.util.ArrayList; import java.util.List; import javax.validation.Valid; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import net.vz.mongodb.jackson.DBCursor; import net.vz.mongodb.jackson.JacksonDBCollection; import com.yammer.metrics.annotation.Timed; @Path("/blogs") @Produces(value = MediaType.APPLICATION_JSON) @Consumes(value = MediaType.APPLICATION_JSON) public class BlogResource { private JacksonDBCollectioncollection; public BlogResource(JacksonDBCollection blogs) { this.collection = blogs; } @POST @Timed public Response publishNewBlog(@Valid Blog blog) { collection.insert(blog); return Response.noContent().build(); } }
下一步,更新BlogService run方法,將BlogResource也加進(jìn)來。
@Override public void run(BlogConfiguration configuration, Environment environment) throws Exception { Mongo mongo = new Mongo(configuration.mongohost, configuration.mongoport); MongoManaged mongoManaged = new MongoManaged(mongo); environment.manage(mongoManaged); environment.addHealthCheck(new MongoHealthCheck(mongo)); DB db = mongo.getDB(configuration.mongodb); JacksonDBCollectionblogs = JacksonDBCollection.wrap(db.getCollection("blogs"), Blog.class, String.class); environment.addResource(new IndexResource()); environment.addResource(new BlogResource(blogs)); }
將BlogService類作為一個(gè)Java應(yīng)用程序運(yùn)行。為了測(cè)試BlogResource,做一個(gè)curl請(qǐng)求:
$ curl -i -X POST -H "Content-Type: application/json" -d "{"title":"Day 12: OpenCV--Face Detection for Java Developers","url":"https://www.openshift.com/blogs/day-12-opencv-face-detection-for-java-developers"}" http://localhost:8080/blogs HTTP/1.1 204 No Content Date: Sun, 10 Nov 2013 14:08:03 GMT Content-Type: application/json第8步:更新IndexResource
現(xiàn)在,更新IndexResource index()方法來從MongoDB獲取所有的博客文件。
import java.util.ArrayList; import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import net.vz.mongodb.jackson.DBCursor; import net.vz.mongodb.jackson.JacksonDBCollection; import com.yammer.metrics.annotation.Timed; @Path("/") public class IndexResource { private JacksonDBCollectioncollection; public IndexResource(JacksonDBCollection blogs) { this.collection = blogs; } @GET @Produces(value = MediaType.APPLICATION_JSON) @Timed public List index() { DBCursor dbCursor = collection.find(); List blogs = new ArrayList<>(); while (dbCursor.hasNext()) { Blog blog = dbCursor.next(); blogs.add(blog); } return blogs; } }
更新BlogService run方法將博客集合傳遞給IndexResource。
@Override public void run(BlogConfiguration configuration, Environment environment) throws Exception { Mongo mongo = new Mongo(configuration.mongohost, configuration.mongoport); MongoManaged mongoManaged = new MongoManaged(mongo); environment.manage(mongoManaged); environment.addHealthCheck(new MongoHealthCheck(mongo)); DB db = mongo.getDB(configuration.mongodb); JacksonDBCollectionblogs = JacksonDBCollection.wrap(db.getCollection("blogs"), Blog.class, String.class); environment.addResource(new IndexResource(blogs)); environment.addResource(new BlogResource(blogs)); }
將BlogService類作為一個(gè)Java應(yīng)用程序運(yùn)行。為了測(cè)試BlogResource,做一個(gè)curl請(qǐng)求:
$ curl http://localhost:8080 [{"id":"527f9806300462bbd300687e","title":"Day 12: OpenCV--Face Detection for Java Developers","url":"https://www.openshift.com/blogs/day-12-opencv-face-detection-for-java-developers","publishedOn":1384093702592}]第9步:部署到云端
這里有一篇文章,教你如何在OpenShift部署Dropwizard應(yīng)用,點(diǎn)擊這里。
今天就這些,歡迎反饋。
原文 Day 13: Dropwizard--The Awesome Java REST Server Stack
整理 SegmentFault
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/63989.html
摘要:是當(dāng)時(shí)唯一的書,而且只有語言規(guī)范。仍然在中使用未來可能被取代,但不是現(xiàn)在。仍然是大學(xué)里教授的主要語言,并且存在于很多優(yōu)秀的庫中,比如。筆者期待積極的討論。的確存在缺陷,但這些缺陷并不妨礙它在世界上最主要的公司和系統(tǒng)內(nèi)全天候地完成工作。 【編者按】本文作者為資深碼農(nóng) Tim Spann,主要講述 Java 讓人無法抗拒的眾多優(yōu)點(diǎn)以及一些些缺陷。本文系國內(nèi) ITOM 管理平臺(tái) OneAPM...
摘要:是什么是一個(gè)用編寫的開源機(jī)器學(xué)習(xí)服務(wù)器應(yīng)用,可以幫助你方便地使用搭建推薦引擎。是一個(gè)可伸縮的機(jī)器學(xué)習(xí)庫,它提供眾多聚集分類過濾算法。我為什么要關(guān)心我決定學(xué)習(xí)是因?yàn)槲蚁胧褂靡粋€(gè)可以幫助我加上機(jī)器學(xué)習(xí)功能的庫。 編者注:我們發(fā)現(xiàn)了比較有趣的系列文章《30天學(xué)習(xí)30種新技術(shù)》,準(zhǔn)備翻譯,一天一篇更新,年終禮包。下面是第四天的內(nèi)容。 今天是30天學(xué)習(xí)30種新技術(shù)的第4天。到目前為止我很享...
摘要:會(huì)警告該插件未簽名。以上命令告訴創(chuàng)建一個(gè)名為的項(xiàng)目,使用包。的工具使從部署應(yīng)用非常方便。域名構(gòu)成了分配給應(yīng)用的的一部分。這將為我們創(chuàng)建一個(gè)應(yīng)用容器,自動(dòng)配置和。同時(shí)將創(chuàng)建一個(gè)私有的倉庫并克隆到本地。 編者注:我們發(fā)現(xiàn)了有趣的系列文章《30天學(xué)習(xí)30種新技術(shù)》,正在翻譯,一天一篇更新,年終禮包。下面是第 17 天的內(nèi)容。 今天的30天學(xué)習(xí)30種新技術(shù)挑戰(zhàn),我決定學(xué)習(xí)一下JBoss ...
摘要:譯文地址譯唯快不破應(yīng)用的個(gè)優(yōu)化步驟前端的逆襲知乎專欄原文地址時(shí)過境遷,應(yīng)用比以往任何時(shí)候都更具交互性。使用負(fù)載均衡方案我們?cè)谥坝懻摼彺娴臅r(shí)候簡(jiǎn)要提到了內(nèi)容分發(fā)網(wǎng)絡(luò)。換句話說,元素的串形訪問會(huì)削弱負(fù)載均衡器以最佳形式 歡迎關(guān)注知乎專欄 —— 前端的逆襲歡迎關(guān)注我的博客,知乎,GitHub。 譯文地址:【譯】唯快不破:Web 應(yīng)用的 13 個(gè)優(yōu)化步驟 - 前端的逆襲 - 知乎專欄原文地...
閱讀 2198·2021-09-22 10:56
閱讀 1493·2021-09-07 10:11
閱讀 1814·2019-08-30 15:54
閱讀 2301·2019-08-30 15:44
閱讀 2319·2019-08-29 12:40
閱讀 3040·2019-08-28 18:25
閱讀 1751·2019-08-26 10:24
閱讀 3200·2019-08-23 18:39