入門
本文將指導(dǎo)您完成一個(gè)簡單的Dropwizard的Hello World項(xiàng)目怠褐。在此過程中,我們將解釋各種底層庫及其作用雏门,以及Dropwizard中的重要概念鼎姐,并建議一些組織技術(shù)來幫助您的項(xiàng)目能持續(xù)健康地增長。
概覽
Dropwizard跨越了作為lib庫和框架之間的界限船殉。其目標(biāo)是為生產(chǎn)就緒的Web應(yīng)用程序所需的所有內(nèi)容提供高性能鲫趁,高可靠的實(shí)現(xiàn)。并且這些功能被封裝到可重用的庫中利虫,因此您的應(yīng)用程序仍然很精簡和專注挨厚,從而縮短了產(chǎn)品上線時(shí)間和維護(hù)負(fù)擔(dān)。
用于HTTP的Jetty
因?yàn)槟腤eb應(yīng)用程序不能沒有HTTP糠惫,Dropwizard使用Jetty 疫剃,一個(gè)令人難以置信的調(diào)優(yōu)HTTP服務(wù)器直接嵌入到您的項(xiàng)目中。Dropwizard項(xiàng)目沒有將應(yīng)用程序交給復(fù)雜的應(yīng)用程序服務(wù)器硼讽,而是有一個(gè)main
方法運(yùn)行HTTP服務(wù)器巢价。將您的應(yīng)用程序作為一個(gè)簡單的過程運(yùn)行,消除了生產(chǎn)中Java的許多令人討厭的方面(沒有PermGen問題,沒有應(yīng)用程序服務(wù)器配置和維護(hù)蹄溉,沒有神秘的部署工具,沒有類加載器問題您炉,沒有隱藏的應(yīng)用程序日志柒爵,沒有嘗試調(diào)整單個(gè)垃圾收集器與多個(gè)應(yīng)用程序工作負(fù)載一起工作)并允許您使用所有現(xiàn)有的Unix進(jìn)程管理工具。
用于REST的Jersey
為了構(gòu)建RESTful Web應(yīng)用程序赚爵,我們發(fā)現(xiàn)在功能或性能方面沒有任何東西勝過Jersey(JAX-RS參考實(shí)現(xiàn))棉胀。它允許您編寫干凈,可測試的類冀膝,這些類可以優(yōu)雅地將HTTP請求映射到簡單的Java對象唁奢。它支持流輸出,矩陣URI參數(shù)窝剖,條件GET
請求等等麻掸。
用于JSON的Jackson
在數(shù)據(jù)格式方面,JSON已成為網(wǎng)絡(luò)的通用語言赐纱,而Jackson則是JVM上的JSON之王脊奋。除了快速閃電之外,它還有一個(gè)復(fù)雜的對象映射器疙描,允許您直接導(dǎo)出域模型诚隙。
用于監(jiān)控的Metrics
指標(biāo)有助于分析問題,為您提供無與倫比的洞悉您的生產(chǎn)環(huán)境中的代碼的行為起胰。
其他集成的工具
除了Jetty久又,Jersey和Jackson之外,Dropwizard還包括一些庫效五,可以幫助您更快速高效地開發(fā)地消。
- Guava除了高度優(yōu)化的不可變數(shù)據(jù)結(jié)構(gòu)外,還提供了越來越多的類來加速Java的開發(fā)畏妖。
- Logback和slf4j用于高性能和靈活的日志記錄犯建。
- Hibernate Validator是JSR 349參考實(shí)現(xiàn),它提供了一個(gè)簡單的聲明性框架瓜客,用于驗(yàn)證用戶輸入并生成有用且易于i18n的錯(cuò)誤消息适瓦。
- 在Apache的HttpClient的和Jersey客戶端庫允許都與其他Web服務(wù)低收入和高層次的互動(dòng)。
- JDBI是使用Java的關(guān)系數(shù)據(jù)庫最直接的方法谱仪。
- Liquibase是在整個(gè)開發(fā)和發(fā)布周期中檢查數(shù)據(jù)庫模式的好方法玻熙,應(yīng)用高級數(shù)據(jù)庫重構(gòu)而不是一次性DDL腳本。
- Freemarker和Mustache是簡單的模板系統(tǒng)疯攒,適用于面向用戶的更多應(yīng)用程序嗦随。
- Joda Time是一個(gè)非常完整,理智的庫,用于處理日期和時(shí)間枚尼。
既然你已經(jīng)了解到這了贴浙,那就讓我們深入挖掘吧!
使用Maven進(jìn)行設(shè)置
我們建議您將Maven用于新的Dropwizard應(yīng)用程序署恍。如果你是一個(gè)大型的Ant / Ivy崎溃,Buildr, Gradle盯质,SBT袁串,Leiningen或Gant粉絲,這很酷呼巷,但我們使用Maven囱修,我們將在使用Maven時(shí)通過這個(gè)示例應(yīng)用程序。如果您對Maven如何運(yùn)作有任何疑問王悍, Maven:The Complete Reference應(yīng)該有你想要的東西破镰。
你有三種選擇:
-
使用dropwizard-archetype創(chuàng)建項(xiàng)目:
mvn archetype:generate -DarchetypeGroupId=io.dropwizard.archetypes -DarchetypeArtifactId=java-simple -DarchetypeVersion=[REPLACE WITH A VALID DROPWIZARD VERSION]
請按照以下教程了解如何將其包含在現(xiàn)有項(xiàng)目中
教程
首先,dropwizard.version
使用當(dāng)前版本的Dropwizard(1.3.5)向POM 添加屬性:
<properties>
<dropwizard.version>INSERT VERSION HERE</dropwizard.version>
</properties>
將dropwizard-core
庫添加為依賴項(xiàng):
<dependencies>
<dependency>
<groupId>io.dropwizard</groupId>
<artifactId>dropwizard-core</artifactId>
<version>${dropwizard.version}</version>
</dependency>
</dependencies>
很好压储,這些足夠了啤咽。我們現(xiàn)在已經(jīng)建立了一個(gè)Maven項(xiàng)目,現(xiàn)在是時(shí)候開始編寫真正的代碼了渠脉。
創(chuàng)建配置類
每個(gè)Dropwizard應(yīng)用程序都有自己的Configuration
類的子類宇整,它指定特定的環(huán)境參數(shù)。這些參數(shù)在YAML配置文件中指定芋膘,該文件被反序列化為應(yīng)用程序配置類的實(shí)例鳞青。
我們將要構(gòu)建的應(yīng)用程序是一個(gè)高性能的Hello World服務(wù)。我們需要至少指定兩件事:一個(gè)用于說出問候的模板和一個(gè)默認(rèn)名稱为朋,以防用戶未指定其名稱臂拓。
package com.example.helloworld;
import io.dropwizard.Configuration;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty;
public class HelloWorldConfiguration extends Configuration {
@NotEmpty
private String template;
@NotEmpty
private String defaultName = "Stranger";
@JsonProperty
public String getTemplate() {
return template;
}
@JsonProperty
public void setTemplate(String template) {
this.template = template;
}
@JsonProperty
public String getDefaultName() {
return defaultName;
}
@JsonProperty
public void setDefaultName(String name) {
this.defaultName = name;
}
}
這里有很多知識點(diǎn)习寸,所以讓我們解釋一下吧胶惰。
當(dāng)從YAML文件反序列化該類時(shí),它將從YAML對象中提取兩個(gè)根級別字段:template
霞溪,我們的Hello World說明的模板孵滞,以及defaultName
要使用的默認(rèn)名稱。template
和defaultName
都標(biāo)注了@NotEmpty
鸯匹,所以如果YAML配置文件有任何空值或缺少template
完全的信息會拋出異常坊饶,并且應(yīng)用程序?qū)o法啟動(dòng)。
template
和 defaultName
的getter和setter都有注釋 @JsonProperty
殴蓬,這允許Jackson既可以從YAML文件反序列化屬性匿级,也可以序列化它。
注意
從YAML到您的應(yīng)用程序
Configuration
實(shí)例的映射由Jackson完成。這意味著您的Configuration
類可以使用Jackson的所有對象映射注釋痘绎。驗(yàn)證@NotEmpty
由Hibernate Validator處理藤违,它具有 廣泛的內(nèi)置約束供您使用搓茬。
我們的YAML文件將如下所示消痛,完整的示例yml在這里:
template: Hello, %s!
defaultName: Stranger
Dropwizard有許多比這更多的配置參數(shù)倒彰,但他們都有健全的默認(rèn)值涂身,這樣可以保持你的配置文件小消别,重點(diǎn)突出不傅。
因此若锁,將YAML文件保存在您計(jì)劃運(yùn)行的jar的目錄中(見下文)hello-world.yml
凌净,因?yàn)槲覀兒芸炀蜁?dòng)并運(yùn)行悲龟,我們將需要它。接下來冰寻,我們正在創(chuàng)建我們的應(yīng)用程序類须教!
創(chuàng)建應(yīng)用程序類
結(jié)合項(xiàng)目的Configuration
子類,Application
子類構(gòu)成了Dropwizard應(yīng)用程序的核心斩芭。所述Application
類啟動(dòng)各bundle和command命令轻腺,其提供基本功能在一起(稍后會詳細(xì)介紹)。但是現(xiàn)在划乖,我們 HelloWorldApplication
看起來像這樣:
package com.example.helloworld;
import io.dropwizard.Application;
import io.dropwizard.setup.Bootstrap;
import io.dropwizard.setup.Environment;
import com.example.helloworld.resources.HelloWorldResource;
import com.example.helloworld.health.TemplateHealthCheck;
public class HelloWorldApplication extends Application<HelloWorldConfiguration> {
public static void main(String[] args) throws Exception {
new HelloWorldApplication().run(args);
}
@Override
public String getName() {
return "hello-world";
}
@Override
public void initialize(Bootstrap<HelloWorldConfiguration> bootstrap) {
// nothing to do yet
}
@Override
public void run(HelloWorldConfiguration configuration,
Environment environment) {
// nothing to do yet
}
}
如您所見贬养,HelloWorldApplication
使用應(yīng)用程序的配置類型HelloWorldConfiguration
進(jìn)行參數(shù)化。initialize
方法用于在運(yùn)行應(yīng)用程序之前配置所需應(yīng)用程序的各個(gè)方面琴庵,如bundle误算,配置源提供程序等。此外迷殿,我們還添加了一個(gè)static
main
方法儿礼,它將成為我們應(yīng)用程序的入口點(diǎn)。現(xiàn)在庆寺,我們沒有實(shí)現(xiàn)任何功能蚊夫,所以我們的run
方法有點(diǎn)無聊。讓我們解決這個(gè)問題懦尝!
創(chuàng)建表示類
在我們進(jìn)入Hello World應(yīng)用程序的細(xì)節(jié)之前知纷,我們需要停下來思考一下我們的API。幸運(yùn)的是陵霉,我們的應(yīng)用程序需要符合行業(yè)標(biāo)準(zhǔn)RFC 1149屈扎,它規(guī)定了Hello World的以下JSON表示:
{
"id": 1,
"content": "Hi!"
}
該id
字段是該問候的唯一標(biāo)識符,并且content
是該問候的文本表示撩匕。(值得慶幸的是鹰晨,這是一個(gè)相當(dāng)直接的行業(yè)標(biāo)準(zhǔn)。)
要對此表示進(jìn)行建模,我們將創(chuàng)建一個(gè)表示類:
package com.example.helloworld.api;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.Length;
public class Saying {
private long id;
@Length(max = 3)
private String content;
public Saying() {
// Jackson deserialization
}
public Saying(long id, String content) {
this.id = id;
this.content = content;
}
@JsonProperty
public long getId() {
return id;
}
@JsonProperty
public String getContent() {
return content;
}
}
這是一個(gè)非常簡單的POJO模蜡,但有一些值得注意的事情漠趁。
首先,它是不可改變的忍疾。這使得Saying
實(shí)例在多線程環(huán)境以及單線程環(huán)境中非常容易推理闯传。其次,它使用JavaBeans標(biāo)準(zhǔn)id
和content
屬性卤妒。這允許Jackson將其序列化為我們需要的JSON甥绿。Jackson對象映射代碼將id
使用返回值填充JSON對象的字段#getId()
,同樣使用content
和#getContent()
则披。最后共缕,bean利用驗(yàn)證來確保內(nèi)容大小不超過3。
注意
這里的JSON序列化由Jackson完成士复,它支持的不僅僅是像這樣的簡單JavaBean對象图谷。除了復(fù)雜的注釋集,您甚至可以編寫自定義序列化程序和反序列化程序阱洪。
既然我們已經(jīng)有了表示類便贵,接下來學(xué)習(xí)下資源。
創(chuàng)建資源類
Jersey資源是Dropwizard應(yīng)用程序的核心冗荸。每個(gè)資源類都與URI模板相關(guān)聯(lián)承璃。對于我們的應(yīng)用程序,我們需要從URI /hello-world
返回一個(gè)Saying
實(shí)例蚌本,因此我們的資源類如下所示:
package com.example.helloworld.resources;
import com.example.helloworld.api.Saying;
import com.codahale.metrics.annotation.Timed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import java.util.concurrent.atomic.AtomicLong;
import java.util.Optional;
@Path("/hello-world")
@Produces(MediaType.APPLICATION_JSON)
public class HelloWorldResource {
private final String template;
private final String defaultName;
private final AtomicLong counter;
public HelloWorldResource(String template, String defaultName) {
this.template = template;
this.defaultName = defaultName;
this.counter = new AtomicLong();
}
@GET
@Timed
public Saying sayHello(@QueryParam("name") Optional<String> name) {
final String value = String.format(template, name.orElse(defaultName));
return new Saying(counter.incrementAndGet(), value);
}
}
HelloWorldResource
有兩個(gè)注釋:@Path
和@Produces
绸硕。@Path("/hello-world")
告訴Jersey,這個(gè)資源可以在URI上訪問/hello-world
魂毁,并且 @Produces(MediaType.APPLICATION_JSON)
讓Jersey的內(nèi)容協(xié)商代碼知道這個(gè)資源產(chǎn)生的表示形式是application/json
玻佩。
HelloWorldResource
采用兩個(gè)參數(shù)進(jìn)行構(gòu)造:template
它用于產(chǎn)生問候語,當(dāng)用戶拒絕告訴我們他們的名字時(shí)使用defaultName
席楚。AtomicLong
為我們提供了一種廉價(jià)咬崔,線程安全的方法來生成唯一(ish)ID。
警告
資源類由多個(gè)線程同時(shí)使用烦秩。一般來說垮斯,我們建議資源是無狀態(tài)/不可變的,但重要的是要記住上下文只祠。
#sayHello(Optional<String>)
是這個(gè)類的核心兜蠕,這是一個(gè)相當(dāng)簡單的方法。@QueryParam("name")
注解告訴Jersey從請求參數(shù)字符串中把name
參數(shù)賦值給方法中的name
參數(shù)抛寝。如果客戶端發(fā)送請求 /hello-world?name=Dougie
熊杨,sayHello
將被調(diào)用Optional.of("Dougie")
; 如果name
查詢字符串中沒有參數(shù)曙旭,sayHello
則將調(diào)用Optional.absent()
。(支持Guava的Optional
是Dropwizard為Jersey的現(xiàn)有功能添加的一些額外的功能)
注意
如果客戶端發(fā)送請求
/hello-world?name=
晶府,sayHello
將被調(diào)用Optional.of("")
桂躏。這可能看起來很奇怪,但這遵循標(biāo)準(zhǔn)(應(yīng)用程序可能具有不同的行為川陆,具體取決于參數(shù)是否為空而不存在)剂习。如果你希望/hello-world?name=
返回“Hello,Stranger较沪!”鳞绕,可以用NonEmptyStringParam
替換Optional<String>
參數(shù)。有關(guān)資源參數(shù)的更多信息尸曼,請參閱 文檔
在sayHello
方法內(nèi)部们何,我們遞增計(jì)數(shù)器,使用格式化模板String.format(String,Object...)
骡苞,并返回一個(gè)Saying
新實(shí)例垂蜗。
因?yàn)?code>sayHello帶有注釋@Timed
楷扬,Dropwizard會自動(dòng)將其調(diào)用的持續(xù)時(shí)間和速率記錄為Metrics Timer解幽。
一旦sayHello
返回,Jersey就會獲取Saying
實(shí)例并查找可以將Saying
實(shí)例寫為application/json
的轉(zhuǎn)換類烘苹。Dropwizard內(nèi)置了一個(gè)這樣的轉(zhuǎn)換類躲株,允許使用Java對象生成JSON對象,JSON對象生成Java對象镣衡。該轉(zhuǎn)換類生成JSON霜定,客戶端會收到200 OK
的內(nèi)容類型為application/json
的響應(yīng)。
注冊資源
不過廊鸥,在這一切生效之前望浩,我們需要回到HelloWorldApplication
并注冊這個(gè)新的資源類。在run
方法中惰说,我們可以從HelloWorldConfiguration
實(shí)例中讀取模板和默認(rèn)名稱 磨德,創(chuàng)建一個(gè)新HelloWorldResource
實(shí)例,然后將其添加到應(yīng)用程序的Jersey環(huán)境中:
@Override
public void run(HelloWorldConfiguration configuration,
Environment environment) {
final HelloWorldResource resource = new HelloWorldResource(
configuration.getTemplate(),
configuration.getDefaultName()
);
environment.jersey().register(resource);
}
當(dāng)我們的應(yīng)用程序啟動(dòng)時(shí)吆视,我們使用配置文件中的參數(shù)創(chuàng)建一個(gè)新的資源類實(shí)例典挑,并將其交給它Environment
,它就像應(yīng)用程序可以執(zhí)行的所有操作的注冊表啦吧。
注意
Dropwizard應(yīng)用程序可以包含許多資源類您觉,每個(gè)資源類都對應(yīng)于自己的URI。只需添加另一個(gè)
@Path
注釋資源類授滓,并使用新類的實(shí)例調(diào)用register
方法即可琳水。
在我們走得太遠(yuǎn)之前肆糕,我們應(yīng)該為我們的應(yīng)用添加健康檢查。
創(chuàng)建健康檢查
運(yùn)行狀況檢查為您提供了一種向應(yīng)用程序添加小測試的方法炫刷,以便您驗(yàn)證應(yīng)用程序在生產(chǎn)中是否正常運(yùn)行擎宝。我們強(qiáng)烈建議您的所有應(yīng)用程序至少具有一組最小的運(yùn)行狀況檢查。
注意
事實(shí)上浑玛,我們強(qiáng)烈推薦這一點(diǎn)绍申,如果你忽略了為你的項(xiàng)目添加健康檢查,Dropwizard會嘮叨你顾彰。
由于格式化字符串在應(yīng)用程序運(yùn)行時(shí)不太可能失敿摹(與數(shù)據(jù)庫連接池不同),因此我們必須在這里想一些創(chuàng)意涨享。我們將添加一個(gè)運(yùn)行狀況檢查筋搏,以確保我們可以格式化提供的模板:
package com.example.helloworld.health;
import com.codahale.metrics.health.HealthCheck;
public class TemplateHealthCheck extends HealthCheck {
private final String template;
public TemplateHealthCheck(String template) {
this.template = template;
}
@Override
protected Result check() throws Exception {
final String saying = String.format(template, "TEST");
if (!saying.contains("TEST")) {
return Result.unhealthy("template doesn't include a name");
}
return Result.healthy();
}
}
TemplateHealthCheck
檢查兩件事:提供的模板確實(shí)是格式良好的格式字符串,模板確實(shí)能生成具有給定名稱的輸出厕隧。
如果字符串不是格式良好的格式字符串(例如奔脐,有人意外地將Hello,%s%
放入 配置文件中),那么String.format(String, Object...)
將拋出一個(gè)IllegalFormatException
吁讨,并且運(yùn)行狀況檢查將隱式失敗髓迎。如果呈現(xiàn)的問候語不包括測試字符串,則運(yùn)行狀況檢查將通過返回不健康的Result
而顯式失敗建丧。
添加健康檢查
與Dropwizard中的大多數(shù)內(nèi)容一樣排龄,我們使用適當(dāng)?shù)膮?shù)創(chuàng)建一個(gè)新實(shí)例并將其添加到Environment
:
@Override
public void run(HelloWorldConfiguration configuration,
Environment environment) {
final HelloWorldResource resource = new HelloWorldResource(
configuration.getTemplate(),
configuration.getDefaultName()
);
final TemplateHealthCheck healthCheck =
new TemplateHealthCheck(configuration.getTemplate());
environment.healthChecks().register("template", healthCheck);
environment.jersey().register(resource);
}
現(xiàn)在我們快要準(zhǔn)備好了!
建立工程的JAR包
我們建議把Dropwizard應(yīng)用程序構(gòu)建為“單” JAR文件-一個(gè).jar
包含所有的運(yùn)行應(yīng)用程序所需的.class
文件翎朱。這允許您構(gòu)建單個(gè)可部署工件橄维,您可以將其從開發(fā)環(huán)境升級到測試環(huán)境再到生產(chǎn)環(huán)境,而無需擔(dān)心已安裝庫中的差異拴曲。要開始構(gòu)建我們的Hello World應(yīng)用程序作為單JAR争舞,我們需要配置一個(gè)名為maven-shade
的Maven插件。在文件的<build><plugins>
部分中pom.xml
澈灼,添加以下內(nèi)容:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.helloworld.HelloWorldApplication</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
這將配置Maven在其package
階段執(zhí)行以下操作:
- 生成一個(gè)
pom.xml
文件竞川,該文件不包含在單JAR中的庫的依賴項(xiàng)的內(nèi)容。 - 從已簽名的JAR中排除所有數(shù)字簽名蕉汪。如果不這樣做流译,則Java認(rèn)為簽名無效,并且不會加載或運(yùn)行您的JAR文件者疤。
- 整理JAR中
META-INF/services
的各種條目而不是覆蓋它們福澡。(如果沒有那些,那么Dropwizard和Jersey都不會工作) - 把
com.example.helloworld.HelloWorldApplication
設(shè)為JARMainClass
驹马。這將允許您使用java -jar
運(yùn)行JAR 革砸。
警告
如果您的應(yīng)用程序具有必須簽名的依賴項(xiàng)(例如除秀,JCA / JCE提供程序或其他可信庫),則必須在 該庫的
maven-shade-plugin
配置中添加排除項(xiàng)算利,并將該JAR包含在類路徑中册踩。
警告
由于Dropwizard使用Java ServiceLoader功能來注冊和加載擴(kuò)展,因此maven-shade-plugin的minimizeJar選項(xiàng)將導(dǎo)致應(yīng)用程序JAR不能正常工作效拭。
版本化您的JAR
Dropwizard也可以使用項(xiàng)目版本暂吉,如果它嵌入在JAR的清單中作為 Implementation-Version
。要使用Maven嵌入此信息缎患,請將以下內(nèi)容添加到文件的 <build><plugins>
部分pom.xml
:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
在嘗試確定您在計(jì)算機(jī)上部署的應(yīng)用程序版本時(shí)慕的,這非常方便。
完成配置后挤渔,進(jìn)入項(xiàng)目目錄并運(yùn)行mvn package
(或從IDE 運(yùn)行package
目標(biāo))肮街。你應(yīng)該看到這樣的東西:
[INFO] Including org.eclipse.jetty:jetty-util:jar:7.6.0.RC0 in the shaded jar.
[INFO] Including com.google.guava:guava:jar:10.0.1 in the shaded jar.
[INFO] Including com.google.code.findbugs:jsr305:jar:1.3.9 in the shaded jar.
[INFO] Including org.hibernate:hibernate-validator:jar:4.2.0.Final in the shaded jar.
[INFO] Including javax.validation:validation-api:jar:1.0.0.GA in the shaded jar.
[INFO] Including org.yaml:snakeyaml:jar:1.9 in the shaded jar.
[INFO] Replacing original artifact with shaded artifact.
[INFO] Replacing /Users/yourname/Projects/hello-world/target/hello-world-0.0.1-SNAPSHOT.jar with /Users/yourname/Projects/hello-world/target/hello-world-0.0.1-SNAPSHOT-shaded.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.415s
[INFO] Finished at: Fri Dec 02 16:26:42 PST 2011
[INFO] Final Memory: 11M/81M
[INFO] ------------------------------------------------------------------------
恭喜!你已經(jīng)建立了你的第一個(gè)Dropwizard項(xiàng)目判导!現(xiàn)在是時(shí)候運(yùn)行了嫉父!
運(yùn)行您的應(yīng)用程序
現(xiàn)在您已經(jīng)構(gòu)建了一個(gè)JAR文件,現(xiàn)在是時(shí)候運(yùn)行它了眼刃。
在項(xiàng)目目錄中绕辖,運(yùn)行以下命令:
java -jar target/hello-world-0.0.1-SNAPSHOT.jar
您應(yīng)該看到如下內(nèi)容:
usage: java -jar hello-world-0.0.1-SNAPSHOT.jar
[-h] [-v] {server} ...
positional arguments:
{server} available commands
optional arguments:
-h, --help show this help message and exit
-v, --version show the service version and exit
Dropwizard接受第一個(gè)命令行參數(shù)并將其分派給匹配的命令。在這種情況下鸟整,唯一可用的命令是server
引镊,將您的應(yīng)用程序作為HTTP服務(wù)器運(yùn)行朦蕴。該 server
命令需要一個(gè)配置文件篮条,所以讓我們繼續(xù)為它提供 我們之前保存的YAML文件:
java -jar target/hello-world-0.0.1-SNAPSHOT.jar server hello-world.yml
您應(yīng)該看到如下內(nèi)容:
INFO [2011-12-03 00:38:32,927] io.dropwizard.cli.ServerCommand: Starting hello-world
INFO [2011-12-03 00:38:32,931] org.eclipse.jetty.server.Server: jetty-7.x.y-SNAPSHOT
INFO [2011-12-03 00:38:32,936] org.eclipse.jetty.server.handler.ContextHandler: started o.e.j.s.ServletContextHandler{/,null}
INFO [2011-12-03 00:38:32,999] com.sun.jersey.server.impl.application.WebApplicationImpl: Initiating Jersey application, version 'Jersey: 1.10 11/02/2011 03:53 PM'
INFO [2011-12-03 00:38:33,041] io.dropwizard.setup.Environment:
GET /hello-world (com.example.helloworld.resources.HelloWorldResource)
INFO [2011-12-03 00:38:33,215] org.eclipse.jetty.server.handler.ContextHandler: started o.e.j.s.ServletContextHandler{/,null}
INFO [2011-12-03 00:38:33,235] org.eclipse.jetty.server.AbstractConnector: Started BlockingChannelConnector@0.0.0.0:8080 STARTING
INFO [2011-12-03 00:38:33,238] org.eclipse.jetty.server.AbstractConnector: Started SocketConnector@0.0.0.0:8081 STARTING
您的Dropwizard應(yīng)用程序現(xiàn)在正在偵聽8080
應(yīng)用程序請求和8081
管理請求的端口。如果按^C
吩抓,應(yīng)用程序?qū)⒄jP(guān)閉涉茧,首先關(guān)閉服務(wù)器套接字,然后等待處理正在進(jìn)行的請求疹娶,然后關(guān)閉進(jìn)程本身伴栓。
大功告成,試一下雨饺! http://localhost:8080/hello-world
我們正在產(chǎn)生問候語钳垮,真棒。當(dāng)然你的應(yīng)用程序能做到的遠(yuǎn)遠(yuǎn)不止這些额港。使用Dropwizard的主要原因之一是它提供的開箱即用的操作工具饺窿,所有這些工具都可以在管理端口上 http://localhost:8081/找到。
如果訪問指標(biāo)資源 http://localhost:8081/metrics移斩,則可以看到所有應(yīng)用程序的指標(biāo)都表示為JSON對象肚医。
訪問線程的資源 http://localhost:8081/threads可以讓您快速獲得在這個(gè)過程中運(yùn)行的所有線程的線程轉(zhuǎn)儲绢馍。
提示
當(dāng)Jetty工作線程處理傳入的HTTP請求時(shí),線程名稱將設(shè)置為請求的方法和URI肠套。在調(diào)試性能不佳的請求時(shí)舰涌,這非常有用。
在健康檢查資源運(yùn)行 健康檢查類你稚。你應(yīng)該看到這樣的東西:
* deadlocks: OK
* template: OK
template
這是你的TemplateHealthCheck
的結(jié)果瓷耙,毫不奇怪地通過了。 deadlocks
是一個(gè)內(nèi)置的運(yùn)行狀況檢查刁赖,它查找死鎖的JVM線程并打印出列表(如果找到)哺徊。
下一步
嗯,恭喜乾闰。您已經(jīng)準(zhǔn)備好用于生產(chǎn)的Hello World應(yīng)用程序(除了缺少測試)落追,它能夠每秒執(zhí)行30,000-50,000個(gè)請求。希望您已經(jīng)了解了Dropwizard如何將Jetty涯肩,Jersey轿钠,Jackson和其他穩(wěn)定,成熟的庫結(jié)合起來病苗,為開發(fā)RESTful Web應(yīng)用程序提供了一個(gè)非凡的平臺疗垛。
Dropwizard還有很多內(nèi)容(命令commands,綁定bundles硫朦,servlet贷腕,高級配置,驗(yàn)證validation咬展,HTTP客戶端泽裳,數(shù)據(jù)庫客戶端,視圖等)破婆,所有這些都在用戶手冊中介紹涮总。
官網(wǎng) https://www.dropwizard.io/1.3.5/docs/getting-started.html